Files
openclaw/docs/gateway/configuration.md

480 lines
15 KiB
Markdown
Raw Normal View History

---
summary: "Configuration overview: common tasks, quick setup, and links to the full reference"
read_when:
- Setting up OpenClaw for the first time
- Looking for common configuration patterns
- Navigating to specific config sections
title: "Configuration"
---
2026-01-31 21:13:13 +09:00
# Configuration
OpenClaw reads an optional <Tooltip tip="JSON5 supports comments and trailing commas">**JSON5**</Tooltip> config from `~/.openclaw/openclaw.json`.
If the file is missing, OpenClaw uses safe defaults. Common reasons to add a config:
2026-01-31 21:13:13 +09:00
- Connect channels and control who can message the bot
- Set models, tools, sandboxing, or automation (cron, hooks)
- Tune sessions, media, networking, or UI
See the [full reference](/gateway/configuration-reference) for every available field.
<Tip>
**New to configuration?** Start with `openclaw onboard` for interactive setup, or check out the [Configuration Examples](/gateway/configuration-examples) guide for complete copy-paste configs.
</Tip>
2026-01-19 03:38:51 +00:00
## Minimal config
2026-01-31 21:13:13 +09:00
2026-01-09 20:42:16 +00:00
```json5
// ~/.openclaw/openclaw.json
2026-01-09 20:42:16 +00:00
{
agents: { defaults: { workspace: "~/.openclaw/workspace" } },
channels: { whatsapp: { allowFrom: ["+15555550123"] } },
2026-01-09 20:42:16 +00:00
}
```
## Editing config
<Tabs>
<Tab title="Interactive wizard">
```bash
openclaw onboard # full setup wizard
openclaw configure # config wizard
```
</Tab>
<Tab title="CLI (one-liners)">
```bash
openclaw config get agents.defaults.workspace
openclaw config set agents.defaults.heartbeat.every "2h"
openclaw config unset tools.web.search.apiKey
```
</Tab>
<Tab title="Control UI">
Open [http://127.0.0.1:18789](http://127.0.0.1:18789) and use the **Config** tab.
The Control UI renders a form from the config schema, with a **Raw JSON** editor as an escape hatch.
</Tab>
<Tab title="Direct edit">
Edit `~/.openclaw/openclaw.json` directly. The Gateway watches the file and applies changes automatically (see [hot reload](#config-hot-reload)).
</Tab>
</Tabs>
## Strict validation
<Warning>
OpenClaw only accepts configurations that fully match the schema. Unknown keys, malformed types, or invalid values cause the Gateway to **refuse to start**.
</Warning>
2026-01-31 21:13:13 +09:00
When validation fails:
2025-12-25 23:50:52 +01:00
- The Gateway does not boot
- Only diagnostic commands work (`openclaw doctor`, `openclaw logs`, `openclaw health`, `openclaw status`)
- Run `openclaw doctor` to see exact issues
- Run `openclaw doctor --fix` (or `--yes`) to apply repairs
2026-01-03 21:35:44 +01:00
## Common tasks
2026-01-03 21:35:44 +01:00
<AccordionGroup>
<Accordion title="Set up a channel (WhatsApp, Telegram, Discord, etc.)">
Each channel has its own config section under `channels.<provider>`. See the dedicated channel page for setup steps:
- [WhatsApp](/channels/whatsapp) — `channels.whatsapp`
- [Telegram](/channels/telegram) — `channels.telegram`
- [Discord](/channels/discord) — `channels.discord`
- [Slack](/channels/slack) — `channels.slack`
- [Signal](/channels/signal) — `channels.signal`
- [iMessage](/channels/imessage) — `channels.imessage`
- [Google Chat](/channels/googlechat) — `channels.googlechat`
- [Mattermost](/channels/mattermost) — `channels.mattermost`
- [MS Teams](/channels/msteams) — `channels.msteams`
2026-01-31 21:13:13 +09:00
All channels share the same DM policy pattern:
2026-01-03 21:35:44 +01:00
```json5
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing", // pairing | allowlist | open | disabled
allowFrom: ["tg:123"], // only for allowlist/open
},
},
}
```
2026-01-07 02:31:51 +01:00
</Accordion>
2026-01-06 23:22:49 +01:00
<Accordion title="Choose and configure models">
Set the primary model and optional fallbacks:
```json5
{
agents: {
defaults: {
model: {
primary: "anthropic/claude-sonnet-4-5",
fallbacks: ["openai/gpt-5.2"],
},
models: {
"anthropic/claude-sonnet-4-5": { alias: "Sonnet" },
"openai/gpt-5.2": { alias: "GPT" },
},
2026-01-31 21:13:13 +09:00
},
},
}
```
2026-01-03 22:11:43 +01:00
- `agents.defaults.models` defines the model catalog and acts as the allowlist for `/model`.
- Model refs use `provider/model` format (e.g. `anthropic/claude-opus-4-6`).
- See [Models CLI](/concepts/models) for switching models in chat and [Model Failover](/concepts/model-failover) for auth rotation and fallback behavior.
- For custom/self-hosted providers, see [Custom providers](/gateway/configuration-reference#custom-providers-and-base-urls) in the reference.
2026-01-04 14:32:47 +00:00
</Accordion>
<Accordion title="Control who can message the bot">
DM access is controlled per channel via `dmPolicy`:
2026-01-12 10:13:32 -07:00
- `"pairing"` (default): unknown senders get a one-time pairing code to approve
- `"allowlist"`: only senders in `allowFrom` (or the paired allow store)
- `"open"`: allow all inbound DMs (requires `allowFrom: ["*"]`)
- `"disabled"`: ignore all DMs
2026-01-31 21:13:13 +09:00
For groups, use `groupPolicy` + `groupAllowFrom` or channel-specific allowlists.
2026-01-31 21:13:13 +09:00
See the [full reference](/gateway/configuration-reference#dm-and-group-access) for per-channel details.
</Accordion>
2025-12-23 02:48:57 +01:00
<Accordion title="Set up group chat mention gating">
Group messages default to **require mention**. Configure patterns per agent:
2025-12-23 02:48:57 +01:00
```json5
{
agents: {
list: [
2025-12-23 02:48:57 +01:00
{
id: "main",
groupChat: {
mentionPatterns: ["@openclaw", "openclaw"],
},
2026-01-31 21:13:13 +09:00
},
],
},
channels: {
whatsapp: {
groups: { "*": { requireMention: true } },
},
},
}
```
2026-01-06 11:35:47 -03:00
- **Metadata mentions**: native @-mentions (WhatsApp tap-to-mention, Telegram @bot, etc.)
- **Text patterns**: regex patterns in `mentionPatterns`
- See [full reference](/gateway/configuration-reference#group-chat-mention-gating) for per-channel overrides and self-chat mode.
2026-01-06 11:35:47 -03:00
</Accordion>
2026-01-10 16:32:21 +01:00
<Accordion title="Configure sessions and resets">
Sessions control conversation continuity and isolation:
2026-01-06 11:35:47 -03:00
```json5
{
session: {
dmScope: "per-channel-peer", // recommended for multi-user
reset: {
mode: "daily",
atHour: 4,
idleMinutes: 120,
},
},
}
```
2026-01-31 21:13:13 +09:00
- `dmScope`: `main` (shared) | `per-peer` | `per-channel-peer` | `per-account-channel-peer`
- See [Session Management](/concepts/session) for scoping, identity links, and send policy.
- See [full reference](/gateway/configuration-reference#session) for all fields.
2026-01-06 11:35:47 -03:00
</Accordion>
2026-01-12 06:47:57 +00:00
<Accordion title="Enable sandboxing">
Run agent sessions in isolated Docker containers:
2026-01-12 06:47:57 +00:00
```json5
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // off | non-main | all
scope: "agent", // session | agent | shared
2026-01-31 21:13:13 +09:00
},
},
2026-01-31 21:13:13 +09:00
},
}
```
Build the image first: `scripts/sandbox-setup.sh`
See [Sandboxing](/gateway/sandboxing) for the full guide and [full reference](/gateway/configuration-reference#sandbox) for all options.
2026-01-13 00:22:03 +00:00
</Accordion>
2026-01-13 00:22:03 +00:00
<Accordion title="Set up heartbeat (periodic check-ins)">
```json5
{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last",
2026-01-31 21:13:13 +09:00
},
},
2026-01-31 21:13:13 +09:00
},
}
```
2026-01-13 00:22:03 +00:00
- `every`: duration string (`30m`, `2h`). Set `0m` to disable.
- `target`: `last` | `whatsapp` | `telegram` | `discord` | `none`
- See [Heartbeat](/gateway/heartbeat) for the full guide.
2026-01-31 21:13:13 +09:00
</Accordion>
2026-01-13 00:22:03 +00:00
<Accordion title="Configure cron jobs">
```json5
{
cron: {
enabled: true,
maxConcurrentRuns: 2,
sessionRetention: "24h",
},
}
```
2025-12-27 00:48:15 +00:00
See [Cron jobs](/automation/cron-jobs) for the feature overview and CLI examples.
2025-12-27 00:48:15 +00:00
</Accordion>
<Accordion title="Set up webhooks (hooks)">
Enable HTTP webhook endpoints on the Gateway:
```json5
{
hooks: {
enabled: true,
token: "shared-secret",
path: "/hooks",
mappings: [
{
match: { path: "gmail" },
action: "agent",
agentId: "main",
deliver: true,
2026-01-31 21:13:13 +09:00
},
],
},
}
```
See [full reference](/gateway/configuration-reference#hooks) for all mapping options and Gmail integration.
2026-01-31 21:13:13 +09:00
</Accordion>
<Accordion title="Configure multi-agent routing">
Run multiple isolated agents with separate workspaces and sessions:
2026-01-12 05:57:49 +00:00
```json5
{
agents: {
list: [
{ id: "home", default: true, workspace: "~/.openclaw/workspace-home" },
{ id: "work", workspace: "~/.openclaw/workspace-work" },
2026-01-31 21:13:13 +09:00
],
},
bindings: [
{ agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
{ agentId: "work", match: { channel: "whatsapp", accountId: "biz" } },
],
}
```
2026-01-11 12:11:12 +00:00
See [Multi-Agent](/concepts/multi-agent) and [full reference](/gateway/configuration-reference#multi-agent-routing) for binding rules and per-agent access profiles.
2026-01-31 21:13:13 +09:00
</Accordion>
2026-01-11 12:11:12 +00:00
<Accordion title="Split config into multiple files ($include)">
Use `$include` to organize large configs:
2026-01-11 12:11:12 +00:00
```json5
// ~/.openclaw/openclaw.json
{
gateway: { port: 18789 },
agents: { $include: "./agents.json5" },
broadcast: {
$include: ["./clients/a.json5", "./clients/b.json5"],
2026-01-31 21:13:13 +09:00
},
}
```
2025-12-30 04:14:36 +01:00
- **Single file**: replaces the containing object
- **Array of files**: deep-merged in order (later wins)
- **Sibling keys**: merged after includes (override included values)
- **Nested includes**: supported up to 10 levels deep
- **Relative paths**: resolved relative to the including file
- **Error handling**: clear errors for missing files, parse errors, and circular includes
</Accordion>
</AccordionGroup>
2026-01-03 23:34:18 +01:00
## Config hot reload
The Gateway watches `~/.openclaw/openclaw.json` and applies changes automatically — no manual restart needed for most settings.
2026-01-03 19:52:24 +00:00
### Reload modes
2026-01-03 19:52:24 +00:00
| Mode | Behavior |
| ---------------------- | --------------------------------------------------------------------------------------- |
| **`hybrid`** (default) | Hot-applies safe changes instantly. Automatically restarts for critical ones. |
| **`hot`** | Hot-applies safe changes only. Logs a warning when a restart is needed — you handle it. |
| **`restart`** | Restarts the Gateway on any config change, safe or not. |
| **`off`** | Disables file watching. Changes take effect on the next manual restart. |
2026-01-03 19:52:24 +00:00
```json5
{
gateway: {
reload: { mode: "hybrid", debounceMs: 300 },
2026-01-31 21:13:13 +09:00
},
2025-12-24 14:32:55 +00:00
}
```
### What hot-applies vs what needs a restart
2026-01-31 21:13:13 +09:00
Most fields hot-apply without downtime. In `hybrid` mode, restart-required changes are handled automatically.
2025-12-24 14:32:55 +00:00
| Category | Fields | Restart needed? |
| ------------------- | -------------------------------------------------------------------- | --------------- |
| Channels | `channels.*`, `web` (WhatsApp) — all built-in and extension channels | No |
| Agent & models | `agent`, `agents`, `models`, `routing` | No |
| Automation | `hooks`, `cron`, `agent.heartbeat` | No |
| Sessions & messages | `session`, `messages` | No |
| Tools & media | `tools`, `browser`, `skills`, `audio`, `talk` | No |
| UI & misc | `ui`, `logging`, `identity`, `bindings` | No |
| Gateway server | `gateway.*` (port, bind, auth, tailscale, TLS, HTTP) | **Yes** |
| Infrastructure | `discovery`, `canvasHost`, `plugins` | **Yes** |
2026-01-31 21:13:13 +09:00
<Note>
`gateway.reload` and `gateway.remote` are exceptions — changing them does **not** trigger a restart.
</Note>
2025-12-24 14:32:55 +00:00
## Config RPC (programmatic updates)
2025-12-24 14:32:55 +00:00
<AccordionGroup>
<Accordion title="config.apply (full replace)">
Validates + writes the full config and restarts the Gateway in one step.
2026-01-31 21:13:13 +09:00
<Warning>
`config.apply` replaces the **entire config**. Use `config.patch` for partial updates, or `openclaw config set` for single keys.
</Warning>
2025-12-24 19:39:36 +00:00
Params:
2025-12-24 19:39:36 +00:00
- `raw` (string) — JSON5 payload for the entire config
- `baseHash` (optional) — config hash from `config.get` (required when config exists)
- `sessionKey` (optional) — session key for the post-restart wake-up ping
- `note` (optional) — note for the restart sentinel
- `restartDelayMs` (optional) — delay before restart (default 2000)
2025-12-24 19:39:36 +00:00
```bash
openclaw gateway call config.get --params '{}' # capture payload.hash
openclaw gateway call config.apply --params '{
"raw": "{ agents: { defaults: { workspace: \"~/.openclaw/workspace\" } } }",
"baseHash": "<hash>",
"sessionKey": "agent:main:whatsapp:dm:+15555550123"
}'
```
2026-01-31 21:13:13 +09:00
</Accordion>
<Accordion title="config.patch (partial update)">
Merges a partial update into the existing config (JSON merge patch semantics):
2026-01-31 21:13:13 +09:00
- Objects merge recursively
- `null` deletes a key
- Arrays replace
2026-01-03 03:03:49 +01:00
Params:
- `raw` (string) — JSON5 with just the keys to change
- `baseHash` (required) — config hash from `config.get`
- `sessionKey`, `note`, `restartDelayMs` — same as `config.apply`
2025-12-18 11:36:46 +01:00
```bash
openclaw gateway call config.patch --params '{
"raw": "{ channels: { telegram: { groups: { \"*\": { requireMention: false } } } } }",
"baseHash": "<hash>"
}'
```
2025-12-18 11:36:46 +01:00
</Accordion>
</AccordionGroup>
2025-12-18 11:36:46 +01:00
## Environment variables
2026-01-31 21:13:13 +09:00
OpenClaw reads env vars from the parent process plus:
2025-12-18 11:36:46 +01:00
- `.env` from the current working directory (if present)
- `~/.openclaw/.env` (global fallback)
2026-01-31 21:13:13 +09:00
Neither file overrides existing env vars. You can also set inline env vars in config:
2026-01-04 15:22:47 +01:00
2025-12-18 11:36:46 +01:00
```json5
{
env: {
OPENROUTER_API_KEY: "sk-or-...",
vars: { GROQ_API_KEY: "gsk-..." },
2026-01-31 21:13:13 +09:00
},
2025-12-18 11:36:46 +01:00
}
```
<Accordion title="Shell env import (optional)">
If enabled and expected keys aren't set, OpenClaw runs your login shell and imports only the missing keys:
2026-01-16 05:28:33 +00:00
```json5
{
env: {
shellEnv: { enabled: true, timeoutMs: 15000 },
2026-01-31 21:13:13 +09:00
},
}
```
Env var equivalent: `OPENCLAW_LOAD_SHELL_ENV=1`
</Accordion>
<Accordion title="Env var substitution in config values">
Reference env vars in any config string value with `${VAR_NAME}`:
```json5
{
gateway: { auth: { token: "${OPENCLAW_GATEWAY_TOKEN}" } },
models: { providers: { custom: { apiKey: "${CUSTOM_API_KEY}" } } },
}
```
Rules:
- Only uppercase names matched: `[A-Z_][A-Z0-9_]*`
- Missing/empty vars throw an error at load time
- Escape with `$${VAR}` for literal output
- Works inside `$include` files
- Inline substitution: `"${BASE}/v1"``"https://api.example.com/v1"`
</Accordion>
See [Environment](/help/environment) for full precedence and sources.
## Full reference
fix: unify session maintenance and cron run pruning (#13083) * fix: prune stale session entries, cap entry count, and rotate sessions.json The sessions.json file grows unbounded over time. Every heartbeat tick (default: 30m) triggers multiple full rewrites, and session keys from groups, threads, and DMs accumulate indefinitely with large embedded objects (skillsSnapshot, systemPromptReport). At >50MB the synchronous JSON parse blocks the event loop, causing Telegram webhook timeouts and effectively taking the bot down. Three mitigations, all running inside saveSessionStoreUnlocked() on every write: 1. Prune stale entries: remove entries with updatedAt older than 30 days (configurable via session.maintenance.pruneDays in openclaw.json) 2. Cap entry count: keep only the 500 most recently updated entries (configurable via session.maintenance.maxEntries). Entries without updatedAt are evicted first. 3. File rotation: if the existing sessions.json exceeds 10MB before a write, rename it to sessions.json.bak.{timestamp} and keep only the 3 most recent backups (configurable via session.maintenance.rotateBytes). All three thresholds are configurable under session.maintenance in openclaw.json with Zod validation. No env vars. Existing tests updated to use Date.now() instead of epoch-relative timestamps (1, 2, 3) that would be incorrectly pruned as stale. 27 new tests covering pruning, capping, rotation, and integration scenarios. * feat: auto-prune expired cron run sessions (#12289) Add TTL-based reaper for isolated cron run sessions that accumulate indefinitely in sessions.json. New config option: cron.sessionRetention: string | false (default: '24h') The reaper runs piggy-backed on the cron timer tick, self-throttled to sweep at most every 5 minutes. It removes session entries matching the pattern cron:<jobId>:run:<uuid> whose updatedAt + retention < now. Design follows the Kubernetes ttlSecondsAfterFinished pattern: - Sessions are persisted normally (observability/debugging) - A periodic reaper prunes expired entries - Configurable retention with sensible default - Set to false to disable pruning entirely Files changed: - src/config/types.cron.ts: Add sessionRetention to CronConfig - src/config/zod-schema.ts: Add Zod validation for sessionRetention - src/cron/session-reaper.ts: New reaper module (sweepCronRunSessions) - src/cron/session-reaper.test.ts: 12 tests covering all paths - src/cron/service/state.ts: Add cronConfig/sessionStorePath to deps - src/cron/service/timer.ts: Wire reaper into onTimer tick - src/gateway/server-cron.ts: Pass config and session store path to deps Closes #12289 * fix: sweep cron session stores per agent * docs: add changelog for session maintenance (#13083) (thanks @skyfallsin, @Glucksberg) * fix: add warn-only session maintenance mode * fix: warn-only maintenance defaults to active session * fix: deliver maintenance warnings to active session * docs: add session maintenance examples * fix: accept duration and size maintenance thresholds * refactor: share cron run session key check * fix: format issues and replace defaultRuntime.warn with console.warn --------- Co-authored-by: Pradeep Elankumaran <pradeepe@gmail.com> Co-authored-by: Glucksberg <markuscontasul@gmail.com> Co-authored-by: max <40643627+quotentiroler@users.noreply.github.com> Co-authored-by: quotentiroler <max.nussbaumer@maxhealth.tech>
2026-02-09 23:42:35 -05:00
For the complete field-by-field reference, see **[Configuration Reference](/gateway/configuration-reference)**.
fix: unify session maintenance and cron run pruning (#13083) * fix: prune stale session entries, cap entry count, and rotate sessions.json The sessions.json file grows unbounded over time. Every heartbeat tick (default: 30m) triggers multiple full rewrites, and session keys from groups, threads, and DMs accumulate indefinitely with large embedded objects (skillsSnapshot, systemPromptReport). At >50MB the synchronous JSON parse blocks the event loop, causing Telegram webhook timeouts and effectively taking the bot down. Three mitigations, all running inside saveSessionStoreUnlocked() on every write: 1. Prune stale entries: remove entries with updatedAt older than 30 days (configurable via session.maintenance.pruneDays in openclaw.json) 2. Cap entry count: keep only the 500 most recently updated entries (configurable via session.maintenance.maxEntries). Entries without updatedAt are evicted first. 3. File rotation: if the existing sessions.json exceeds 10MB before a write, rename it to sessions.json.bak.{timestamp} and keep only the 3 most recent backups (configurable via session.maintenance.rotateBytes). All three thresholds are configurable under session.maintenance in openclaw.json with Zod validation. No env vars. Existing tests updated to use Date.now() instead of epoch-relative timestamps (1, 2, 3) that would be incorrectly pruned as stale. 27 new tests covering pruning, capping, rotation, and integration scenarios. * feat: auto-prune expired cron run sessions (#12289) Add TTL-based reaper for isolated cron run sessions that accumulate indefinitely in sessions.json. New config option: cron.sessionRetention: string | false (default: '24h') The reaper runs piggy-backed on the cron timer tick, self-throttled to sweep at most every 5 minutes. It removes session entries matching the pattern cron:<jobId>:run:<uuid> whose updatedAt + retention < now. Design follows the Kubernetes ttlSecondsAfterFinished pattern: - Sessions are persisted normally (observability/debugging) - A periodic reaper prunes expired entries - Configurable retention with sensible default - Set to false to disable pruning entirely Files changed: - src/config/types.cron.ts: Add sessionRetention to CronConfig - src/config/zod-schema.ts: Add Zod validation for sessionRetention - src/cron/session-reaper.ts: New reaper module (sweepCronRunSessions) - src/cron/session-reaper.test.ts: 12 tests covering all paths - src/cron/service/state.ts: Add cronConfig/sessionStorePath to deps - src/cron/service/timer.ts: Wire reaper into onTimer tick - src/gateway/server-cron.ts: Pass config and session store path to deps Closes #12289 * fix: sweep cron session stores per agent * docs: add changelog for session maintenance (#13083) (thanks @skyfallsin, @Glucksberg) * fix: add warn-only session maintenance mode * fix: warn-only maintenance defaults to active session * fix: deliver maintenance warnings to active session * docs: add session maintenance examples * fix: accept duration and size maintenance thresholds * refactor: share cron run session key check * fix: format issues and replace defaultRuntime.warn with console.warn --------- Co-authored-by: Pradeep Elankumaran <pradeepe@gmail.com> Co-authored-by: Glucksberg <markuscontasul@gmail.com> Co-authored-by: max <40643627+quotentiroler@users.noreply.github.com> Co-authored-by: quotentiroler <max.nussbaumer@maxhealth.tech>
2026-02-09 23:42:35 -05:00
---
_Related: [Configuration Examples](/gateway/configuration-examples) · [Configuration Reference](/gateway/configuration-reference) · [Doctor](/gateway/doctor)_