Skip to main content

Slack

Status: ✅ Supported (OpenClaw, Hermes)

Mode: Socket Mode (default) — outbound WebSocket, no public endpoint needed.

Slack channel allows your agent to operate as a bot in Slack workspaces, responding to mentions, DMs, and thread messages.


Token Model

Socket Mode requires two tokens:

TokenPrefixSecret NamePurpose
Bot Tokenxoxb-SLACK_BOT_TOKENAuthenticates bot actions (send messages, read channels)
App Tokenxapp-SLACK_APP_TOKENAuthenticates the WebSocket connection to Slack

Both tokens use SecretRef objects in config and fall back to environment variables.

Env Fallback

For the default account, tokens resolve from environment if not in config:

SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...

⚠️ Critical Prerequisites for DMs

Before creating your Slack app, understand that these permissions are non-negotiable for direct messages to work:

Required OAuth Scopes

Without these, you cannot DM the bot:

  • im:history - Bot MUST be able to read DM history
  • im:read - Bot MUST be able to access DM metadata
  • im:write - Bot MUST be able to write to DMs (⚠️ see security note below — applies to both OpenClaw and Hermes)
  • chat:write - Bot MUST be able to send messages

⚠️ Security note on im:write (applies to OpenClaw and Hermes): This scope lets the bot initiate unsolicited DMs to any workspace member — neither OpenClaw's allowFrom nor Hermes' SLACK_ALLOWED_USERS gate outbound messages. A compromised agent host or leaked xoxb- token can DM-spam or phish the entire workspace. Mitigations: keep the host hardened; treat the bot token as a high-value secret; rotate the token immediately on suspicion (Slack API → OAuth & PermissionsRotate Tokens → update the channel record (clawctl channel registry edit <channel-name> --token-stdin <<<"$NEW_BOT_TOKEN" then clawctl channel registry edit <channel-name> --app-token "$NEW_APP_TOKEN") and clawctl agent sync <name>); audit users:read calls in your workspace's Slack audit log if you suspect abuse.

Required Event Subscriptions

Without these, the bot will not receive your DMs:

  • message.im - Fires when you send a DM to the bot (CRITICAL)
  • app_mention - Fires when you @-mention the bot in channels

What Happens Without These?

  • Missing im:* scopes: Slack UI won't let you message the bot (Message button disabled/missing in Slack app directory)
  • Missing message.im event: Bot receives no notification when you DM it (messages sent but bot never sees them)
  • Missing chat:write scope: Bot can receive messages but cannot respond

Verification After Setup:

  1. Go to https://api.slack.com/apps → Select your app
  2. Navigate to Event SubscriptionsSubscribe to bot events
  3. Confirm message.im is listed
  4. If not, add it and reinstall the app to your workspace (required for changes to take effect)

Setup

Step 1: Create a Slack App

  1. Go to https://api.slack.com/apps/new
  2. Choose From a manifest
  3. Select your workspace
  4. Paste this manifest (includes all required scopes and events for DM support):
{
"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
}
},
"oauth_config": {
"scopes": {
"bot": [
"app_mentions:read",
"channels:history",
"channels:read",
"chat:write",
"im:history",
"im:read",
"im:write",
"mpim:history",
"mpim:read",
"mpim:write",
"reactions:read",
"reactions:write",
"users:read",
"pins:read"
]
}
},
"settings": {
"socket_mode_enabled": true,
"event_subscriptions": {
"bot_events": [
"app_mention",
"message.channels",
"message.im",
"message.mpim",
"reaction_added",
"member_joined_channel"
]
}
}
}

Note: The manifest includes im:history, im:read, im:write (DM scopes) and message.im (DM event) which are required for direct messaging. Without these, users cannot send DMs to your bot.

  1. Click Create

Step 2: Generate App-Level Token

This is the xapp- token required for Socket Mode.

  1. Go to Basic Information (sidebar) > App-Level Tokens
  2. Click Generate Token and Scopes
  3. Name it: socket-mode
  4. Add scope: connections:write
  5. Click Generate
  6. Copy the token — it starts with xapp-
  7. Save this — you'll enter it as SLACK_APP_TOKEN during configuration

Step 3: Verify Event Subscriptions (Critical for DMs)

