OpenClaw Integration Guide
Technology: openclaw · Category: ai · Last reviewed: 2026-08-23
Source: https://tech-stack.codeamanilabs.org/guide/openclaw
Insight:
OpenClaw is a self-hosted agent gateway, not an SDK — one long-lived daemon on your own box that fronts 30+ messaging channels, 50+ model providers, and a file-based skill system, all driven by the
openclawCLI. The trade-off is ownership for ops: you get a WhatsApp/Telegram-native agent with no per-seat SaaS bill, but you run the daemon, hold the keys, and inherit the blast radius of an agent that canexec. For codeAmani it is the fastest way to put a Claude-backed brain behind a WhatsApp number — ideal for internal ops and prototyping the Kenya builds, with the Meta Cloud API still the answer for customer-facing production traffic.
██████╗ ██████╗ ███████╗███╗ ██╗ ██████╗██╗ █████╗ ██╗ ██╗
██╔═══██╗██╔══██╗██╔════╝████╗ ██║██╔════╝██║ ██╔══██╗██║ ██║
██║ ██║██████╔╝█████╗ ██╔██╗ ██║██║ ██║ ███████║██║ █╗ ██║
██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██║ ██║ ██╔══██║██║███╗██║
╚██████╔╝██║ ███████╗██║ ╚████║╚██████╗███████╗██║ ██║╚███╔███╔╝
╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═════╝╚══════╝╚═╝ ╚═╝ ╚══╝╚══╝
OpenClaw Integration Guide
Focus: Running a self-hosted OpenClaw Gateway as a personal/ops AI agent that lives inside WhatsApp, Telegram, Slack and friends — install, config, agents, skills, MCP, and how to harden it before it leaves loopback.
Overview
OpenClaw (MIT, github.com/openclaw/openclaw, developed in the open by the non-profit OpenClaw Foundation — openclaw.org) is "a personal AI assistant that runs on your devices and meets you in the channels you already use." It is not a library you import — there is no import { OpenClaw }. It is a daemon plus a CLI: you install the openclaw npm package globally, run an onboarding wizard, and end up with a long-lived Gateway process on 127.0.0.1:18789 that owns your messaging connections, your model providers, your agent sessions, and your tool policy.
The design point that makes it different from an agent framework: the messaging platform is the UI. There is no app to build. You DM a WhatsApp or Telegram number, the Gateway routes that message to an agent, the agent runs tools in a workspace directory on your machine, and the reply comes back down the same channel. A browser Control UI (openclaw dashboard) exists for administration, not as the primary surface.
| OpenClaw | Agent SDK / framework | Managed bot platform | |
|---|---|---|---|
| Shape | Daemon + CLI you self-host | Library you compile into an app | Hosted SaaS |
| UI | Existing messaging apps | You build it | Vendor's console |
| Model | Bring your own key, 50+ providers | Whatever you wire | Vendor's models |
| Secrets | Your disk (~/.openclaw/) |
Your env | Vendor holds them |
| Ops burden | Yours (process, updates, auth) | Yours (deploy) | None |
| Multi-tenant | No — single-operator by design | Yes, if you build it | Yes |
flowchart LR
subgraph CH["Channels"]
W["WhatsApp"]
T["Telegram"]
S["Slack / Discord / Signal"]
end
subgraph HOST["Your host — one Gateway daemon"]
G["Gateway<br/>127.0.0.1:18789<br/>WebSocket + HTTP"]
A["Agents<br/>agents.entries.*<br/>workspace + skills"]
TP["Tool policy<br/>tools.allow / tools.deny"]
end
subgraph CP["Control plane"]
C["openclaw CLI"]
U["Control UI<br/>openclaw dashboard"]
N["Nodes<br/>macOS / iOS / Android"]
end
P["Model providers<br/>anthropic/ · openai/ · ollama/"]
M["MCP servers<br/>stdio · HTTP · SSE"]
W --> G
T --> G
S --> G
C --> G
U --> G
N --> G
G --> A
A --> TP
TP --> M
A --> P
Official Documentation
| Resource | URL |
|---|---|
| Getting started | https://docs.openclaw.ai/start/getting-started |
| Install (all methods) | https://docs.openclaw.ai/install |
| Architecture (Gateway, nodes, frames) | https://docs.openclaw.ai/concepts/architecture |
| Gateway config & security | https://docs.openclaw.ai/gateway |
Agent config (agents.*, bindings) |
https://docs.openclaw.ai/gateway/config-agents |
| Channels index | https://docs.openclaw.ai/channels |
| WhatsApp channel | https://docs.openclaw.ai/channels/whatsapp |
| Model providers (50+) | https://docs.openclaw.ai/providers |
| Anthropic provider | https://docs.openclaw.ai/providers/anthropic |
Skills (SKILL.md) |
https://docs.openclaw.ai/tools/skills |
| Tools & tool policy | https://docs.openclaw.ai/tools |
| MCP servers | https://docs.openclaw.ai/tools/mcp |
| CLI reference | https://docs.openclaw.ai/cli |
| ClawHub (plugin/skill registry) | https://clawhub.ai |
| Repository | https://github.com/openclaw/openclaw |
Install
Requirements: Node 22.22.3+, 24.15+, or 25.9+ (Node 26 recommended), plus an API key from at least one model provider.
The one-liner installers handle Node and the daemon for you:
# macOS / Linux / WSL2
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
# Windows (PowerShell)
iwr -useb https://openclaw.ai/install.ps1 | iex
If you manage Node yourself, install the npm package globally. npm 12+ blocks unapproved lifecycle scripts, so the --allow-scripts flag is required (this is the exact form the docs ship):
npm install -g openclaw@latest --allow-scripts openclaw
openclaw onboard --install-daemon
# pnpm
pnpm add -g --allow-build=openclaw openclaw@latest && openclaw onboard --install-daemon
# bun
bun add -g --trust openclaw@latest && openclaw onboard --install-daemon
Verify:
openclaw --version
openclaw doctor # config + environment diagnostics
openclaw gateway status # should report listening on 18789
openclaw dashboard # opens the Control UI in a browser
Releases are date-versioned (
2026.7.1-2style) and ship on four dist-tags:latest,extended-stable,beta,alpha. Pinextended-stableon anything you don't want moving under you.
Configuration
State lives in $HOME/.openclaw/; the config file is JSON5 (comments and trailing commas allowed) and is normally ~/.openclaw/openclaw.json. Override the path with OPENCLAW_CONFIG_PATH (keep it a real file — OpenClaw rewrites config atomically, so a symlinked openclaw.json gets its target replaced). You can edit it directly: the Gateway watches the file and hot-reloads changes, and it refuses to start on a config that fails validation. Still, prefer the CLI so a typo is caught up front rather than at reload:
openclaw config file # print the resolved config path
openclaw config get agents.defaults.model
openclaw config set agents.defaults.model.primary "anthropic/claude-opus-5"
openclaw config validate
openclaw config schema # full JSON Schema
Model providers
Models are addressed as "provider/model". Provider credentials live under env.vars in the config (or in the process environment):
{
env: {
vars: {
ANTHROPIC_API_KEY: "sk-ant-...", // resolved from your secret manager, not committed
},
},
agents: {
defaults: {
model: {
primary: "anthropic/claude-opus-5",
fallbacks: ["anthropic/claude-sonnet-5"],
},
utilityModel: "anthropic/claude-fable-5", // cheap model for routing/summarisation
thinkingDefault: "low",
},
},
}
openclaw onboard --anthropic-api-key "$ANTHROPIC_API_KEY"
openclaw models list --provider anthropic
The "provider/model" shape and the Claude ids used here are verified against docs/providers/anthropic.md in the tree, which documents anthropic/claude-opus-5, anthropic/claude-sonnet-5, anthropic/claude-fable-5, anthropic/claude-mythos-5, and dated builds such as anthropic/claude-opus-4-8. (Anthropic can also be driven through an existing Claude Code CLI login on the same host instead of an API key; for a long-lived Gateway, prefer a dedicated ANTHROPIC_API_KEY.)
OpenClaw's provider directory covers 50+ backends — Anthropic, OpenAI, Google, Mistral, Cohere, Bedrock, Groq, Together AI, DeepSeek, Perplexity, plus local runtimes (Ollama, LM Studio, vLLM, llama.cpp, SGLang). Per codeAmani's AI routing policy, keep primary on Anthropic Claude and reserve cheaper tiers for utilityModel.
Agents
Agents are config objects, not code. agents.defaults sets the inherited baseline; agents.entries.<id> overrides per agent; bindings route channels to agents.
{
agents: {
ownership: "explicit", // required once you run more than one agent
defaults: {
workspace: "~/.openclaw/workspace",
model: { primary: "anthropic/claude-opus-5" },
skills: ["duka-inventory"],
heartbeat: { every: "30m" },
},
entries: {
ops: {
name: "Ops Agent",
workspace: "~/.openclaw/workspace-ops",
model: "anthropic/claude-opus-5",
identity: { name: "Amani", emoji: "🕊️" },
},
support: {
workspace: "~/.openclaw/workspace-support",
model: { primary: "anthropic/claude-sonnet-5", fallbacks: [] },
skills: ["docs-search"],
},
},
},
bindings: [
{ agentId: "ops", match: { channel: "whatsapp", accountId: "internal" } },
{ agentId: "support", match: { channel: "telegram" } },
],
}
Binding resolution is deterministic and narrows outward: peer → guild/team → account → channel-wide fallback. With ownership: "explicit" there is no default agent — an unbound channel simply has nowhere to route.
openclaw agents list
openclaw agents add
openclaw agents bind # attach an agent to a channel/account
Channels
Telegram, Reef, and WebChat are bundled. Everything else — WhatsApp, Slack, Discord, Signal, iMessage, Matrix, Microsoft Teams, Google Chat, LINE, SMS, IRC, Twitch and more — is an official plugin installed on demand.
openclaw plugins install clawhub:@openclaw/whatsapp
openclaw channels add --channel whatsapp # interactive; installs the plugin if missing
openclaw channels login --channel whatsapp # QR pairing
openclaw channels list
Set the access policy before you log in, or the first stranger to message the number becomes a conversation:
{
channels: {
whatsapp: {
dmPolicy: "pairing", // unknown senders need owner approval
allowFrom: ["+254712345678"],
groupPolicy: "allowlist",
groupAllowFrom: ["+254712345678"],
textChunkLimit: 4000, // default; lower it for 2G/3G users
sendReadReceipts: true,
replyToMode: "first", // off | first | all | batched
},
},
}
dmPolicy |
Effect |
|---|---|
pairing |
Unknown senders raise an approval request (expires after 1h, max 3 pending) |
allowlist |
Only numbers in allowFrom get through |
open |
Everyone — requires an explicit allowFrom: ["*"] |
disabled |
No DMs at all |
Approve a pending pairing from the Control UI (Settings → Channels → DM access requests) or the CLI:
openclaw pairing approve whatsapp <CODE>
Session credentials land in ~/.openclaw/credentials/whatsapp/<accountId>/creds.json — treat that directory as a secret. Multi-account setups live under channels.whatsapp.accounts.<id>, which is how one Gateway serves a personal and a business number with different agents bound to each.
Read this before shipping (settled against the source): the WhatsApp channel links a WhatsApp account via QR pairing over WhatsApp Web, not the Meta WhatsApp Business Cloud API and not Twilio. This is not inference —
extensions/whatsappdepends onbaileys(the WhatsApp-Web multi-device library), its login path is QR-only (login-qr-*,onQr), and the docs state it plainly: "production-ready via WhatsApp Web (Baileys). The gateway owns the linked session(s); there is no separate Twilio WhatsApp channel." Perfect for an internal ops number or a prototype; the wrong tool for customer-facing volume on a business number — see codeAmani notes.
Skills
Skills are the extension unit for agent behaviour, and they are just files: a directory containing a SKILL.md with YAML frontmatter plus a markdown body, following the AgentSkills spec.
---
name: mpesa-reconcile
description: Reconcile M-Pesa C2B callbacks against open orders and flag mismatches.
---
# M-Pesa reconciliation
When asked to reconcile payments:
1. Read `orders.csv` from the workspace.
2. Match on `CheckoutRequestID`, never on amount alone.
3. Report unmatched rows as a table; never auto-refund.
Discovery walks up to 6 levels deep inside configured roots, and the name in frontmatter wins over the directory name. When the same name appears twice, the highest-priority source wins:
| Priority | Source |
|---|---|
| 1 | Workspace skills — <workspace>/skills |
| 2 | Project agent skills — <workspace>/.agents/skills |
| 3 | Personal agent skills — ~/.agents/skills |
| 4 | Managed/local skills — <state-dir>/skills |
| 5 | Bundled skills (shipped with OpenClaw) |
| 6 | Extra directories + plugin skills |
openclaw skills install @owner/slug # from ClawHub
openclaw skills install git:owner/repo@ref # from a git ref
openclaw skills install ./path/to/skill --as mpesa-reconcile
openclaw skills install @owner/slug --global # visible to every agent
openclaw skills verify @owner/slug # trust check before install
openclaw skills update --all
At run time OpenClaw resolves eligible skills against gating rules and allowlists, injects skills.entries.<name>.env variables, and compiles a snapshot into the system prompt as XML. Skills surface as slash commands (/mpesa-reconcile) and as $mpesa-reconcile references inside a prompt; set disable-model-invocation: true in frontmatter to make a skill user-only.
Tools and tool policy
Agents get a broad built-in toolset — exec, process, terminal, code_execution; read/write/edit/apply_patch; web_search, x_search, web_fetch, browser; view_image, image_generate, tts; sessions_*, subagents, agents_wait, goal; cron and heartbeat_respond for background work; ask_user, message, screen.
Policy is enforced before the model call — a denied tool's schema is never sent for that turn, so the model cannot even attempt it:
{
agents: {
entries: {
support: {
tools: {
deny: ["exec", "terminal", "process", "code_execution"],
},
},
},
},
}
That deny-list is the single most important config line for any agent reachable from a public channel.
MCP servers
MCP servers plug in as first-class tool sources under mcp.servers, over stdio, streamable HTTP, or SSE:
openclaw mcp add
openclaw mcp login <name> # OAuth for protected servers
openclaw mcp doctor <name> --probe # reachability + capability probe
openclaw mcp status --verbose
Their tools flow through the same tool-profile and policy controls, and can be narrowed with toolFilter.include / toolFilter.exclude.
Gateway operations & security
One Gateway per host, one multiplexed port for WebSocket control, HTTP APIs, and the Control UI (the node/device bridge listens separately on 18790, and channel plugins that need an inbound webhook — e.g. MS Teams on 3978 — open their own).
openclaw gateway start
openclaw gateway status
openclaw gateway restart
openclaw logs
openclaw health
Port resolves --port → OPENCLAW_GATEWAY_PORT → gateway.port → 18789.
Bind resolves CLI override → gateway.bind → loopback (containers default to auto, i.e. 0.0.0.0, unless Tailscale serve/funnel is active, which forces loopback).
Authentication is mandatory by default, and OpenClaw refuses to bind a non-loopback interface without it:
{
gateway: {
bind: "loopback",
auth: { token: "..." }, // or auth.password
controlUi: {
allowedOrigins: ["https://claw.internal.example"], // required for remote browsers
},
},
}
Equivalent env vars: OPENCLAW_GATEWAY_TOKEN, OPENCLAW_GATEWAY_PASSWORD. For a reverse proxy that terminates auth itself, set gateway.auth.mode: "trusted-proxy".
For remote access the docs push Tailscale/VPN first, SSH tunnel second — and an SSH tunnel does not bypass gateway auth; clients still send the token:
ssh -N -L 18789:127.0.0.1:18789 user@gateway-host
Control-plane clients (CLI, Control UI, macOS app, automation) and nodes (macOS/iOS/Android/headless devices exposing camera.*, screen.record, location.get) all speak the same typed WebSocket protocol: a mandatory connect handshake, then {type:"req", id, method, params} → {type:"res", id, ok, payload|error} with events pushed as {type:"event", event, payload, seq?, stateVersion?}. Side-effecting methods (send, agent) accept idempotency keys — use them, because a reconnect that replays a send is a duplicate WhatsApp message to a customer.
Environment Variables
# Model provider (codeAmani primary — see AI routing policy)
ANTHROPIC_API_KEY=sk-ant-...
# Gateway auth — required for any non-loopback bind
OPENCLAW_GATEWAY_TOKEN=...
# or
OPENCLAW_GATEWAY_PASSWORD=...
# Optional
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_CONFIG_PATH=/etc/openclaw/openclaw.json
OPENCLAW_SERVICE_REPAIR_POLICY=... # hand lifecycle to an external supervisor
Repository layout (grounding)
If you clone openclaw/openclaw to read the source, the monorepo is pnpm-workspace'd (packages: [., ui, packages/*, extensions/*, examples/*]) and the names in the docs don't map 1:1 to folders:
| In the tree | Is | Note |
|---|---|---|
extensions/ (~157 pkgs) |
Channels + model providers + tools | What the docs and CLI call "plugins." Per the repo's own AGENTS.md: "Product/docs/UI/changelog wording: 'plugin/plugins'; extensions/ is internal." WhatsApp is extensions/whatsapp (pkg @openclaw/whatsapp), Anthropic is extensions/anthropic. |
apps/ |
Companion clients | android, ios, macos, linux, shared — the "nodes" that expose camera.*/screen.*/location.*. |
config/ |
Repo tooling config | lint/tsconfig/budgets — not runtime Gateway config (that lives at ~/.openclaw/openclaw.json). |
deploy/ |
Deploy fragments | just fly.private.toml; root also ships Dockerfile, docker-compose.yml, fly.toml, render.yaml. |
docs/ |
The published docs | Same paths as docs.openclaw.ai (e.g. docs/channels/whatsapp.md → /channels/whatsapp). |
AGENTS.md |
Contributor policy | CLAUDE.md is a symlink to it — edit AGENTS.md only. |
The shipped docker-compose.yml starts the Gateway with --bind ${OPENCLAW_GATEWAY_BIND:-lan} and publishes 18789 (Gateway), 18790 (node/device bridge) and 3978 (MS Teams); it pins OPENCLAW_STATE_DIR/OPENCLAW_CONFIG_PATH/OPENCLAW_WORKSPACE_DIR under /home/node/.openclaw and expects OPENCLAW_GATEWAY_TOKEN — a containerised deploy is non-loopback by construction, so the token is mandatory.
codeAmani notes
- Secrets stay on the host. Provider keys land in
~/.openclaw/openclaw.jsonunderenv.vars, and channel credentials in~/.openclaw/credentials/. That whole directory is a secret store — never sync it, never bake it into an image, and pull the values from Hazina at provisioning time rather than committing them. Rungitleaksbefore any repo that references an OpenClaw config goes near a push. - Bind loopback, tunnel for the rest. The default
loopbackbind is the correct production posture. If you must reach it remotely, use Tailscale or the SSH tunnel and setgateway.auth.token— non-loopback without auth is refused, and that refusal is a feature. Also note the container default flips toauto(0.0.0.0), so a naivedocker runis the one config that quietly exposes the port. - Deny
execon anything customer-facing. An OpenClaw agent can run shell commands in its workspace by default. For a public WhatsApp number,tools.deny: ["exec", "terminal", "process", "code_execution"]plusdmPolicy: "allowlist"is the baseline, and even then treat inbound messages as untrusted input — the same prompt-injection boundary as any webhook payload. - AI routing. Set
model.primarytoanthropic/claude-opus-5per the house policy, keep a Sonnet fallback for provider blips, and pointutilityModelat a cheap tier so routing and summarisation don't bill at flagship rates. OpenClaw's provider list also carries Together AI and DeepSeek if a project has already picked those. - Kenya-targeted projects — the honest fit. OpenClaw's messaging-first model maps cleanly onto the WhatsApp + M-Pesa builds (
duka-order-bot,boda-dispatch,clinic-salon-booking): a self-hosted agent brain behind a WhatsApp number, with M-Pesa reconciliation logic expressed as aSKILL.mdrather than app code. But the WhatsApp channel pairs by QR against a WhatsApp account, not the Meta WhatsApp Business Cloud API — so it is the right tool for the internal ops number, the merchant-side assistant, and fast prototyping of conversation flows, and the wrong one for customer-facing volume where a Cloud API number, template messages, and the 24-hour customer-service window are the compliance surface. Prototype the flow in OpenClaw; ship the customer path on the official API. - Low bandwidth. Default
textChunkLimitis 4,000 characters and media caps at 50 MB — both are generous for a 2G/3G handset. Lower the chunk limit, prompt for short replies, and avoidimage_generate/ttson the customer path unless the user asked for it. Every reply is billable data on the recipient's bundle. - Swahili needs no OpenClaw configuration — it is entirely a model-level concern. Put the language instruction in the agent's
identity/system prompt and pick the model on Swahili quality (see the R&D report inresearch-and-development/). - Single-operator by design. OpenClaw is a personal assistant gateway: one host, one owner, multiple agents. It is not a multi-tenant backend, and trying to make one Gateway serve many customers' numbers fights the architecture. One Gateway per operator, or use it as an ops tool alongside a purpose-built Next.js app.
Troubleshooting
| Issue | Fix |
|---|---|
npm install -g openclaw skips setup / CLI missing |
npm 12+ blocks lifecycle scripts — reinstall with --allow-scripts openclaw (pnpm: --allow-build=openclaw, bun: --trust) |
| Refuses to start: "refusing to bind gateway … without auth" | Non-loopback bind requires gateway.auth.token/.password or OPENCLAW_GATEWAY_TOKEN |
| Control UI blocked in a remote browser | Add the origin to gateway.controlUi.allowedOrigins |
| Tunnel works but requests are rejected | SSH tunnels do not bypass gateway auth — the client must still send the token |
| WhatsApp QR expires on a headless box | Get the QR to your phone fast, or run openclaw channels login from a machine with a display and copy the credentials dir |
| Bot ignores an incoming DM | dmPolicy: "pairing" is waiting on approval — openclaw pairing approve whatsapp <CODE> (expires after 1h, max 3 pending) |
| Messages arrive but no agent replies | With agents.ownership: "explicit" there is no default agent — add a bindings entry for that channel/account |
| Skill installed but never used | Check the name in SKILL.md frontmatter (it overrides the directory), the source precedence table, and whether disable-model-invocation: true is set |
| MCP tools missing from the agent | openclaw mcp doctor <name> --probe, then check toolFilter.include/exclude and tools.allow/deny |
| Duplicate outbound messages after a reconnect | Send send/agent requests with idempotency keys |
| Node version errors on install | Needs Node 22.22.3+, 24.15+, or 25.9+ (26 recommended) |
Official docs: