Status: production-ready for DMs + channels via Slack app integrations. Default mode is Socket Mode; HTTP Events API mode is also supported.
<CardGroup cols={3}>
</CardGroup>
botToken + appToken are required for Socket Mode.botToken + signingSecret.SLACK_BOT_TOKEN / SLACK_APP_TOKEN env fallback applies only to the default account.userToken (xoxp-...) is config-only (no env fallback) and defaults to read-only behavior (userTokenReadOnly: true).chat:write.customize if you want outgoing messages to use the active agent identity (custom username and icon). icon_emoji uses :emoji_name: syntax.`.
</Tab>
`channels.slack.groupPolicy` controls channel handling:
- `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 configured
Channel messages are mention-gated by default.
Mention 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`
</Tabs>
## 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 global `commands.native: true`).
- When native commands are enabled, register matching slash commands in Slack (`/ ` 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: false`
- `name: "coderclaw"`
- `sessionPrefix: "slack:slash"`
- `ephemeral: true`
Slash sessions use isolated keys:
- `agent::slack:slash:`
and still route command execution against the target conversation session (`CommandTargetSessionKey`).
## Threading, sessions, and reply tags
- DMs route as `direct`; channels as `channel`; MPIMs as `group`.
- With default `session.dmScope=main`, Slack DMs collapse to agent main session.
- Channel sessions: `agent::slack:channel:`.
- Thread replies can create thread session suffixes (`:thread:`) when applicable.
- `channels.slack.thread.historyScope` default is `thread`; `thread.inheritParent` default is `false`.
- `channels.slack.thread.initialHistoryLimit` controls how many existing thread messages are fetched when a new thread session starts (default `20`; set `0` to disable).
Reply threading controls:
- `channels.slack.replyToMode`: `off|first|all` (default `off`)
- `channels.slack.replyToModeByChatType`: per `direct|group|channel`
- legacy fallback for direct chats: `channels.slack.dm.replyToMode`
Manual reply tags are supported:
- `[[reply_to_current]]`
- `[[reply_to:]]`
Note: `replyToMode="off"` disables implicit reply threading. Explicit `[[reply_to_*]]` tags are still honored.
## Media, chunking, and delivery
Slack file attachments are downloaded from Slack-hosted private URLs (token-authenticated request flow) and written to the media store when fetch succeeds and size limits permit.
Runtime inbound size cap defaults to `20MB` unless overridden by `channels.slack.mediaMaxMb`.
- text chunks use `channels.slack.textChunkLimit` (default 4000)
- `channels.slack.chunkMode="newline"` enables paragraph-first splitting
- file sends use Slack upload APIs and can include thread replies (`thread_ts`)
- outbound media cap follows `channels.slack.mediaMaxMb` when configured; otherwise channel sends use MIME-kind defaults from media pipeline
Preferred explicit targets:
- `user:` for DMs
- `channel:` for channels
Slack DMs are opened via Slack conversation APIs when sending to user targets.
</Accordion>
</AccordionGroup>
## 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
- 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.setStatus` and require bot scope `assistant:write`.
- `channel_id_changed` can migrate channel config keys when `configWrites` is 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_submission` and `view_closed` events with routed channel metadata and form inputs
## Ack reactions
`ackReaction` sends an acknowledgement emoji while CoderClaw is processing an inbound message.
Resolution order:
- `channels.slack.accounts..ackReaction`
- `channels.slack.ackReaction`
- `messages.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
```json
{
"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"
]
}
}
}
```
If you configure `channels.slack.userToken`, typical read scopes are:
- `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
Check, in order:
- `groupPolicy`
- channel allowlist (`channels.slack.channels`)
- `requireMention`
- per-channel `users` allowlist
Useful commands:
```bash
coderclaw channels status --probe
coderclaw logs --follow
coderclaw doctor
```
Check:
- `channels.slack.dm.enabled`
- `channels.slack.dmPolicy` (or legacy `channels.slack.dm.policy`)
- pairing approvals / allowlist entries
```bash
coderclaw pairing list slack
```
Validate bot + app tokens and Socket Mode enablement in Slack app settings.
Validate:
- signing secret
- webhook path
- Slack Request URLs (Events + Interactivity + Slash Commands)
- unique `webhookPath` per HTTP account
Verify whether you intended:
- 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
CoderClaw supports Slack native text streaming via the Agents and AI Apps API.
By default, streaming is enabled. Disable it per account:
```yaml
channels:
slack:
streaming: false
```
### Requirements
1. Enable **Agents and AI Apps** in your Slack app settings.
2. Ensure the app has the `assistant:write` scope.
3. A reply thread must be available for that message. Thread selection still follows `replyToMode`.
### 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
Primary reference:
- [Configuration reference - Slack](/gateway/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`
## Related
- [Pairing](/channels/pairing)
- [Channel routing](/channels/channel-routing)
- [Troubleshooting](/channels/troubleshooting)
- [Configuration](/gateway/configuration)
- [Slash commands](/tools/slash-commands)