OpenClaw Runbook

Chapter 8 of 8 · 10 min read

Config Reference

An annotated openclaw.json walkthrough, a sanitized production config, file structure, custom providers and a post-setup checklist.

01Quick start #

The sanitized config lives in the original runbook repository. The snippets below are updated to the current config schema; if your copy predates it, openclaw doctor --fix migrates most legacy keys for you.

  1. 1Copy the sanitized configcp sanitized-config.json ~/.openclaw/openclaw.json
  2. 2Replace all placeholders<YOUR_*> → real tokens, or ${ENV_VAR} references
  3. 3Validate the schemaopenclaw config validate
  4. 4Migrate legacy keys and repair stateopenclaw doctor --fix
  5. 5Security auditopenclaw security audit --deep

02Model configuration agents.defaults.model#

The coordinator vs worker pattern:

  • Keep the most expensive models (Opus) out of the primary slot
  • Use a capable but not overkill model as your default, with cheap fallbacks
  • Pin strong models to specific agents, or switch to them per session with an alias
  • Point utilityModel at a small model: it handles titles, recaps and other short internal tasks
openclaw.json · model defaults
"agents": {
  "defaults": {
    "model": {
      "primary": "anthropic/claude-sonnet-5-5",
      "fallbacks": [
        "kimi/k3-256k",
        "zai/glm-5.3",
        "openai/gpt-6-luna",
        "google/gemini-3.5-flash-lite"
      ]
    },
    "utilityModel": "openai/gpt-6-luna",
    "models": {
      "anthropic/claude-haiku-5-5": { "alias": "haiku" },
      "anthropic/claude-sonnet-5-5": { "alias": "sonnet" },
      "anthropic/claude-opus-5-5": { "alias": "opus" },
      "openai/gpt-6-luna": { "alias": "luna" },
      "kimi/k3-256k": { "alias": "kimi" }
    }
  }
}

03Named agents #

Each agent is an entry under agents.entries, keyed by its id, with its own workspace. The agent's instructions live in that workspace's AGENTS.md.

openclaw.json · agent entries
"agents": {
  "entries": {
    "main": {
      "workspace": "~/.openclaw/workspace",
      "subagents": { "allowAgents": ["monitor", "researcher"] }
    },
    "monitor": {
      "workspace": "~/.openclaw/workspace-monitor",
      "model": {
        "primary": "openai/gpt-6-luna",
        "fallbacks": ["anthropic/claude-haiku-5-5"]
      }
    },
    "researcher": {
      "workspace": "~/.openclaw/workspace-researcher",
      "model": {
        "primary": "kimi/k3-256k",
        "fallbacks": [
          "zai/glm-5.3",
          "openai/gpt-6-luna"
        ]
      }
    }
  }
}

A string model on an entry is strict, with no fallback. Use the { primary, fallbacks } form to opt an agent into fallback. subagents.allowAgents lets the coordinator spawn the other agents by id.

The full prompts for these agents are in the Agent Prompts chapter.

04Concurrency limits #

openclaw.json · concurrency
"agents": {
  "defaults": {
    "maxConcurrent": 4,
    "subagents": {
      "maxConcurrent": 8,
      "maxChildrenPerAgent": 5,
      "maxSpawnDepth": 1
    }
  }
}

Without an explicit value, maxConcurrent defaults to max(8, CPUs × 4), which is 32 parallel runs on an 8-core box. That suits a busy team Gateway, not a personal budget. A low cap, plus maxSpawnDepth: 1 so children can't spawn children, stops one bad task from fanning out and burning your quota in minutes.

05Custom model providers #

NVIDIA no longer needs a hand-written provider block: it ships as a built-in provider that serves open models for free through an OpenAI-compatible API.

bash · NVIDIA
export NVIDIA_API_KEY="nvapi-..."
openclaw onboard --auth-choice nvidia-api-key
openclaw models set nvidia/nvidia/nemotron-3-ultra-550b-a55b

