Slack
Status: production-ready for DMs + channels via Slack app integrations. Default mode is Socket Mode; HTTP Events API mode is also supported.
Quick setup
Section titled “Quick setup” - enable **Socket Mode** - create **App Token** (`xapp-...`) with `connections:write` - install app and copy **Bot Token** (`xoxb-...`) </Step>
<Step title="Configure CoderClaw">{ channels: { slack: { enabled: true, mode: "socket", appToken: "xapp-...", botToken: "xoxb-...", }, },} Env fallback (default account only):SLACK_APP_TOKEN=xapp-...SLACK_BOT_TOKEN=xoxb-... </Step>
<Step title="Subscribe app events"> Subscribe bot events for:
- `app_mention` - `message.channels`, `message.groups`, `message.im`, `message.mpim` - `reaction_added`, `reaction_removed` - `member_joined_channel`, `member_left_channel` - `channel_rename` - `pin_added`, `pin_removed`
Also enable App Home **Messages Tab** for DMs. </Step>
<Step title="Start gateway">coderclaw gateway </Step></Steps> - set mode to HTTP (`channels.slack.mode="http"`) - copy Slack **Signing Secret** - set Event Subscriptions + Interactivity + Slash command Request URL to the same webhook path (default `/slack/events`)
</Step>
<Step title="Configure CoderClaw HTTP mode">{ channels: { slack: { enabled: true, mode: "http", botToken: "xoxb-...", signingSecret: "your-signing-secret", webhookPath: "/slack/events", }, },} </Step>
<Step title="Use unique webhook paths for multi-account HTTP"> Per-account HTTP mode is supported.
Give each account a distinct `webhookPath` so registrations do not collide. </Step></Steps>Token model
Section titled “Token model”botToken+appTokenare required for Socket Mode.- HTTP mode requires
botToken+signingSecret. - Config tokens override env fallback.
SLACK_BOT_TOKEN/SLACK_APP_TOKENenv fallback applies only to the default account.userToken(xoxp-...) is config-only (no env fallback) and defaults to read-only behavior (userTokenReadOnly: true).- Optional: add
chat:write.customizeif you want outgoing messages to use the active agent identity (customusernameand icon).icon_emojiuses:emoji_name:syntax.
Access control and routing
Section titled “Access control and routing”- `pairing` (default)- `allowlist`- `open` (requires `channels.slack.allowFrom` to include `"*"`; legacy: `channels.slack.dm.allowFrom`)- `disabled`
DM flags:
- `dm.enabled` (default true)- `channels.slack.allowFrom` (preferred)- `dm.allowFrom` (legacy)- `dm.groupEnabled` (group DMs default false)- `dm.groupChannels` (optional MPIM allowlist)
Pairing in DMs uses `coderclaw pairing approve slack <code>`.- `open`- `allowlist`- `disabled`
Channel allowlist lives under `channels.slack.channels`.
Runtime note: if `channels.slack` is completely missing (env-only setup) and `channels.defaults.groupPolicy` is unset, runtime falls back to `groupPolicy="open"` and logs a warning.
Name/ID resolution:
- channel allowlist entries and DM allowlist entries are resolved at startup when token access allows- unresolved entries are kept as configuredMention sources:
- explicit app mention (`<@botId>`)- mention regex patterns (`agents.list[].groupChat.mentionPatterns`, fallback `messages.groupChat.mentionPatterns`)- implicit reply-to-bot thread behavior
Per-channel controls (`channels.slack.channels.<id|name>`):
- `requireMention`- `users` (allowlist)- `allowBots`- `skills`- `systemPrompt`- `tools`, `toolsBySender`Commands and slash behavior
Section titled “Commands and slash behavior”- Native command auto-mode is off for Slack (
commands.native: "auto"does not enable Slack native commands). - Enable native Slack command handlers with
channels.slack.commands.native: true(or globalcommands.native: true). - When native commands are enabled, register matching slash commands in Slack (
/<command>names). - If native commands are not enabled, you can run a single configured slash command via
channels.slack.slashCommand. - Native arg menus now adapt their rendering strategy:
- up to 5 options: button blocks
- 6-100 options: static select menu
- more than 100 options: external select with async option filtering when interactivity options handlers are available
- if encoded option values exceed Slack limits, the flow falls back to buttons
- For long option payloads, Slash command argument menus use a confirm dialog before dispatching a selected value.
Default slash command settings:
enabled: falsename: "coderclaw"sessionPrefix: "slack:slash"ephemeral: true
Slash sessions use isolated keys:
agent:<agentId>:slack:slash:<userId>
and still route command execution against the target conversation session (CommandTargetSessionKey).
Threading, sessions, and reply tags
Section titled “Threading, sessions, and reply tags”- DMs route as
direct; channels aschannel; MPIMs asgroup. - With default
session.dmScope=main, Slack DMs collapse to agent main session. - Channel sessions:
agent:<agentId>:slack:channel:<channelId>. - Thread replies can create thread session suffixes (
:thread:<threadTs>) when applicable. channels.slack.thread.historyScopedefault isthread;thread.inheritParentdefault isfalse.channels.slack.thread.initialHistoryLimitcontrols how many existing thread messages are fetched when a new thread session starts (default20; set0to disable).
Reply threading controls:
channels.slack.replyToMode:off|first|all(defaultoff)channels.slack.replyToModeByChatType: perdirect|group|channel- legacy fallback for direct chats:
channels.slack.dm.replyToMode
Manual reply tags are supported:
[[reply_to_current]][[reply_to:<id>]]
Note: replyToMode="off" disables implicit reply threading. Explicit [[reply_to_*]] tags are still honored.
Media, chunking, and delivery
Section titled “Media, chunking, and delivery”Runtime inbound size cap defaults to `20MB` unless overridden by `channels.slack.mediaMaxMb`.- `user:<id>` for DMs- `channel:<id>` for channels
Slack DMs are opened via Slack conversation APIs when sending to user targets.Actions and gates
Section titled “Actions and gates”Slack actions are controlled by channels.slack.actions.*.
Available action groups in current Slack tooling:
| Group | Default |
|---|---|
| messages | enabled |
| reactions | enabled |
| pins | enabled |
| memberInfo | enabled |
| emojiList | enabled |
Events and operational behavior
Section titled “Events and operational behavior”- Message edits/deletes/thread broadcasts are mapped into system events.
- Reaction add/remove events are mapped into system events.
- Member join/leave, channel created/renamed, and pin add/remove events are mapped into system events.
- Assistant thread status updates (for “is typing…” indicators in threads) use
assistant.threads.setStatusand require bot scopeassistant:write. channel_id_changedcan migrate channel config keys whenconfigWritesis enabled.- Channel topic/purpose metadata is treated as untrusted context and can be injected into routing context.
- Block actions and modal interactions emit structured
Slack interaction: ...system events with rich payload fields:- block actions: selected values, labels, picker values, and
workflow_*metadata - modal
view_submissionandview_closedevents with routed channel metadata and form inputs
- block actions: selected values, labels, picker values, and
Ack reactions
Section titled “Ack reactions”ackReaction sends an acknowledgement emoji while CoderClaw is processing an inbound message.
Resolution order:
channels.slack.accounts.<accountId>.ackReactionchannels.slack.ackReactionmessages.ackReaction- agent identity emoji fallback (
agents.list[].identity.emoji, else ”👀”)
Notes:
- Slack expects shortcodes (for example
"eyes"). - Use
""to disable the reaction for a channel or account.
Manifest and scope checklist
Section titled “Manifest and scope checklist”{ "display_information": { "name": "CoderClaw", "description": "Slack connector for CoderClaw" }, "features": { "bot_user": { "display_name": "CoderClaw", "always_online": false }, "app_home": { "messages_tab_enabled": true, "messages_tab_read_only_enabled": false }, "slash_commands": [ { "command": "/coderclaw", "description": "Send a message to CoderClaw", "should_escape": false } ] }, "oauth_config": { "scopes": { "bot": [ "chat:write", "channels:history", "channels:read", "groups:history", "im:history", "mpim:history", "users:read", "app_mentions:read", "assistant:write", "reactions:read", "reactions:write", "pins:read", "pins:write", "emoji:read", "commands", "files:read", "files:write" ] } }, "settings": { "socket_mode_enabled": true, "event_subscriptions": { "bot_events": [ "app_mention", "message.channels", "message.groups", "message.im", "message.mpim", "reaction_added", "reaction_removed", "member_joined_channel", "member_left_channel", "channel_rename", "pin_added", "pin_removed" ] } }}- `channels:history`, `groups:history`, `im:history`, `mpim:history`- `channels:read`, `groups:read`, `im:read`, `mpim:read`- `users:read`- `reactions:read`- `pins:read`- `emoji:read`- `search:read` (if you depend on Slack search reads)Troubleshooting
Section titled “Troubleshooting”- `groupPolicy`- channel allowlist (`channels.slack.channels`)- `requireMention`- per-channel `users` allowlist
Useful commands:coderclaw channels status --probecoderclaw logs --followcoderclaw doctor- `channels.slack.dm.enabled`- `channels.slack.dmPolicy` (or legacy `channels.slack.dm.policy`)- pairing approvals / allowlist entriescoderclaw pairing list slack- signing secret- webhook path- Slack Request URLs (Events + Interactivity + Slash Commands)- unique `webhookPath` per HTTP account- native command mode (`channels.slack.commands.native: true`) with matching slash commands registered in Slack- or single slash command mode (`channels.slack.slashCommand.enabled: true`)
Also check `commands.useAccessGroups` and channel/user allowlists.Text streaming
Section titled “Text streaming”CoderClaw supports Slack native text streaming via the Agents and AI Apps API.
By default, streaming is enabled. Disable it per account:
channels: slack: streaming: falseRequirements
Section titled “Requirements”- Enable Agents and AI Apps in your Slack app settings.
- Ensure the app has the
assistant:writescope. - A reply thread must be available for that message. Thread selection still follows
replyToMode.
Behavior
Section titled “Behavior”- First text chunk starts a stream (
chat.startStream). - Later text chunks append to the same stream (
chat.appendStream). - End of reply finalizes stream (
chat.stopStream). - Media and non-text payloads fall back to normal delivery.
- If streaming fails mid-reply, CoderClaw falls back to normal delivery for remaining payloads.
Configuration reference pointers
Section titled “Configuration reference pointers”Primary reference:
-
Configuration reference - Slack
High-signal Slack fields:
- mode/auth:
mode,botToken,appToken,signingSecret,webhookPath,accounts.* - DM access:
dm.enabled,dmPolicy,allowFrom(legacy:dm.policy,dm.allowFrom),dm.groupEnabled,dm.groupChannels - channel access:
groupPolicy,channels.*,channels.*.users,channels.*.requireMention - threading/history:
replyToMode,replyToModeByChatType,thread.*,historyLimit,dmHistoryLimit,dms.*.historyLimit - delivery:
textChunkLimit,chunkMode,mediaMaxMb - ops/features:
configWrites,commands.native,slashCommand.*,actions.*,userToken,userTokenReadOnly
- mode/auth: