OpenClaw Configuration Reference
OpenClaw stores all configuration in ~/.openclaw/openclaw.json using JSON5 format (comments allowed, trailing commas OK). The gateway validates strictly on startup — unknown keys or wrong types prevent it from starting. This is the complete reference for every top-level object.
openclaw onboard — interactive first-time setup wizard
openclaw config get agents.defaults.model — read a specific key
openclaw config set agents.defaults.heartbeat.every "2h" — set a value
openclaw config schema — view full JSON Schema
openclaw doctor — diagnose config problems
openclaw doctor --fix — auto-repair common issues
Top-Level Structure
The config file is a single JSON5 object. All top-level keys are optional — OpenClaw applies defaults for anything missing.
| Key | Purpose |
|---|---|
agents | Agent defaults, model list, skills, sandbox settings, heartbeat |
channels | Channel integrations: WhatsApp, Telegram, Discord, Slack, email, etc. |
session | Conversation scope, thread bindings, daily reset behaviour |
gateway | Server port, auth token, health monitoring, hot-reload mode |
cron | Scheduled job settings, concurrency, session retention, run logs |
hooks | Webhook endpoints, routing mappings, security tokens |
env | Environment variables, secrets, shell imports |
ui | Web UI customisation |
broadcast | Multi-client configuration |
agents — Model, Skills & Sandbox
{
agents: {
defaults: {
workspace: "~/.openclaw/workspace",
// Primary model + fallbacks
model: {
primary: "anthropic/claude-sonnet-4-6",
fallbacks: ["openai/gpt-4.1"]
},
// Model allowlist — defines which models users can switch to
models: {
"anthropic/claude-sonnet-4-6": { alias: "Sonnet" },
"anthropic/claude-haiku-4-5": { alias: "Haiku" },
"openai/gpt-4.1": { alias: "GPT4" }
},
// Skills enabled by default for all agents
skills: ["github", "weather", "daily-brief"],
// Sandbox controls which tools run in isolation
sandbox: {
mode: "non-main", // off | non-main | all
scope: "agent" // session | agent | shared
},
// Heartbeat: proactive check-ins on a schedule
heartbeat: {
every: "30m", // cron or duration string. "0" = disabled
target: "last" // "last" = most recent session
}
},
// Multiple named agents
list: [
{
id: "main",
default: true,
workspace: "~/.openclaw/workspace",
skills: ["github", "daily-brief"],
groupChat: {
mentionPatterns: ["@openclaw", "openclaw"]
}
},
{
id: "work",
workspace: "~/.openclaw/workspace-work",
skills: ["github", "jira"]
}
]
}
}
Sandbox Modes
| Mode | Behaviour |
|---|---|
off | No sandboxing — all skills run with full host access |
non-main | Non-primary agents run sandboxed; main agent runs direct (recommended) |
all | All agents sandboxed — most secure, slowest startup |
channels — All Integrations
Every channel uses the same DM access pattern. The key config fields are consistent across all providers:
{
channels: {
<provider>: {
enabled: true,
dmPolicy: "pairing", // pairing | allowlist | open | disabled
allowFrom: ["+15555550123"], // phone numbers, user IDs, or "*"
groupPolicy: "mention", // open | allowlist | disabled
groups: {
"*": { requireMention: true }
}
}
}
}
dmPolicy Values
| Value | Behaviour | Use case |
|---|---|---|
pairing | New users send /start, get a code, you approve it on the server | Personal use — most secure default |
allowlist | Only user IDs in allowFrom can DM the agent | Family/team where you know all IDs upfront |
open | Anyone who discovers the bot can message it | Public bots only — not recommended for personal agents |
disabled | DMs completely blocked; group-only access | Group-only deployments |
Telegram
{
channels: {
telegram: {
enabled: true,
botToken: "${TELEGRAM_BOT_TOKEN}",
dmPolicy: "pairing",
allowFrom: ["8734062810"], // your numeric Telegram user ID
groupPolicy: "allowlist",
groups: {
"-1001234567890": { // group chat ID (negative number)
requireMention: true,
allowFrom: ["8734062810", "745123456"]
}
}
}
}
}
{
channels: {
whatsapp: {
enabled: true,
dmPolicy: "allowlist",
allowFrom: ["+15555550123"], // E.164 format
groupPolicy: "mention"
}
}
}
Discord
{
channels: {
discord: {
enabled: true,
botToken: "${DISCORD_BOT_TOKEN}",
applicationId: "123456789012345678",
dmPolicy: "allowlist",
allowFrom: ["your-discord-user-id"]
}
}
}
session — Scope & Reset
{
session: {
// How conversation history is scoped
dmScope: "per-channel-peer",
// Options:
// main — one global session for all DMs
// per-peer — one session per sender (across channels)
// per-channel-peer — one session per sender per channel (recommended)
// per-account-channel-peer — adds account-level isolation
threadBindings: {
enabled: true,
idleHours: 24, // thread expires after 24h of inactivity
maxAgeHours: 0 // 0 = no hard limit
},
reset: {
mode: "daily", // daily | idle | off
atHour: 4, // 4 AM local time
idleMinutes: 120 // reset after 2h of no messages
}
}
}
gateway — Server Settings
{
gateway: {
port: 18789,
bind: "127.0.0.1", // NEVER change to 0.0.0.0 on a public VPS
auth: {
token: "${OPENCLAW_GATEWAY_TOKEN}"
},
reload: {
mode: "hybrid", // hybrid | hot | restart | off
debounceMs: 300
},
// Health monitoring
channelHealthCheckMinutes: 5,
channelStaleEventThresholdMinutes: 30,
channelMaxRestartsPerHour: 10
}
}
Reload Modes
| Mode | Behaviour |
|---|---|
hybrid | Most changes apply live; gateway changes queue for next restart (recommended) |
hot | All changes apply immediately — some instability possible |
restart | Full restart on any config change |
off | Manual restart required for all changes |
cron — Scheduled Jobs
The cron block controls the scheduler's global behaviour. Individual jobs are defined inside the agent's workspace HEARTBEAT.md file (see SOUL.md & Agent Personas).
{
cron: {
enabled: true,
maxConcurrentRuns: 2, // max simultaneous job runs
sessionRetention: "24h", // how long cron session logs are kept
runLog: {
maxBytes: "2mb",
keepLines: 2000
}
}
}
Individual cron jobs are scheduled inside your agent's workspace. Typical example in HEARTBEAT.md:
# HEARTBEAT TASKS
## Daily Morning Brief — 7:00 AM
Schedule: 0 7 * * *
Action: Run the daily-brief skill and send result to Telegram
## Disk Check — Every 30 Minutes
Schedule: */30 * * * *
Action: Check disk usage. If any partition > 85%, alert immediately.
## Weekly Security Audit — Monday 9 AM
Schedule: 0 9 * * 1
Action: Run healthcheck skill and summarise results to my DM.
env — Secrets & Environment Variables
{
env: {
// Direct values (less secure — prefer shellEnv below)
OPENROUTER_API_KEY: "sk-or-...",
// Nested vars object — same behaviour
vars: {
GROQ_API_KEY: "gsk-..."
},
// Import from shell environment (most secure)
shellEnv: {
enabled: true,
timeoutMs: 15000
}
}
}
Reference env vars anywhere in the config with "${VAR_NAME}". Only uppercase names are supported. Missing variables cause a startup error — use openclaw doctor to diagnose.
The best practice is to use shellEnv: { enabled: true } and export your API keys in your shell profile (~/.zshrc or ~/.bashrc). This way the config file itself contains no secrets and can be safely version-controlled.
Multi-Agent Routing
Route different channels or accounts to different agents using bindings:
{
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" } },
{ agentId: "work", match: { channel: "telegram" } }
]
}
Config Includes — Split Into Multiple Files
Large configs can be split across files using $include:
// ~/.openclaw/openclaw.json
{
agents: { $include: "./agents.json5" },
channels: { $include: "./channels.json5" },
broadcast: { $include: ["./clients/a.json5", "./clients/b.json5"] }
}
Single files replace the object they're assigned to. Arrays deep-merge in order. This lets you keep Telegram credentials in a separate file with tighter filesystem permissions.
← Back to OpenClaw hub · See also: Telegram Setup · Security Hardening · Cost Optimisation