Skill: encryptshawn/openclaw-administrator (version 1.0.2)

--- name: openclaw-administrator description: Administration guide for the OpenClaw CLI. Use this skill whenever the user asks how to run, configure, or troubleshoot any openclaw command or concept, including: gateway and daemon lifecycle, setup and onboarding (interactive and headless/VPS), multi-agent setup and routing bindings, sub-agent spawning and delegation, workspace and bootstrap file management (AGENTS.md, SOUL.md, IDENTITY.md, USER.md, TOOLS.md), adding and configuring AI model providers, setting primary and fallback models, per-agent model overrides, the model allowlist, local models (Ollama/vLLM/LM Studio), custom providers via models.providers, the OpenAI-compatible HTTP endpoint (Open WebUI, LobeChat, LibreChat integration), channel login and connectivity, messaging, memory and wiki, plugins and skills, MCP servers, cron, tasks, flows, sandbox, browser automation, nodes, security audits, backups, and diagnostics. Also use for global flags (--dev, --profile, --container), command family routing, and any question about how openclaw subcommands work. --- ### 🛡️ EMERGENCY SAFETY PROTOCOL - **NO OVERWRITES:** Never use `cat`, redirection (>), or raw file writes to `openclaw.json`. Use a validated JSON utility script that loads-modifies-saves. - **SCHEMA VALIDITY:** Before adding new keys (e.g., `mcp`, `tools`), verify against official schema. Never guess keys. - **PRE-BOUNCE VERIFICATION:** 1. Validate JSON syntax (`python -m json.tool`). 2. Run `openclaw doctor`. 3. If any errors, **ABORT** the bounce. - **BACKUP INTEGRITY:** Maintain a rotating history of up to 3 validated backups (`openclaw.json.bak.1` to `.bak.3`). After a verified successful bounce, prune any backups older than 24 hours and maintain the most recent 3 verified snapshots. - **SECRET HYGIENE:** Never write credential-like patterns (`PAT`, `TOKEN`, `KEY`) into any workspace file. Before removing any existing configuration that contains keys/credentials, ensure they are secured in the environment (`~/.openclaw/credentials/.env`) first. - **EXPLICIT AUTHORIZATION:** I must never make changes to the `openclaw.json` or system configuration without *first* proposing the change, explaining the "Why," and obtaining explicit user permission. - **EXTERNAL SKILL AUDIT:** Never install a skill from ClawHub or any external repository without *first* inspecting the source code. Look specifically for: - Exfiltration of data/tokens to unknown URLs. - Malicious/damaging system commands (e.g., recursive deletion, system modifications). - Hardcoded or suspicious credential usage. Only proceed with installation once the source has been audited as benign. ## Execution Workflow 1. **Clarify the target state.** Ask what should change and what must stay untouched. 2. **Select runtime scope first.** Default profile unless isolation is explicitly needed: - `openclaw --dev ...` → isolated dev state under `~/.openclaw-dev`, gateway port `19001`. - `openclaw --profile <n> ...` → isolated state under `~/.openclaw-<n>`. - `openclaw --container <n> ...` → target a named container for execution. 3. **Route to the right command family.** Use `references/command-map.md` for quick routing. 4. **Expand subcommands before risky operations.** Run `openclaw <family> --help` for starred families; confirm flags before executing. 5. **Prefer machine-readable output for automation.** Use `--json` where available; parse and verify. 6. **Verify outcomes explicitly.** Check with `openclaw status`, `openclaw health`, `openclaw doctor`, or command-specific follow-up. ## Safety Rules - Require explicit user confirmation before `reset`, `uninstall`, destructive `--force` flows, or operations that remove stored provider keys. - Prefer non-destructive diagnostics first: `status`, `health`, `doctor`, `logs`, `security audit`. - Keep profile scope consistent across a workflow — never mix `--dev` and default in the same sequence. - For gateway issues, diagnose before restart unless restart is explicitly requested. - Keep the OpenAI HTTP endpoint on loopback/tailnet only — never expose to the public internet. ## Triage Sequence For any "OpenClaw not working" incident: 1. `openclaw status` 2. `openclaw health` 3. `openclaw doctor` 4. `openclaw security audit` (if config or provider connection settings may be misconfigured) 5. `openclaw backup verify <archive>` (if data integrity is suspected) 6. Check `openclaw gateway ...`, `openclaw channels ...`, or `openclaw nodes ...` based on where failure appears. 7. Escalate to targeted commands in `references/command-map.md`. --- ## Architecture Overview OpenClaw runs as a **single Gateway** (WebSocket, default `127.0.0.1:18789`) that: - Owns all messaging surfaces (WhatsApp/Telegram/Discord/Slack/Signal/iMessage/etc.) - Hosts one or many **agents**, each with isolated workspace + auth + session store - Exposes a **typed WS API** for CLI/app/automation clients - Optionally serves an **OpenAI-compatible HTTP surface** at the same port Clients (CLI, macOS app, web UI) connect over WebSocket. Nodes (macOS/iOS/Android/headless) also connect with `role: node`. The canvas UI is served at `/__openclaw__/canvas/`. --- ## Workspace and Bootstrap Files Each agent has a **workspace** directory (`~/.openclaw/workspace` by default) containing markdown files the agent reads on boot: | File | Purpose | |---|---| | `AGENTS.md` | Core instructions, memory, tool policy | | `SOUL.md` | Persona, tone, boundaries | | `IDENTITY.md` | Name, emoji, theme, avatar | | `USER.md` | Who the user is; preferences | | `TOOLS.md` | Tool usage notes and policies | | `HEARTBEAT.md` | Periodic check-in template | | `BOOT.md` | One-time boot ritual (delete after) | | `BOOTSTRAP.md` | Startup sequence instructions | | `MEMORY.md` + `memory/*.md` | Persistent memory store | - Missing files get a placeholder marker injected at session start; execution continues. - Size limits: `bootstrapMaxChars` (default 12 000 chars per file), `bootstrapTotalMaxChars` (default 60 000 total). - `openclaw setup --workspace <path>` recreates any missing defaults without overwriting existing ones. - Keep the workspace in a **private git repo** for backup and recovery. Never commit `~/.openclaw/` state dirs. - If `~/openclaw/` (old path) exists alongside `~/.openclaw/workspace`, keep only one active workspace to avoid auth/session drift. --- ## Agent System ### Single-Agent Mode (default) Out of the box: one agent, `agentId = main`, sessions keyed `agent:main:<mainKey>`. ### Multi-Agent Setup Each agent is a fully isolated brain: - Own workspace (`agents.defaults.workspace` or per-agent override) - Own `agentDir` (`~/.openclaw/agents/<agentId>/agent`) — holds `auth-profiles.json`, model registry, per-agent config - Own session store (`~/.openclaw/agents/<agentId>/sessions`) - **Never reuse `agentDir` across agents** — causes auth/session collisions. **Creating a new agent:** ```bash openclaw agents add coding openclaw agents add work --workspace ~/.openclaw/workspace-work --non-interactive ``` **Identity setup:** ```bash openclaw agents set-identity --agent main --name "OpenClaw" --emoji "🦞" --avatar avatars/oc.png openclaw agents set-identity --workspace ~/.openclaw/workspace --from-identity # reads IDENTITY.md ``` **Listing and verifying:** ```bash openclaw agents list openclaw agents list --bindings openclaw agents bindings --agent work ``` ### Routing Bindings Bindings route inbound messages to the correct agent. **Most-specific match wins** (priority order): 1. `peer` (exact DM/group id) 2. `parentPeer` (thread inheritance) 3. `guildId + roles` (Discord role routing) 4. `guildId` (Discord server) 5. `teamId` (Slack workspace) 6. Explicit `accountId` for a channel 7. `accountId: "*"` (channel-wide fallback, all accounts) 8. Default agent (`agents.list[].default`, else first entry, else `main`) **Managing bindings:** ```bash openclaw agents bind --agent work --bind telegram:ops --bind discord:guild-a openclaw agents unbind --agent work --bind telegram:ops openclaw agents unbind --agent work --all ``` Omitting `--agent` targets the current default. A channel-only binding (no `accountId`) is auto-upgraded to account-scoped when you later add an explicit accountId for the same channel+agent. **Config example (WhatsApp DM split):** ```json { "agents": { "list": [ { "id": "home", "default": true, "workspace": "~/.openclaw/workspace-home" }, { "id": "work", "workspace": "~/.openclaw/workspace-work" } ] }, "bindings": [ { "agentId": "home", "match": { "channel": "whatsapp", "accountId": "personal" } }, { "agentId": "work", "match": { "channel": "whatsapp", "accountId": "biz" } } ] } ``` See `references/multi-agent-recipes.md` for full Discord, Telegram, and WhatsApp examples. ### Sub-Agents Sub-agents are background agent runs spawned by the main agent to handle tasks in parallel. They run in their own isolated session (`agent:<agentId>:subagent:<uuid>`), receive only the instructions given to them (not full conversation history), and announce results back to the requester channel when done. **Key characteristics:** - Depth limit: currently flat (sub-agents cannot spawn their own sub-agents; this restriction is expected to be lifted in a future release) - Restricted tool policies relative to the parent - Auto-announce on completion (direct delivery first, falls back to queue routing, then exponential backoff) - Tracked as background tasks; inspect/control via slash commands **Slash command control:** ``` /subagents # list all background sub-agent runs /subagents spawn <agentId> <task> [--model <m>] [--thinking <level>] /focus <target> # bind current thread to a sub-agent session /unfocus # detach thread binding /session idle # inspect/update inactivity auto-unfocus /session max-age # control hard session age cap ``` **When to use sub-agents vs sessions_send:** - Sub-agent (`sessions_spawn`): need the result now, in this conversation; parallel fan-out. - `sessions_send`: fire-and-forget delegation; the other agent works independently and responds later. **Allowlist config (to let sub-agents target named agents):** ```json { "agents": { "list": [ { "id": "main", "subagents": { "allowAgents": ["coding", "research"] } } ] } } ``` --- ## Running an Agent Turn ```bash # Run via gateway (default) openclaw agent --to +15555550123 --message "Status update" --deliver openclaw agent --agent ops --message "Summarize logs" --thinking medium openclaw agent --session-id 1234 --message "Summarize inbox" --json # Run embedded (local, no gateway) openclaw agent --agent ops --message "Run locally" --local # Deliver to a different channel/account openclaw agent --agent ops --message "Generate report" \ --deliver --reply-channel slack --reply-to "#reports" ``` Key flags: `--thinking <off|minimal|low|medium|high|xhigh>`, `--verbose <on|off>`, `--timeout <seconds>`. Gateway mode falls back to embedded when the gateway request fails; `--local` forces embedded up front. --- ## OpenAI-Compatible HTTP API The Gateway can serve an OpenAI-compatible HTTP surface at the same port as WebSocket. **Disabled by default.** **Enable in `~/.openclaw/openclaw.json`:** ```json { "gateway": { "http": { "endpoints": { "chatCompletions": { "enabled": true } } } } } ``` **Endpoints (when enabled):** - `POST /v1/chat/completions` - `GET /v1/models` / `GET /v1/models/{id}` - `POST /v1/embeddings` - `POST /v1/responses` **Model field = agent target:** - `"openclaw"` or `"openclaw/default"` → configured default agent - `"openclaw/<agentId>"` → specific agent (e.g. `"openclaw/research"`) - Legacy aliases: `"openclaw:<agentId>"`, `"agent:<agentId>"` **Optional request headers:** - `x-openclaw-model: <provider/model>` — override backend model for the agent - `x-openclaw-agent-id: <agentId>` — compatibility agent override - `x-openclaw-session-key: <key>` — control session routing - `x-openclaw-message-channel: <channel>` — set synthetic ingress channel context **Session behavior:** stateless per request by default. If the request includes an OpenAI `user` string, a stable session key is derived from it so repeated calls share the same agent session. **Note:** OpenClaw's gateway token is what any connected client uses to authenticate. Keep this endpoint on loopback or a private network (tailnet/VPN) — don't expose it directly to the public internet. **Examples:** ```bash # Non-streaming curl -sS http://127.0.0.1:18789/v1/chat/completions \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"model":"openclaw/default","messages":[{"role":"user","content":"hi"}]}' # Streaming with backend model override curl -N http://127.0.0.1:18789/v1/chat/completions \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -H 'x-openclaw-model: openai/gpt-4o' \ -d '{"model":"openclaw/research","stream":true,"messages":[{"role":"user","content":"hi"}]}' # List agent targets curl -sS http://127.0.0.1:18789/v1/models \ -H 'Authorization: Bearer YOUR_TOKEN' # Embeddings curl -sS http://127.0.0.1:18789/v1/embeddings \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -H 'x-openclaw-model: openai/text-embedding-3-small' \ -d '{"model":"openclaw/default","input":["alpha","beta"]}' ``` **Open WebUI quick setup:** - Base URL: `http://127.0.0.1:18789/v1` (Docker on macOS: `http://host.docker.internal:18789/v1`) - API key: your gateway bearer token - Model: `openclaw/default` --- ## Storing provider keys outside the config file (SecretRefs) OpenClaw supports referencing provider keys via environment variables, files, or exec commands instead of writing plaintext values into `openclaw.json`. This is an OpenClaw configuration feature — the skill just explains how to set it up. | Reference type | Syntax | Example | |---|---|---| | Env variable | `secretref-env:VAR_NAME` | `secretref-env:ANTHROPIC_API_KEY` | | File path | `secretref-file:/path/to/file` | `secretref-file:~/.secrets/openai_key` | | Exec command | `secretref-exec:command` | `secretref-exec:op read op://vault/item/field` | **Set a reference via CLI:** ```bash openclaw config set providers.anthropic.key \ --ref-provider env --ref-source ANTHROPIC_API_KEY openclaw secrets configure # interactive setup wizard openclaw secrets reload # reload without gateway restart openclaw secrets audit # check all references resolve correctly openclaw secrets audit --check # non-zero exit on failures (CI use) ``` **Use ref mode during non-interactive onboard:** ```bash openclaw onboard --non-interactive \ --auth-choice anthropic-api-key \ --secret-input-mode ref \ --anthropic-api-key secretref-env:ANTHROPIC_API_KEY ``` --- ## Setup and Onboarding **Interactive (recommended for first-time):** ```bash openclaw onboard ``` **Non-interactive (VPS/headless):** ```bash openclaw onboard \ --non-interactive \ --auth-choice anthropic-api-key \ --anthropic-api-key <key> \ --gateway-bind loopback \ --install-daemon \ --daemon-runtime node \ --node-manager pnpm \ --skip-channels \ --skip-search ``` Key `--auth-choice` values: `anthropic-api-key`, `openai-api-key`, `openrouter-api-key`, `gemini-api-key`, `github-copilot`, `chutes`, `deepseek-api-key`, `custom-api-key`, `skip`. Key gateway bind modes: `loopback` (default), `lan`, `tailnet`, `auto`. For Tailscale: `--tailscale <off|serve|funnel>`. For remote gateway: `--mode remote --remote-url <url> --remote-token <token>`. --- ## Models and Providers **Read `references/models-and-providers.md` for the full reference.** It covers: model selection order, primary/fallback config, per-agent overrides, the model allowlist, custom providers, local models (Ollama/vLLM/LM Studio), multi-key rotation, how failover and cooldowns work, and sub-agent model config. **Quick orientation:** Model refs use `provider/model` format: `anthropic/claude-opus-4-6`, `openai/gpt-5.4`, `ollama/llama3.3`. ```bash # Essential commands openclaw models list # see configured models openclaw models status # primary, fallbacks, auth overview openclaw models set anthropic/claude-opus-4-6 # set primary model openclaw models set-image openai/gpt-image-1 # set image model openclaw models fallbacks add openrouter/auto # add a fallback openclaw models aliases add Opus anthropic/claude-opus-4-6 openclaw models auth login # add/re-auth a provider openclaw models auth login-github-copilot # GitHub Copilot device login openclaw models scan # find free models on OpenRouter ``` **Config: primary + fallback chain:** ```json { "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-6", "fallbacks": [ [REDACTED_SECRET], "openai/gpt-5.4" ] } } } } ``` **Config: add a custom/third-party provider** (any OpenAI-compatible API): ```json { "models": { "mode": "merge", "providers": { "my-provider": { "baseUrl": "https://api.example.com/v1", "apiKey": "${MY_PROVIDER_KEY}", "api": "openai-completions", "models": [ { "id": "my-model", "name": "My Model" } ] } } } } ``` Use `api: "anthropic-messages"` for Anthropic-compatible endpoints. After adding a provider: `openclaw config validate`, `openclaw models list --provider my-provider`, `openclaw gateway restart`. **Per-agent model** (each agent can use a different model): ```json { "agents": { "list": [ { "id": "main", "model": "anthropic/claude-opus-4-6" }, { "id": "fast", "model": "anthropic/claude-haiku-4-5" } ] } } ``` For built-in providers (Anthropic, OpenAI, Google, OpenRouter, GitHub Copilot, Mistral, xAI, DeepSeek, Ollama, and 20+ more) and their `--auth-choice` values, see `references/models-and-providers.md`. --- ## Inference CLI (`infer` / `capability`) Direct inference without a full agent run: ```bash openclaw infer list # list capabilities openclaw infer model run --model anthropic/claude-sonnet-4-6 --prompt "hi" openclaw infer image generate --prompt "a lobster in space" openclaw infer image describe path/to/image.jpg openclaw infer audio transcribe recording.mp3 openclaw infer tts convert --text "Hello" --voice nova openclaw infer web search "latest OpenClaw release" openclaw infer web fetch https://example.com openclaw infer embedding create --input "embed this text" ``` --- ## Channels ```bash openclaw channels list openclaw channels status --probe # live per-account probe openclaw channels add --channel telegram --account alerts --token $TOKEN openclaw channels add --channel discord --account work --token $DISCORD_TOKEN openclaw channels remove --channel discord --account work --delete openclaw channels login --channel whatsapp --account personal --verbose openclaw channels logout --channel whatsapp --account personal openclaw channels capabilities --channel telegram --account alerts openclaw channels logs --channel whatsapp --lines 200 ``` Supported channels: `whatsapp`, `telegram`, `discord`, `googlechat`, `slack`, `signal`, `imessage`, `msteams`, `mattermost` (plugin), and many more via plugins. DM security policies: `dmPolicy: "pairing"` (unknown senders get a code), `dmPolicy: "allowlist"` (explicit list only), `dmPolicy: "open"`. --- ## Resources Read the appropriate reference file before answering deep questions in these areas: | Reference | When to read it | |---|---| | `references/command-map.md` | Full command tree, routing quick-map, common recipes, caution commands | | `references/models-and-providers.md` | Adding providers, fallback chains, custom config, local models, auth rotation, failover | | `references/multi-agent-recipes.md` | Annotated multi-agent JSON configs (WhatsApp, Discord, Telegram, channel split) | | `references/openai-http-api.md` | Enabling the HTTP endpoint, model targeting, headers, Open WebUI setup | Live docs: `openclaw docs [query]` or `https://docs.openclaw.ai`