Before installing, verify the event subscriptions are correct:

  1. Go to Event Subscriptions (sidebar)
  2. Confirm Enable Events is ON
  3. Scroll to Subscribe to bot events
  4. Verify message.im is in the list (required for DMs)
  5. If message.im is missing:
    • Click Add Bot User Event
    • Select message.im
    • Click Save Changes

Why this matters: Without message.im, your bot will never receive direct messages. This is the #1 reason DMs don't work.

Step 4: Install App to Workspace

  1. Go to OAuth & Permissions (sidebar)
  2. Click Install to Workspace
  3. Authorize the app
  4. Copy the Bot User OAuth Token — it starts with xoxb-
  5. Save this — you'll enter it as SLACK_BOT_TOKEN during configuration

Step 5: Invite Bot to a Channel

In Slack, go to the channel where you want the bot and type:

@OpenClaw

Slack will prompt you to invite the bot to the channel.

Step 6: Get Your User ID

  1. In Slack, click your profile picture (top right)
  2. Click (three dots) > Copy Member ID
  3. The ID starts with U (e.g., U01ABC2DEF)
  4. This goes in the allowFrom list during configuration

Step 7: Register and attach in Clawrium

# 1. Register the channel in the registry
clawctl channel registry create <channel-name> --type slack \
--token-stdin <<<"$SLACK_BOT_TOKEN" \
--app-token "$SLACK_APP_TOKEN" \
--allowed-user U01ABC2DEF3 \
--home-channel C01234567890

# 2. Attach to the agent and sync
clawctl agent channel attach <channel-name> --agent <agent-name>
clawctl agent sync <agent-name>

Configuration Structure

After setup, the Slack config in your agent's openclaw.json looks like:

{
"channels": {
"slack": {
"enabled": true,
"mode": "socket",
"botToken": {
"source": "env",
"provider": "default",
"id": "SLACK_BOT_TOKEN"
},
"appToken": {
"source": "env",
"provider": "default",
"id": "SLACK_APP_TOKEN"
},
"allowFrom": ["U01ABC2DEF"],
"groupPolicy": "allowlist",
"dmPolicy": "pairing"
}
}
}
FieldTypeDefaultDescription
enabledbooltrueEnable Slack channel
modestring"socket"Connection mode (Socket Mode)
botTokenSecretRefBot token reference (xoxb-...)
appTokenSecretRefApp-level token reference (xapp-...)
allowFromstring[][]User IDs allowed to interact with the bot
groupPolicystring"allowlist"Group access policy: open, allowlist, disabled
dmPolicystring"pairing"DM access policy: pairing, allowlist, open, disabled

SecretRef Object

Tokens use SecretRef objects instead of plaintext values. The secret value is stored in Clawrium's encrypted secrets storage, not in config files.

{
"source": "env",
"provider": "default",
"id": "SLACK_BOT_TOKEN"
}

At runtime, OpenClaw resolves the token from the environment file written by Clawrium.


Hermes Configuration

Hermes uses a simpler configuration model — env vars rendered directly into ~/.hermes/.env. There are no SecretRef objects; tokens are written as plain values in the env file (mode 0600 on the agent host).

Env vars rendered by clawctl

VariableRequiredDescription
SLACK_BOT_TOKENyesBot User OAuth Token (xoxb-...)
SLACK_APP_TOKENyesApp-Level Token for Socket Mode (xapp-...)
SLACK_ALLOWED_USERSyesComma-separated Slack Member IDs (e.g., U01ABC2DEF3,U04XYZ7GHI8)
SLACK_HOME_CHANNELnoChannel ID for cron/scheduled messages (e.g., C01234567890)
SLACK_HOME_CHANNEL_NAMEnoDisplay name for the home channel

Required scopes (minimal set for Hermes)

⚠️ Critical for DMs: The three im:* scopes below are required for direct messaging. Without them, users cannot DM the bot in Slack.

ScopeRequired ForWhat Breaks Without It
app_mentions:readChannelsBot won't see @-mentions in channels
chat:writeAllBot cannot send any messages (DMs or channels)
channels:readChannelsBot cannot list/join public channels
groups:readPrivate ChannelsBot cannot list private channels it's in
im:historyDMsBot cannot read DM history (DMs fail)
im:readDMsBot cannot access DM metadata (DMs fail)
im:writeDMsSlack won't allow users to message the bot
users:readAllBot cannot look up user info for allowlist checks

