How to Connect Your AI Agent to Slack (Complete Setup Guide)
Your AI agent lives on your machine. Your team lives in Slack. The gap between those two is where most "AI at work" experiments die — an agent nobody can talk to is an agent nobody uses.
OpenClaw's Slack integration bridges that gap. It connects your agent to Slack via either Socket Mode or HTTP Events API, giving your agent the ability to participate in DMs, channels, and threads like any other team member. Not a webhook that dumps text — a real conversational presence with access control, threading, reactions, and file handling.
This guide walks through the complete setup, from creating a Slack app to fine-tuning channel policies. By the end, your agent will be a Slack citizen.
Prerequisites
Before you start, you'll need:
- OpenClaw installed and running — if you haven't done this yet, check out What is OpenClaw?
- A Slack workspace where you have admin permissions (or can ask an admin to install apps)
- 5-10 minutes — the setup is straightforward once you know the steps
Step 1: Create a Slack App
Head to api.slack.com/apps and click "Create New App". Choose "From a manifest" — it's faster than clicking through every permission screen manually.
Here's a manifest that covers everything OpenClaw needs:
{
"display_information": {
"name": "OpenClaw",
"description": "Slack connector for OpenClaw"
},
"features": {
"bot_user": {
"display_name": "OpenClaw",
"always_online": false
},
"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": [
"chat:write",
"channels:history",
"channels:read",
"groups:history",
"im:history",
"im:read",
"im:write",
"mpim:history",
"mpim:read",
"mpim:write",
"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"
]
}
}
} After creating the app, install it to your workspace. Slack will ask you to authorize the scopes — approve them. You'll get a Bot Token (xoxb-...) on the install confirmation page. Save it.
Step 2: Get Your Tokens
You need two tokens for Socket Mode (the recommended approach):
- Bot Token (
xoxb-...) — found under OAuth & Permissions after installing the app - App Token (
xapp-...) — go to Basic Information → App-Level Tokens, click "Generate Token", name it anything, and add theconnections:writescope
The Bot Token lets your agent send messages and read channels. The App Token opens the WebSocket connection that Slack uses to push events to your agent in real time.
Step 3: Configure OpenClaw
Add the Slack channel to your openclaw.json:
{
"channels": {
"slack": {
"enabled": true,
"mode": "socket",
"appToken": "xapp-1-...",
"botToken": "xoxb-..."
}
}
} Or use environment variables if you prefer keeping tokens out of config files:
SLACK_APP_TOKEN=xapp-1-...
SLACK_BOT_TOKEN=xoxb-... Config tokens take precedence over env vars. The env fallback only works for the default account.
Why Socket Mode?
Socket Mode is the default for good reason. It uses a persistent WebSocket connection — no public URL needed, no webhook endpoints to expose, no SSL certificates to manage. Your agent connects outbound to Slack, which means it works behind firewalls, on home networks, even on a Raspberry Pi. If you're just getting started, use Socket Mode.
Step 4: Start the Gateway
openclaw gateway That's it. OpenClaw connects to Slack, establishes the WebSocket, and your agent is online. Send it a DM in Slack — you should see a response within seconds.
Controlling DM Access
By default, Slack DMs use pairing mode. This means when someone DMs your agent for the first time, they get a pairing code. You approve the pairing from the CLI:
openclaw pairing approve slack <code> This is the most secure default — nobody talks to your agent without explicit approval. But you have other options:
pairing(default) — require explicit pairing approval per userallowlist— only specific Slack user IDs can DM the agentopen— anyone in the workspace can DM (requiresallowFrom: ["*"])disabled— no DMs at all, channels only
{
"channels": {
"slack": {
"enabled": true,
"mode": "socket",
"appToken": "xapp-...",
"botToken": "xoxb-...",
"dmPolicy": "allowlist",
"allowFrom": ["U01ABC123", "U02DEF456"]
}
}
} Group DMs (MPIMs) are disabled by default. Enable them with "dm": { "groupEnabled": true } if your team uses group chats.
Adding Channel Access
DMs are one-on-one. Channels are where teams actually work. To let your agent participate in Slack channels, configure the group policy:
{
"channels": {
"slack": {
"groupPolicy": "allowlist",
"channels": {
"C0A4G5T2DLM": {
"requireMention": true
},
"C0ACMC7HM18": {
"requireMention": false,
"users": ["U01ABC123"]
}
}
}
}
} Key channel settings:
requireMention— whentrue, the agent only responds when explicitly@mentioned. This is the right default for most channels — you don't want your agent jumping into every conversation.users— restrict which users the agent responds to in this channel. Useful for QA channels where only certain people should interact with the bot.allowBots— let the agent respond to other bots. Usually keep this off unless you're building bot-to-bot workflows.systemPrompt— inject a per-channel system prompt. Your agent can behave differently in#engineeringvs#marketing.skills— restrict which skills are available per channel for tighter access control.
The agent detects mentions through explicit @bot tags and configurable mention patterns. It also recognizes when someone replies in a thread the agent started — no explicit mention needed for thread continuations.
HTTP Events API Mode (Alternative)
If you need a publicly accessible endpoint — maybe you're running on a VPS with a domain, or your organization requires HTTP mode — OpenClaw supports that too:
{
"channels": {
"slack": {
"enabled": true,
"mode": "http",
"botToken": "xoxb-...",
"signingSecret": "your-signing-secret",
"webhookPath": "/slack/events"
}
}
} In HTTP mode, you set your webhook URL (https://your-domain.com/slack/events) as the Request URL in three places in your Slack app settings: Event Subscriptions, Interactivity, and Slash Commands.
The signingSecret (found under Basic Information in Slack app settings) verifies that incoming requests actually come from Slack. No App Token needed in HTTP mode.
Threading and Sessions
Slack threads are where real work conversations happen. OpenClaw maps threads to isolated sessions, so context stays clean:
- DMs route as
directsessions — with the defaultsession.dmScope=main, Slack DMs share your agent's main session context - Channels create per-channel sessions —
agent:<agentId>:slack:channel:<channelId> - Threads can spawn thread-scoped sub-sessions when applicable
Control reply threading behavior with replyToMode:
{
"channels": {
"slack": {
"replyToMode": "all",
"replyToModeByChatType": {
"direct": "off",
"channel": "all"
}
}
}
} Options: off (no threading), first (first reply threads, rest don't), all (everything threads). Note that in Slack, replyToMode: "off" disables all reply threading, including manual [[reply_to_*]] tags — because Slack threads hide messages from the main channel view.
Live Streaming Responses
Nobody likes staring at a typing indicator for 30 seconds. OpenClaw supports Slack native text streaming — your agent's responses appear token-by-token, like watching someone type in real time.
{
"channels": {
"slack": {
"streaming": "partial",
"nativeStreaming": true
}
}
} This uses Slack's Agents and AI Apps API (chat.startStream / chat.appendStream / chat.stopStream). Requirements:
- Enable Agents and AI Apps in your Slack app settings
- Ensure the
assistant:writescope is granted - A reply thread must be available for the message
Streaming modes: partial (default — replaces preview text with latest output), block (appends chunks), progress (shows status text while generating, then sends final), or off.
Reactions and Acknowledgments
When someone sends a message, your agent can react with an emoji to acknowledge it's processing:
{
"channels": {
"slack": {
"ackReaction": "eyes"
}
}
} The reaction appears immediately while the agent thinks about its response. Slack expects shortcodes (e.g., "eyes", not ":eyes:"). Set it to "" to disable. If unset, it falls back to the agent's identity emoji or 👀 by default.
Your agent can also add reactions to messages as part of its workflow — acknowledging bug reports with 🔨, marking tasks complete with ✅, or flagging urgent items with 🚨. This is controlled through the actions.reactions config.
File Handling
Slack files work both ways:
- Inbound — files shared with the agent are downloaded (authenticated via the Bot Token) and processed. Default size cap: 20MB, adjustable via
mediaMaxMb. - Outbound — the agent can upload files to Slack, including thread replies. Images, documents, code files — anything the Slack upload API supports.
Text messages are automatically chunked at 4000 characters (Slack's limit). Configure chunkMode: "newline" for paragraph-aware splitting that won't break mid-sentence.
Slash Commands
OpenClaw supports two slash command approaches:
- Single slash command — configure
slashCommand.enabled: trueand your agent receives everything sent to/openclaw - Native command mode — enable
commands.native: trueto expose OpenClaw's built-in commands as individual slash commands (/status,/model, etc.)
One quirk: Slack reserves the /status command, so if you're using native mode, register /agentstatus instead.
For argument menus (commands with options), OpenClaw adapts automatically: up to 5 options render as buttons, 6-100 as a select menu, and 100+ use async filtering. It handles Slack's payload limits gracefully.
Multi-Account Setup
Running your agent across multiple Slack workspaces? OpenClaw supports named accounts:
{
"channels": {
"slack": {
"enabled": true,
"accounts": {
"primary": {
"mode": "socket",
"appToken": "xapp-primary-...",
"botToken": "xoxb-primary-...",
"allowFrom": ["U01ABC123"]
},
"client-workspace": {
"mode": "http",
"botToken": "xoxb-client-...",
"signingSecret": "client-secret",
"webhookPath": "/slack/client-events"
}
}
}
}
} Each account gets its own auth, policies, and routing. Named accounts inherit global allowFrom settings when their own isn't set, but they don't inherit from other named accounts.
Troubleshooting
When things aren't working, here's where to look:
Agent Not Responding in Channels
Check in order: groupPolicy → channel allowlist → requireMention setting → per-channel users allowlist. Run openclaw channels status --probe to see what's connected.
DMs Being Ignored
Verify dm.enabled is true, check dmPolicy, and confirm pairing is approved (openclaw pairing list slack).
Socket Mode Won't Connect
Double-check both tokens. Ensure Socket Mode is actually enabled in Slack app settings (it's separate from the manifest).
General Debugging
openclaw channels status --probe
openclaw logs --follow
openclaw doctor openclaw doctor runs a comprehensive health check and will flag most configuration issues before you have to dig through logs.
What's Next
Once Slack is connected, your agent is a team member. But there's more to explore:
- Set up persistent memory so your agent remembers conversations across sessions
- Configure cron jobs to make your agent proactive — morning standup summaries, daily reports, automated monitoring
- Run your agent as a full employee with identity, workspace, and daily operations
Slack is usually the first channel people set up, and for good reason — it's where work happens. But OpenClaw supports Telegram, Discord, WhatsApp, Signal, iMessage, and more. Same agent, multiple surfaces. We'll cover multi-channel setups in a future post.
Want the complete guide? Get The OpenClaw Playbook — $9.99