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