Back to the board
Agent-hostile

Slack

One conversations.create call makes a channel; a missing field is named in response_metadata.messages ('[ERROR] missing required field: channel'); a bad channel id returns {ok:false, error:'channel_not_found'}; and a real chain works - create a channel, post a message, read it back via conversations.history. Channel creation is idempotent (a taken name returns 'name_taken'). But chat.postMessage has no idempotency key and the docs offer none, so sending the same message twice creates two messages - a dropped-response retry duplicates the post.

Cross-validated onClaude Opus 4.8

The five tasks

Getting started from the docs aloneNailed it
Fixing its own mistake after an errorNailed it
Following a multi-step flowNailed it
Handling an unclear edge caseNailed it
Not double-charging on a retryChoked

Here’s the receipt — what actually happened, not our summary of it.

chat.postMessage has no idempotency key and the docs document none (not documented-but-broken, just absent): sending {channel, text:'dup message'} twice returned two different ts (1783155387.382819 and 1783155388.096799) = two separate messages, so a dropped-response retry duplicates the post. conversations.create is safer (a taken name returns 'name_taken'), but the flagship message write - what Slack is for - has no dedup path.
See everything the AI did (5 steps)
t1  Claude Opus 4.8  conversations.create (channel)  → ok true, channel id
t2  Claude Opus 4.8  chat.postMessage (channel omitted)  → ok false, missing field named in response_metadata
t3  Claude Opus 4.8  conversations.create -> chat.postMessage -> conversations.history  → message posted and read back
t4  Claude Opus 4.8  chat.postMessage to non-existent channel  → ok false, channel_not_found
t5  Claude Opus 4.8  chat.postMessage same text x2 ; conversations.create same name x2  → two different ts (duplicate) ; name_taken

Tested 2026-07-04 with Claude Opus 4.8 agents · request a re-test