path: README.md
content: # OpenClaw CLI Skill

A Codex skill for operating, configuring, and troubleshooting the OpenClaw CLI safely and efficiently. Updated for OpenClaw `2026.4.x`.

## What This Skill Covers

- **Setup and onboarding** — interactive and non-interactive (`onboard`, `setup`, `configure`), including headless VPS setup with all `--auth-choice` providers and `--secret-input-mode ref` for storing provider keys as env var references instead of plaintext
- **Gateway lifecycle** — foreground, service install/start/stop/restart, `daemon`, `logs`, health probes
- **Multi-agent routing** — creating isolated agents, routing bindings (`agents add`, `agents bind`), per-agent workspace and `agentDir`, account-scoped vs channel-wide bindings, identity files
- **Sub-agent spawning** — `sessions_spawn` vs `sessions_send` patterns, depth limits, allowlist config, `/subagents` slash command control
- **Agent turns** — `agent` command flags, `--thinking`, `--deliver`, `--local`, session routing
- **OpenAI-compatible HTTP API** — enabling `POST /v1/chat/completions`, model target syntax (`openclaw/default`, `openclaw/<agentId>`), `x-openclaw-model` header, Open WebUI/LobeChat/LibreChat integration
- **Workspace bootstrap files** — `AGENTS.md`, `SOUL.md`, `IDENTITY.md`, `USER.md`, `TOOLS.md`, `HEARTBEAT.md`, size limits, git backup
- **Config file references** — storing provider keys as env var references, file paths, or exec commands (`secrets reload/audit/configure`)
- **Models and inference** — `models` full surface, `infer` CLI (image, audio, TTS, video, web, embeddings), fallback chains, multi-provider auth
- **Channels** — multi-account login, `channels add/remove/status/capabilities/resolve/logs`, DM policies
- **Memory and wiki** — `memory status/index/search/promote`, `wiki` with Obsidian integration
- **Tasks, flows, cron** — background task management, scheduled jobs
- **Plugins and skills** — install, enable/disable, marketplace, doctor
- **MCP** — serve, list, show, set/unset
- **Security and secrets** — `security audit`, `secrets audit/reload/configure/apply`, `backup create/verify`
- **Sandbox, browser, nodes** — container management, browser automation, node control (camera, canvas, location)
- **Diagnostics** — full triage sequence (`status`, `health`, `doctor`, `security audit`, `backup verify`)

