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:
| Token | Prefix | Secret Name | Purpose |
|---|---|---|---|
| Bot Token | xoxb- | SLACK_BOT_TOKEN | Authenticates bot actions (send messages, read channels) |
| App Token | xapp- | SLACK_APP_TOKEN | Authenticates 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-...
Setup
Step 1: Create a Slack App
- Go to https://api.slack.com/apps/new
- Choose From a manifest
- Select your workspace
- Paste this manifest:
{
"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"
]
}
}
}
- Click Create
Step 2: Generate App-Level Token
This is the xapp- token required for Socket Mode.
- Go to Basic Information (sidebar) > App-Level Tokens
- Click Generate Token and Scopes
- Name it:
socket-mode - Add scope:
connections:write - Click Generate
- Copy the token — it starts with
xapp- - Save this — you'll enter it as
SLACK_APP_TOKENduring configuration
Step 3: Install App to Workspace
- Go to OAuth & Permissions (sidebar)
- Click Install to Workspace
- Authorize the app
- Copy the Bot User OAuth Token — it starts with
xoxb- - Save this — you'll enter it as
SLACK_BOT_TOKENduring configuration
Step 4: 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 5: Get Your User ID
- In Slack, click your profile picture (top right)
- Click ⋯ (three dots) > Copy Member ID
- The ID starts with
U(e.g.,U01ABC2DEF) - This goes in the
allowFromlist during configuration
Step 6: Configure in Clawrium
clawctl agent configure <agent-name>
# Select "slack" when prompted for channel
# Enter your Bot Token, App Token, and User ID
Or reconfigure just the channels stage:
clawctl agent configure <agent-name> --stage channels
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"
}
}
}
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable Slack channel |
mode | string | "socket" | Connection mode (Socket Mode) |
botToken | SecretRef | — | Bot token reference (xoxb-...) |
appToken | SecretRef | — | App-level token reference (xapp-...) |
allowFrom | string[] | [] | User IDs allowed to interact with the bot |
groupPolicy | string | "allowlist" | Group access policy: open, allowlist, disabled |
dmPolicy | string | "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
| Variable | Required | Description |
|---|---|---|
SLACK_BOT_TOKEN | yes | Bot User OAuth Token (xoxb-...) |
SLACK_APP_TOKEN | yes | App-Level Token for Socket Mode (xapp-...) |
SLACK_ALLOWED_USERS | yes | Comma-separated Slack Member IDs (e.g., U01ABC2DEF3,U04XYZ7GHI8) |
SLACK_HOME_CHANNEL | no | Channel ID for cron/scheduled messages (e.g., C01234567890) |
SLACK_HOME_CHANNEL_NAME | no | Display name for the home channel |
Required scopes (minimal set for Hermes)
| Scope | Purpose |
|---|---|
app_mentions:read | Bot can see when @-mentioned in channels |
chat:write | Bot can send messages |
channels:read | Bot can list public channels |
groups:read | Bot can list private channels it's a member of |
im:history | Bot can read DM history |
im:read | Bot can read DM metadata |
im:write | Bot can open/write DMs |
users:read | Bot can look up user info |
Required event subscriptions
| Event | Purpose |
|---|---|
app_mention | Fires when someone @-mentions the bot in a channel |
message.im | Fires on direct messages to the bot |
Access control differences from OpenClaw
| Aspect | OpenClaw | Hermes |
|---|---|---|
| Config location | openclaw.json (SecretRef objects) | ~/.hermes/.env (plain env vars) |
| DM policy | Configurable (pairing, allowlist, open, disabled) | SLACK_ALLOWED_USERS allowlist only |
| Group policy | Configurable (open, allowlist, disabled) | Channel membership controls access (invite-only) |
| Token storage | secrets.json → rendered to env at runtime | secrets.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.
Interactive setup (Hermes)
clawctl agent configure <hermes-name> --stage channels
The wizard offers cli, discord, and slack. Pick slack and the CLI prompts for:
| Prompt | Stored where | Required | Notes |
|---|---|---|---|
| Slack Bot Token | secrets.json as SLACK_BOT_TOKEN | yes | Masked input. Must start with xoxb-. |
| Slack App Token | secrets.json as SLACK_APP_TOKEN | yes | Masked input. Must start with xapp-. |
| Allowed Slack user IDs | hosts.json channels.slack.allowed_users | yes | Comma-separated Member IDs (format: U + 8+ alphanumeric chars). |
| Slack home channel ID | hosts.json channels.slack.home_channel | optional | Channel for cron/scheduled messages. Format: C + alphanumeric. |
| Slack home channel name | hosts.json channels.slack.home_channel_name | optional | Display name for the home channel. |
clawctl then runs the configure playbook which re-renders ~/.hermes/.env with the SLACK_* block and restarts hermes-<name>.service.
Resulting on-disk shape (Hermes)
hosts.json (non-sensitive only):
"config": {
"api_server": {"enabled": true, "host": "127.0.0.1", "port": 8642},
"provider": {...},
"channels": {
"slack": {
"enabled": true,
"allowed_users": ["U01ABC2DEF3"],
"home_channel": "C01234567890",
"home_channel_name": "general"
}
}
}
secrets.json:
"192.168.1.36:hermes:<name>": {
"HERMES_API_SERVER_KEY": {...},
"SLACK_BOT_TOKEN": {"value": "xoxb-...", "description": "Slack bot token", ...},
"SLACK_APP_TOKEN": {"value": "xapp-...", "description": "Slack app token", ...}
}
Both tokens never land in hosts.json — the configure flow stores them exclusively in secrets.json (B3 invariant). Re-running clawctl agent configure --stage channels 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 delete <name> --force purges the entire instance entry from secrets.json, including both Slack tokens. There is no separate "rotate Slack token" command — re-run the channels stage with new tokens to overwrite.
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-run clawctl agent configure — 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.
Bot doesn't respond to DMs
- Confirm your Slack Member ID is in
hosts.jsonchannels.slack.allowed_users. Hermes drops messages from non-allowlisted users silently. - Verify
im:history,im:read, andim:writescopes are present. - Verify
message.imevent subscription is enabled.
Bot doesn't respond in channels
- The bot only listens for
app_mentionevents in channels — you must @-mention it. - Confirm the bot has been invited to the channel (
/invite @Hermes). - Verify
app_mentions:readandchannels:readscopes are enabled.
Socket Mode not connecting
- Verify Socket Mode is enabled in the Slack app settings.
- Confirm
SLACK_APP_TOKENstarts withxapp-and has theconnections:writescope. - 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)
| Policy | Behavior |
|---|---|
pairing (default) | New DM users must approve via clawctl pairing approve slack <code> |
allowlist | Only users in allowFrom can DM |
open | Anyone can DM (requires allowFrom: ["*"]) |
disabled | No DMs allowed |
Group Policy (groupPolicy)
| Policy | Behavior |
|---|---|
allowlist (default) | Bot only responds in explicitly allowed channels |
open | Bot responds in all channels it's invited to |
disabled | No channel responses |
Troubleshooting
Bot not responding in channels
- Verify
groupPolicyis notdisabled - Check bot is invited to the channel (
@OpenClawin channel) - Verify
app_mentions:readandchannels:historyscopes are enabled
Bot not responding to DMs
- Check
dmPolicy— default ispairing, new users must be approved first - Run
clawctl pairing list slackto see pending approvals
Socket Mode not connecting
- Verify both
SLACK_BOT_TOKENandSLACK_APP_TOKENare set - Check that Socket Mode is enabled in Slack app settings
- Verify the App-Level Token has
connections:writescope
"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