You already have OpenClaw running with a Telegram bot connected. One agent, one channel — that is a solid start. But OpenClaw’s real power emerges when you treat each messaging platform as a dedicated entry point into a specialized AI persona. Slack becomes your work assistant that understands your team’s context. Discord becomes the coding agent that never forgets your project conventions. WhatsApp handles scheduling and reminders with a different tone and tool set entirely.
This tutorial covers the full multi-channel routing setup: adding Slack and Discord channels, configuring WhatsApp via the Baileys library, writing routing rules that direct each channel to its own agent workspace, and optionally enabling voice modes for macOS and Android. By the end, you will have a single OpenClaw daemon that presents a different, context-isolated AI personality depending on which app you use to reach it.
Before continuing, confirm that you have completed Getting Started with OpenClaw and OpenClaw Telegram Bot Setup. Multi-channel routing extends the foundation built in those guides.
Why Route Different Channels to Different Agents?
The temptation is to wire every channel to the same agent and let it handle everything. In practice, a single undifferentiated agent accumulates a tangled mix of contexts: code review feedback from Slack sits alongside a shopping list from WhatsApp, and a Discord conversation about a side project bleeds into work-related memory. The agent starts making suggestions that are appropriate for one context but bizarre in another.
Specialized agents are more useful. A coding agent configured with knowledge of your active repositories, preferred languages, and recent debugging sessions gives better code suggestions than a general-purpose agent that also knows about your weekend plans. A scheduling agent tuned with your calendar access and communication style is more effective at drafting replies than an agent optimized for technical tasks.
Workspace isolation is a safety measure. When each agent operates in its own workspace directory, its file system access is scoped to that context. The coding agent cannot accidentally include personal documents in a code review. The work agent cannot expose a private side-project file when responding to a Slack thread.
The routing overhead is minimal. OpenClaw’s router adds microseconds to the message path. The practical cost of running multiple specialized agents is a slightly larger memory footprint on your server — typically 50–100 MB per active agent instance, well within the capacity of a $6/month VPS.
Tone and model can differ by channel. You might want your Slack work agent to use a formal tone and Claude 3.5 Sonnet, while your Discord coding agent runs DeepSeek R1 for its stronger code reasoning and adopts a more casual register. Multi-channel routing makes this trivial to configure.
How Multi-Channel Routing Works
OpenClaw’s routing architecture follows a five-layer pipeline from incoming message to agent response.
Incoming message
│
▼
┌─────────────────────────────────────────────────────────┐
│ CHANNEL ADAPTERS │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ Telegram │ │ Slack │ │ Discord │ │ WA │ │
│ │ (grammY) │ │ (OAuth) │ │ (SDK) │ │(Baileys│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───┬────┘ │
└───────┼─────────────┼─────────────┼─────────────┼──────┘
│ │ │ │
└─────────────┴──────┬──────┴─────────────┘
│
▼
┌──────────────────┐
│ MESSAGE ROUTER │
│ (routing.json) │
└────────┬─────────┘
│ matches channel → agent mapping
▼
┌────────────────────────┐
│ AGENT DISPATCHER │
│ resolves workspace + │
│ model + system prompt │
└────────────┬───────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ coding-agent │ │ work-agent │
│ workspace: │ │ workspace: │
│ ~/oc-coding/ │ │ ~/oc-work/ │
│ model: deepseek │ │ model: claude │
└──────────────────┘ └──────────────────┘
Each channel adapter receives messages from its platform and normalizes them into OpenClaw’s internal message format. The Message Router reads ~/.openclaw/routing.json to determine which agent definition handles messages from that channel. The Agent Dispatcher spins up or reconnects to the appropriate agent instance, which has its own workspace directory, system prompt, and LLM model configuration. Responses flow back through the same channel adapter to the originating platform.
The key design principle is that the router is stateless — it matches channel identifiers to agent definitions based on static configuration. All state (conversation history, file system contents, session data) lives inside the agent’s workspace. This makes the routing layer trivially reliable and easy to debug.
Adding a Slack Channel
Slack requires OAuth app registration, which takes a few minutes more than Telegram’s BotFather flow. The payoff is a deeply integrated workspace experience: the agent can read channel history, respond in threads, post formatted messages, and receive file attachments.
Create a Slack App
Navigate to api.slack.com/apps and sign in with the Slack account associated with the workspace you want to connect.
Click Create New App and select From Scratch. Give the app a name — something like OpenClaw Agent — and select the workspace where it will live.
Configure OAuth Scopes
In the left sidebar, click OAuth & Permissions. Scroll to Bot Token Scopes and add the following scopes:
| Scope | Purpose |
|---|---|
chat:write | Send messages as the bot |
im:history | Read direct message history |
im:read | View direct message metadata |
im:write | Open and manage DM conversations |
channels:history | Read messages in public channels the bot is added to |
users:read | Look up user display names for context |
files:read | Access file content shared in conversations |
For a minimal setup (DM-only), the im:* scopes and chat:write are sufficient. Add the channels:* scopes only if you plan to add the bot to shared channels.
Scroll up and click Install to Workspace. Slack will ask you to authorize the scopes you configured. After authorization, you land back on the OAuth & Permissions page with a Bot User OAuth Token displayed — a string beginning with xoxb-. Copy this immediately.
Enable Event Subscriptions
OpenClaw uses Slack’s Events API (rather than RTM, which is deprecated for new apps). In the left sidebar, click Event Subscriptions and toggle Enable Events on.
OpenClaw needs a public URL to receive event payloads. If your server has a public IP or domain, the URL format is https://your-server.example.com/webhooks/slack. If you are developing locally, use ngrok to expose a temporary public URL:
# Install ngrok and expose OpenClaw's webhook port
ngrok http 3821
ngrok prints a forwarding URL like https://abc123.ngrok.io. Use https://abc123.ngrok.io/webhooks/slack as your Request URL in Slack’s Event Subscriptions panel. Slack will send a verification challenge to that URL — OpenClaw automatically handles the url_verification event and responds with the correct challenge value, so as long as the daemon is running the verification succeeds immediately.
Under Subscribe to Bot Events, add:
message.im— receive direct messages sent to the botmessage.channels— receive messages in public channels the bot is added to (optional)
Save your changes.
Connect Slack to OpenClaw
With your Bot User OAuth Token and Events API URL configured, register the Slack channel in OpenClaw:
openclaw channel add slack
The interactive prompt asks for your bot token:
OpenClaw Channel Setup — Slack
--------------------------------
Enter your Slack Bot User OAuth Token (xoxb-...): █
Enter your Slack Signing Secret: █
Webhook path [/webhooks/slack]: █
The Signing Secret is found in your Slack app’s Basic Information page, under App Credentials. OpenClaw uses it to verify that incoming event payloads genuinely originate from Slack (HMAC-SHA256 verification on every request).
After completing the prompts:
✓ Slack bot token validated. Workspace: Acme Corp
✓ Signing secret stored.
Channel "slack" registered successfully.
Next steps:
1. Start the daemon: openclaw start
2. In Slack, find your bot and send it a direct message
3. Optionally configure an Allow List: openclaw channel config slack --allow-user U0123ABCDEF
Verify the channel is registered:
openclaw channel list
Channel Status Details
--------- --------- ------------------------------
telegram active @my_openclaw_bot
slack registered Workspace: Acme Corp
Adding a Discord Bot
Discord’s bot system is developer-friendly and well-documented. The main difference from Telegram is that you work through the Discord Developer Portal rather than a chat interface.
Create a Discord Application
Go to discord.com/developers/applications and click New Application. Name it (for example, OpenClaw) and accept the developer terms.
In the left sidebar, click Bot and then Add Bot. Confirm by clicking Yes, do it!. Discord creates a bot user attached to your application.
On the Bot page, scroll down to Privileged Gateway Intents and enable:
- Message Content Intent — required to read the text content of messages (Discord disabled this by default in 2022; your bot cannot read messages without it)
- Server Members Intent — optional, but useful if you want the agent to reference member names by their server display name rather than their user ID
Click Save Changes.
Scroll back up to the Token section and click Reset Token, then copy the token displayed. This is your bot token — a string beginning with MT or similar. Store it securely the same way you handled your Telegram token.
Generate an Invite URL
Click OAuth2 in the left sidebar, then URL Generator. Under Scopes, check bot. Under Bot Permissions, check:
Send MessagesRead Message HistoryView Channels
Copy the generated URL and open it in a browser. Select the server you want to add the bot to and authorize it. The bot now appears in that server’s member list with an offline status — it will come online once OpenClaw connects.
Configure Discord in OpenClaw
Register the Discord channel using the bot token you copied:
openclaw channel add discord
OpenClaw Channel Setup — Discord
----------------------------------
Enter your Discord bot token: █
Listen mode:
(1) DMs only — bot responds only to direct messages
(2) Mentions only — bot responds only when @mentioned in a server channel
(3) Both
Select [1/2/3]: █
For most personal setups, option 1 (DMs only) keeps the agent’s activity private. Option 2 (mentions only) is useful for team servers where you want the agent to participate in specific channels without spamming unrelated ones.
After selection:
✓ Discord bot token validated. Bot username: OpenClaw#4821
Channel "discord" registered successfully.
Update the channel list:
openclaw channel list
Channel Status Details
--------- --------- ------------------------------
telegram active @my_openclaw_bot
slack registered Workspace: Acme Corp
discord registered OpenClaw#4821
Setting Up WhatsApp (Advanced)
WhatsApp integration in OpenClaw is powered by Baileys, an unofficial Node.js library that implements the WhatsApp Web protocol. Unlike Telegram and Discord — which use official, stable APIs — WhatsApp integration carries meaningful caveats that you should understand before proceeding.
Important considerations before enabling WhatsApp:
- This is an unofficial integration. Baileys reverse-engineers the WhatsApp Web protocol. Meta does not support or endorse this usage and has been known to ban accounts it detects as using automated bots. Use a secondary phone number rather than your primary WhatsApp account.
- QR code re-authentication may be required periodically. WhatsApp Web sessions expire. When they do, you need to re-scan a QR code from the server’s terminal output. This is the primary operational inconvenience of the WhatsApp integration.
- Message rate limits apply. Sending too many messages too quickly — even in a personal context — can trigger WhatsApp’s anti-spam systems. Keep usage to conversational volumes.
With those caveats noted, here is how to configure it.
First, ensure you have a phone with WhatsApp installed on a secondary number you are willing to use for this integration. Then register the channel:
openclaw channel add whatsapp
OpenClaw starts a QR code pairing flow immediately:
OpenClaw Channel Setup — WhatsApp (Baileys)
---------------------------------------------
Starting WhatsApp Web session...
Scan the QR code below with your WhatsApp app:
▄▄▄▄▄▄▄ ▄ ▄ ▄▄▄▄▄▄▄
█ ▄▄▄ █ ▀▄▀▀ █ ▄▄▄ █
█ ███ █ █▀▄█ █ ███ █
█▄▄▄▄▄█ ▄▀▄▀ █▄▄▄▄▄█
▄▄ ▄ ▄▄█▀▄ ▄ ▄ ▄▄
...
On your phone: WhatsApp > Settings > Linked Devices > Link a Device
QR code expires in 60 seconds.
Open WhatsApp on your secondary phone, go to Settings > Linked Devices > Link a Device, and scan the QR code. Once scanned, the terminal confirms:
✓ WhatsApp session established. Number: +1 555-0192
Channel "whatsapp" registered successfully.
The session credentials are encrypted and stored in ~/.openclaw/sessions/whatsapp/. If the session expires and you need to re-authenticate:
# Force a new QR code pairing
openclaw channel reconnect whatsapp
Configuring Agent Routing Rules
Now that multiple channels are registered, you need to define which agent each channel routes to. This is done by editing ~/.openclaw/routing.json. If this file does not yet exist, create it:
openclaw routing init
This generates a default routing.json that routes all channels to the default agent. Open it and configure per-channel routing:
{
"version": 1,
"defaultAgent": "general",
"routes": [
{
"channel": "telegram",
"agent": "coding-agent"
},
{
"channel": "slack",
"agent": "work-agent"
},
{
"channel": "discord",
"agent": "coding-agent"
},
{
"channel": "whatsapp",
"agent": "personal-agent"
}
],
"agents": {
"coding-agent": {
"model": "deepseek/deepseek-r1",
"workspace": "/home/openclaw-runner/workspaces/coding",
"systemPrompt": "You are a coding assistant with deep knowledge of Python, TypeScript, and shell scripting. You have access to the coding workspace. Be concise and prioritize working code over explanations. When writing code, always include error handling.",
"maxContextTokens": 32000
},
"work-agent": {
"model": "anthropic/claude-sonnet-4-5",
"workspace": "/home/openclaw-runner/workspaces/work",
"systemPrompt": "You are a professional work assistant. You help with drafting communications, summarizing documents, planning tasks, and answering questions in a professional tone. You have access to the work workspace. Keep responses concise and action-oriented.",
"maxContextTokens": 16000
},
"personal-agent": {
"model": "anthropic/claude-sonnet-4-5",
"workspace": "/home/openclaw-runner/workspaces/personal",
"systemPrompt": "You are a friendly personal assistant. Help with scheduling, reminders, research, and general questions. Be conversational and warm in tone.",
"maxContextTokens": 8000
},
"general": {
"model": "anthropic/claude-sonnet-4-5",
"workspace": "/home/openclaw-runner/openclaw-workspace",
"systemPrompt": "You are a helpful AI assistant.",
"maxContextTokens": 16000
}
}
}
Create the workspace directories before applying the configuration:
mkdir -p /home/openclaw-runner/workspaces/{coding,work,personal}
Apply the routing configuration and restart the daemon:
openclaw routing apply
openclaw restart
Verify that the routing loaded correctly:
openclaw routing status
Routing Status
---------------
Version: 1
Default agent: general
Channel Agent Model Workspace
----------- ------------- ----------------------- ----------------------------------
telegram coding-agent deepseek/deepseek-r1 /home/.../workspaces/coding
slack work-agent anthropic/claude-sonnet /home/.../workspaces/work
discord coding-agent deepseek/deepseek-r1 /home/.../workspaces/coding
whatsapp personal-agent anthropic/claude-sonnet /home/.../workspaces/personal
Workspace isolation is automatic. Once routing is applied, each agent reads and writes exclusively to its configured workspace directory. A conversation in Slack cannot access files in the coding workspace, and vice versa. OpenClaw enforces this at the workspace resolver level — path traversal attempts (../other-workspace/secret.txt) are rejected with a permission error before the LLM response is processed.
Session isolation follows the same boundary. Each agent maintains its own conversation history. The work-agent does not carry forward context from a Telegram coding session. Sessions are identified by the combination of channel name and user ID — so even if the same physical person uses both Telegram and Slack, their conversations are stored and surfaced separately, per the routing configuration.
Voice Mode Setup
OpenClaw includes voice input and output capabilities that vary by platform. These are optional but useful for hands-free workflows on mobile and desktop.
macOS Wake Word Mode
On macOS, OpenClaw can listen continuously for a configurable wake word — similar to smart speakers — and then accept a spoken command before returning to idle listening.
To enable wake word mode, first ensure you have the openclaw-voice optional dependency installed:
npm install -g openclaw-voice
Then configure the voice settings in ~/.openclaw/openclaw.json:
{
"voice": {
"enabled": true,
"platform": "macos",
"wakeWord": "hey claw",
"wakeWordSensitivity": 0.7,
"inputDevice": "default",
"outputDevice": "default",
"tts": "system",
"channel": "telegram"
}
}
The channel key specifies which routing channel the voice input uses. In the example above, voice commands are routed through the telegram channel definition — which means they reach the coding-agent based on the routing rules you configured earlier. If you want voice to reach a different agent, create a dedicated voice channel entry in routing.json.
After saving the configuration, restart the daemon:
openclaw restart
Test wake word detection:
openclaw voice test
Listening for wake word "hey claw"...
(Speak "hey claw" into your microphone)
✓ Wake word detected. Listening for command...
(Speak your command)
✓ Command captured: "list the files in my coding workspace"
Processing...
✓ Response received and spoken via system TTS.
The default macOS TTS uses the say command with the Alex voice. You can override this in the voice config with "tts": "elevenlabs" if you prefer a more natural-sounding voice (requires an ElevenLabs API key — see Android section below).
Android Talk Mode
Android does not support persistent background wake word listening without a dedicated system app. Instead, OpenClaw uses Talk Mode — a push-to-talk conversation flow triggered from the OpenClaw Android companion app or via an ADB command during development.
Talk Mode uses ElevenLabs for text-to-speech by default, producing natural-sounding audio responses. To configure it, add your ElevenLabs API key and preferred voice ID to your configuration:
{
"voice": {
"enabled": true,
"platform": "android",
"mode": "talk",
"tts": "elevenlabs",
"elevenlabs": {
"apiKey": "your-elevenlabs-api-key",
"voiceId": "21m00Tcm4TlvDq8ikWAM",
"model": "eleven_multilingual_v2"
},
"channel": "telegram",
"continuousMode": true
}
}
With "continuousMode": true, OpenClaw automatically listens for a follow-up after speaking each response — creating a natural back-and-forth conversation flow without requiring you to re-trigger Talk Mode for every turn. Tap the stop button in the companion app (or send openclaw voice stop via ADB) to end the session.
If you do not have an ElevenLabs account, set "tts": "system" to use Android’s built-in TTS engine. Quality is lower, but it works out of the box with no additional API key.
Testing Your Multi-Channel Setup
With routing configured and the daemon restarted, send a test message through each channel and verify that the correct agent responds.
Test 1: Telegram → Coding Agent
Open Telegram and send your bot a coding question:
Write a Python function that reads all .py files in a directory and counts total lines of code.
The coding agent (DeepSeek R1) should respond with clean, idiomatic Python including error handling — its system prompt optimizes for this.
Check the daemon logs to confirm routing:
openclaw logs --tail 20
[INFO] [router] Message from telegram/391847562 → coding-agent
[INFO] [coding-agent] Model: deepseek/deepseek-r1 | Tokens: 312 in, 487 out
[INFO] [telegram] Response delivered to 391847562
Test 2: Slack → Work Agent
In Slack, open a DM with your OpenClaw bot and send:
Draft a short follow-up email to a client who hasn't responded to a proposal in two weeks.
The work agent (Claude Sonnet) should produce a professional, concise email draft — appropriate for a work context.
openclaw logs --tail 20
[INFO] [router] Message from slack/U0123ABCDEF → work-agent
[INFO] [work-agent] Model: anthropic/claude-sonnet-4-5 | Tokens: 198 in, 312 out
[INFO] [slack] Response delivered to U0123ABCDEF
Test 3: Verify Workspace Isolation
This test confirms that workspaces are genuinely isolated. From the Telegram coding agent, ask it to create a file:
Create a file called routing-test.txt in my workspace with the text "from coding agent".
Then from Slack, ask the work agent to list its workspace files:
List the files in my workspace.
The work agent’s file listing should not include routing-test.txt — that file lives in the coding workspace, which the work agent cannot access. If workspace isolation is working correctly, the work agent will report an empty workspace (or only files that were previously created through Slack conversations).
Test 4: Check Routing Table
At any point, you can inspect the live routing state without restarting:
openclaw routing status --verbose
Active Agents
--------------
coding-agent Sessions: 1 Last active: 14s ago Workspace files: 3
work-agent Sessions: 1 Last active: 2m ago Workspace files: 0
personal-agent Sessions: 0 Last active: never Workspace files: 0
general Sessions: 0 Last active: never Workspace files: 0
An agent with zero sessions has not yet been activated (no messages routed to it). Once a message arrives, OpenClaw lazily initializes the agent instance and its workspace context.
Frequently Asked Questions
Can I have different LLM models per channel?
Yes — this is one of the primary reasons to use multi-channel routing. In routing.json, each agent definition has its own model field. You can assign deepseek/deepseek-r1 to your coding agent for stronger code reasoning, anthropic/claude-sonnet-4-5 to your work agent for better instruction-following and writing quality, and a lighter or cheaper model to a high-frequency personal assistant channel to manage API costs.
The model is resolved at the agent level, not the channel level, so if two channels route to the same agent definition they share the same model. If you need different models on channels that would otherwise share an agent, create separate agent definitions — even if their workspace and system prompt are identical — and route each channel to its own definition.
OpenRouter is the recommended provider for multi-model setups because a single API key grants access to models from Anthropic, DeepSeek, OpenAI, and others. Update the model field in routing.json and run openclaw routing apply && openclaw restart to switch models without reconfiguring the provider.
How do I prevent cross-contamination between agent contexts?
Workspace isolation and session isolation are the two mechanisms OpenClaw uses to prevent context leakage between agents.
Workspace isolation is enforced at the file system level. Each agent definition’s workspace field resolves to a dedicated directory. The agent dispatcher validates all file paths against this root before executing any file operation. A path outside the configured workspace — including relative paths that traverse directories with ../ — is rejected with a WorkspaceBoundaryError before it reaches the LLM or any tool execution layer.
Session isolation means that conversation history is stored per {channel, userID} tuple. Even if the same person sends messages through both Telegram and Slack, their session histories are independent. The coding agent’s conversation log does not bleed into the work agent’s context window. You can inspect session files directly in ~/.openclaw/sessions/ — each agent has its own subdirectory.
If you suspect cross-contamination — for example, the work agent seems to “know about” something that only happened in a coding session — run openclaw routing status --verbose to confirm both sessions are showing the correct agent assignment, and check the session files to see what context each agent is actually using.
Can one message trigger agents on multiple channels?
Not by default — the routing model is one-message-to-one-agent. Each incoming message is matched to exactly one agent definition based on the originating channel and routing configuration.
However, you can build fan-out behavior using OpenClaw’s agent-to-agent messaging API. An agent can explicitly send a message to a different agent in its response by calling the internal @agent tool:
User (via Slack): "Summarize today's coding work and send a WhatsApp summary to remind me tonight."
work-agent response includes tool call:
@agent personal-agent "Evening reminder: today's coding work summary — [summary here]. Reply 'done' when you want to clear this."
The work agent sends a message to the personal-agent instance, which then delivers a WhatsApp notification. This is a deliberate, explicit fan-out rather than implicit — the message content and destination are visible in the routing logs. To enable agent-to-agent messaging, set "agentMessaging": true in your routing.json at the root level. Be aware that this introduces additional complexity and potential for recursive agent loops; review the OpenClaw documentation on agent-to-agent communication before enabling it in production.
Next Steps
You now have a fully operational multi-channel routing setup: Slack routes to a professional work agent, Telegram and Discord route to a specialized coding agent, and WhatsApp connects to a personal assistant — each with isolated workspaces and independently configured models.
Add scheduled automation. The next step in the OpenClaw build series covers cron-based automation: having agents proactively push messages to channels on a schedule rather than waiting for user input. This unlocks workflows like daily coding standup summaries delivered to Slack every morning, or a weekly digest of completed tasks sent to WhatsApp every Sunday. If you have used building AI workflows with n8n for scheduled tasks before, you will find OpenClaw’s native cron integration simpler for agent-specific automation because it has direct access to agent workspaces and routing context without requiring webhook bridges.
Refine your system prompts. The system prompts in routing.json are the single biggest lever for improving agent quality. Spend time iterating on each agent’s prompt using real conversation logs as feedback. A well-crafted system prompt that includes specific behavioral constraints, preferred output formats, and domain knowledge dramatically outperforms a generic “helpful assistant” prompt.
Monitor routing logs. As traffic grows across channels, openclaw logs --tail 100 | grep router gives a clean view of routing decisions. Watch for unexpected routing (messages ending up at the default general agent when you expected a specific one) and token consumption patterns per agent to stay ahead of API cost surprises.
Explore additional channel adapters. Beyond the four channels covered in this tutorial, OpenClaw’s adapter ecosystem includes Signal (via the Signal CLI bridge), Microsoft Teams (OAuth app, similar to Slack), Matrix, LINE, iMessage (via the BlueBubbles server on macOS), and Feishu. Each follows the same pattern: register the channel with openclaw channel add <name>, then add a routing rule in routing.json. The underlying routing and workspace isolation mechanics are identical regardless of the channel.