⚠️ Security note on im:write: This scope also permits the bot to initiate unsolicited DMs to any workspace member — the SLACK_ALLOWED_USERS allowlist only gates inbound commands, not outbound messages. A compromised agent host or leaked bot token could DM-spam or phish the entire workspace. Keep the agent host hardened and the xoxb- bot token in secrets.json only. On suspicion of leakage: rotate via Slack API → OAuth & PermissionsRotate Tokens, then update the channel record (clawctl channel registry edit <channel-name> --token-stdin <<<"$NEW_BOT_TOKEN" then clawctl channel registry edit <channel-name> --app-token "$NEW_APP_TOKEN") and clawctl agent sync <name>.

Required event subscriptions

⚠️ Critical for DMs: Without message.im, the bot will never receive your direct messages even if you can send them.

EventRequired ForWhat Breaks Without It
app_mentionChannelsBot won't respond to @-mentions
message.imDMsBot receives no notification when you DM it

Access control differences from OpenClaw

AspectOpenClawHermes
Config locationopenclaw.json (SecretRef objects)~/.hermes/.env (plain env vars)
DM policyConfigurable (pairing, allowlist, open, disabled)SLACK_ALLOWED_USERS allowlist only
Group policyConfigurable (open, allowlist, disabled)Channel membership controls access (invite-only)
Token storagesecrets.json → rendered to env at runtimesecrets.json → rendered to .env at configure time

Hermes uses Socket Mode — the bot maintains an outbound WebSocket to Slack, so no public endpoint or ingress is required on the agent host.

Setup (Hermes)

# 1. Register the channel in the registry
clawctl channel registry create <channel-name> --type slack \
--token-stdin <<<"$SLACK_BOT_TOKEN" \
--app-token "$SLACK_APP_TOKEN" \
--allowed-user U01ABC2DEF3 \
--home-channel C01234567890

# 2. Attach and sync
clawctl agent channel attach <channel-name> --agent <hermes-name>
clawctl agent sync <hermes-name>

Flags accepted by clawctl channel registry create --type slack:

FlagRequiredNotes
--token / --token-stdinyesBot User OAuth Token. Stored in secrets.json under channel:<channel-name>:SLACK_BOT_TOKEN. Must start with xoxb-.
--app-tokenyesApp-Level Token for Socket Mode. Stored in secrets.json under channel:<channel-name>:SLACK_APP_TOKEN. Must start with xapp-.
--allowed-user <id> (repeatable)yesSlack Member IDs (format: U + 8+ alphanumeric chars).
--home-channel <id>optionalChannel ID for cron/scheduled messages. Format: C + alphanumeric.

clawctl agent sync re-renders ~/.hermes/.env with the SLACK_* block from the attached channel's registry record and restarts hermes-<name>.service.

Resulting on-disk shape (Hermes)

channels.json (non-sensitive — one record per chat surface):

{
"<channel-name>": {
"name": "<channel-name>",
"type": "slack",
"config": {
"allowed_users": ["U01ABC2DEF3"],
"home_channel": "C01234567890"
}
}
}

hosts.json carries the attachment list under agents.<name>.channels[].

secrets.json:

"channel:<channel-name>": {
"SLACK_BOT_TOKEN": {"value": "xoxb-...", "description": "Slack bot token"},
"SLACK_APP_TOKEN": {"value": "xapp-...", "description": "Slack app token"}
}

Both tokens never land in channels.json or hosts.jsonclawctl channel registry create stores them exclusively in secrets.json (B3 invariant). Re-creating the channel record with the same tokens reuses them byte-identical.

Rendered .env (Slack block, Hermes)

After configure, the relevant section of ~/.hermes/.env on the agent host looks like:

# Slack
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
SLACK_ALLOWED_USERS=U01ABC2DEF3
SLACK_HOME_CHANNEL=C01234567890
SLACK_HOME_CHANNEL_NAME=general

Removal (Hermes)

clawctl agent channel detach <channel-name> --agent <hermes-name> then clawctl agent sync <hermes-name> drops the SLACK_* block from ~/.hermes/.env. To wipe the channel record and its tokens entirely: clawctl channel registry delete <channel-name> --yes --force. To rotate tokens without dropping the attachment: clawctl channel registry edit <channel-name> --token-stdin <<<"$NEW_BOT_TOKEN" and clawctl agent sync <hermes-name>.

Hermes-specific troubleshooting

Bot connects but gets missing_scope errors