Rate limits: the free tier is rate-limited and busy models queue. Use it sparingly or as a fallback, not as your primary.

For anything not built in, such as a LiteLLM proxy or a self-hosted vLLM server, register it under models.providers:

openclaw.json · custom provider
"models": {
  "mode": "merge",
  "providers": {
    "custom-proxy": {
      "baseUrl": "http://localhost:4000/v1",
      "apiKey": "${LITELLM_KEY}",
      "api": "openai-completions",
      "models": [
        {
          "id": "llama-3.1-8b",
          "name": "Llama 3.1 8B",
          "reasoning": false,
          "input": ["text"],
          "cost": { "input": 0, "output": 0 },
          "contextWindow": 128000,
          "maxTokens": 32000
        }
      ]
    }
  }
}

Use api: "openai-completions" for /v1/chat/completions backends; openai-responses only when the backend supports /v1/responses. Keep keys in environment variables and reference them as ${VAR}.

06Channels: Telegram, Discord, Slack #

openclaw.json · channels
"channels": {
  "telegram": {
    "enabled": true,
    "botToken": "<YOUR_TELEGRAM_BOT_TOKEN>",
    "dmPolicy": "pairing",
    "groupPolicy": "allowlist",
    "streaming": { "mode": "partial" }
  },
  "discord": {
    "enabled": true,
    "token": "<YOUR_DISCORD_BOT_TOKEN>",
    "dmPolicy": "allowlist",
    "allowFrom": ["<YOUR_DISCORD_USER_ID>"],
    "groupPolicy": "allowlist",
    "guilds": {
      "<YOUR_DISCORD_GUILD_ID>": {
        "requireMention": false,
        "users": ["<YOUR_DISCORD_USER_ID>"],
        "channels": { "general": { "enabled": true } }
      }
    }
  },
  "slack": {
    "enabled": true,
    "mode": "socket",
    "botToken": "<YOUR_SLACK_BOT_TOKEN>",
    "appToken": "<YOUR_SLACK_APP_TOKEN>",
    "groupPolicy": "allowlist",
    "channels": {}
  }
}

Tokens can also come from the environment (TELEGRAM_BOT_TOKEN, SLACK_BOT_TOKEN, SLACK_APP_TOKEN) so they never sit in the file. Older flat keys such as streamMode are no longer read; run openclaw doctor --fix to migrate them to streaming.mode.

07Tools, media and messages #

openclaw.json · tools, media, messages
"tools": {
  "profile": "full",
  "web": {
    "search": { "enabled": true, "provider": "brave" },
    "fetch": { "enabled": true }
  },
  "media": {
    "models": [{
      "type": "cli",
      "command": "/path/to/whisper-wrapper",
      "args": ["{{AttachmentPath}}"],
      "capabilities": ["audio"]
    }],
    "audio": { "enabled": true }
  }
},
"plugins": {
  "entries": {
    "brave": {
      "config": { "webSearch": { "apiKey": "<YOUR_BRAVE_API_KEY>" } }
    }
  }
},
"messages": {
  "ackReactionScope": "group-mentions"
},
"tts": {
  "auto": "inbound",
  "provider": "microsoft",
  "providers": {
    "microsoft": { "speakerVoice": "en-GB-RyanNeural" }
  }
}
  • The Brave key moved from tools.web.search to the Brave plugin's config (BRAVE_API_KEY also works).
  • Media models are one list; each entry declares the capabilities it handles. CLI args use {{AttachmentPath}} instead of the old {input}.
  • Text-to-speech is a top-level tts block. Edge TTS is now the microsoft provider (edge still works as an alias).

08Hooks #

openclaw.json · hooks
"hooks": {
  "internal": {
    "enabled": true,
    "entries": {
      "command-logger": { "enabled": true },
      "boot-md": { "enabled": true },
      "session-memory": { "enabled": true }
    }
  }
}

09Gateway #