## Repository Structure

```
openclaw-cli/
├── SKILL.md                          # Core skill: workflow, architecture, agent system, HTTP API, models summary
├── README.md                         # This file
├── _meta.json                        # Skill metadata
└── references/
    ├── command-map.md                # Full command tree, routing map, all recipes, caution commands
    ├── models-and-providers.md       # Models: selection, fallbacks, custom providers, local, failover, rotation
    ├── multi-agent-recipes.md        # Annotated JSON configs for multi-agent routing scenarios
    └── openai-http-api.md            # OpenAI-compatible HTTP endpoint complete reference
```

`SKILL.md` covers the most commonly needed surfaces inline. For deep dives:
- Full command syntax → `references/command-map.md`
- Models, providers, fallbacks, custom config → `references/models-and-providers.md`
- Multi-agent config examples → `references/multi-agent-recipes.md`
- HTTP API details and curl examples → `references/openai-http-api.md`

## Installation

Clone into your Codex skills directory:

```bash
mkdir -p ~/.codex/skills
git clone https://github.com/ramensushi2026/openclaw-cli-skill.git ~/.codex/skills/openclaw-cli
```

Or copy the folder so the final path is `~/.codex/skills/openclaw-cli`.

## Usage

```text
Use $openclaw-cli to set up a headless OpenClaw instance on a VPS.
Use $openclaw-cli to create a second agent bound to a Telegram bot.
Use $openclaw-cli to enable the OpenAI HTTP endpoint and connect Open WebUI.
Use $openclaw-cli to diagnose why my WhatsApp channel keeps disconnecting.
Use $openclaw-cli to configure provider keys as environment variable references instead of plaintext in the config file.
Use $openclaw-cli to spawn a sub-agent for parallel research tasks.
```

## Safety Model

- Confirms intent before `reset`, `uninstall`, `--force`, or `sandbox recreate --all`.
- Always recommends `openclaw backup create --verify` before risky operations.
- Diagnoses before restarting (uses `status`, `health`, `doctor` first).
- Keeps profile context consistent (`--dev` / `--profile` / default) across a workflow.
- Keeps the OpenAI HTTP endpoint guidance scoped to loopback/private networks — flags it should not face the public internet.

## Version History

| Version | Notes |
|---|---|
| `2.0.0` | Major update for OpenClaw 2026.4.x: multi-agent routing, sub-agents, HTTP API, SecretRefs, `infer`, `tasks`, `flows`, `wiki`, `backup`, `secrets`, `browser`, `nodes`, `mcp`, full onboard flags, workspace bootstrap files |
| `1.0.0` | Initial release — basic command families, gateway/node lifecycle, channel login, `agent`, `doctor` |

## References

- OpenClaw CLI docs: `https://docs.openclaw.ai/cli`
- Live docs search: `openclaw docs [query]`
- Gateway architecture: `https://docs.openclaw.ai/concepts/architecture`
- Multi-agent routing: `https://docs.openclaw.ai/concepts/multi-agent`
- Sub-agents: `https://docs.openclaw.ai/tools/subagents`
- OpenAI HTTP API: `https://docs.openclaw.ai/gateway/openai-http-api`


path: references/command-map.md
content: # OpenClaw CLI Command Map

## Table of Contents

