OpenClaw Multi-Channel Gateway Integration: Production Deployment Guide
Integrating OpenClaw into production systems requires more than running openclaw gateway start. You need authentication, monitoring, high availability, secrets management, and channel-specific configurations that scale. This guide covers everything from single-instance deployments to multi-tenant architectures, with real-world examples from production OpenClaw installations.
Architecture Overview
OpenClaw's gateway architecture separates concerns cleanly:
┌─────────────────┐
│ Chat Channels │ WhatsApp, Telegram, Discord, Slack, iMessage
└────────┬────────┘
│
┌────────▼────────┐
│ Gateway Core │ Authentication, routing, session management
└────────┬────────┘
│
┌────────▼────────┐
│ Agent Runtime │ Pi, Claude, GPT-4, local models
└────────┬────────┘
│
┌────────▼────────┐
│ Tool Layer │ exec, browser, files, web, custom tools
└─────────────────┘
Each layer is configurable independently. This modularity lets you scale components based on load—run multiple gateways behind a load balancer, or shard channels across instances.
Configuration Management
Production deployments need structured config management. OpenClaw stores configuration in ~/.openclaw/openclaw.json, but managing this file across environments (dev, staging, prod) requires a system.
Environment-Based Config
Use separate config files per environment:
~/.openclaw/
├── openclaw.json # Symlink to active config
├── openclaw.dev.json # Development settings
├── openclaw.staging.json # Staging settings
└── openclaw.prod.json # Production settings
Switch environments:
ln -sf ~/.openclaw/openclaw.prod.json ~/.openclaw/openclaw.json
openclaw gateway restart
Config Inheritance
Base config shared across environments:
openclaw.base.json:
{
"gateway": {
"port": 18789
},
"providers": {
"anthropic": {
"apiKey": "$ANTHROPIC_API_KEY"
}
},
"sessions": {
"compaction": {
"enabled": true,
"maxTokens": 100000
}
}
}
openclaw.prod.json:
{
"extends": "~/.openclaw/openclaw.base.json",
"gateway": {
"authentication": {
"tokens": {
"gateway": "$PROD_GATEWAY_TOKEN"
}
}
},
"channels": {
"whatsapp": {
"enabled": true,
"allowFrom": ["$PROD_ALLOWED_NUMBERS"]
}
}
}
OpenClaw merges configs, with specific overriding base.
Secrets Management
Never commit API keys to Git. Use ~/.openclaw/secrets.json:
{
"ANTHROPIC_API_KEY": "sk-ant-...",
"PROD_GATEWAY_TOKEN": "gw_...",
"PROD_ALLOWED_NUMBERS": ["+15555550123", "+15555550124"],
"TELEGRAM_BOT_TOKEN": "123456789:ABCD...",
"DISCORD_BOT_TOKEN": "MTA..."
}
Reference secrets in config with $VARIABLE:
{
"providers": {
"anthropic": {
"apiKey": "$ANTHROPIC_API_KEY"
}
}
}
OpenClaw resolves variables at runtime from secrets.json and environment variables.
Production pattern: Store secrets in encrypted vaults (AWS Secrets Manager, HashiCorp Vault) and inject as environment variables:
export ANTHROPIC_API_KEY=$(aws secretsmanager get-secret-value --secret-id openclaw/anthropic --query SecretString --output text)
openclaw gateway
Authentication and Security
Public-facing gateways need authentication to prevent unauthorized access.
Gateway Token Authentication
Set a gateway token:
{
"security": {
"tokens": {
"gateway": "your-secret-token-here"
}
}
}
Clients must include this token:
curl -H "Authorization: Bearer your-secret-token-here" \
http://localhost:18789/api/v1/sessions
Best practices:
- Generate tokens with
openssl rand -base64 32 - Rotate tokens quarterly
- Use different tokens per environment
- Store in secrets manager, not config files
Channel-Specific Allowlists
Restrict who can message your agent:
WhatsApp:
{
"channels": {
"whatsapp": {
"allowFrom": ["+15555550123"],
"groups": {
"*": { "requireMention": true }
}
}
}
}
Telegram:
{
"channels": {
"telegram": {
"allowedUsers": [123456789, 987654321],
"allowedChats": [-1001234567890]
}
}
}
Discord:
{
"channels": {
"discord": {
"allowedGuilds": ["1234567890123456789"],
"allowedChannels": ["9876543210987654321"]
}
}
}
Rate Limiting
Protect against abuse with per-user rate limits:
{
"security": {
"rateLimits": {
"perUser": {
"messages": 50,
"windowSeconds": 3600
}
}
}
}
Users hitting limits get a temporary cooldown message.
Channel Integration Patterns
Different channels require different setups. Here's how to configure each for production.
WhatsApp uses a local client that pairs via QR code. For production, run this on a stable server with persistent storage.
Setup:
openclaw gatewayopenclaw channels statusPersistence: WhatsApp session data lives in ~/.openclaw/sessions/whatsapp/. Back this up—losing it requires re-pairing.
Monitoring: Check connection status every 15 minutes:
status=$(openclaw channels status whatsapp --json | jq -r '.connected')
if [ "$status" != "true" ]; then
alert "WhatsApp disconnected"
fi
Gotchas:
- WhatsApp Web has concurrent session limits (max 4-5 devices)
- Connection drops if phone dies or goes offline for >2 weeks
- QR pairing expires after 60 seconds—automate with expect scripts if needed
Telegram
Telegram bots are stateless and reliable. Best choice for production environments.
Setup:
123456789:ABC...{
"channels": {
"telegram": {
"enabled": true,
"token": "$TELEGRAM_BOT_TOKEN",
"allowUpdates": {
"message": true,
"callback_query": true,
"inline_query": false
}
}
}
}
Webhook vs Polling:
Default (polling):
{
"telegram": {
"webhook": {
"enabled": false
}
}
}
Production (webhook):
{
"telegram": {
"webhook": {
"enabled": true,
"url": "https://your-domain.com/webhooks/telegram",
"secret": "$TELEGRAM_WEBHOOK_SECRET"
}
}
}
Webhooks are faster and more reliable. Set them up via HTTPS with valid TLS certs.
Commands: Register bot commands so users see them:
curl -X POST "https://api.telegram.org/bot$TOKEN/setMyCommands" \
-H "Content-Type: application/json" \
-d '{
"commands": [
{"command": "start", "description": "Start conversation"},
{"command": "help", "description": "Show help"},
{"command": "status", "description": "Check agent status"}
]
}'
Discord
Discord bots require application setup and OAuth2.
Setup:
Config:
{
"channels": {
"discord": {
"enabled": true,
"token": "$DISCORD_BOT_TOKEN",
"intents": ["GUILDS", "GUILD_MESSAGES", "MESSAGE_CONTENT"],
"presence": {
"status": "online",
"activity": {
"type": "LISTENING",
"name": "your commands"
}
}
}
}
}
Permissions: Grant minimum necessary:
- Read Messages
- Send Messages
- Embed Links
- Attach Files
- Add Reactions
Slash commands: Discord heavily promotes slash commands. Register them:
const commands = [
{
name: 'ask',
description: 'Ask the AI agent a question',
options: [
{
name: 'question',
description: 'Your question',
type: 3, // STRING
required: true
}
]
}
];
// Register via Discord API
await fetch(`https://discord.com/api/v10/applications/${appId}/commands`, {
method: 'PUT',
headers: {
'Authorization': `Bot ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(commands)
});
Slack
Slack uses OAuth2 and socket mode (or webhooks).
Setup:
chat:write, channels:history, groups:historyConfig:
{
"channels": {
"slack": {
"enabled": true,
"botToken": "$SLACK_BOT_TOKEN",
"appToken": "$SLACK_APP_TOKEN",
"socketMode": true
}
}
}
Events: Subscribe to events in Slack app settings:
message.channelsmessage.groupsapp_mention
Gotchas:
- Socket mode requires app-level token (starts with
xapp-) - OAuth scopes must match subscribed events
- Slack rate limits are aggressive (1 req/sec per method)
iMessage (macOS)
iMessage integration works only on macOS and uses AppleScript.
Setup:
openclaw channels add imessage
Permissions: Grant Terminal (or OpenClaw app) access to:
- Contacts
- Messages
- Automation
Production considerations:
- Requires physical Mac (M1 Mac Mini recommended)
- Messages app must stay open
- AppleScript has ~200ms latency per message
- No delivery receipts or typing indicators
Alternative (BlueBubbles):
For headless servers, use BlueBubbles bridge:
{
"channels": {
"bluebubbles": {
"enabled": true,
"url": "http://mac-server:1234",
"password": "$BLUEBUBBLES_PASSWORD"
}
}
}
BlueBubbles provides HTTP API over iMessage.
High Availability
Production deployments need uptime. Here's how to architect for HA.
Multiple Gateway Instances
Run N gateways behind a load balancer:
Load Balancer
│
┌─────────────┼─────────────┐
│ │ │
Gateway 1 Gateway 2 Gateway 3
(port 18789) (port 18790) (port 18791)
Each gateway handles a subset of channels or users.
Sticky sessions: Use IP-based routing to keep users on the same gateway:
upstream openclaw {
ip_hash;
server 10.0.1.10:18789;
server 10.0.1.11:18789;
server 10.0.1.12:18789;
}
This ensures session continuity—users don't jump between instances mid-conversation.
Health Checks
Implement health checks for load balancers:
HTTP endpoint:
curl http://localhost:18789/health
Returns JSON:
{
"status": "healthy",
"uptime": 86400,
"channels": {
"telegram": "connected",
"discord": "connected",
"whatsapp": "connected"
}
}
Load balancer config (HAProxy):
backend openclaw
option httpchk GET /health
server gw1 10.0.1.10:18789 check inter 10s
server gw2 10.0.1.11:18789 check inter 10s
Instances failing health checks are removed from rotation.
Session Persistence
For HA, sessions must persist across restarts. Options:
1. Shared filesystem (NFS, EFS):
# Mount shared storage
sudo mount -t nfs server:/openclaw /mnt/openclaw
# Run gateway with shared config
openclaw gateway --config /mnt/openclaw/openclaw.json
All instances read/write the same session files.
2. Redis session store (future OpenClaw feature):
{
"sessions": {
"store": "redis",
"redis": {
"url": "redis://cluster:6379"
}
}
}
Sessions live in Redis, accessible from any gateway instance.
3. Database-backed sessions (SQLite → PostgreSQL):
Move session storage from files to Postgres:
{
"sessions": {
"store": "postgresql",
"connection": "$DATABASE_URL"
}
}
All gateways query the same database.
Failover
Automate failover with process managers:
systemd (Linux):
[Unit]
Description=OpenClaw Gateway
After=network.target
[Service]
Type=simple
User=openclaw
ExecStart=/usr/local/bin/openclaw gateway
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Gateway crashes are auto-restarted within 10 seconds.
PM2 (Node.js):
pm2 start openclaw --name gateway -- gateway
pm2 save
pm2 startup
PM2 monitors the process and restarts on failure.
Docker Swarm:
version: '3.8'
services:
gateway:
image: openclaw/gateway:latest
deploy:
replicas: 3
restart_policy:
condition: on-failure
max_attempts: 5
Swarm maintains 3 replicas, restarting failed containers automatically.
Monitoring and Observability
Production systems need visibility. Instrument OpenClaw with logs, metrics, and alerts.
Structured Logging
Enable JSON logs for machine parsing:
{
"logging": {
"format": "json",
"level": "info"
}
}
Logs now output:
{"level":"info","time":"2026-03-07T12:34:56Z","msg":"Message received","channel":"telegram","user":"@alice"}
Ship to Elasticsearch, Splunk, or CloudWatch.
Metrics
Expose metrics endpoint:
curl http://localhost:18789/metrics
Returns Prometheus-compatible metrics:
openclaw_messages_total{channel="telegram"} 1234
openclaw_sessions_active 42
openclaw_tool_calls_total{tool="exec"} 567
openclaw_errors_total 3
Scrape with Prometheus:
scrape_configs:
- job_name: 'openclaw'
static_configs:
- targets: ['localhost:18789']
Graph in Grafana for real-time dashboards.
Alerts
Set up alerts for critical conditions:
Prometheus alerting rules:
groups:
- name: openclaw
rules:
- alert: OpenClawDown
expr: up{job="openclaw"} == 0
for: 5m
annotations:
summary: "OpenClaw gateway is down"
- alert: HighErrorRate
expr: rate(openclaw_errors_total[5m]) > 0.05
for: 10m
annotations:
summary: "Error rate exceeds 5%"
- alert: ChannelDisconnected
expr: openclaw_channel_connected{channel="whatsapp"} == 0
for: 15m
annotations:
summary: "WhatsApp disconnected"
Trigger PagerDuty/Slack notifications when firing.
Distributed Tracing
For multi-service setups, use OpenTelemetry:
{
"telemetry": {
"enabled": true,
"endpoint": "http://jaeger:14268/api/traces",
"serviceName": "openclaw-gateway"
}
}
Trace requests across gateways, agents, and external APIs.
Deployment Patterns
Single-Tenant (Personal Use)
Setup: One gateway per user, running on their laptop or VPS.
Config:
{
"channels": {
"whatsapp": { "enabled": true },
"telegram": { "enabled": true }
},
"security": {
"rateLimits": { "enabled": false }
}
}
No authentication needed—user controls the machine.
Pros: Simple, full control, maximum privacy
Cons: Not scalable, single point of failure
Multi-Tenant (SaaS)
Setup: One gateway per tenant, isolated namespaces.
Architecture:
Reverse Proxy (Nginx)
│
├─ /tenant-a → Gateway A (port 18789)
├─ /tenant-b → Gateway B (port 18790)
└─ /tenant-c → Gateway C (port 18791)
Each tenant gets their own:
- Config directory:
~/.openclaw/tenants// - Sessions:
~/.openclaw/tenants//sessions/ - Workspace:
~/.openclaw/tenants//workspace/
Nginx config:
location /tenant-a/ {
proxy_pass http://localhost:18789/;
proxy_set_header X-Tenant-ID tenant-a;
}
Pros: Isolation, independent scaling
Cons: High resource usage (N processes)
Shared Gateway (Enterprise)
Setup: One gateway serves all users, with routing and access control.
Config:
{
"multiTenant": {
"enabled": true,
"tenants": {
"acme-corp": {
"channels": ["telegram", "slack"],
"model": "anthropic/claude-sonnet-4",
"allowFrom": ["@acme.com"]
},
"widgets-inc": {
"channels": ["discord"],
"model": "openai/gpt-4-turbo",
"allowFrom": ["@widgets.com"]
}
}
}
}
Single process, multiple isolated tenants.
Pros: Resource efficient, centralized management
Cons: Shared fate (one crash affects all)
Performance Optimization
Connection Pooling
Reuse HTTP connections to providers:
{
"providers": {
"anthropic": {
"connectionPool": {
"maxSockets": 50,
"keepAlive": true
}
}
}
}
Reduces latency by avoiding TCP handshakes.
Message Batching
For high-volume channels, batch outbound messages:
{
"channels": {
"telegram": {
"batching": {
"enabled": true,
"maxBatchSize": 10,
"flushIntervalMs": 100
}
}
}
}
Send 10 messages in one API call instead of 10 separate calls.
Caching
Cache expensive operations:
{
"cache": {
"enabled": true,
"provider": "redis",
"ttl": 3600,
"keys": [
"web_fetch:*",
"web_search:*"
]
}
}
Repeated web fetches hit cache instead of making new HTTP requests.
Worker Threads
Offload CPU-intensive work to threads:
{
"workers": {
"enabled": true,
"count": 4,
"tasks": ["image_processing", "pdf_generation"]
}
}
Keeps main thread responsive while background tasks run.
Security Hardening
TLS Termination
Never expose raw HTTP in production. Use TLS:
Option 1: Reverse proxy (Nginx)
server {
listen 443 ssl http2;
server_name gateway.example.com;
ssl_certificate /etc/letsencrypt/live/gateway.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gateway.example.com/privkey.pem;
location / {
proxy_pass http://localhost:18789;
}
}
Option 2: Built-in TLS (future OpenClaw feature)
{
"gateway": {
"tls": {
"enabled": true,
"cert": "/path/to/cert.pem",
"key": "/path/to/key.pem"
}
}
}
Sandboxing
Run OpenClaw in restricted environment:
Docker container (unprivileged):
docker run --user 1000:1000 \
--read-only \
--tmpfs /tmp \
openclaw/gateway
systemd hardening:
[Service]
PrivateTmp=true
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/openclaw
Limits blast radius if compromised.
Input Validation
Validate all user inputs:
{
"security": {
"validation": {
"maxMessageLength": 10000,
"allowedMimeTypes": ["image/png", "image/jpeg", "application/pdf"],
"blockPatterns": ["eval\\(", "exec\\(", "<script>"]
}
}
}
Reject messages containing suspicious content.
Migration and Upgrades
Zero-Downtime Updates
Use blue-green deployment:
HAProxy config:
backend openclaw
server gw-blue 10.0.1.10:18789 check
server gw-green 10.0.1.10:18790 check backup
Mark blue as active, green as backup. Swap on upgrade.
Configuration Migration
OpenClaw versions may change config schema. Use migration scripts:
openclaw config migrate \
--from ~/.openclaw/openclaw.v1.json \
--to ~/.openclaw/openclaw.v2.json
Review diff before applying:
diff -u openclaw.v1.json openclaw.v2.json
Data Backup
Back up critical data before upgrades:
#!/bin/bash
DATE=$(date +%Y%m%d)
tar -czf openclaw-backup-$DATE.tar.gz \
~/.openclaw/openclaw.json \
~/.openclaw/secrets.json \
~/.openclaw/sessions/ \
~/.openclaw/workspace/
Store backups in S3 or equivalent.
Troubleshooting Production Issues
Channel Disconnections
Symptom: WhatsApp shows "disconnected" in status
Diagnosis:
openclaw channels status whatsapp --json | jq .
Fixes:
- Check phone connectivity (must be online)
- Verify session files exist:
ls ~/.openclaw/sessions/whatsapp/ - Re-pair if session corrupted:
openclaw channels logout whatsapp && openclaw channels login
High Latency
Symptom: Agent responses take >10 seconds
Diagnosis:
openclaw status
Check:
- Model provider latency (Anthropic/OpenAI status pages)
- Network latency (
ping api.anthropic.com) - Session compaction (large transcripts?)
Fixes:
- Enable prompt caching
- Switch to faster model (Claude Haiku instead of Opus)
- Increase connection pool size
Memory Leaks
Symptom: Gateway process uses increasing RAM
Diagnosis:
top -p $(pgrep -f openclaw)
Fixes:
- Enable session pruning
- Clear old logs:
rm ~/.openclaw/logs/*.log.* - Restart gateway weekly (systemd timer)
Failed Tool Calls
Symptom: exec commands return errors
Diagnosis:
openclaw logs --grep "tool" --level error
Fixes:
- Verify sandbox vs elevated mode
- Check file permissions
- Test commands manually:
openclaw tools exec --command "ls -la"
Real-World Examples
Multi-Channel Customer Support Bot
Setup: Discord, Telegram, and WhatsApp connected to one agent
Config:
{
"channels": {
"discord": { "enabled": true },
"telegram": { "enabled": true },
"whatsapp": { "enabled": true }
},
"multiAgent": {
"routing": "per-sender"
},
"tools": {
"enabled": ["web_fetch", "memory_search"]
}
}
Features:
- Customers message on any platform
- Agent maintains context per user
- Searches knowledge base for answers
- Escalates complex issues to humans
Automated Code Review System
Setup: GitHub webhooks trigger agent reviews
Config:
{
"webhooks": {
"github": {
"enabled": true,
"secret": "$GITHUB_WEBHOOK_SECRET",
"events": ["pull_request.opened", "pull_request.synchronize"]
}
},
"tools": {
"enabled": ["exec", "web_fetch"]
}
}
Workflow:
Personal Assistant (24/7)
Setup: Single user, all channels, VPS deployment
Config:
{
"channels": {
"telegram": { "enabled": true },
"imessage": { "enabled": true, "via": "bluebubbles" }
},
"cron": [
{
"name": "Morning Briefing",
"schedule": "0 8 * * *",
"task": "Check email, calendar, and weather. Send summary."
}
]
}
Features:
- Message from phone (iMessage) or anywhere (Telegram)
- Daily briefings
- Voice notes transcribed and processed
- Location-based reminders
Next Steps
Deploy to production:
Scale incrementally:
- Start with one gateway instance
- Add load balancing when traffic increases
- Implement shared session store for HA
- Monitor metrics and optimize bottlenecks
Join the community:
- Discord for troubleshooting
- GitHub Discussions for feature requests
- ClawHub for production-tested skills
OpenClaw is infrastructure. Build reliable, scalable agent systems on top of it.
Resources: