Caricamento in corso...
Caricamento in corso...
Last synced: Today, 22:00
Technical reference for the OpenClaw framework. Real-time synchronization with the official documentation engine.
Use this file to discover all available pages before exploring further.
Production-ready for DMs and channels via Slack app integrations. Default mode is Socket Mode; HTTP Request URLs are also supported.
Slack DMs default to pairing mode.
Native command behavior and command catalog.
Cross-channel diagnostics and repair playbooks.
text* choose **from a manifest** and select a workspace for your app * paste the [example manifest](#manifest-and-scope-checklist) from below and continue to create * generate an **App-Level Token** (`xapp-...`) with `connections:write` * install app and copy the **Bot Token** (`xoxb-...`) shown </Step> <Step title="Configure OpenClaw"> Recommended SecretRef setup: ```bash} export SLACK_APP_TOKEN=xapp-... export SLACK_BOT_TOKEN=xoxb-... cat > slack.socket.patch.json5 <<'JSON5' { channels: { slack: { enabled: true, mode: "socket", appToken: { source: "env", provider: "default", id: "SLACK_APP_TOKEN" }, botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" }, }, }, } JSON5 openclaw config patch --file ./slack.socket.patch.json5 --dry-run openclaw config patch --file ./slack.socket.patch.json5 ``` Env fallback (default account only): ```bash} SLACK_APP_TOKEN=xapp-... SLACK_BOT_TOKEN=xoxb-... ``` </Step> <Step title="Start gateway"> ```bash} openclaw gateway ``` </Step> </Steps>
text* choose **from a manifest** and select a workspace for your app * paste the [example manifest](#manifest-and-scope-checklist) and update the URLs before create * save the **Signing Secret** for request verification * install app and copy the **Bot Token** (`xoxb-...`) shown </Step> <Step title="Configure OpenClaw"> Recommended SecretRef setup: ```bash} export SLACK_BOT_TOKEN=xoxb-... export SLACK_SIGNING_SECRET=... cat > slack.http.patch.json5 <<'JSON5' { channels: { slack: { enabled: true, mode: "http", botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" }, signingSecret: { source: "env", provider: "default", id: "SLACK_SIGNING_SECRET" }, webhookPath: "/slack/events", }, }, } JSON5 openclaw config patch --file ./slack.http.patch.json5 --dry-run openclaw config patch --file ./slack.http.patch.json5 ``` <Note> Use unique webhook paths for multi-account HTTP Give each account a distinct `webhookPath` (default `/slack/events`) so registrations do not collide. </Note> </Step> <Step title="Start gateway"> ```bash} openclaw gateway ``` </Step> </Steps>
OpenClaw sets the Slack SDK client pong timeout to 15 seconds by default for Socket Mode. Override the transport settings only when you need workspace- or host-specific tuning:
json5{ channels: { slack: { mode: "socket", socketMode: { clientPingTimeout: 20000, serverPingTimeout: 30000, pingPongLoggingEnabled: false, }, }, }, }
Use this only for Socket Mode workspaces that log Slack websocket pong/server-ping timeouts or run on hosts with known event-loop starvation.
clientPingTimeoutserverPingTimeoutThe base Slack app manifest is the same for Socket Mode and HTTP Request URLs. Only the
settingsurlBase manifest (Socket Mode default):
json{ "display_information": { "name": "OpenClaw", "description": "Slack connector for OpenClaw" }, "features": { "bot_user": { "display_name": "OpenClaw", "always_online": true }, "app_home": { "messages_tab_enabled": true, "messages_tab_read_only_enabled": false }, "slash_commands": [ { "command": "/openclaw", "description": "Send a message to OpenClaw", "should_escape": false } ] }, "oauth_config": { "scopes": { "bot": [ "app_mentions:read", "assistant:write", "channels:history", "channels:read", "chat:write", "commands", "emoji:read", "files:read", "files:write", "groups:history", "groups:read", "im:history", "im:read", "im:write", "mpim:history", "mpim:read", "mpim:write", "pins:read", "pins:write", "reactions:read", "reactions:write", "users:read" ] } }, "settings": { "socket_mode_enabled": true, "event_subscriptions": { "bot_events": [ "app_mention", "channel_rename", "member_joined_channel", "member_left_channel", "message.channels", "message.groups", "message.im", "message.mpim", "pin_added", "pin_removed", "reaction_added", "reaction_removed" ] } } }
For HTTP Request URLs mode, replace
settingsurljson{ "features": { "slash_commands": [ { "command": "/openclaw", "description": "Send a message to OpenClaw", "should_escape": false, "url": "https://gateway-host.example.com/slack/events" } ] }, "settings": { "event_subscriptions": { "request_url": "https://gateway-host.example.com/slack/events", "bot_events": [ /* same as Socket Mode */ ] }, "interactivity": { "is_enabled": true, "request_url": "https://gateway-host.example.com/slack/events", "message_menu_options_url": "https://gateway-host.example.com/slack/events" } } }
Surface different features that extend the above defaults.
botTokenappTokenbotTokensigningSecretbotTokenappTokensigningSecretuserTokenSLACK_BOT_TOKENSLACK_APP_TOKENuserTokenxoxp-...userTokenReadOnly: trueStatus snapshot behavior:
*Source*StatusbotTokenappTokensigningSecretuserTokenavailableconfigured_unavailablemissingconfigured_unavailablesigningSecretStatusbotTokenStatusappTokenStatusSlack 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 |
Current Slack message actions include
sendupload-filedownload-filereadeditdeletepinunpinlist-pinsmember-infoemoji-listdownload-filetext* `pairing` (default) * `allowlist` * `open` (requires `channels.slack.allowFrom` to include `"*"`) * `disabled` DM flags: * `dm.enabled` (default true) * `channels.slack.allowFrom` * `dm.allowFrom` (legacy) * `dm.groupEnabled` (group DMs default false) * `dm.groupChannels` (optional MPIM allowlist) Multi-account precedence: * `channels.slack.accounts.default.allowFrom` applies only to the `default` account. * Named accounts inherit `channels.slack.allowFrom` when their own `allowFrom` is unset. * Named accounts do not inherit `channels.slack.accounts.default.allowFrom`. Legacy `channels.slack.dm.policy` and `channels.slack.dm.allowFrom` still read for compatibility. `openclaw doctor --fix` migrates them to `dmPolicy` and `allowFrom` when it can do so without changing access. Pairing in DMs uses `openclaw pairing approve slack <code>`.
text* `open` * `allowlist` * `disabled` Channel allowlist lives under `channels.slack.channels` and **must use stable Slack channel IDs** (for example `C12345678`) as config keys. Runtime note: if `channels.slack` is completely missing (env-only setup), runtime falls back to `groupPolicy="allowlist"` and logs a warning (even if `channels.defaults.groupPolicy` is set). Name/ID resolution: * channel allowlist entries and DM allowlist entries are resolved at startup when token access allows * unresolved channel-name entries are kept as configured but ignored for routing by default * inbound authorization and channel routing are ID-first by default; direct username/slug matching requires `channels.slack.dangerouslyAllowNameMatching: true` <Warning> Name-based keys (`#channel-name` or `channel-name`) do **not** match under `groupPolicy: "allowlist"`. The channel lookup is ID-first by default, so a name-based key will never route successfully and all messages in that channel will be silently blocked. This differs from `groupPolicy: "open"`, where the channel key is not required for routing and a name-based key appears to work. Always use the Slack channel ID as the key. To find it: right-click the channel in Slack → **Copy link** — the ID (`C...`) appears at the end of the URL. Correct: ```json5} { channels: { slack: { groupPolicy: "allowlist", channels: { C12345678: { allow: true, requireMention: true }, }, }, }, } ``` Incorrect (silently blocked under `groupPolicy: "allowlist"`): ```json5} { channels: { slack: { groupPolicy: "allowlist", channels: { "#eng-my-channel": { allow: true, requireMention: true }, }, }, }, } ``` </Warning>
textMention sources: * explicit app mention (`<@botId>`) * mention regex patterns (`agents.list[].groupChat.mentionPatterns`, fallback `messages.groupChat.mentionPatterns`) * implicit reply-to-bot thread behavior (disabled when `thread.requireExplicitMention` is `true`) Per-channel controls (`channels.slack.channels.<id>`; names only via startup resolution or `dangerouslyAllowNameMatching`): * `requireMention` * `users` (allowlist) * `allowBots` * `skills` * `systemPrompt` * `tools`, `toolsBySender` * `toolsBySender` key format: `id:`, `e164:`, `username:`, `name:`, or `"*"` wildcard (legacy unprefixed keys still map to `id:` only) `allowBots` is conservative for channels and private channels: bot-authored room messages are accepted only when the sending bot is explicitly listed in that room's `users` allowlist, or when at least one explicit Slack owner ID from `channels.slack.allowFrom` is currently a room member. Wildcards and display-name owner entries do not satisfy owner presence. Owner presence uses Slack `conversations.members`; make sure the app has the matching read scope for the room type (`channels:read` for public channels, `groups:read` for private channels). If the member lookup fails, OpenClaw drops the bot-authored room message.
directchannelgroupsession.dmScope=mainagent:<agentId>:slack:channel:<channelId>:thread:<threadTs>channels.slack.thread.historyScopethreadthread.inheritParentfalsechannels.slack.thread.initialHistoryLimit200channels.slack.thread.requireExplicitMentionfalsetrue@botrequireMentionReply threading controls:
channels.slack.replyToModeoff|first|all|batchedoffchannels.slack.replyToModeByChatTypedirect|group|channelchannels.slack.dm.replyToModeManual reply tags are supported:
[[reply_to_current]][[reply_to:<id>]]ackReactionResolution order:
channels.slack.accounts.<accountId>.ackReactionchannels.slack.ackReactionmessages.ackReactionagents.list[].identity.emojiNotes:
"eyes"""channels.slack.streamingoffpartialblockprogressstreaming.preview.toolProgresstruefalsechannels.slack.streaming.nativeTransportchannels.slack.streaming.modepartialtruereplyToModetypingReactionUse draft preview instead of Slack native text streaming:
json5{ channels: { slack: { streaming: { mode: "partial", nativeTransport: false, }, }, }, }
Legacy keys:
channels.slack.streamModereplace | status_final | appendchannels.slack.streaming.modechannels.slack.streamingchannels.slack.streaming.modechannels.slack.streaming.nativeTransportchannels.slack.nativeStreamingchannels.slack.streaming.nativeTransporttypingReactionResolution order:
channels.slack.accounts.<accountId>.typingReactionchannels.slack.typingReactionNotes:
"hourglass_flowing_sand"Slash commands appear in Slack as either a single configured command or multiple native commands. Configure
channels.slack.slashCommandenabled: falsename: "openclaw"sessionPrefix: "slack:slash"ephemeral: truetxt/openclaw /help
Native commands require additional manifest settings in your Slack app and are enabled with
channels.slack.commands.native: truecommands.native: truecommands.native: "auto"txt/help
Native argument menus use an adaptive rendering strategy that shows a confirmation modal before dispatching a selected option value:
txt/think
Slash sessions use isolated keys like
agent:<agentId>:slack:slash:<userId>CommandTargetSessionKeySlack can render agent-authored interactive reply controls, but this feature is disabled by default.
Enable it globally:
json5{ channels: { slack: { capabilities: { interactiveReplies: true, }, }, }, }
Or enable it for one Slack account only:
json5{ channels: { slack: { accounts: { ops: { capabilities: { interactiveReplies: true, }, }, }, }, }, }
When enabled, agents can emit Slack-only reply directives:
[[slack_buttons: Approve:approve, Reject:reject]][[slack_select: Choose a target | Canary:canary, Production:production]]These directives compile into Slack Block Kit and route clicks or selections back through the existing Slack interaction event path.
Notes:
Slack can act as a native approval client with interactive buttons and interactions, instead of falling back to the Web UI or terminal.
channels.slack.execApprovals.*plugin:This uses the same shared approval button surface as other channels. When
interactivity/approveConfig path:
channels.slack.execApprovals.enabledchannels.slack.execApprovals.approverscommands.ownerAllowFromchannels.slack.execApprovals.targetdmchannelbothdmagentFiltersessionFilterSlack auto-enables native exec approvals when
enabled"auto"enabled: falseenabled: trueDefault behavior with no explicit Slack exec approval config:
json5{ commands: { ownerAllowFrom: ["slack:U12345678"], }, }
Explicit Slack-native config is only needed when you want to override approvers, add filters, or opt into origin-chat delivery:
json5{ channels: { slack: { execApprovals: { enabled: true, approvers: ["U12345678"], target: "both", }, }, }, }
Shared
approvals.execapprovals.pluginSame-chat
/approvechannel_id_changedconfigWritesSlack interaction: ...workflow_*view_submissionview_closedPrimary reference: Configuration reference - Slack.
Slack can attach downloaded media to the agent turn when Slack file downloads succeed and size limits permit. Image files can be passed through the media understanding path or directly to a vision-capable reply model; other files are retained as downloadable file context rather than treated as image input.
| Media type | Source | Current behavior | Notes |
|---|---|---|---|
| JPEG / PNG / GIF / WebP images | Slack file URL | Downloaded and attached to the turn for vision-capable handling | Per-file cap: text channels.slack.mediaMaxMb |
| PDF files | Slack file URL | Downloaded and exposed as file context for tools such as text download-filetext pdf | Slack inbound does not convert PDFs into image-vision input automatically |
| Other files | Slack file URL | Downloaded when possible and exposed as file context | Binary files are not treated as image input |
| Thread replies | Thread starter files | Root-message files can be hydrated as context when the reply has no direct media | File-only starters use an attachment placeholder |
| Multi-image messages | Multiple Slack files | Each file is evaluated independently | Slack processing is capped at eight files per message |
When a Slack message with file attachments arrives:
xoxb-...When a message arrives in a thread (has a
thread_tsWhen a single Slack message contains multiple file attachments:
channels.slack.mediaMaxMbagents.defaults.imageModel| Scenario | Current behavior | Workaround |
|---|---|---|
| Expired Slack file URL | File skipped; no error shown | Re-upload the file in Slack |
| Vision model not configured | Image attachments are stored as media references, but not analyzed as images | Configure text agents.defaults.imageModel |
| Very large images (> 20 MB by default) | Skipped per size cap | Increase text channels.slack.mediaMaxMb |
| Forwarded/shared attachments | Text and Slack-hosted image/file media are best-effort | Re-share directly in the OpenClaw thread |
| PDF attachments | Stored as file/media context, not automatically routed through image vision | Use text download-filetext pdf |
© 2024 TaskFlow Mirror
Powered by TaskFlow Sync Engine