openclaw.json · gateway
"gateway": {
  "port": 18789,
  "mode": "local",
  "bind": "loopback",
  "auth": {
    "mode": "token",
    "token": "<GENERATE_RANDOM_TOKEN>",
    "allowTailscale": true
  },
  "tailscale": { "mode": "serve" }
}

Critical: bind: "loopback" (the default) makes the gateway listen only on 127.0.0.1; Tailscale Serve then publishes it to your tailnet only. bind takes modes (loopback, tailnet, lan, auto, custom), not IP addresses. See the VPS Deployment chapter for verification steps.

10File structure #

Expected layout
~/.openclaw/
├── openclaw.json              # Main config (chmod 600)
├── credentials/               # Channel creds + pairing allowlists
├── state/openclaw.sqlite      # Shared runtime state
├── agents/<agentId>/agent/
│   └── openclaw-agent.sqlite  # Auth profiles, sessions, transcripts
├── skills/                    # Managed skills (all agents)
└── workspace/                 # The agent's working directory
    ├── AGENTS.md              # Instructions + "## Tools" notes
    ├── SOUL.md
    ├── USER.md
    ├── IDENTITY.md
    ├── MEMORY.md
    ├── BOOT.md                # Optional, with the boot-md hook
    ├── memory/
    │   ├── 2026-10-14.md
    │   └── ...
    └── skills/                # Workspace skills (highest precedence)

TOOLS.md is gone: local tool notes now live in a ## Tools section of AGENTS.md. Heartbeat instructions moved out of HEARTBEAT.md into the heartbeat monitor's scratch, and model auth profiles live in each agent's SQLite database rather than in credentials/. openclaw doctor --fix migrates all three.

11Common mistakes #

  1. 1. Leaving expensive models as default Opus in primary means quota burnout. Move them to fallbacks or agent-specific configs.
  2. 2. No context pruning Token usage climbs and costs spiral. Add contextPruning with cache-ttl.
  3. 3. Gateway exposed to the networkbind: "lan" listens on every interface. Keep bind: "loopback" and reach it over Tailscale Serve.
  4. 4. Trusting the default concurrency The default scales with your CPU count, not your budget. Set maxConcurrent to something sane (4–8).
  5. 5. Skipping the security audit Run openclaw security audit --deep after every config change.

12Cost tracking #

OpenClaw tracks usage itself now: it pulls quota windows and balances straight from providers such as Anthropic, OpenAI, OpenRouter, MiniMax and z.ai. The Control UI's Usage page charts the same data.

bash · usage and cost
# Per-provider quota windows and balances
openclaw status --usage

# Local cost summary from session logs
openclaw gateway usage-cost

# In chat
/status        # session tokens + estimated cost
/usage full    # per-response usage footer
/usage cost    # today / last 30 days

Target: $45–50 a month for moderate usage (main session plus occasional subagents).

13Next steps #

  1. 1 Set up your channels (Telegram, Discord, etc.)
  2. 2 Configure role-specific agents (monitor, researcher, communicator)
  3. 3 Add skills to the workspace skills/ directory
  4. 4 Tune the heartbeat cadence and its monitor scratch checklist
  5. 5 Test in a local session before enabling 24/7 mode

14Final thoughts #

You don't need expensive hardware or expensive subscriptions to make OpenClaw useful. What you need is to be deliberate about configuration, keep visibility into what's happening, and resist the urge to over-engineer before you understand the basics.

Keep the Mega Cheatsheet open for the CLI commands and paths you'll reach for day to day.

15Resources #

16On Anthropic bans #

Bans usually come down to how aggressively Claude is being hit, not OpenClaw itself. The reported cases were tied to aggressive automated usage patterns rather than simply running OpenClaw. If you aren't hammering the API beyond normal usage, there's no obvious reason to worry.

The supported Anthropic paths are an API key, the claude setup-token token, and reusing a local Claude CLI login. For an always-on gateway, the docs recommend an API key: it's the most predictable option, with billing you control.

Adapted from digitalknk/openclaw-runbook. OpenClaw changes fast: check the official docs before copying config into production.