Multi-Agent: Channel-Based Routing
Route different channels to different agents with isolated workspaces.
This walkthrough demonstrates OpenClaw's multi-agent routing — where WhatsApp messages go to one agent and Telegram messages go to another. Each agent gets its own workspace and can run a different model.
What you'll configure:
- Provider in WebSocket mode (live connection to the gateway)
- Gateway with token authentication
- Shared agent defaults
- WhatsApp as a "personal" channel
- Telegram as a "work" channel
- Health check data source
Why Multi-Agent?
A single agent works fine for personal use, but as your usage grows you might want:
- Separation of concerns — a personal assistant on WhatsApp, a coding agent on Telegram
- Different models — use Opus for complex tasks, Sonnet for quick replies
- Isolated workspaces — prevent work files from mixing with personal projects
- Per-channel policies — open DMs on one channel, strict allowlists on another
Step 1 — Provider with WebSocket Mode
Unlike the basic example, this config connects to a running gateway via WebSocket. Changes are applied immediately via the config.patch RPC.
terraform {
required_providers {
openclaw = {
source = "registry.terraform.io/kylemclaren/openclaw"
}
}
}
provider "openclaw" {
gateway_url = var.gateway_url
token = var.gateway_token
}
variable "gateway_url" {
type = string
default = "ws://127.0.0.1:18789"
}
variable "gateway_token" {
type = string
sensitive = true
default = ""
}Step 2 — Gateway with Authentication
When the gateway is reachable over a network (e.g. via Tailscale), you should enable token auth to prevent unauthorized access.
resource "openclaw_gateway" "main" {
port = 18789
bind = "loopback"
reload_mode = "hybrid"
auth_mode = "token"
auth_token = var.gateway_token
}The auth_token here must match the token in the provider block. Both are marked sensitive so they never appear in plan output.
Step 3 — Shared Agent Defaults
These defaults apply to all agents. Individual agents can override any of these values.
resource "openclaw_agent_defaults" "shared" {
model_primary = "anthropic/claude-opus-4-6"
timeout_seconds = 600
thinking_default = "low"
sandbox_mode = "non-main"
sandbox_scope = "agent"
}With sandbox_scope = "agent", each agent's sandbox is isolated — one agent can't access another's files.
Step 4 — Channel Configuration
Set up WhatsApp for personal use with a pairing flow, and Telegram for work with a strict allowlist.
resource "openclaw_channel_whatsapp" "personal" {
dm_policy = "pairing"
allow_from = ["+15555550123"]
group_policy = "allowlist"
}variable "telegram_bot_token" {
type = string
sensitive = true
}
resource "openclaw_channel_telegram" "work" {
enabled = true
bot_token = var.telegram_bot_token
dm_policy = "allowlist"
allow_from = ["tg:111222333"]
stream_mode = "partial"
history_limit = 50
}Notice the different DM policies: WhatsApp uses "pairing" (scan-to-connect), while Telegram uses "allowlist" (only pre-approved user IDs can chat).
Step 5 — Health Check
Since we're connected via WebSocket, we can use the health data source to verify the gateway is operational:
data "openclaw_health" "gw" {}
output "gateway_status" {
value = data.openclaw_health.gw.status
}
output "gateway_version" {
value = data.openclaw_health.gw.version
}This is useful as a precondition — if the gateway is down, terraform plan will fail early with a clear error instead of timing out.
Apply It
Start the gateway first (since we're using WebSocket mode):
openclaw gateway --port 18789Then apply:
terraform init
terraform apply \
-var="gateway_token=my-secret" \
-var="telegram_bot_token=YOUR_TOKEN"Full Source
See examples/multi-agent/main.tf for the complete file.
Next Steps
- Add bindings to route specific channels to specific agents
- Add Discord with rich action permissions — see Full-Stack Example
- Set up session reset policies for clean conversation boundaries