1. [Global Flags](#global-flags)
2. [Command Routing Quick Map](#command-routing-quick-map)
3. [Full Command Tree](#full-command-tree)
4. [Command Families Reference](#command-families-reference)
5. [Common Recipes](#common-recipes)
6. [Caution Commands](#caution-commands)

---

## Global Flags

Apply before the command family:

```bash
openclaw [--dev] [--profile <n>] [--container <n>] <command>
```

| Flag | Effect |
|---|---|
| `--dev` | Isolate under `~/.openclaw-dev`; default gateway port `19001` |
| `--profile <n>` | Isolate under `~/.openclaw-<n>` |
| `--container <n>` | Target a named container for execution |
| `--no-color` | Disable ANSI colors (also `NO_COLOR=1`) |
| `--update` | Shorthand for `openclaw update` (source installs only) |
| `-V`, `--version`, `-v` | Print version and exit |
| `-h`, `--help` | Show help |

Always choose profile flags before the command family:
```bash
openclaw --dev status
openclaw --profile staging gateway start
```

---

## Command Routing Quick Map

| Goal | Command family |
|---|---|
| Setup / first-time onboarding | `onboard`, `setup`, `configure` |
| Interactive config wizard | `configure`, `config` (no subcommand) |
| Non-interactive config | `config get/set/unset/validate` |
| Diagnose health | `status`, `health`, `doctor`, `logs` |
| Run an agent turn | `agent` |
| Manage isolated agents | `agents` |
| Spawn/control sub-agents (in-session) | `/subagents` slash command |
| Operate gateway runtime | `gateway`, `daemon` |
| Operate headless node service | `node`, `nodes` |
| Manage channel auth/connectivity | `channels`, `pairing`, `devices`, `qr` |
| Send/read messages | `message` |
| Direct inference (no agent) | `infer` (alias: `capability`) |
| Model discovery/config | `models` |
| Memory management | `memory`, `wiki` |
| Background tasks | `tasks`, `flows` |
| Scheduled jobs | `cron` |
| Plugin/extension management | `plugins` |
| Skill management | `skills` |
| MCP server management | `mcp` |
| ACP tooling | `acp` |
| Security and policy | `security`, `approvals`, `sandbox` |
| Config file references (env vars, files, exec) | `secrets` |
| Backup / restore | `backup` |
| Browser automation | `browser` |
| Voice calls | `voicecall` (plugin, if installed) |
| System events / presence | `system` |
| Live docs search | `docs` |
| Control UI | `dashboard` |
| Terminal UI | `tui` |
| DNS helpers | `dns` |
| Contact/group directory | `directory` |
| Device pairing tokens | `devices` |
| Update CLI | `update` |
| Reset local data | `reset` |
| Full removal | `uninstall` |

For starred families (`*`), always inspect subcommands first:
```bash
openclaw <family> --help
```

---

## Full Command Tree

```
openclaw [--dev] [--profile <n>] [--container <n>] <command>

# Setup and Configuration
  setup            Initialize config + workspace
  onboard          Interactive/non-interactive full setup
  configure        Interactive configuration wizard
  config
    get <path>
    set <path> <value>
    set --ref-provider <p> --ref-source 
 --ref-id <id>   (SecretRef mode)
    set --batch-json '<json>'                                 (batch mode)
    set --batch-file <path>
    set --dry-run [--json] [--allow-exec]
    unset <path>
    file
    schema
    validate [--json]
  completion [-s <shell>] [-i]
  doctor [--repair] [--deep] [--yes] [--non-interactive]

# Updates and Maintenance
  update [--channel <stable|beta|dev>] [--tag <spec>] [--yes] [--dry-run]
  update status [--json]
  update wizard
  backup
    create [--output <path>] [--dry-run] [--verify] [--only-config]
    verify <archive>

# Dashboard and UI
  dashboard [--no-open]
  tui

# Security and Secrets
  security
    audit [--deep] [--fix]
  secrets
    reload [--url] [--token] [--timeout] [--expect-final] [--json]
    audit [--check] [--allow-exec] [--json]
    configure [--apply] [--yes] [--providers-only] [--agent <id>] [--json]
    apply --from <path> [--dry-run] [--allow-exec] [--json]
  approvals
    get
    set
    allowlist add|remove

# Gateway and Services
  gateway
    run                     (foreground)
    start | stop | restart
    install | uninstall
    service                 (alias for lifecycle subcommands)
    health
    status
    call <method> [params]
    usage-cost
    probe
    discover
  daemon                    (legacy alias for gateway service commands)
    status | install | uninstall | start | stop | restart
  logs [--lines <n>]

# Agents and Sessions
  agent
    -m/--message <text>
    -t/--to <dest>
    --session-id <id>
    --agent <id>
    --thinking <off|minimal|low|medium|high|xhigh>
    --verbose <on|off>
    --deliver
    --local
    --reply-channel <channel>
    --reply-to <target>
    --reply-account <id>
    --timeout <seconds>
    --json
  agents
    list [--bindings] [--json]
    add [name] [--workspace <dir>] [--model <id>] [--bind <ch[:acctId]>] [--non-interactive]
    bindings [--agent <id>] [--json]
    bind --agent <id> --bind <ch[:acctId]> (repeatable)
    unbind --agent <id> --bind <ch[:acctId]> | --all
    delete <id> [--force]
    set-identity [--agent <id>] [--from-identity] [--name] [--theme] [--emoji] [--avatar]
  sessions
    cleanup
  hooks
    list | info | check | enable | disable | install | update

# Inference
  infer (alias: capability)
    list
    inspect
    model run|list|inspect|providers
    model auth login|logout|status
    image generate|edit|describe|describe-many|providers
    audio transcribe|providers
    tts convert|voices|providers|status|enable|disable|set-provider
    video generate|describe|providers
    web search|fetch|providers
    embedding create|providers
    auth add|login|login-github-copilot|setup-token|paste-token
    auth order get|set|clear

# Models
  models
    list [--json]
    status
    set <model>
    set-image <model>
    aliases list|add|remove
    fallbacks list|add|remove|clear
    image-fallbacks list|add|remove|clear
    scan
    auth add|login|login-github-copilot|setup-token|paste-token
    auth order get|set|clear

# Memory and Knowledge
  memory
    status [--deep] [--fix]
    index
    search "<query>" | --query "<query>"
    promote
  wiki
    status | doctor | init | ingest | compile | lint | search | get | apply
    bridge import
    unsafe-local import
    obsidian status|search|open|command|daily

# Messaging and Channels
  message
    send --target <dest> --message <text> [--channel <ch>] [--json]
    broadcast
    poll
    react | reactions
    read | edit | delete | pin | unpin | pins
    permissions | search
    thread create|list|reply
    emoji list|upload
    sticker send|upload
    role info|add|remove
    channel info|list
    member info
    voice status
    event list|create
    timeout | kick | ban
  channels
    list [--no-usage] [--json]
    status [--probe] [--timeout <ms>] [--json]
    capabilities [--channel <n>] [--account <id>] [--target <dest>] [--json]
    resolve <entries...> [--channel <n>] [--kind <auto|user|group>] [--json]
    add [--channel <n>] [--account <id>] [--name <label>] [--token ...]
    remove [--channel <n>] [--account <id>] [--delete]
    login [--channel <ch>] [--account <id>] [--verbose]
    logout [--channel <ch>] [--account <id>]
    logs [--channel <name|all>] [--lines <n>] [--json]
  directory
    self
    peers list [--query <text>] [--limit <n>]
    groups list [--query <text>] [--limit <n>]
    groups members --group-id <id> [--limit <n>]
  pairing
    list | approve
  devices
    list | remove | clear | approve | reject | rotate | revoke
  qr
  clawbot
    qr                      (legacy alias)

# Tasks and Automation
  tasks
    list | audit | maintenance | show | notify | cancel
    flow list|show|cancel
  flows
  cron
    status | list | add | edit | rm | enable | disable | runs | run

# Plugins and Skills
  plugins
    list [--json]
    inspect <id>
    install <path|.tgz|npm-spec|plugin@marketplace> [--force]
    marketplace list <marketplace>
    enable <id> | disable <id>
    uninstall <id>
    update [<id>|--all]
    doctor
  skills
    search [query...] [--limit <n>] [--json]
    install <slug> [--version <v>] [--force]
    update <slug|--all>
    list [--verbose] [--eligible] [--json]
    info <n> [--json]
    check [--json]

# MCP and ACP
  mcp
    serve
    list [--json]
    show [name]
    set <name> <value>
    unset <name>
  acp
    client

# Sandbox
  sandbox
    list [--browser] [--json]
    recreate [--all] [--session <key>] [--agent <id>] [--browser] [--force]
    explain [--session <key>] [--agent <id>] [--json]

# System
  system
    event
    heartbeat last|enable|disable
    presence
  status
  health [--verbose]

# Node Host (headless)
  node
    run | status | install | uninstall | stop | restart
  nodes
    status | describe | list | pending | approve | reject | rename
    invoke | notify | push
    canvas snapshot|present|hide|navigate|eval
    canvas a2ui push|reset
    camera list|snap|clip
    screen record
    location get

# Browser
  browser
    status | start | stop | reset-profile
    tabs | open | focus | close
    profiles | create-profile | delete-profile
    screenshot | snapshot
    navigate | resize | click | type | press | hover | drag | select
    upload | fill | dialog | wait | evaluate | console | pdf

# Utility
  docs [query...]
  dns
    setup
  webhooks
    gmail setup|run
  update           (see above)
  reset
  uninstall
  voicecall        (plugin; if installed)
```

---

## Command Families Reference

### `gateway` ★

Run/inspect/manage the WebSocket Gateway.

```bash
openclaw gateway                     # start foreground (logs to stdout)
openclaw gateway start               # start as background service
openclaw gateway stop
openclaw gateway restart
openclaw gateway install             # register launchd/systemd
openclaw gateway uninstall
openclaw gateway health              # fetch health via RPC
openclaw gateway status              # show service state
openclaw gateway call <method>       # raw RPC call
openclaw gateway usage-cost          # token/cost summary
openclaw gateway probe               # live connectivity probe
openclaw gateway discover            # find other gateway instances
openclaw --dev gateway               # isolated dev gateway
openclaw gateway --port 18789
openclaw gateway --force             # forcefully clear port conflicts (CAUTION)
```

### `agent`

Execute one agent turn via the Gateway (or embedded with `--local`).

```bash
openclaw agent --to +15555550123 --message "Run summary" --deliver
openclaw agent --agent ops --message "Summarize inbox" --thinking high
openclaw agent --session-id 1234 --message "Continue" --json
openclaw agent --agent ops --message "Task" --deliver \
  --reply-channel slack --reply-to "#ops"
```

### `agents` ★

Manage isolated agents, auth, routing, workspaces.

```bash
openclaw agents list --bindings
openclaw agents add coding
openclaw agents add work --workspace ~/.openclaw/workspace-work --non-interactive
openclaw agents bind --agent work --bind telegram:work-bot
openclaw agents unbind --agent work --all
openclaw agents set-identity --agent main --from-identity
openclaw agents delete work --force
```

`main` cannot be added (reserved) or deleted.

### `channels` ★

Manage chat channel connections. Multi-account supported on most platforms.

```bash
openclaw channels list
openclaw channels status --probe
openclaw channels add --channel telegram --account alerts --name "Alerts" --token $TOKEN
openclaw channels login --channel whatsapp --account personal --verbose
openclaw channels capabilities --channel telegram
openclaw channels logs --channel all --lines 500
```

### `models` ★

Discover, configure, and authenticate model providers.

```bash
openclaw models list
openclaw models set anthropic/claude-sonnet-4-6
openclaw models fallbacks add openrouter/anthropic/claude-sonnet-4-6
openclaw models auth login
openclaw models auth login-github-copilot
openclaw models auth order set anthropic openrouter openai
openclaw models scan
```

### `infer` ★ (alias: `capability`)

Direct inference without a full agent session.

```bash
openclaw infer list
openclaw infer model run --model anthropic/claude-haiku-4-5 --prompt "Hello"
openclaw infer image generate --prompt "a lobster"
openclaw infer audio transcribe meeting.mp3
openclaw infer tts convert --text "Hello" --voice nova
openclaw infer web search "OpenClaw changelog"
openclaw infer embedding create --input "embed this"
```

### `config` ★

Non-interactive config helpers.

```bash
openclaw config get agents.defaults.model
openclaw config set agents.defaults.model anthropic/claude-sonnet-4-6
openclaw config set providers.openai.key --ref-provider env --ref-source OPENAI_API_KEY
openclaw config set --batch-file updates.json
openclaw config set --dry-run --json
openclaw config unset channels.slack.token
openclaw config file
openclaw config schema
openclaw config validate --json
```

### `onboard`

Interactive or non-interactive full setup.

```bash
# Interactive
openclaw onboard

# Non-interactive headless
openclaw onboard \
  --non-interactive \
  --auth-choice anthropic-api-key \
  --anthropic-api-key $ANTHROPIC_KEY \
  --gateway-bind loopback \
  --gateway-auth token \
  --install-daemon \
  --daemon-runtime node \
  --node-manager pnpm \
  --skip-channels \
  --skip-search

# With Tailscale
openclaw onboard --non-interactive --tailscale serve

# Custom provider
openclaw onboard --non-interactive \
  --auth-choice custom-api-key \
  --custom-base-url https://api.example.com/v1 \
  --custom-model-id my-model \
  --custom-api-key $CUSTOM_KEY \
  --custom-compatibility openai
```

`--auth-choice` values include: `anthropic-api-key`, `openai-api-key`, `openrouter-api-key`, `gemini-api-key`, `github-copilot`, `chutes`, `deepseek-api-key`, `kilocode-api-key`, `litellm-api-key`, `moonshot-api-key`, `venice-api-key`, `xai-api-key`, `mistral-api-key`, `qwen-api-key`, `volcengine-api-key`, `custom-api-key`, `skip`.

### `memory`

Vector search over workspace memory files.

```bash
openclaw memory status --deep
openclaw memory index
openclaw memory search "previous conversations about deployment"
openclaw memory promote                # rank and optionally append top recalls to MEMORY.md
```

### `wiki`

Workspace wiki management with optional Obsidian integration.

```bash
openclaw wiki init
openclaw wiki ingest
openclaw wiki compile
openclaw wiki search "authentication patterns"
openclaw wiki get "my-note-title"
openclaw wiki obsidian status
openclaw wiki obsidian daily
```

### `tasks`

Manage background task queue.

```bash
openclaw tasks list
openclaw tasks show <id>
openclaw tasks cancel <id>
openclaw tasks audit
openclaw tasks maintenance
openclaw tasks flow list
openclaw tasks flow cancel <id>
```

### `cron`

Manage scheduled agent jobs.

```bash
openclaw cron list
openclaw cron add --schedule "0 9 * * *" --message "Daily summary" --agent main
openclaw cron edit <id>
openclaw cron rm <id>
openclaw cron enable <id> | disable <id>
openclaw cron runs <id>
openclaw cron run <id>          # trigger immediately
```

### `plugins` ★

Manage extensions.

```bash
openclaw plugins list
openclaw plugins install my-plugin
openclaw plugins install @myorg/plugin@marketplace
openclaw plugins install ./local-plugin --force
openclaw plugins enable my-plugin
openclaw plugins disable my-plugin
openclaw plugins doctor
openclaw plugins marketplace list openclaw-marketplace
```

Most plugin changes require a gateway restart.

### `skills` ★

List and manage ClawHub skills.

```bash
openclaw skills search "github"
openclaw skills install my-skill-slug
openclaw skills install my-skill-slug --version 1.2.0 --force
openclaw skills update --all
openclaw skills list --verbose
openclaw skills info my-skill-slug
openclaw skills check
```

### `mcp`

Manage MCP (Model Context Protocol) servers.

```bash
openclaw mcp list
openclaw mcp show my-server
openclaw mcp set my-server someKey someValue
openclaw mcp unset my-server someKey
openclaw mcp serve          # start an MCP server on stdio
```

### `sandbox`

Manage isolated execution containers.

```bash
openclaw sandbox list
openclaw sandbox list --browser
openclaw sandbox recreate --all
openclaw sandbox recreate --agent coding
openclaw sandbox explain --agent coding
```

`recreate` removes existing runtimes so the next use re-seeds them from current config.

### `security`

Security tooling and config audits.

```bash
openclaw security audit             # audit config + state
openclaw security audit --deep      # best-effort live gateway probe
openclaw security audit --fix       # tighten safe defaults automatically
```

### `secrets`

Manage config file references — store provider keys as environment variable refs, file paths, or exec commands instead of plaintext in `openclaw.json`.

```bash
openclaw secrets audit
openclaw secrets audit --check          # non-zero exit on findings (CI use)
openclaw secrets reload                 # hot-reload without gateway restart
openclaw secrets configure              # interactive setup
openclaw secrets apply --from plan.json # apply a pre-built plan
openclaw secrets apply --from plan.json --dry-run
```

### `backup`

Create and verify local state archives.

```bash
openclaw backup create
openclaw backup create --output ~/backups/openclaw-$(date +%Y%m%d).tar.gz
openclaw backup create --verify                  # create and immediately verify
openclaw backup create --only-config             # config only, no workspace
openclaw backup verify my-backup.tar.gz
```

### `browser` ★

Manage and automate a dedicated browser instance.

```bash
openclaw browser status
openclaw browser start
openclaw browser navigate "https://example.com"
openclaw browser screenshot --output page.png
openclaw browser click --selector "#submit-btn"
openclaw browser type --selector "#search" --text "query"
openclaw browser evaluate --script "return document.title"
openclaw browser tabs
openclaw browser pdf --output page.pdf
```

### `nodes` ★

Manage gateway-owned node pairings (macOS/iOS/Android/headless).

```bash
openclaw nodes list
openclaw nodes status
openclaw nodes pending
openclaw nodes approve <nodeId>
openclaw nodes invoke <nodeId> <command>
openclaw nodes canvas snapshot <nodeId>
openclaw nodes camera snap <nodeId>
openclaw nodes location get <nodeId>
```

### `doctor`

Run health checks and quick fixes.

```bash
openclaw doctor
openclaw doctor --repair                  # attempt automatic repairs
openclaw doctor --deep                    # scan for extra gateway installs
openclaw doctor --yes --non-interactive   # headless / CI
```

### `status` and `health`

```bash
openclaw status             # channel health + recent recipients + provider usage
openclaw status --deep      # broader gateway health probes
openclaw health             # fetch health from running gateway
openclaw health --verbose   # live probe + expanded human-readable output
```

### `update`

```bash
openclaw update
openclaw update --channel beta
openclaw update --tag 2026.4.9
openclaw update --dry-run --json
openclaw update status
```

### `logs`

```bash
openclaw logs                     # tail gateway logs via RPC
openclaw logs --lines 500
```

---

## Common Recipes

### Full fresh setup (headless VPS with Anthropic)

```bash
npm install -g openclaw
openclaw onboard \
  --non-interactive \
  --auth-choice anthropic-api-key \
  --anthropic-api-key $ANTHROPIC_API_KEY \
  --gateway-bind loopback \
  --install-daemon \
  --node-manager pnpm \
  --skip-channels
openclaw doctor
openclaw status
```

### Add a second agent and bind to Telegram bot

```bash
openclaw agents add research --workspace ~/.openclaw/workspace-research
openclaw channels add --channel telegram --account research-bot --token $TG_TOKEN
openclaw agents bind --agent research --bind telegram:research-bot
openclaw gateway restart
openclaw agents list --bindings
```

### Enable Open WebUI via the HTTP API

```bash
# Edit ~/.openclaw/openclaw.json
openclaw config set gateway.http.endpoints.chatCompletions.enabled true
openclaw gateway restart
# Then in Open WebUI: base URL = http://127.0.0.1:18789/v1, model = openclaw/default
```

### Run a gateway locally with dev profile

```bash
openclaw --dev gateway --port 19001
openclaw --dev status
```

### Diagnose channel disconnection

```bash
openclaw status
openclaw channels status --probe
openclaw channels logs --channel all
openclaw doctor --repair
```

### Send a message with JSON output

```bash
openclaw message send --target +15555550123 --message "Hello" --json
openclaw message send --channel telegram --target @mychat --message "Hello"
```

### Run an agent turn and deliver reply

```bash
openclaw agent --to +15555550123 --message "Run daily summary" --deliver
```

### Set model failover chain

```bash
openclaw models set anthropic/claude-opus-4-6
openclaw models fallbacks add openrouter/anthropic/claude-opus-4-6
openclaw models fallbacks add openai/gpt-4o
openclaw models fallbacks list
```

### Non-destructive full diagnostic

```bash
openclaw status
openclaw health --verbose
openclaw doctor
openclaw security audit
openclaw channels status --probe
openclaw nodes status
```

### Backup before a risky operation

```bash
openclaw backup create --verify --output ~/backups/pre-update.tar.gz
openclaw update
openclaw doctor
```

---

## Caution Commands

Always confirm intent before running these:

| Command | Effect |
|---|---|
| `openclaw reset` | Destructive local state + config reset (CLI stays installed) |
| `openclaw uninstall` | Removes gateway service + all local data |
| `openclaw gateway --force` | Forcefully kills port conflicts |
| `openclaw sandbox recreate --all` | Destroys all sandbox runtimes |
| `openclaw agents delete <id> --force` | Moves workspace/state/sessions to Trash without prompting |
| `openclaw onboard --reset --reset-scope full` | Full wipe including workspace |

**Recommended pre-flight for any caution command:**
```bash
openclaw backup create --verify
```


path: references/models-and-providers.md
content: # Models and Providers

## Table of Contents

1. [How model selection works](#how-model-selection-works)
2. [Model ref format](#model-ref-format)
3. [Setting the primary model](#setting-the-primary-model)
4. [Fallback chains](#fallback-chains)
5. [Image, PDF, and generation models](#image-pdf-and-generation-models)
6. [Per-agent model overrides](#per-agent-model-overrides)
7. [Model allowlist](#model-allowlist)
8. [Switching models in chat](#switching-models-in-chat)
9. [Built-in providers](#built-in-providers)
10. [Adding a custom or third-party provider](#adding-a-custom-or-third-party-provider)
11. [Local models (Ollama, vLLM, LM Studio)](#local-models)
12. [Multi-key provider rotation](#multi-key-provider-rotation)
13. [Model failover and cooldowns](#model-failover-and-cooldowns)
14. [Sub-agent model config](#sub-agent-model-config)
15. [Scanning for free models](#scanning-for-free-models)
16. [Verifying your setup](#verifying-your-setup)

---

## How model selection works

OpenClaw selects models in this priority order for every agent run:

1. **Session override** (if the user ran `/model <ref>` in chat)
2. **Primary model** (`agents.defaults.model.primary` or `agents.defaults.model`)
3. **Fallbacks** in `agents.defaults.model.fallbacks` (in order)
4. **Provider failover** — within each candidate, OpenClaw tries additional configured keys before advancing to the next model

The key separation to understand:
- `agents.defaults.model` → **which model to use** (primary + fallback chain)
- `agents.defaults.models` → **allowlist and aliases** — if set, only listed models are available

---

## Model ref format

All model refs use `provider/model`:

```
anthropic/claude-opus-4-6
openai/gpt-5.4
google/gemini-3.1-pro-preview
openrouter/auto
ollama/llama3.3
moonshot/kimi-k2.5
```

Provider aliases normalize automatically: `z.ai/*` → `zai/*`, `openai-codex` is the provider id for the Codex login flow, etc.

For OpenRouter-style nested IDs (e.g. `moonshotai/kimi-k2`), always include the provider prefix: `openrouter/moonshotai/kimi-k2`.

---

## Setting the primary model

**Via CLI (recommended):**
```bash
openclaw models set anthropic/claude-opus-4-6
openclaw models set openai/gpt-5.4
openclaw models set openrouter/auto
```

**Via config (`~/.openclaw/openclaw.json`):**
```json
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-opus-4-6"
      }
    }
  }
}
```

Shorthand (model string directly, no primary/fallbacks object):
```json
{
  "agents": {
    "defaults": {
      "model": "anthropic/claude-opus-4-6"
    }
  }
}
```

---

## Fallback chains

Fallbacks kick in when a model fails with a failover-worthy error (rate limit, auth exhaustion, overload). Non-retryable errors (bad request, context overflow) do **not** trigger fallback.

**Via CLI:**
```bash
openclaw models fallbacks list
openclaw models fallbacks add openrouter/anthropic/claude-opus-4-6
openclaw models fallbacks add openai/gpt-4o
openclaw models fallbacks remove openai/gpt-4o
openclaw models fallbacks clear
```

**Via config:**
```json
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-opus-4-6",
        "fallbacks": [
          "openrouter/anthropic/claude-opus-4-6",
          "openai/gpt-5.4",
          "openrouter/auto"
        ]
      }
    }
  }
}
```

**Fallback resolution rules:**
- Per-provider key rotation happens inside each candidate before advancing to the next.
- If the current run is on an override model not in the configured chain, OpenClaw appends the configured primary at the end so it can settle back to the default once earlier candidates are exhausted.
- If every candidate fails, a `FallbackSummaryError` is thrown with per-attempt detail and the soonest cooldown expiry.

**Recommended strategy:**
- Primary: best/strongest model you have access to.
- First fallback: same model on a proxy (e.g. OpenRouter) for redundancy.
- Second fallback: a faster/cheaper model as a cost backstop.
- Third fallback: `openrouter/auto` as a catch-all.

---

## Image, PDF, and generation models

```bash
openclaw models set-image openai/gpt-image-1     # vision model when primary can't accept images
openclaw models image-fallbacks add google/gemini-3.1-pro-preview

openclaw models set-image-generation openai/gpt-image-1   # image generation
```

Via config:
```json
{
  "agents": {
    "defaults": {
      "model": { "primary": "anthropic/claude-opus-4-6" },
      "imageModel": { "primary": "openai/gpt-5.4", "fallbacks": ["google/gemini-3.1-pro-preview"] },
      "pdfModel": "anthropic/claude-sonnet-4-6",
      "imageGenerationModel": "openai/gpt-image-1"
    }
  }
}
```

- `imageModel` is used only when the primary model cannot accept image inputs.
- `pdfModel` is used by the pdf tool. Falls back to `imageModel`, then the resolved session model.
- `imageGenerationModel` is used by the `image_generate` capability.

---

## Per-agent model overrides

Each agent in `agents.list` can have its own model, independently of global defaults:

```json
{
  "agents": {
    "defaults": {
      "model": { "primary": "anthropic/claude-sonnet-4-6" }
    },
    "list": [
      {
        "id": "main",
        "model": "anthropic/claude-opus-4-6"
      },
      {
        "id": "fast",
        "workspace": "~/.openclaw/workspace-fast",
        "model": "anthropic/claude-haiku-4-5"
      },
      {
        "id": "research",
        "workspace": "~/.openclaw/workspace-research",
        "model": {
          "primary": "anthropic/claude-opus-4-6",
          "fallbacks": ["openrouter/anthropic/claude-opus-4-6"]
        }
      }
    ]
  }
}
```

You can also set a per-agent default thinking level:
```json
{
  "id": "deep",
  "model": "anthropic/claude-opus-4-6",
  "thinkingDefault": "high"
}
```

---

## Model allowlist

If `agents.defaults.models` is set, it becomes an **allowlist** — only listed models are eligible for `/model` switching and session overrides. Users trying to pick an unlisted model see:

```
Model "provider/model" is not allowed. Use /model to list available models.
```

Use this to prevent unintended model drift in production setups.

```json
{
  "agents": {
    "defaults": {
      "model": { "primary": "anthropic/claude-sonnet-4-6" },
      "models": {
        "anthropic/claude-sonnet-4-6": { "alias": "Sonnet" },
        "anthropic/claude-opus-4-6": { "alias": "Opus" },
        "anthropic/claude-haiku-4-5": { "alias": "Haiku" },
        "openrouter/auto": { "alias": "auto" }
      }
    }
  }
}
```

- Aliases let users pick models by short name in chat (`/model Sonnet`).
- An empty `models.defaults.models` object (omitted) means all configured models are available.
- Per-agent `agents.list[].skills` can override the global model list.

**Managing aliases via CLI:**
```bash
openclaw models aliases list
openclaw models aliases add Sonnet anthropic/claude-sonnet-4-6
openclaw models aliases remove Sonnet
```

---

## Switching models in chat

Users can switch models per-session without restarting:

```
/model                        # interactive picker
/model list                   # numbered list
/model 3                      # pick by number
/model openai/gpt-5.4         # pick by ref
/model Sonnet                 # pick by alias
/model status                 # detailed view: auth candidates, endpoint info
```

On Discord, `/model` and `/models` open an interactive picker with provider and model dropdowns.

**Live switch behavior:**
- If the agent is idle, the next run uses the new model immediately.
- If a run is already active, the switch is queued and takes effect at the next clean retry point.
- Once tool activity or reply output has started, the queued switch waits until the next user turn.

---

## Built-in providers

These require **no** `models.providers` config entry. Run `openclaw onboard` or set the relevant env var on the machine running OpenClaw, then pick a model ref.

| Provider | Provider ID | How OpenClaw connects | Example model | `--auth-choice` for onboard |
|---|---|---|---|---|
| Anthropic | `anthropic` | `ANTHROPIC_API_KEY` env var | `anthropic/claude-opus-4-6` | `anthropic-api-key` |
| OpenAI | `openai` | `OPENAI_API_KEY` env var | `openai/gpt-5.4` | `openai-api-key` |
| OpenAI Codex | `openai-codex` | device login flow via `openclaw models auth login` | `openai-codex/gpt-5.4` | `openai-codex` |
| Google Gemini | `google` | `GEMINI_API_KEY` env var | `google/gemini-3.1-pro-preview` | `gemini-api-key` |
| Google Vertex | `google-vertex` | gcloud login on the gateway host | `google-vertex/gemini-3.1-pro` | — |
| Google Gemini CLI | `google-gemini-cli` | device login flow via `openclaw models auth login` | `google-gemini-cli/gemini-3-flash-preview` | `google-gemini-cli` |
| OpenRouter | `openrouter` | `OPENROUTER_API_KEY` env var | `openrouter/auto` | `openrouter-api-key` |
| GitHub Copilot | `github-copilot` | device login flow via `openclaw models auth login-github-copilot` | `github-copilot/claude-sonnet-4-6` | `github-copilot` |
| OpenCode Zen | `opencode` | `OPENCODE_API_KEY` env var | `opencode/claude-opus-4-6` | `opencode-zen` |
| OpenCode Go | `opencode-go` | `OPENCODE_API_KEY` env var | `opencode-go/kimi-k2.5` | `opencode-go` |
| Mistral | `mistral` | `MISTRAL_API_KEY` env var | `mistral/mistral-large` | `mistral-api-key` |
| xAI (Grok) | `xai` | `XAI_API_KEY` env var | `xai/grok-3` | `xai-api-key` |
| DeepSeek | `deepseek` | `DEEPSEEK_API_KEY` env var | `deepseek/deepseek-r1` | `deepseek-api-key` |
| Z.AI (GLM) | `zai` | `ZAI_API_KEY` env var | `zai/glm-5.1` | `zai-api-key` |
| Kilo Gateway | `kilocode` | `KILOCODE_API_KEY` env var | `kilocode/kilo/auto` | `kilocode-api-key` |
| Vercel AI Gateway | `vercel-ai-gateway` | `AI_GATEWAY_API_KEY` env var | `vercel-ai-gateway/anthropic/claude-opus-4.6` | `ai-gateway-api-key` |
| Moonshot (Kimi) | `kimi` | `KIMI_API_KEY` env var | `kimi/kimi-k2.5` | `kimi-code-api-key` |
| MiniMax | `minimax` | device login or `MINIMAX_API_KEY` env var | `minimax/abab7-chat` | `minimax-global-api` |
| Qwen | `qwen` | device login or `QWEN_API_KEY` env var | `qwen/qwen-max` | `qwen-api-key` |
| Chutes | `chutes` | `CHUTES_API_KEY` env var | `chutes/deepseek-v3` | `chutes` |
| Venice | `venice` | `VENICE_API_KEY` env var | `venice/llama-3.3-70b` | `venice-api-key` |
| Together | `together` | `TOGETHER_API_KEY` env var | `together/llama-3.3-70b` | `together-api-key` |
| HuggingFace | `huggingface` | `HUGGINGFACE_HUB_TOKEN` env var | [REDACTED_SECRET] | `huggingface-api-key` |
| Ollama (local) | `ollama` | `OLLAMA_API_KEY` env var (any value enables auto-detection) | `ollama/llama3.3` | via plugin |
| vLLM (local) | `vllm` | `VLLM_API_KEY` env var (any value enables auto-detection) | `vllm/my-model` | via plugin |

**Connecting a provider via the onboard wizard:**
```bash
openclaw onboard                                      # interactive — picks up where you are
openclaw models auth login                            # add or re-authenticate any provider interactively
openclaw models auth login-github-copilot             # GitHub Copilot device login flow
openclaw models auth login --provider google-gemini-cli
openclaw models auth order set anthropic openrouter openai  # set provider priority order
```

---

## Adding a custom or third-party provider

Use `models.providers` in `openclaw.json` for any OpenAI-compatible or Anthropic-compatible API.

**When to use `models.providers`:**
- The provider is not in OpenClaw's built-in catalog
- You have a self-hosted inference server (vLLM, LiteLLM, LM Studio)
- You want to use a specific provider endpoint or relay
- You want to add models before official support arrives

**Config structure:**
```json
{
  "models": {
    "mode": "merge",
    "providers": {
      "<provider-id>": {
        "baseUrl": "https://api.example.com/v1",
        "apiKey": "${MY_API_KEY}",
        "api": "openai-completions",
        "models": [
          { "id": "my-model-id", "name": "My Model", "contextWindow": 128000 }
        ]
      }
    }
  }
}
```

**Key fields:**

| Field | Values | Notes |
|---|---|---|
| `baseUrl` | URL string | Base API endpoint (no trailing `/chat/completions`) |
| `apiKey` | string or `${ENV_VAR}` | Use `${ENV_VAR}` to reference an env var |
| `api` | `openai-completions` or `anthropic-messages` | Use `openai-completions` for any `/v1/chat/completions` API |
| `models[].id` | string | The model id sent to the provider |
| `models[].name` | string | Display name |
| `models[].contextWindow` | number | Native context window (metadata) |
| `models[].contextTokens` | number | Effective runtime cap (overrides contextWindow) |

**Use `"mode": "merge"`** (default) — OpenClaw merges your providers into `models.json` alongside built-ins. Use `"replace"` only if you want to remove all built-in providers.

**OpenAI-compatible example (Moonshot / Kimi K2.5):**
```json
{
  "models": {
    "mode": "merge",
    "providers": {
      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
        "models": [
          { "id": "kimi-k2.5", "name": "Kimi K2.5", "contextWindow": 131072 },
          { "id": "kimi-k2-thinking", "name": "Kimi K2 Thinking" }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": { "primary": "moonshot/kimi-k2.5" }
    }
  }
}
```

**LiteLLM proxy (OpenAI-compatible, multiple upstream providers):**
```json
{
  "models": {
    "mode": "merge",
    "providers": {
      "litellm": {
        "baseUrl": "http://localhost:4000/v1",
        "apiKey": "${LITELLM_MASTER_KEY}",
        "api": "openai-completions",
        "models": [
          { "id": "claude-opus-4-6", "name": "Claude Opus via LiteLLM" },
          { "id": "gpt-5.4", "name": "GPT-5.4 via LiteLLM" }
        ]
      }
    }
  }
}
```

**Private vLLM server (openai-compatible):**
```json
{
  "models": {
    "mode": "merge",
    "providers": {
      "my-vllm": {
        "baseUrl": "http://10.0.0.5:8000/v1",
        "apiKey": "token-from-vllm",
        "api": "openai-completions",
        "models": [
          { "id": "Qwen/Qwen2.5-72B-Instruct", "name": "Qwen 2.5 72B" }
        ]
      }
    }
  }
}
```

**After adding a custom provider, always add to allowlist and verify:**
```bash
openclaw config validate
openclaw models list --provider moonshot
openclaw models set moonshot/kimi-k2.5
openclaw gateway restart
openclaw models status
```

---

## Local models

### Ollama

Ollama is auto-detected at `http://127.0.0.1:11434`. Set any value for `OLLAMA_API_KEY` to opt in to auto-discovery:

```bash
export OLLAMA_API_KEY=ollama
openclaw plugins enable ollama   # if not already enabled
openclaw models list --local
openclaw models set ollama/llama3.3
```

Custom config (if Ollama runs on a different host/port):
```json
{
  "models": {
    "mode": "merge",
    "providers": {
      "ollama": {
        "baseUrl": "http://10.0.0.10:11434/v1",
        "apiKey": "ollama",
        "api": "openai-completions",
        "models": [
          { "id": "qwen3.5:32b", "name": "Qwen 3.5 32B" },
          { "id": "llama3.3:latest", "name": "Llama 3.3" }
        ]
      }
    }
  }
}
```

**Ollama model management:**
```bash
ollama pull llama3.3        # pull a model before using it in OpenClaw
ollama list                 # list downloaded models
openclaw models scan --provider ollama --no-probe
```

### vLLM and SGLang

Default ports: vLLM `8000`, SGLang `30000`. Set `VLLM_API_KEY` (any value) to opt in:
```bash
export VLLM_API_KEY=any-value
openclaw models list --local
```

Or configure explicitly (see vLLM example above under custom providers).

### LM Studio

LM Studio exposes an OpenAI-compatible endpoint at `http://127.0.0.1:1234/v1`:
```json
{
  "models": {
    "providers": {
      "lmstudio": {
        "baseUrl": "http://127.0.0.1:1234/v1",
        "apiKey": "lm-studio",
        "api": "openai-completions",
        "models": [
          { "id": "loaded-model-name", "name": "My LM Studio Model" }
        ]
      }
    }
  }
}
```

---

## Multi-key provider rotation

OpenClaw can automatically rotate between multiple provider keys when one hits a rate limit (429, quota exceeded). This is configured on the machine running OpenClaw, not inside this skill. Non-rate-limit errors fail immediately without rotation.

**Environment variable naming patterns OpenClaw recognises:**

```bash
# Single key
ANTHROPIC_API_KEY="sk-ant-key1"

# Multiple keys (comma or semicolon separated)
ANTHROPIC_API_KEYS="sk-ant-key1,sk-ant-key2,sk-ant-key3"

# Numbered keys
ANTHROPIC_API_KEY_1="sk-ant-key1"
ANTHROPIC_API_KEY_2="sk-ant-key2"

# Single live override (highest priority)
OPENCLAW_LIVE_ANTHROPIC_KEY="sk-ant-override"
```

Same naming pattern applies to other providers: `OPENAI_API_KEYS`, `OPENROUTER_API_KEYS`, `GEMINI_API_KEYS`, etc.

**View and adjust provider priority:**
```bash
openclaw models auth order get
openclaw models auth order set anthropic openrouter openai
```

---

## How failover and cooldowns work

When a model run fails, OpenClaw works through its candidate chain automatically. This section describes that behaviour so you can configure it correctly.

**Sequence for a single run:**
1. Try primary model with the first configured key/profile for that provider.
2. On rate limit: try the next key/profile for the same provider.
3. When all profiles for that model are exhausted: advance to the next model in the fallback list.
4. Repeat until a model succeeds or every candidate fails.

**Cooldown behaviour:**
- Rate-limited profiles are cooled down with exponential backoff before retrying.
- Persistent failures (e.g. billing holds): backoff starts at 5 hours, doubles per failure, caps at 24 hours. Counter resets after 24 hours clean.
- Overloaded responses: one same-provider key rotation is tried before moving to the next fallback model.
- Cooldown state is stored in `~/.openclaw/agents/<agentId>/agent/auth-state.json` on the machine running OpenClaw.

**Inspect the current state:**
```bash
openclaw models status          # shows primary, fallbacks, and any provider warnings
openclaw models status --check  # non-zero exit if any provider is missing or expiring (CI use)
openclaw health --verbose       # broader gateway and provider health view
```

**Force a specific model for the current session:**
```
/model anthropic/claude-opus-4-6
```

---

## Sub-agent model config

Sub-agents inherit the calling agent's model by default. To use a cheaper model for background work:

```json
{
  "agents": {
    "defaults": {
      "subagents": {
        "model": "anthropic/claude-haiku-4-5",
        "thinking": "minimal"
      }
    }
  }
}
```

Per-agent override:
```json
{
  "agents": {
    "list": [
      {
        "id": "main",
        "subagents": {
          "model": "anthropic/claude-sonnet-4-6",
          "thinking": "low",
          "runTimeoutSeconds": 120
        }
      }
    ]
  }
}
```

A `model` passed directly in `sessions_spawn` always wins over these defaults.

---

## Scanning for free models

`openclaw models scan` inspects OpenRouter's free model catalog and ranks candidates for use as fallbacks:

```bash
openclaw models scan                         # interactive scan (requires OPENROUTER_API_KEY)
openclaw models scan --no-probe              # metadata only, no live probes
openclaw models scan --min-params 7          # filter to >=7B parameter models
openclaw models scan --max-age-days 60       # skip models older than 60 days
openclaw models scan --set-default           # set top result as primary
openclaw models scan --max-candidates 3 --yes  # non-interactive, accept top 3
```

Scan rankings: image support → tool latency → context size → parameter count.

---

## Verifying your setup

```bash
openclaw models list              # all configured models
openclaw models list --all        # full catalog including built-ins
openclaw models list --local      # local providers only
openclaw models status            # primary, fallbacks, image model, auth overview
openclaw models status --check    # CI-friendly: non-zero if auth missing or expiring
openclaw config validate          # validate the full config including models.providers
```

**Debug tip:** start minimal when adding a custom provider — `baseUrl`, `apiKey`, `api`, and one model. Verify with `openclaw models list --provider <id>`. Add more models and params only after the basic connection works. Never edit `~/.openclaw/agents/<agentId>/agent/models.json` directly — it is regenerated from `openclaw.json`.


path: references/openai-http-api.md
content: # OpenAI-Compatible HTTP API

OpenClaw's Gateway can serve an OpenAI-compatible HTTP surface at the same port as the WebSocket. **Disabled by default.**

## Enable

Add to `~/.openclaw/openclaw.json`:

```json
{
  "gateway": {
    "http": {
      "endpoints": {
        "chatCompletions": { "enabled": true }
      }
    }
  }
}
```

Or via CLI:
```bash
openclaw config set gateway.http.endpoints.chatCompletions.enabled true
openclaw gateway restart
```

## Endpoints (when enabled)

| Method | Path | Purpose |
|---|---|---|
| `POST` | `/v1/chat/completions` | Chat completions (OpenAI-compatible) |
| `GET` | `/v1/models` | List agent targets |
| `GET` | `/v1/models/{id}` | Get single agent target |
| `POST` | `/v1/embeddings` | Embeddings |
| `POST` | `/v1/responses` | OpenResponses-compatible endpoint |

All run on the same port as the Gateway WebSocket (default `18789`).

## Gateway token

The HTTP endpoint uses the same token as your OpenClaw gateway. Send it as a bearer token on every request:

```
Authorization: Bearer <your-gateway-token>
```

Gateway token config modes (set in `openclaw.json`):
- `gateway.auth.mode="token"`: token comes from `gateway.auth.token` or the `OPENCLAW_GATEWAY_TOKEN` env var
- `gateway.auth.mode="password"`: password comes from `gateway.auth.password` or `OPENCLAW_GATEWAY_PASSWORD`
- `gateway.auth.mode="none"`: no token needed (only appropriate on a private/loopback interface)

Keep this endpoint on loopback or a private network — not exposed to the public internet.

## Model Field = Agent Target

The OpenAI `model` field is treated as an **agent target**, not a raw provider model id:

| `model` value | Routes to |
|---|---|
| `"openclaw"` | Configured default agent |
| `"openclaw/default"` | Configured default agent (stable alias) |
| `"openclaw/<agentId>"` | Specific agent (e.g. `"openclaw/research"`) |
| `"openclaw:<agentId>"` | Legacy alias (still supported) |
| `"agent:<agentId>"` | Legacy alias (still supported) |

`openclaw/default` is always stable even if the real default agent id changes between environments.

## Optional Request Headers

| Header | Effect |
|---|---|
| `x-openclaw-model: <provider/model>` | Override backend model for the selected agent |
| `x-openclaw-agent-id: <agentId>` | Compatibility agent override |
| `x-openclaw-session-key: <key>` | Fully control session routing |
| `x-openclaw-message-channel: <ch>` | Set synthetic ingress channel context |

`x-openclaw-model` examples: `openai/gpt-4o`, `anthropic/claude-opus-4-6`, `gpt-4o` (bare alias).

## Session Behavior

- **Default:** stateless per request — a new session key is generated each call.
- **With `user` field:** if the request includes an OpenAI `user` string, the Gateway derives a stable session key from it, so repeated calls share the same agent session.

## Streaming

Set `"stream": true` to receive Server-Sent Events (SSE):
- `Content-Type: text/event-stream`
- Each event line: `data: <json>`
- Stream ends: `data: [DONE]`

## Examples

### Non-streaming chat completion

```bash
curl -sS http://127.0.0.1:18789/v1/chat/completions \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "openclaw/default",
    "messages": [{"role":"user","content":"hi"}]
  }'
```

### Streaming with backend model override

```bash
curl -N http://127.0.0.1:18789/v1/chat/completions \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'x-openclaw-model: anthropic/claude-opus-4-6' \
  -d '{
    "model": "openclaw/research",
    "stream": true,
    "messages": [{"role":"user","content":"Explain the gateway architecture"}]
  }'
```

### Target a specific agent

```bash
curl -sS http://127.0.0.1:18789/v1/chat/completions \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "openclaw/coding",
    "messages": [{"role":"user","content":"Review this PR"}]
  }'
```

### Stable session (using `user` field)

```bash
curl -sS http://127.0.0.1:18789/v1/chat/completions \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "openclaw/default",
    "user": "my-stable-session-id",
    "messages": [{"role":"user","content":"Remember what we discussed?"}]
  }'
```

### List agent targets

```bash
curl -sS http://127.0.0.1:18789/v1/models \
  -H 'Authorization: Bearer YOUR_TOKEN'
```

Returns `openclaw`, `openclaw/default`, and `openclaw/<agentId>` entries. Not raw provider catalogs.

### Get a single agent target

```bash
curl -sS http://127.0.0.1:18789/v1/models/openclaw%2Fdefault \
  -H 'Authorization: Bearer YOUR_TOKEN'
```

### Embeddings

```bash
curl -sS http://127.0.0.1:18789/v1/embeddings \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'x-openclaw-model: openai/text-embedding-3-small' \
  -d '{
    "model": "openclaw/default",
    "input": ["embed this text", "and this one too"]
  }'
```

`input` can be a string or array of strings. Use `x-openclaw-model` to specify the embedding model; without it, the agent's normal embedding setup is used.

## Open WebUI Quick Setup

1. Base URL: `http://127.0.0.1:18789/v1`
   - Docker on macOS: `http://host.docker.internal:18789/v1`
2. API key: your gateway bearer token
3. Model: `openclaw/default`

Smoke test first:
```bash
curl -sS http://127.0.0.1:18789/v1/models -H 'Authorization: Bearer YOUR_TOKEN'
```

If `openclaw/default` is in the response, Open WebUI (and most other compatible frontends) will connect without extra config.

## Notes

- `/v1/models` lists OpenClaw agent targets — not raw provider model catalogs.
- Sub-agents are internal execution topology and do not appear as pseudo-models.
- Backend provider/model overrides belong in `x-openclaw-model`, not the OpenAI `model` field.
- Requests are executed as normal Gateway agent runs — same codepath as `openclaw agent`.


path: references/multi-agent-recipes.md
content: # Multi-Agent Recipes

Practical configuration examples for running multiple agents in one Gateway.

## Concepts Recap

| Term | Meaning |
|---|---|
| `agentId` | One isolated brain (workspace, auth, sessions) |
| `accountId` | One channel account (e.g. `"personal"` WhatsApp vs `"biz"`) |
| `binding` | Routes `(channel, accountId, peer)` inbound to an `agentId` |
| `agentDir` | `~/.openclaw/agents/<agentId>/agent` — auth profiles, model registry |

**Never reuse `agentDir` across agents.** Never share `auth-profiles.json` between agents without deliberately copying it.

---

## Recipe 1: Two WhatsApp Accounts → Two Agents

```bash
# Link both accounts first
openclaw channels login --channel whatsapp --account personal
openclaw channels login --channel whatsapp --account biz
```

`~/.openclaw/openclaw.json`:
```json
{
  "agents": {
    "list": [
      {
        "id": "home",
        "default": true,
        "name": "Home",
        "workspace": "~/.openclaw/workspace-home",
        "agentDir": "~/.openclaw/agents/home/agent"
      },
      {
        "id": "work",
        "name": "Work",
        "workspace": "~/.openclaw/workspace-work",
        "agentDir": "~/.openclaw/agents/work/agent"
      }
    ]
  },
  "bindings": [
    { "agentId": "home", "match": { "channel": "whatsapp", "accountId": "personal" } },
    { "agentId": "work", "match": { "channel": "whatsapp", "accountId": "biz" } },
    {
      "agentId": "work",
      "match": {
        "channel": "whatsapp",
        "accountId": "personal",
        "peer": { "kind": "group", "id": "[REDACTED_SECRET]" }
      }
    }
  ],
  "channels": {
    "whatsapp": {
      "accounts": {
        "personal": {},
        "biz": {}
      }
    }
  }
}
```

---

## Recipe 2: WhatsApp DM Split (One Number → Multiple Agents)

Route different phone numbers to different agents on the same WhatsApp account.

```json
{
  "agents": {
    "list": [
      { "id": "alex", "workspace": "~/.openclaw/workspace-alex" },
      { "id": "mia", "workspace": "~/.openclaw/workspace-mia" }
    ]
  },
  "bindings": [
    {
      "agentId": "alex",
      "match": { "channel": "whatsapp", "peer": { "kind": "direct", "id": "+15551230001" } }
    },
    {
      "agentId": "mia",
      "match": { "channel": "whatsapp", "peer": { "kind": "direct", "id": "+15551230002" } }
    }
  ],
  "channels": {
    "whatsapp": {
      "dmPolicy": "allowlist",
      "allowFrom": ["+15551230001", "+15551230002"]
    }
  }
}
```

Notes:
- DM access control is global per WhatsApp account (not per agent).
- Direct chats collapse to `agent:<agentId>:main` — true isolation requires one agent per person.

---

## Recipe 3: Discord — One Bot Per Agent

```json
{
  "agents": {
    "list": [
      { "id": "main", "workspace": "~/.openclaw/workspace-main" },
      { "id": "coding", "workspace": "~/.openclaw/workspace-coding" }
    ]
  },
  "bindings": [
    { "agentId": "main", "match": { "channel": "discord", "accountId": "default" } },
    { "agentId": "coding", "match": { "channel": "discord", "accountId": "coding" } }
  ],
  "channels": {
    "discord": {
      "groupPolicy": "allowlist",
      "accounts": {
        "default": {
          "token": "DISCORD_BOT_TOKEN_MAIN",
          "guilds": {
            "123456789012345678": {
              "channels": {
                "222222222222222222": { "allow": true, "requireMention": false }
              }
            }
          }
        },
        "coding": {
          "token": "DISCORD_BOT_TOKEN_CODING",
          "guilds": {
            "123456789012345678": {
              "channels": {
                "333333333333333333": { "allow": true, "requireMention": false }
              }
            }
          }
        }
      }
    }
  }
}
```

Each Discord bot account needs its token at `channels.discord.accounts.<id>.token`. Invite each bot to the guild and enable Message Content Intent in the Discord developer portal.

---

## Recipe 4: Telegram — One Bot Per Agent

```json
{
  "agents": {
    "list": [
      { "id": "main", "workspace": "~/.openclaw/workspace-main" },
      { "id": "alerts", "workspace": "~/.openclaw/workspace-alerts" }
    ]
  },
  "bindings": [
    { "agentId": "main", "match": { "channel": "telegram", "accountId": "default" } },
    { "agentId": "alerts", "match": { "channel": "telegram", "accountId": "alerts" } }
  ],
  "channels": {
    "telegram": {
      "accounts": {
        "default": {
          "botToken": "123456:ABC...",
          "dmPolicy": "pairing"
        },
        "alerts": {
          "botToken": "987654:XYZ...",
          "dmPolicy": "allowlist",
          "allowFrom": ["tg:123456789"]
        }
      }
    }
  }
}
```

---

## Recipe 5: Channel Split (WhatsApp Fast + Telegram Deep)

Route WhatsApp to a fast everyday agent and Telegram to a higher-reasoning agent.

```json
{
  "agents": {
    "list": [
      {
        "id": "chat",
        "name": "Everyday",
        "workspace": "~/.openclaw/workspace-chat",
        "model": "anthropic/claude-haiku-4-5"
      },
      {
        "id": "deep",
        "name": "Deep Work",
        "workspace": "~/.openclaw/workspace-deep",
        "model": "anthropic/claude-opus-4-6"
      }
    ]
  },
  "bindings": [
    { "agentId": "chat", "match": { "channel": "whatsapp" } },
    { "agentId": "deep", "match": { "channel": "telegram" } }
  ]
}
```

To also route a specific WhatsApp DM to the deep agent:
```json
{
  "bindings": [
    {
      "agentId": "deep",
      "match": { "channel": "whatsapp", "peer": { "kind": "direct", "id": "+15551234567" } }
    },
    { "agentId": "chat", "match": { "channel": "whatsapp" } },
    { "agentId": "deep", "match": { "channel": "telegram" } }
  ]
}
```

Peer bindings always win over channel-wide rules.

---

## Recipe 6: Agent-to-Agent Messaging (Explicit Enable)

Off by default. Must be explicitly enabled and allowlisted:

```json
{
  "tools": {
    "agentToAgent": {
      "enabled": true,
      "allow": ["main", "coding", "research"]
    }
  }
}
```

---

## Recipe 7: Sub-Agent Allowlist for Named Agents

Allow the `main` agent to spawn specific configured agents as sub-agents:

```json
{
  "agents": {
    "list": [
      {
        "id": "main",
        "workspace": "~/.openclaw/workspace-main",
        "subagents": {
          "allowAgents": ["coding", "research"]
        }
      },
      { "id": "coding", "workspace": "~/.openclaw/workspace-coding" },
      { "id": "research", "workspace": "~/.openclaw/workspace-research" }
    ]
  }
}
```

Use `["*"]` to allow any configured agent.

---

## Recipe 8: Per-Agent Model Override

Each agent can use a different model regardless of the global default:

```json
{
  "agents": {
    "defaults": {
      "model": "anthropic/claude-sonnet-4-6"
    },
    "list": [
      { "id": "main" },
      {
        "id": "heavy",
        "workspace": "~/.openclaw/workspace-heavy",
        "model": "anthropic/claude-opus-4-6"
      },
      {
        "id": "fast",
        "workspace": "~/.openclaw/workspace-fast",
        "model": "anthropic/claude-haiku-4-5"
      }
    ]
  }
}
```

---

## Recipe 9: Cross-Agent Memory Search

Let one agent search another agent's session transcripts:

```json
{
  "agents": {
    "list": [
      {
        "id": "main",
        "workspace": "~/.openclaw/workspace-main",
        "memorySearch": {
          "qmd": {
            "extraCollections": [
              { "path": "~/.openclaw/agents/coding/sessions", "name": "coding-sessions" }
            ]
          }
        }
      },
      { "id": "coding", "workspace": "~/.openclaw/workspace-coding" }
    ]
  }
}
```

---

## Verify Everything

After any multi-agent config change:

```bash
openclaw gateway restart
openclaw agents list --bindings
openclaw channels status --probe
openclaw health --verbose
```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)