Hermes logs will show errors like slack_bolt: missing_scope: channels:read. Go to your Slack app's OAuth & Permissions > Scopes and add the missing scope. Then reinstall the app to your workspace (Slack requires reinstall after scope changes). You do NOT need to re-create the channel record — the tokens remain valid after reinstall.

Bot gets not_in_channel error for home channel

The bot must be a member of the home channel. In Slack, go to that channel and type /invite @Hermes. The SLACK_HOME_CHANNEL setting only tells hermes where to post scheduled/cron messages — it doesn't auto-join.

❌ CRITICAL: Bot doesn't respond to DMs

This is the most common issue. Follow these steps in order:

1. Can you even send a DM to the bot?

  • In Slack, go to Apps in the sidebar
  • Find your bot
  • Try to click Message

If you can't click Message or it's grayed out: → Your Slack app is missing the im:write scope. Go to Slack API → OAuth & Permissions → Add im:write → Reinstall app to workspace.

If you can send a DM but bot doesn't respond: → Continue to step 2.

2. Verify Event Subscription

  • Go to https://api.slack.com/apps
  • Select your app
  • Go to Event Subscriptions
  • Scroll to Subscribe to bot events
  • Confirm message.im is in the list

If message.im is missing: → Click Add Bot User Event → Select message.imSave ChangesReinstall app to workspace (required!)

3. Verify OAuth Scopes

Go to OAuth & PermissionsScopesBot Token Scopes and confirm:

  • im:history
  • im:read
  • im:write
  • chat:write

If any are missing: Add them → Reinstall app to workspace.

4. Verify User Allowlist (Hermes only)

Your Slack Member ID must be in the channel record's allowed_users list:

clawctl channel registry describe <channel-name>

Find your Member ID: Slack profile → ⋯ (three dots) → Copy Member ID

If your ID is missing: Re-create the channel record (clawctl channel registry delete <channel-name> --yes --force then clawctl channel registry create <channel-name> --type slack ... --allowed-user <your-id>), re-attach if needed, and clawctl agent sync <name>.

5. Check Agent Logs

ssh <agent-host> "sudo journalctl -u hermes-<name> -f"

Send a test DM and watch for errors. Common errors:

  • missing_scope: im:history → Add scope and reinstall app
  • not_authed → Token expired, regenerate and reconfigure
  • Silent (no logs) → Event subscription message.im is missing
Bot doesn't respond in channels
  1. The bot only listens for app_mention events in channels — you must @-mention it.
  2. Confirm the bot has been invited to the channel (/invite @Hermes).
  3. Verify app_mentions:read and channels:read scopes are enabled.
Socket Mode not connecting
  1. Verify Socket Mode is enabled in the Slack app settings.
  2. Confirm SLACK_APP_TOKEN starts with xapp- and has the connections:write scope.
  3. Check the journal: ssh <agent-host> "sudo journalctl -u hermes-<name>.service -n 200 --no-pager | grep -iE 'slack|socket'".

Access Control

DM Policy (dmPolicy)

PolicyBehavior
pairing (default)New DM users must approve via clawctl pairing approve slack <code>
allowlistOnly users in allowFrom can DM
openAnyone can DM (requires allowFrom: ["*"])
disabledNo DMs allowed

Group Policy (groupPolicy)

PolicyBehavior
allowlist (default)Bot only responds in explicitly allowed channels
openBot responds in all channels it's invited to
disabledNo channel responses

Troubleshooting

Bot not responding in channels

  • Verify groupPolicy is not disabled
  • Check bot is invited to the channel (@OpenClaw in channel)
  • Verify app_mentions:read and channels:history scopes are enabled

Bot not responding to DMs

  • Check dmPolicy — default is pairing, new users must be approved first
  • Run clawctl pairing list slack to see pending approvals

Socket Mode not connecting

  • Verify both SLACK_BOT_TOKEN and SLACK_APP_TOKEN are set
  • Check that Socket Mode is enabled in Slack app settings
  • Verify the App-Level Token has connections:write scope

"Invalid bot token format" error

  • Bot token must start with xoxb- and contain only alphanumeric characters and hyphens
  • Copy the full token from OAuth & Permissions in Slack app settings

"Invalid app token format" error

  • App token must start with xapp-1- followed by alphanumeric and hex characters
  • Copy the full token from Basic Information > App-Level Tokens

Back to Channels