Configuration Reference
Core config reference for~/.openclaw/openclaw.json. For a task-oriented overview, see Configuration.
This page covers the main OpenClaw config surfaces and links out when a subsystem has its own deeper reference. It does not try to inline every channel/plugin-owned command catalog or every deep memory/QMD knob on one page.
Code truth:
openclaw config schemaprints the live JSON Schema used for validation and Control UI, with bundled/plugin/channel metadata merged in when availableconfig.schema.lookupreturns one path-scoped schema node for drill-down toolingpnpm config:docs:check/pnpm config:docs:genvalidate the config-doc baseline hash against the current schema surface
- Memory configuration reference for
agents.defaults.memorySearch.*,memory.qmd.*,memory.citations, and dreaming config underplugins.entries.memory-core.config.dreaming - Slash Commands for the current built-in + bundled command catalog
- owning channel/plugin pages for channel-specific command surfaces
Channels
Each channel starts automatically when its config section exists (unlessenabled: false).
DM and group access
All channels support DM policies and group policies:| DM policy | Behavior |
|---|---|
pairing (default) | Unknown senders get a one-time pairing code; owner must approve |
allowlist | Only senders in allowFrom (or paired allow store) |
open | Allow all inbound DMs (requires allowFrom: ["*"]) |
disabled | Ignore all inbound DMs |
| Group policy | Behavior |
|---|---|
allowlist (default) | Only groups matching the configured allowlist |
open | Bypass group allowlists (mention-gating still applies) |
disabled | Block all group/room messages |
channels.defaults.groupPolicy sets the default when a provider’s groupPolicy is unset.
Pairing codes expire after 1 hour. Pending DM pairing requests are capped at 3 per channel.
If a provider block is missing entirely (channels.<provider> absent), runtime group policy falls back to allowlist (fail-closed) with a startup warning.Channel model overrides
Usechannels.modelByChannel to pin specific channel IDs to a model. Values accept provider/model or configured model aliases. The channel mapping applies when a session does not already have a model override (for example, set via /model).
Channel defaults and heartbeat
Usechannels.defaults for shared group-policy and heartbeat behavior across providers:
channels.defaults.groupPolicy: fallback group policy when a provider-levelgroupPolicyis unset.channels.defaults.contextVisibility: default supplemental context visibility mode for all channels. Values:all(default, include all quoted/thread/history context),allowlist(only include context from allowlisted senders),allowlist_quote(same as allowlist but keep explicit quote/reply context). Per-channel override:channels.<channel>.contextVisibility.channels.defaults.heartbeat.showOk: include healthy channel statuses in heartbeat output.channels.defaults.heartbeat.showAlerts: include degraded/error statuses in heartbeat output.channels.defaults.heartbeat.useIndicator: render compact indicator-style heartbeat output.
Multi-account WhatsApp
Multi-account WhatsApp
- Outbound commands default to account
defaultif present; otherwise the first configured account id (sorted). - Optional
channels.whatsapp.defaultAccountoverrides that fallback default account selection when it matches a configured account id. - Legacy single-account Baileys auth dir is migrated by
openclaw doctorintowhatsapp/default. - Per-account overrides:
channels.whatsapp.accounts.<id>.sendReadReceipts,channels.whatsapp.accounts.<id>.dmPolicy,channels.whatsapp.accounts.<id>.allowFrom.
Telegram
- Bot token:
channels.telegram.botTokenorchannels.telegram.tokenFile(regular file only; symlinks rejected), withTELEGRAM_BOT_TOKENas fallback for the default account. - Optional
channels.telegram.defaultAccountoverrides default account selection when it matches a configured account id. - In multi-account setups (2+ account ids), set an explicit default (
channels.telegram.defaultAccountorchannels.telegram.accounts.default) to avoid fallback routing;openclaw doctorwarns when this is missing or invalid. configWrites: falseblocks Telegram-initiated config writes (supergroup ID migrations,/config set|unset).- Top-level
bindings[]entries withtype: "acp"configure persistent ACP bindings for forum topics (use canonicalchatId:topic:topicIdinmatch.peer.id). Field semantics are shared in ACP Agents. - Telegram stream previews use
sendMessage+editMessageText(works in direct and group chats). - Retry policy: see Retry policy.
Discord
- Token:
channels.discord.token, withDISCORD_BOT_TOKENas fallback for the default account. - Direct outbound calls that provide an explicit Discord
tokenuse that token for the call; account retry/policy settings still come from the selected account in the active runtime snapshot. - Optional
channels.discord.defaultAccountoverrides default account selection when it matches a configured account id. - Use
user:<id>(DM) orchannel:<id>(guild channel) for delivery targets; bare numeric IDs are rejected. - Guild slugs are lowercase with spaces replaced by
-; channel keys use the slugged name (no#). Prefer guild IDs. - Bot-authored messages are ignored by default.
allowBots: trueenables them; useallowBots: "mentions"to only accept bot messages that mention the bot (own messages still filtered). channels.discord.guilds.<id>.ignoreOtherMentions(and channel overrides) drops messages that mention another user or role but not the bot (excluding @everyone/@here).maxLinesPerMessage(default 17) splits tall messages even when under 2000 chars.channels.discord.threadBindingscontrols Discord thread-bound routing:enabled: Discord override for thread-bound session features (/focus,/unfocus,/agents,/session idle,/session max-age, and bound delivery/routing)idleHours: Discord override for inactivity auto-unfocus in hours (0disables)maxAgeHours: Discord override for hard max age in hours (0disables)spawnSubagentSessions: opt-in switch forsessions_spawn({ thread: true })auto thread creation/binding
- Top-level
bindings[]entries withtype: "acp"configure persistent ACP bindings for channels and threads (use channel/thread id inmatch.peer.id). Field semantics are shared in ACP Agents. channels.discord.ui.components.accentColorsets the accent color for Discord components v2 containers.channels.discord.voiceenables Discord voice channel conversations and optional auto-join + TTS overrides.channels.discord.voice.daveEncryptionandchannels.discord.voice.decryptionFailureTolerancepass through to@discordjs/voiceDAVE options (trueand24by default).- OpenClaw additionally attempts voice receive recovery by leaving/rejoining a voice session after repeated decrypt failures.
channels.discord.streamingis the canonical stream mode key. LegacystreamModeand booleanstreamingvalues are auto-migrated.channels.discord.autoPresencemaps runtime availability to bot presence (healthy => online, degraded => idle, exhausted => dnd) and allows optional status text overrides.channels.discord.dangerouslyAllowNameMatchingre-enables mutable name/tag matching (break-glass compatibility mode).channels.discord.execApprovals: Discord-native exec approval delivery and approver authorization.enabled:true,false, or"auto"(default). In auto mode, exec approvals activate when approvers can be resolved fromapproversorcommands.ownerAllowFrom.approvers: Discord user IDs allowed to approve exec requests. Falls back tocommands.ownerAllowFromwhen omitted.agentFilter: optional agent ID allowlist. Omit to forward approvals for all agents.sessionFilter: optional session key patterns (substring or regex).target: where to send approval prompts."dm"(default) sends to approver DMs,"channel"sends to the originating channel,"both"sends to both. When target includes"channel", buttons are only usable by resolved approvers.cleanupAfterResolve: whentrue, deletes approval DMs after approval, denial, or timeout.
off (none), own (bot’s messages, default), all (all messages), allowlist (from guilds.<id>.users on all messages).
Google Chat
- Service account JSON: inline (
serviceAccount) or file-based (serviceAccountFile). - Service account SecretRef is also supported (
serviceAccountRef). - Env fallbacks:
GOOGLE_CHAT_SERVICE_ACCOUNTorGOOGLE_CHAT_SERVICE_ACCOUNT_FILE. - Use
spaces/<spaceId>orusers/<userId>for delivery targets. channels.googlechat.dangerouslyAllowNameMatchingre-enables mutable email principal matching (break-glass compatibility mode).
Slack
- Socket mode requires both
botTokenandappToken(SLACK_BOT_TOKEN+SLACK_APP_TOKENfor default account env fallback). - HTTP mode requires
botTokenplussigningSecret(at root or per-account). botToken,appToken,signingSecret, anduserTokenaccept plaintext strings or SecretRef objects.- Slack account snapshots expose per-credential source/status fields such as
botTokenSource,botTokenStatus,appTokenStatus, and, in HTTP mode,signingSecretStatus.configured_unavailablemeans the account is configured through SecretRef but the current command/runtime path could not resolve the secret value. configWrites: falseblocks Slack-initiated config writes.- Optional
channels.slack.defaultAccountoverrides default account selection when it matches a configured account id. channels.slack.streaming.modeis the canonical Slack stream mode key.channels.slack.streaming.nativeTransportcontrols Slack’s native streaming transport. LegacystreamMode, booleanstreaming, andnativeStreamingvalues are auto-migrated.- Use
user:<id>(DM) orchannel:<id>for delivery targets.
off, own (default), all, allowlist (from reactionAllowlist).
Thread session isolation: thread.historyScope is per-thread (default) or shared across channel. thread.inheritParent copies parent channel transcript to new threads.
- Slack native streaming plus the Slack assistant-style “is typing…” thread status require a reply thread target. Top-level DMs stay off-thread by default, so they use
typingReactionor normal delivery instead of the thread-style preview. typingReactionadds a temporary reaction to the inbound Slack message while a reply is running, then removes it on completion. Use a Slack emoji shortcode such as"hourglass_flowing_sand".channels.slack.execApprovals: Slack-native exec approval delivery and approver authorization. Same schema as Discord:enabled(true/false/"auto"),approvers(Slack user IDs),agentFilter,sessionFilter, andtarget("dm","channel", or"both").
| Action group | Default | Notes |
|---|---|---|
| reactions | enabled | React + list reactions |
| messages | enabled | Read/send/edit/delete |
| pins | enabled | Pin/unpin/list |
| memberInfo | enabled | Member info |
| emojiList | enabled | Custom emoji list |
Mattermost
Mattermost ships as a plugin:openclaw plugins install @openclaw/mattermost.
oncall (respond on @-mention, default), onmessage (every message), onchar (messages starting with trigger prefix).
When Mattermost native commands are enabled:
commands.callbackPathmust be a path (for example/api/channels/mattermost/command), not a full URL.commands.callbackUrlmust resolve to the OpenClaw gateway endpoint and be reachable from the Mattermost server.- Native slash callbacks are authenticated with the per-command tokens returned
by Mattermost during slash command registration. If registration fails or no
commands are activated, OpenClaw rejects callbacks with
Unauthorized: invalid command token. - For private/tailnet/internal callback hosts, Mattermost may require
ServiceSettings.AllowedUntrustedInternalConnectionsto include the callback host/domain. Use host/domain values, not full URLs. channels.mattermost.configWrites: allow or deny Mattermost-initiated config writes.channels.mattermost.requireMention: require@mentionbefore replying in channels.channels.mattermost.groups.<channelId>.requireMention: per-channel mention-gating override ("*"for default).- Optional
channels.mattermost.defaultAccountoverrides default account selection when it matches a configured account id.
Signal
off, own (default), all, allowlist (from reactionAllowlist).
channels.signal.account: pin channel startup to a specific Signal account identity.channels.signal.configWrites: allow or deny Signal-initiated config writes.- Optional
channels.signal.defaultAccountoverrides default account selection when it matches a configured account id.
BlueBubbles
BlueBubbles is the recommended iMessage path (plugin-backed, configured underchannels.bluebubbles).
- Core key paths covered here:
channels.bluebubbles,channels.bluebubbles.dmPolicy. - Optional
channels.bluebubbles.defaultAccountoverrides default account selection when it matches a configured account id. - Top-level
bindings[]entries withtype: "acp"can bind BlueBubbles conversations to persistent ACP sessions. Use a BlueBubbles handle or target string (chat_id:*,chat_guid:*,chat_identifier:*) inmatch.peer.id. Shared field semantics: ACP Agents. - Full BlueBubbles channel configuration is documented in BlueBubbles.
iMessage
OpenClaw spawnsimsg rpc (JSON-RPC over stdio). No daemon or port required.
-
Optional
channels.imessage.defaultAccountoverrides default account selection when it matches a configured account id. - Requires Full Disk Access to the Messages DB.
-
Prefer
chat_id:<id>targets. Useimsg chats --limit 20to list chats. -
cliPathcan point to an SSH wrapper; setremoteHost(hostoruser@host) for SCP attachment fetching. -
attachmentRootsandremoteAttachmentRootsrestrict inbound attachment paths (default:/Users/*/Library/Messages/Attachments). -
SCP uses strict host-key checking, so ensure the relay host key already exists in
~/.ssh/known_hosts. -
channels.imessage.configWrites: allow or deny iMessage-initiated config writes. -
Top-level
bindings[]entries withtype: "acp"can bind iMessage conversations to persistent ACP sessions. Use a normalized handle or explicit chat target (chat_id:*,chat_guid:*,chat_identifier:*) inmatch.peer.id. Shared field semantics: ACP Agents.
iMessage SSH wrapper example
iMessage SSH wrapper example
Matrix
Matrix is plugin-backed and configured underchannels.matrix.
- Token auth uses
accessToken; password auth usesuserId+password. channels.matrix.proxyroutes Matrix HTTP traffic through an explicit HTTP(S) proxy. Named accounts can override it withchannels.matrix.accounts.<id>.proxy.channels.matrix.network.dangerouslyAllowPrivateNetworkallows private/internal homeservers.proxyand this network opt-in are independent controls.channels.matrix.defaultAccountselects the preferred account in multi-account setups.channels.matrix.autoJoindefaults tooff, so invited rooms and fresh DM-style invites are ignored until you setautoJoin: "allowlist"withautoJoinAllowlistorautoJoin: "always".channels.matrix.execApprovals: Matrix-native exec approval delivery and approver authorization.enabled:true,false, or"auto"(default). In auto mode, exec approvals activate when approvers can be resolved fromapproversorcommands.ownerAllowFrom.approvers: Matrix user IDs (e.g.@owner:example.org) allowed to approve exec requests.agentFilter: optional agent ID allowlist. Omit to forward approvals for all agents.sessionFilter: optional session key patterns (substring or regex).target: where to send approval prompts."dm"(default),"channel"(originating room), or"both".- Per-account overrides:
channels.matrix.accounts.<id>.execApprovals.
channels.matrix.dm.sessionScopecontrols how Matrix DMs group into sessions:per-user(default) shares by routed peer, whileper-roomisolates each DM room.- Matrix status probes and live directory lookups use the same proxy policy as runtime traffic.
- Full Matrix configuration, targeting rules, and setup examples are documented in Matrix.
Microsoft Teams
Microsoft Teams is plugin-backed and configured underchannels.msteams.
- Core key paths covered here:
channels.msteams,channels.msteams.configWrites. - Full Teams config (credentials, webhook, DM/group policy, per-team/per-channel overrides) is documented in Microsoft Teams.
IRC
IRC is plugin-backed and configured underchannels.irc.
- Core key paths covered here:
channels.irc,channels.irc.dmPolicy,channels.irc.configWrites,channels.irc.nickserv.*. - Optional
channels.irc.defaultAccountoverrides default account selection when it matches a configured account id. - Full IRC channel configuration (host/port/TLS/channels/allowlists/mention gating) is documented in IRC.
Multi-account (all channels)
Run multiple accounts per channel (each with its ownaccountId):
defaultis used whenaccountIdis omitted (CLI + routing).- Env tokens only apply to the default account.
- Base channel settings apply to all accounts unless overridden per account.
- Use
bindings[].match.accountIdto route each account to a different agent. - If you add a non-default account via
openclaw channels add(or channel onboarding) while still on a single-account top-level channel config, OpenClaw promotes account-scoped top-level single-account values into the channel account map first so the original account keeps working. Most channels move them intochannels.<channel>.accounts.default; Matrix can preserve an existing matching named/default target instead. - Existing channel-only bindings (no
accountId) keep matching the default account; account-scoped bindings remain optional. openclaw doctor --fixalso repairs mixed shapes by moving account-scoped top-level single-account values into the promoted account chosen for that channel. Most channels useaccounts.default; Matrix can preserve an existing matching named/default target instead.
Other plugin channels
Many plugin channels are configured aschannels.<id> and documented in their dedicated channel pages (for example Feishu, Matrix, LINE, Nostr, Zalo, Nextcloud Talk, Synology Chat, and Twitch).
See the full channel index: Channels.
Group chat mention gating
Group messages default to require mention (metadata mention or safe regex patterns). Applies to WhatsApp, Telegram, Discord, Google Chat, and iMessage group chats. Mention types:- Metadata mentions: Native platform @-mentions. Ignored in WhatsApp self-chat mode.
- Text patterns: Safe regex patterns in
agents.list[].groupChat.mentionPatterns. Invalid patterns and unsafe nested repetition are ignored. - Mention gating is enforced only when detection is possible (native mentions or at least one pattern).
messages.groupChat.historyLimit sets the global default. Channels can override with channels.<channel>.historyLimit (or per-account). Set 0 to disable.
DM history limits
telegram, whatsapp, discord, slack, signal, imessage, msteams.
Self-chat mode
Include your own number inallowFrom to enable self-chat mode (ignores native @-mentions, only responds to text patterns):
Commands (chat command handling)
Command details
Command details
- This block configures command surfaces. For the current built-in + bundled command catalog, see Slash Commands.
- This page is a config-key reference, not the full command catalog. Channel/plugin-owned commands such as QQ Bot
/bot-ping/bot-help/bot-logs, LINE/card, device-pair/pair, memory/dreaming, phone-control/phone, and Talk/voiceare documented in their channel/plugin pages plus Slash Commands. - Text commands must be standalone messages with leading
/. native: "auto"turns on native commands for Discord/Telegram, leaves Slack off.nativeSkills: "auto"turns on native skill commands for Discord/Telegram, leaves Slack off.- Override per channel:
channels.discord.commands.native(bool or"auto").falseclears previously registered commands. - Override native skill registration per channel with
channels.<provider>.commands.nativeSkills. channels.telegram.customCommandsadds extra Telegram bot menu entries.bash: trueenables! <cmd>for host shell. Requirestools.elevated.enabledand sender intools.elevated.allowFrom.<channel>.config: trueenables/config(reads/writesopenclaw.json). For gatewaychat.sendclients, persistent/config set|unsetwrites also requireoperator.admin; read-only/config showstays available to normal write-scoped operator clients.mcp: trueenables/mcpfor OpenClaw-managed MCP server config undermcp.servers.plugins: trueenables/pluginsfor plugin discovery, install, and enable/disable controls.channels.<provider>.configWritesgates config mutations per channel (default: true).- For multi-account channels,
channels.<provider>.accounts.<id>.configWritesalso gates writes that target that account (for example/allowlist --config --account <id>or/config set channels.<provider>.accounts.<id>...). restart: falsedisables/restartand gateway restart tool actions. Default:true.ownerAllowFromis the explicit owner allowlist for owner-only commands/tools. It is separate fromallowFrom.ownerDisplay: "hash"hashes owner ids in the system prompt. SetownerDisplaySecretto control hashing.allowFromis per-provider. When set, it is the only authorization source (channel allowlists/pairing anduseAccessGroupsare ignored).useAccessGroups: falseallows commands to bypass access-group policies whenallowFromis not set.- Command docs map:
Agent defaults
agents.defaults.workspace
Default: ~/.openclaw/workspace.
agents.defaults.repoRoot
Optional repository root shown in the system prompt’s Runtime line. If unset, OpenClaw auto-detects by walking upward from the workspace.
agents.defaults.skills
Optional default skill allowlist for agents that do not set
agents.list[].skills.
- Omit
agents.defaults.skillsfor unrestricted skills by default. - Omit
agents.list[].skillsto inherit the defaults. - Set
agents.list[].skills: []for no skills. - A non-empty
agents.list[].skillslist is the final set for that agent; it does not merge with defaults.
agents.defaults.skipBootstrap
Disables automatic creation of workspace bootstrap files (AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, BOOTSTRAP.md).
agents.defaults.contextInjection
Controls when workspace bootstrap files are injected into the system prompt. Default: "always".
"continuation-skip": safe continuation turns (after a completed assistant response) skip workspace bootstrap re-injection, reducing prompt size. Heartbeat runs and post-compaction retries still rebuild context.
agents.defaults.bootstrapMaxChars
Max characters per workspace bootstrap file before truncation. Default: 12000.
agents.defaults.bootstrapTotalMaxChars
Max total characters injected across all workspace bootstrap files. Default: 60000.
agents.defaults.bootstrapPromptTruncationWarning
Controls agent-visible warning text when bootstrap context is truncated.
Default: "once".
"off": never inject warning text into the system prompt."once": inject warning once per unique truncation signature (recommended)."always": inject warning on every run when truncation exists.
Context budget ownership map
OpenClaw has multiple high-volume prompt/context budgets, and they are intentionally split by subsystem instead of all flowing through one generic knob.agents.defaults.bootstrapMaxChars/agents.defaults.bootstrapTotalMaxChars: normal workspace bootstrap injection.agents.defaults.startupContext.*: one-shot/newand/resetstartup prelude, including recent dailymemory/*.mdfiles.skills.limits.*: the compact skills list injected into the system prompt.agents.defaults.contextLimits.*: bounded runtime excerpts and injected runtime-owned blocks.memory.qmd.limits.*: indexed memory-search snippet and injection sizing.
agents.list[].skillsLimits.maxSkillsPromptCharsagents.list[].contextLimits.*
agents.defaults.startupContext
Controls the first-turn startup prelude injected on bare /new and /reset
runs.
agents.defaults.contextLimits
Shared defaults for bounded runtime context surfaces.
memoryGetMaxChars: defaultmemory_getexcerpt cap before truncation metadata and continuation notice are added.memoryGetDefaultLines: defaultmemory_getline window whenlinesis omitted.toolResultMaxChars: live tool-result cap used for persisted results and overflow recovery.postCompactionMaxChars: AGENTS.md excerpt cap used during post-compaction refresh injection.
agents.list[].contextLimits
Per-agent override for the shared contextLimits knobs. Omitted fields inherit
from agents.defaults.contextLimits.
skills.limits.maxSkillsPromptChars
Global cap for the compact skills list injected into the system prompt. This
does not affect reading SKILL.md files on demand.
agents.list[].skillsLimits.maxSkillsPromptChars
Per-agent override for the skills prompt budget.
agents.defaults.imageMaxDimensionPx
Max pixel size for the longest image side in transcript/tool image blocks before provider calls.
Default: 1200.
Lower values usually reduce vision-token usage and request payload size for screenshot-heavy runs.
Higher values preserve more visual detail.
agents.defaults.userTimezone
Timezone for system prompt context (not message timestamps). Falls back to host timezone.
agents.defaults.timeFormat
Time format in system prompt. Default: auto (OS preference).
agents.defaults.model
model: accepts either a string ("provider/model") or an object ({ primary, fallbacks }).- String form sets only the primary model.
- Object form sets primary plus ordered failover models.
imageModel: accepts either a string ("provider/model") or an object ({ primary, fallbacks }).- Used by the
imagetool path as its vision-model config. - Also used as fallback routing when the selected/default model cannot accept image input.
- Used by the
imageGenerationModel: accepts either a string ("provider/model") or an object ({ primary, fallbacks }).- Used by the shared image-generation capability and any future tool/plugin surface that generates images.
- Typical values:
google/gemini-3.1-flash-image-previewfor native Gemini image generation,fal/fal-ai/flux/devfor fal, oropenai/gpt-image-2for OpenAI Images. - If you select a provider/model directly, configure the matching provider auth/API key too (for example
GEMINI_API_KEYorGOOGLE_API_KEYforgoogle/*,OPENAI_API_KEYforopenai/*,FAL_KEYforfal/*). - If omitted,
image_generatecan still infer an auth-backed provider default. It tries the current default provider first, then the remaining registered image-generation providers in provider-id order.
musicGenerationModel: accepts either a string ("provider/model") or an object ({ primary, fallbacks }).- Used by the shared music-generation capability and the built-in
music_generatetool. - Typical values:
google/lyria-3-clip-preview,google/lyria-3-pro-preview, orminimax/music-2.5+. - If omitted,
music_generatecan still infer an auth-backed provider default. It tries the current default provider first, then the remaining registered music-generation providers in provider-id order. - If you select a provider/model directly, configure the matching provider auth/API key too.
- Used by the shared music-generation capability and the built-in
videoGenerationModel: accepts either a string ("provider/model") or an object ({ primary, fallbacks }).- Used by the shared video-generation capability and the built-in
video_generatetool. - Typical values:
qwen/wan2.6-t2v,qwen/wan2.6-i2v,qwen/wan2.6-r2v,qwen/wan2.6-r2v-flash, orqwen/wan2.7-r2v. - If omitted,
video_generatecan still infer an auth-backed provider default. It tries the current default provider first, then the remaining registered video-generation providers in provider-id order. - If you select a provider/model directly, configure the matching provider auth/API key too.
- The bundled Qwen video-generation provider supports up to 1 output video, 1 input image, 4 input videos, 10 seconds duration, and provider-level
size,aspectRatio,resolution,audio, andwatermarkoptions.
- Used by the shared video-generation capability and the built-in
pdfModel: accepts either a string ("provider/model") or an object ({ primary, fallbacks }).- Used by the
pdftool for model routing. - If omitted, the PDF tool falls back to
imageModel, then to the resolved session/default model.
- Used by the
pdfMaxBytesMb: default PDF size limit for thepdftool whenmaxBytesMbis not passed at call time.pdfMaxPages: default maximum pages considered by extraction fallback mode in thepdftool.verboseDefault: default verbose level for agents. Values:"off","on","full". Default:"off".elevatedDefault: default elevated-output level for agents. Values:"off","on","ask","full". Default:"on".model.primary: formatprovider/model(e.g.openai/gpt-5.4). If you omit the provider, OpenClaw tries an alias first, then a unique configured-provider match for that exact model id, and only then falls back to the configured default provider (deprecated compatibility behavior, so prefer explicitprovider/model). If that provider no longer exposes the configured default model, OpenClaw falls back to the first configured provider/model instead of surfacing a stale removed-provider default.models: the configured model catalog and allowlist for/model. Each entry can includealias(shortcut) andparams(provider-specific, for exampletemperature,maxTokens,cacheRetention,context1m).- Safe edits: use
openclaw config set agents.defaults.models '<json>' --strict-json --mergeto add entries.config setrefuses replacements that would remove existing allowlist entries unless you pass--replace. - Provider-scoped configure/onboarding flows merge selected provider models into this map and preserve unrelated providers already configured.
- Safe edits: use
params: global default provider parameters applied to all models. Set atagents.defaults.params(e.g.{ cacheRetention: "long" }).paramsmerge precedence (config):agents.defaults.params(global base) is overridden byagents.defaults.models["provider/model"].params(per-model), thenagents.list[].params(matching agent id) overrides by key. See Prompt Caching for details.embeddedHarness: default low-level embedded agent runtime policy. Useruntime: "auto"to let registered plugin harnesses claim supported models,runtime: "pi"to force the built-in PI harness, or a registered harness id such asruntime: "codex". Setfallback: "none"to disable automatic PI fallback.- Config writers that mutate these fields (for example
/models set,/models set-image, and fallback add/remove commands) save canonical object form and preserve existing fallback lists when possible. maxConcurrent: max parallel agent runs across sessions (each session still serialized). Default: 4.
agents.defaults.embeddedHarness
embeddedHarness controls which low-level executor runs embedded agent turns.
Most deployments should keep the default { runtime: "auto", fallback: "pi" }.
Use it when a trusted plugin provides a native harness, such as the bundled
Codex app-server harness.
runtime:"auto","pi", or a registered plugin harness id. The bundled Codex plugin registerscodex.fallback:"pi"or"none"."pi"keeps the built-in PI harness as the compatibility fallback when no plugin harness is selected."none"makes missing or unsupported plugin harness selection fail instead of silently using PI. Selected plugin harness failures always surface directly.- Environment overrides:
OPENCLAW_AGENT_RUNTIME=<id|auto|pi>overridesruntime;OPENCLAW_AGENT_HARNESS_FALLBACK=nonedisables PI fallback for that process. - For Codex-only deployments, set
model: "codex/gpt-5.4",embeddedHarness.runtime: "codex", andembeddedHarness.fallback: "none". - This only controls the embedded chat harness. Media generation, vision, PDF, music, video, and TTS still use their provider/model settings.
agents.defaults.models):
| Alias | Model |
|---|---|
opus | anthropic/claude-opus-4-6 |
sonnet | anthropic/claude-sonnet-4-6 |
gpt | openai/gpt-5.4 |
gpt-mini | openai/gpt-5.4-mini |
gpt-nano | openai/gpt-5.4-nano |
gemini | google/gemini-3.1-pro-preview |
gemini-flash | google/gemini-3-flash-preview |
gemini-flash-lite | google/gemini-3.1-flash-lite-preview |
--thinking off or define agents.defaults.models["zai/<model>"].params.thinking yourself.
Z.AI models enable tool_stream by default for tool call streaming. Set agents.defaults.models["zai/<model>"].params.tool_stream to false to disable it.
Anthropic Claude 4.6 models default to adaptive thinking when no explicit thinking level is set.
agents.defaults.cliBackends
Optional CLI backends for text-only fallback runs (no tool calls). Useful as a backup when API providers fail.
- CLI backends are text-first; tools are always disabled.
- Sessions supported when
sessionArgis set. - Image pass-through supported when
imageArgaccepts file paths.
agents.defaults.systemPromptOverride
Replace the entire OpenClaw-assembled system prompt with a fixed string. Set at the default level (agents.defaults.systemPromptOverride) or per agent (agents.list[].systemPromptOverride). Per-agent values take precedence; an empty or whitespace-only value is ignored. Useful for controlled prompt experiments.
agents.defaults.promptOverlays
Provider-independent prompt overlays applied by model family. GPT-5-family model ids receive the shared behavior contract across providers; personality controls only the friendly interaction-style layer.
"friendly"(default) and"on"enable the friendly interaction-style layer."off"disables only the friendly layer; the tagged GPT-5 behavior contract remains enabled.- Legacy
plugins.entries.openai.config.personalityis still read when this shared setting is unset.
agents.defaults.heartbeat
Periodic heartbeat runs.
every: duration string (ms/s/m/h). Default:30m(API-key auth) or1h(OAuth auth). Set to0mto disable.includeSystemPromptSection: when false, omits the Heartbeat section from the system prompt and skipsHEARTBEAT.mdinjection into bootstrap context. Default:true.suppressToolErrorWarnings: when true, suppresses tool error warning payloads during heartbeat runs.timeoutSeconds: maximum time in seconds allowed for a heartbeat agent turn before it is aborted. Leave unset to useagents.defaults.timeoutSeconds.directPolicy: direct/DM delivery policy.allow(default) permits direct-target delivery.blocksuppresses direct-target delivery and emitsreason=dm-blocked.lightContext: when true, heartbeat runs use lightweight bootstrap context and keep onlyHEARTBEAT.mdfrom workspace bootstrap files.isolatedSession: when true, each heartbeat runs in a fresh session with no prior conversation history. Same isolation pattern as cronsessionTarget: "isolated". Reduces per-heartbeat token cost from ~100K to ~2-5K tokens.- Per-agent: set
agents.list[].heartbeat. When any agent definesheartbeat, only those agents run heartbeats. - Heartbeats run full agent turns — shorter intervals burn more tokens.
agents.defaults.compaction
mode:defaultorsafeguard(chunked summarization for long histories). See Compaction.provider: id of a registered compaction provider plugin. When set, the provider’ssummarize()is called instead of built-in LLM summarization. Falls back to built-in on failure. Setting a provider forcesmode: "safeguard". See Compaction.timeoutSeconds: maximum seconds allowed for a single compaction operation before OpenClaw aborts it. Default:900.identifierPolicy:strict(default),off, orcustom.strictprepends built-in opaque identifier retention guidance during compaction summarization.identifierInstructions: optional custom identifier-preservation text used whenidentifierPolicy=custom.postCompactionSections: optional AGENTS.md H2/H3 section names to re-inject after compaction. Defaults to["Session Startup", "Red Lines"]; set[]to disable reinjection. When unset or explicitly set to that default pair, olderEvery Session/Safetyheadings are also accepted as a legacy fallback.model: optionalprovider/model-idoverride for compaction summarization only. Use this when the main session should keep one model but compaction summaries should run on another; when unset, compaction uses the session’s primary model.notifyUser: whentrue, sends brief notices to the user when compaction starts and when it completes (for example, “Compacting context…” and “Compaction complete”). Disabled by default to keep compaction silent.memoryFlush: silent agentic turn before auto-compaction to store durable memories. Skipped when workspace is read-only.
agents.defaults.contextPruning
Prunes old tool results from in-memory context before sending to the LLM. Does not modify session history on disk.
cache-ttl mode behavior
cache-ttl mode behavior
mode: "cache-ttl"enables pruning passes.ttlcontrols how often pruning can run again (after the last cache touch).- Pruning soft-trims oversized tool results first, then hard-clears older tool results if needed.
... in the middle.Hard-clear replaces the entire tool result with the placeholder.Notes:- Image blocks are never trimmed/cleared.
- Ratios are character-based (approximate), not exact token counts.
- If fewer than
keepLastAssistantsassistant messages exist, pruning is skipped.
Block streaming
- Non-Telegram channels require explicit
*.blockStreaming: trueto enable block replies. - Channel overrides:
channels.<channel>.blockStreamingCoalesce(and per-account variants). Signal/Slack/Discord/Google Chat defaultminChars: 1500. humanDelay: randomized pause between block replies.natural= 800–2500ms. Per-agent override:agents.list[].humanDelay.
Typing indicators
- Defaults:
instantfor direct chats/mentions,messagefor unmentioned group chats. - Per-session overrides:
session.typingMode,session.typingIntervalSeconds.
agents.defaults.sandbox
Optional sandboxing for the embedded agent. See Sandboxing for the full guide.
Sandbox details
Sandbox details
Backend:OpenShell mode:
docker: local Docker runtime (default)ssh: generic SSH-backed remote runtimeopenshell: OpenShell runtime
backend: "openshell" is selected, runtime-specific settings move to
plugins.entries.openshell.config.SSH backend config:target: SSH target inuser@host[:port]formcommand: SSH client command (default:ssh)workspaceRoot: absolute remote root used for per-scope workspacesidentityFile/certificateFile/knownHostsFile: existing local files passed to OpenSSHidentityData/certificateData/knownHostsData: inline contents or SecretRefs that OpenClaw materializes into temp files at runtimestrictHostKeyChecking/updateHostKeys: OpenSSH host-key policy knobs
identityDatawins overidentityFilecertificateDatawins overcertificateFileknownHostsDatawins overknownHostsFile- SecretRef-backed
*Datavalues are resolved from the active secrets runtime snapshot before the sandbox session starts
- seeds the remote workspace once after create or recreate
- then keeps the remote SSH workspace canonical
- routes
exec, file tools, and media paths over SSH - does not sync remote changes back to the host automatically
- does not support sandbox browser containers
none: per-scope sandbox workspace under~/.openclaw/sandboxesro: sandbox workspace at/workspace, agent workspace mounted read-only at/agentrw: agent workspace mounted read/write at/workspace
session: per-session container + workspaceagent: one container + workspace per agent (default)shared: shared container and workspace (no cross-session isolation)
mirror: seed remote from local before exec, sync back after exec; local workspace stays canonicalremote: seed remote once when the sandbox is created, then keep the remote workspace canonical
remote mode, host-local edits made outside OpenClaw are not synced into the sandbox automatically after the seed step.
Transport is SSH into the OpenShell sandbox, but the plugin owns sandbox lifecycle and optional mirror sync.setupCommand runs once after container creation (via sh -lc). Needs network egress, writable root, root user.Containers default to network: "none" — set to "bridge" (or a custom bridge network) if the agent needs outbound access.
"host" is blocked. "container:<id>" is blocked by default unless you explicitly set
sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true (break-glass).Inbound attachments are staged into media/inbound/* in the active workspace.docker.binds mounts additional host directories; global and per-agent binds are merged.Sandboxed browser (sandbox.browser.enabled): Chromium + CDP in a container. noVNC URL injected into system prompt. Does not require browser.enabled in openclaw.json.
noVNC observer access uses VNC auth by default and OpenClaw emits a short-lived token URL (instead of exposing the password in the shared URL).allowHostControl: false(default) blocks sandboxed sessions from targeting the host browser.networkdefaults toopenclaw-sandbox-browser(dedicated bridge network). Set tobridgeonly when you explicitly want global bridge connectivity.cdpSourceRangeoptionally restricts CDP ingress at the container edge to a CIDR range (for example172.21.0.1/32).sandbox.browser.bindsmounts additional host directories into the sandbox browser container only. When set (including[]), it replacesdocker.bindsfor the browser container.- Launch defaults are defined in
scripts/sandbox-browser-entrypoint.shand tuned for container hosts:--remote-debugging-address=127.0.0.1--remote-debugging-port=<derived from OPENCLAW_BROWSER_CDP_PORT>--user-data-dir=${HOME}/.chrome--no-first-run--no-default-browser-check--disable-3d-apis--disable-gpu--disable-software-rasterizer--disable-dev-shm-usage--disable-background-networking--disable-features=TranslateUI--disable-breakpad--disable-crash-reporter--renderer-process-limit=2--no-zygote--metrics-recording-only--disable-extensions(default enabled)--disable-3d-apis,--disable-software-rasterizer, and--disable-gpuare enabled by default and can be disabled withOPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0if WebGL/3D usage requires it.OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0re-enables extensions if your workflow depends on them.--renderer-process-limit=2can be changed withOPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=<N>; set0to use Chromium’s default process limit.- plus
--no-sandboxand--disable-setuid-sandboxwhennoSandboxis enabled. - Defaults are the container image baseline; use a custom browser image with a custom entrypoint to change container defaults.
sandbox.docker.binds are Docker-only.
Build images:
agents.list (per-agent overrides)
id: stable agent id (required).default: when multiple are set, first wins (warning logged). If none set, first list entry is default.model: string form overridesprimaryonly; object form{ primary, fallbacks }overrides both ([]disables global fallbacks). Cron jobs that only overrideprimarystill inherit default fallbacks unless you setfallbacks: [].params: per-agent stream params merged over the selected model entry inagents.defaults.models. Use this for agent-specific overrides likecacheRetention,temperature, ormaxTokenswithout duplicating the whole model catalog.skills: optional per-agent skill allowlist. If omitted, the agent inheritsagents.defaults.skillswhen set; an explicit list replaces defaults instead of merging, and[]means no skills.thinkingDefault: optional per-agent default thinking level (off | minimal | low | medium | high | xhigh | adaptive | max). Overridesagents.defaults.thinkingDefaultfor this agent when no per-message or session override is set.reasoningDefault: optional per-agent default reasoning visibility (on | off | stream). Applies when no per-message or session reasoning override is set.fastModeDefault: optional per-agent default for fast mode (true | false). Applies when no per-message or session fast-mode override is set.embeddedHarness: optional per-agent low-level harness policy override. Use{ runtime: "codex", fallback: "none" }to make one agent Codex-only while other agents keep the default PI fallback.runtime: optional per-agent runtime descriptor. Usetype: "acp"withruntime.acpdefaults (agent,backend,mode,cwd) when the agent should default to ACP harness sessions.identity.avatar: workspace-relative path,http(s)URL, ordata:URI.identityderives defaults:ackReactionfromemoji,mentionPatternsfromname/emoji.subagents.allowAgents: allowlist of agent ids forsessions_spawn(["*"]= any; default: same agent only).- Sandbox inheritance guard: if the requester session is sandboxed,
sessions_spawnrejects targets that would run unsandboxed. subagents.requireAgentId: when true, blocksessions_spawncalls that omitagentId(forces explicit profile selection; default: false).
Multi-agent routing
Run multiple isolated agents inside one Gateway. See Multi-Agent.Binding match fields
type(optional):routefor normal routing (missing type defaults to route),acpfor persistent ACP conversation bindings.match.channel(required)match.accountId(optional;*= any account; omitted = default account)match.peer(optional;{ kind: direct|group|channel, id })match.guildId/match.teamId(optional; channel-specific)acp(optional; only fortype: "acp"):{ mode, label, cwd, backend }
match.peermatch.guildIdmatch.teamIdmatch.accountId(exact, no peer/guild/team)match.accountId: "*"(channel-wide)- Default agent
bindings entry wins.
For type: "acp" entries, OpenClaw resolves by exact conversation identity (match.channel + account + match.peer.id) and does not use the route binding tier order above.
Per-agent access profiles
Full access (no sandbox)
Full access (no sandbox)
Read-only tools + workspace
Read-only tools + workspace
No filesystem access (messaging only)
No filesystem access (messaging only)
Session
Session field details
Session field details
scope: base session grouping strategy for group-chat contexts.per-sender(default): each sender gets an isolated session within a channel context.global: all participants in a channel context share a single session (use only when shared context is intended).
dmScope: how DMs are grouped.main: all DMs share the main session.per-peer: isolate by sender id across channels.per-channel-peer: isolate per channel + sender (recommended for multi-user inboxes).per-account-channel-peer: isolate per account + channel + sender (recommended for multi-account).
identityLinks: map canonical ids to provider-prefixed peers for cross-channel session sharing.reset: primary reset policy.dailyresets atatHourlocal time;idleresets afteridleMinutes. When both configured, whichever expires first wins.resetByType: per-type overrides (direct,group,thread). Legacydmaccepted as alias fordirect.parentForkMaxTokens: max parent-sessiontotalTokensallowed when creating a forked thread session (default100000).- If parent
totalTokensis above this value, OpenClaw starts a fresh thread session instead of inheriting parent transcript history. - Set
0to disable this guard and always allow parent forking.
- If parent
mainKey: legacy field. Runtime always uses"main"for the main direct-chat bucket.agentToAgent.maxPingPongTurns: maximum reply-back turns between agents during agent-to-agent exchanges (integer, range:0–5).0disables ping-pong chaining.sendPolicy: match bychannel,chatType(direct|group|channel, with legacydmalias),keyPrefix, orrawKeyPrefix. First deny wins.maintenance: session-store cleanup + retention controls.mode:warnemits warnings only;enforceapplies cleanup.pruneAfter: age cutoff for stale entries (default30d).maxEntries: maximum number of entries insessions.json(default500).rotateBytes: rotatesessions.jsonwhen it exceeds this size (default10mb).resetArchiveRetention: retention for*.reset.<timestamp>transcript archives. Defaults topruneAfter; setfalseto disable.maxDiskBytes: optional sessions-directory disk budget. Inwarnmode it logs warnings; inenforcemode it removes oldest artifacts/sessions first.highWaterBytes: optional target after budget cleanup. Defaults to80%ofmaxDiskBytes.
threadBindings: global defaults for thread-bound session features.enabled: master default switch (providers can override; Discord useschannels.discord.threadBindings.enabled)idleHours: default inactivity auto-unfocus in hours (0disables; providers can override)maxAgeHours: default hard max age in hours (0disables; providers can override)
Messages
Response prefix
Per-channel/account overrides:channels.<channel>.responsePrefix, channels.<channel>.accounts.<id>.responsePrefix.
Resolution (most specific wins): account → channel → global. "" disables and stops cascade. "auto" derives [{identity.name}].
Template variables:
| Variable | Description | Example |
|---|---|---|
{model} | Short model name | claude-opus-4-6 |
{modelFull} | Full model identifier | anthropic/claude-opus-4-6 |
{provider} | Provider name | anthropic |
{thinkingLevel} | Current thinking level | high, low, off |
{identity.name} | Agent identity name | (same as "auto") |
{think} is an alias for {thinkingLevel}.
Ack reaction
- Defaults to active agent’s
identity.emoji, otherwise"👀". Set""to disable. - Per-channel overrides:
channels.<channel>.ackReaction,channels.<channel>.accounts.<id>.ackReaction. - Resolution order: account → channel →
messages.ackReaction→ identity fallback. - Scope:
group-mentions(default),group-all,direct,all. removeAckAfterReply: removes ack after reply on Slack, Discord, and Telegram.messages.statusReactions.enabled: enables lifecycle status reactions on Slack, Discord, and Telegram. On Slack and Discord, unset keeps status reactions enabled when ack reactions are active. On Telegram, set it explicitly totrueto enable lifecycle status reactions.
Inbound debounce
Batches rapid text-only messages from the same sender into a single agent turn. Media/attachments flush immediately. Control commands bypass debouncing.TTS (text-to-speech)
autocontrols the default auto-TTS mode:off,always,inbound, ortagged./tts on|offcan override local prefs, and/tts statusshows the effective state.summaryModeloverridesagents.defaults.model.primaryfor auto-summary.modelOverridesis enabled by default;modelOverrides.allowProviderdefaults tofalse(opt-in).- API keys fall back to
ELEVENLABS_API_KEY/XI_API_KEYandOPENAI_API_KEY. openai.baseUrloverrides the OpenAI TTS endpoint. Resolution order is config, thenOPENAI_TTS_BASE_URL, thenhttps://api.openai.com/v1.- When
openai.baseUrlpoints to a non-OpenAI endpoint, OpenClaw treats it as an OpenAI-compatible TTS server and relaxes model/voice validation.
Talk
Defaults for Talk mode (macOS/iOS/Android).talk.providermust match a key intalk.providerswhen multiple Talk providers are configured.- Legacy flat Talk keys (
talk.voiceId,talk.voiceAliases,talk.modelId,talk.outputFormat,talk.apiKey) are compatibility-only and are auto-migrated intotalk.providers.<provider>. - Voice IDs fall back to
ELEVENLABS_VOICE_IDorSAG_VOICE_ID. providers.*.apiKeyaccepts plaintext strings or SecretRef objects.ELEVENLABS_API_KEYfallback applies only when no Talk API key is configured.providers.*.voiceAliaseslets Talk directives use friendly names.silenceTimeoutMscontrols how long Talk mode waits after user silence before it sends the transcript. Unset keeps the platform default pause window (700 ms on macOS and Android, 900 ms on iOS).
Tools
Tool profiles
tools.profile sets a base allowlist before tools.allow/tools.deny:
Local onboarding defaults new local configs to tools.profile: "coding" when unset (existing explicit profiles are preserved).
| Profile | Includes |
|---|---|
minimal | session_status only |
coding | group:fs, group:runtime, group:web, group:sessions, group:memory, cron, image, image_generate, video_generate |
messaging | group:messaging, sessions_list, sessions_history, sessions_send, session_status |
full | No restriction (same as unset) |
Tool groups
| Group | Tools |
|---|---|
group:runtime | exec, process, code_execution (bash is accepted as an alias for exec) |
group:fs | read, write, edit, apply_patch |
group:sessions | sessions_list, sessions_history, sessions_send, sessions_spawn, sessions_yield, subagents, session_status |
group:memory | memory_search, memory_get |
group:web | web_search, x_search, web_fetch |
group:ui | browser, canvas |
group:automation | cron, gateway |
group:messaging | message |
group:nodes | nodes |
group:agents | agents_list |
group:media | image, image_generate, video_generate, tts |
group:openclaw | All built-in tools (excludes provider plugins) |
tools.allow / tools.deny
Global tool allow/deny policy (deny wins). Case-insensitive, supports * wildcards. Applied even when Docker sandbox is off.
tools.byProvider
Further restrict tools for specific providers or models. Order: base profile → provider profile → allow/deny.
tools.elevated
Controls elevated exec access outside the sandbox:
- Per-agent override (
agents.list[].tools.elevated) can only further restrict. /elevated on|off|ask|fullstores state per session; inline directives apply to single message.- Elevated
execbypasses sandboxing and uses the configured escape path (gatewayby default, ornodewhen the exec target isnode).
tools.exec
tools.loopDetection
Tool-loop safety checks are disabled by default. Set enabled: true to activate detection.
Settings can be defined globally in tools.loopDetection and overridden per-agent at agents.list[].tools.loopDetection.
historySize: max tool-call history retained for loop analysis.warningThreshold: repeating no-progress pattern threshold for warnings.criticalThreshold: higher repeating threshold for blocking critical loops.globalCircuitBreakerThreshold: hard stop threshold for any no-progress run.detectors.genericRepeat: warn on repeated same-tool/same-args calls.detectors.knownPollNoProgress: warn/block on known poll tools (process.poll,command_status, etc.).detectors.pingPong: warn/block on alternating no-progress pair patterns.- If
warningThreshold >= criticalThresholdorcriticalThreshold >= globalCircuitBreakerThreshold, validation fails.
tools.web
tools.media
Configures inbound media understanding (image/audio/video):
Media model entry fields
Media model entry fields
Provider entry (
type: "provider" or omitted):provider: API provider id (openai,anthropic,google/gemini,groq, etc.)model: model id overrideprofile/preferredProfile:auth-profiles.jsonprofile selection
type: "cli"):command: executable to runargs: templated args (supports{{MediaPath}},{{Prompt}},{{MaxChars}}, etc.)
capabilities: optional list (image,audio,video). Defaults:openai/anthropic/minimax→ image,google→ image+audio+video,groq→ audio.prompt,maxChars,maxBytes,timeoutSeconds,language: per-entry overrides.- Failures fall back to the next entry.
auth-profiles.json → env vars → models.providers.*.apiKey.Async completion fields:asyncCompletion.directSend: whentrue, completed asyncmusic_generateandvideo_generatetasks try direct channel delivery first. Default:false(legacy requester-session wake/model-delivery path).
tools.agentToAgent
tools.sessions
Controls which sessions can be targeted by the session tools (sessions_list, sessions_history, sessions_send).
Default: tree (current session + sessions spawned by it, such as subagents).
self: only the current session key.tree: current session + sessions spawned by the current session (subagents).agent: any session belonging to the current agent id (can include other users if you run per-sender sessions under the same agent id).all: any session. Cross-agent targeting still requirestools.agentToAgent.- Sandbox clamp: when the current session is sandboxed and
agents.defaults.sandbox.sessionToolsVisibility="spawned", visibility is forced totreeeven iftools.sessions.visibility="all".
tools.sessions_spawn
Controls inline attachment support for sessions_spawn.
- Attachments are only supported for
runtime: "subagent". ACP runtime rejects them. - Files are materialized into the child workspace at
.openclaw/attachments/<uuid>/with a.manifest.json. - Attachment content is automatically redacted from transcript persistence.
- Base64 inputs are validated with strict alphabet/padding checks and a pre-decode size guard.
- File permissions are
0700for directories and0600for files. - Cleanup follows the
cleanuppolicy:deletealways removes attachments;keepretains them only whenretainOnSessionKeep: true.
tools.experimental
Experimental built-in tool flags. Default off unless a strict-agentic GPT-5 auto-enable rule applies.
planTool: enables the structuredupdate_plantool for non-trivial multi-step work tracking.- Default:
falseunlessagents.defaults.embeddedPi.executionContract(or a per-agent override) is set to"strict-agentic"for an OpenAI or OpenAI Codex GPT-5-family run. Settrueto force the tool on outside that scope, orfalseto keep it off even for strict-agentic GPT-5 runs. - When enabled, the system prompt also adds usage guidance so the model only uses it for substantial work and keeps at most one step
in_progress.
agents.defaults.subagents
model: default model for spawned sub-agents. If omitted, sub-agents inherit the caller’s model.allowAgents: default allowlist of target agent ids forsessions_spawnwhen the requester agent does not set its ownsubagents.allowAgents(["*"]= any; default: same agent only).runTimeoutSeconds: default timeout (seconds) forsessions_spawnwhen the tool call omitsrunTimeoutSeconds.0means no timeout.- Per-subagent tool policy:
tools.subagents.tools.allow/tools.subagents.tools.deny.
Custom providers and base URLs
OpenClaw uses the built-in model catalog. Add custom providers viamodels.providers in config or ~/.openclaw/agents/<agentId>/agent/models.json.
- Use
authHeader: true+headersfor custom auth needs. - Override agent config root with
OPENCLAW_AGENT_DIR(orPI_CODING_AGENT_DIR, a legacy environment variable alias). - Merge precedence for matching provider IDs:
- Non-empty agent
models.jsonbaseUrlvalues win. - Non-empty agent
apiKeyvalues win only when that provider is not SecretRef-managed in current config/auth-profile context. - SecretRef-managed provider
apiKeyvalues are refreshed from source markers (ENV_VAR_NAMEfor env refs,secretref-managedfor file/exec refs) instead of persisting resolved secrets. - SecretRef-managed provider header values are refreshed from source markers (
secretref-env:ENV_VAR_NAMEfor env refs,secretref-managedfor file/exec refs). - Empty or missing agent
apiKey/baseUrlfall back tomodels.providersin config. - Matching model
contextWindow/maxTokensuse the higher value between explicit config and implicit catalog values. - Matching model
contextTokenspreserves an explicit runtime cap when present; use it to limit effective context without changing native model metadata. - Use
models.mode: "replace"when you want config to fully rewritemodels.json. - Marker persistence is source-authoritative: markers are written from the active source config snapshot (pre-resolution), not from resolved runtime secret values.
- Non-empty agent
Provider field details
models.mode: provider catalog behavior (mergeorreplace).models.providers: custom provider map keyed by provider id.- Safe edits: use
openclaw config set models.providers.<id> '<json>' --strict-json --mergeoropenclaw config set models.providers.<id>.models '<json-array>' --strict-json --mergefor additive updates.config setrefuses destructive replacements unless you pass--replace.
- Safe edits: use
models.providers.*.api: request adapter (openai-completions,openai-responses,anthropic-messages,google-generative-ai, etc).models.providers.*.apiKey: provider credential (prefer SecretRef/env substitution).models.providers.*.auth: auth strategy (api-key,token,oauth,aws-sdk).models.providers.*.injectNumCtxForOpenAICompat: for Ollama +openai-completions, injectoptions.num_ctxinto requests (default:true).models.providers.*.authHeader: force credential transport in theAuthorizationheader when required.models.providers.*.baseUrl: upstream API base URL.models.providers.*.headers: extra static headers for proxy/tenant routing.models.providers.*.request: transport overrides for model-provider HTTP requests.request.headers: extra headers (merged with provider defaults). Values accept SecretRef.request.auth: auth strategy override. Modes:"provider-default"(use provider’s built-in auth),"authorization-bearer"(withtoken),"header"(withheaderName,value, optionalprefix).request.proxy: HTTP proxy override. Modes:"env-proxy"(useHTTP_PROXY/HTTPS_PROXYenv vars),"explicit-proxy"(withurl). Both modes accept an optionaltlssub-object.request.tls: TLS override for direct connections. Fields:ca,cert,key,passphrase(all accept SecretRef),serverName,insecureSkipVerify.request.allowPrivateNetwork: whentrue, allow HTTPS tobaseUrlwhen DNS resolves to private, CGNAT, or similar ranges, via the provider HTTP fetch guard (operator opt-in for trusted self-hosted OpenAI-compatible endpoints). WebSocket uses the samerequestfor headers/TLS but not that fetch SSRF gate. Defaultfalse.
models.providers.*.models: explicit provider model catalog entries.models.providers.*.models.*.contextWindow: native model context window metadata.models.providers.*.models.*.contextTokens: optional runtime context cap. Use this when you want a smaller effective context budget than the model’s nativecontextWindow.models.providers.*.models.*.compat.supportsDeveloperRole: optional compatibility hint. Forapi: "openai-completions"with a non-empty non-nativebaseUrl(host notapi.openai.com), OpenClaw forces this tofalseat runtime. Empty/omittedbaseUrlkeeps default OpenAI behavior.models.providers.*.models.*.compat.requiresStringContent: optional compatibility hint for string-only OpenAI-compatible chat endpoints. Whentrue, OpenClaw flattens pure textmessages[].contentarrays into plain strings before sending the request.plugins.entries.amazon-bedrock.config.discovery: Bedrock auto-discovery settings root.plugins.entries.amazon-bedrock.config.discovery.enabled: turn implicit discovery on/off.plugins.entries.amazon-bedrock.config.discovery.region: AWS region for discovery.plugins.entries.amazon-bedrock.config.discovery.providerFilter: optional provider-id filter for targeted discovery.plugins.entries.amazon-bedrock.config.discovery.refreshInterval: polling interval for discovery refresh.plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow: fallback context window for discovered models.plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens: fallback max output tokens for discovered models.
Provider examples
Cerebras (GLM 4.6 / 4.7)
Cerebras (GLM 4.6 / 4.7)
cerebras/zai-glm-4.7 for Cerebras; zai/glm-4.7 for Z.AI direct.OpenCode
OpenCode
OPENCODE_API_KEY (or OPENCODE_ZEN_API_KEY). Use opencode/... refs for the Zen catalog or opencode-go/... refs for the Go catalog. Shortcut: openclaw onboard --auth-choice opencode-zen or openclaw onboard --auth-choice opencode-go.Z.AI (GLM-4.7)
Z.AI (GLM-4.7)
ZAI_API_KEY. z.ai/* and z-ai/* are accepted aliases. Shortcut: openclaw onboard --auth-choice zai-api-key.- General endpoint:
https://api.z.ai/api/paas/v4 - Coding endpoint (default):
https://api.z.ai/api/coding/paas/v4 - For the general endpoint, define a custom provider with the base URL override.
Moonshot AI (Kimi)
Moonshot AI (Kimi)
baseUrl: "https://api.moonshot.cn/v1" or openclaw onboard --auth-choice moonshot-api-key-cn.Native Moonshot endpoints advertise streaming usage compatibility on the shared
openai-completions transport, and OpenClaw keys that off endpoint capabilities
rather than the built-in provider id alone.Kimi Coding
Kimi Coding
openclaw onboard --auth-choice kimi-code-api-key.Synthetic (Anthropic-compatible)
Synthetic (Anthropic-compatible)
/v1 (Anthropic client appends it). Shortcut: openclaw onboard --auth-choice synthetic-api-key.MiniMax M2.7 (direct)
MiniMax M2.7 (direct)
MINIMAX_API_KEY. Shortcuts:
openclaw onboard --auth-choice minimax-global-api or
openclaw onboard --auth-choice minimax-cn-api.
The model catalog defaults to M2.7 only.
On the Anthropic-compatible streaming path, OpenClaw disables MiniMax thinking
by default unless you explicitly set thinking yourself. /fast on or
params.fastMode: true rewrites MiniMax-M2.7 to
MiniMax-M2.7-highspeed.Local models (LM Studio)
Local models (LM Studio)
See Local Models. TL;DR: run a large local model via LM Studio Responses API on serious hardware; keep hosted models merged for fallback.
Skills
allowBundled: optional allowlist for bundled skills only (managed/workspace skills unaffected).load.extraDirs: extra shared skill roots (lowest precedence).install.preferBrew: when true, prefer Homebrew installers whenbrewis available before falling back to other installer kinds.install.nodeManager: node installer preference formetadata.openclaw.installspecs (npm|pnpm|yarn|bun).entries.<skillKey>.enabled: falsedisables a skill even if bundled/installed.entries.<skillKey>.apiKey: convenience for skills declaring a primary env var (plaintext string or SecretRef object).
Plugins
- Loaded from
~/.openclaw/extensions,<workspace>/.openclaw/extensions, plusplugins.load.paths. - Discovery accepts native OpenClaw plugins plus compatible Codex bundles and Claude bundles, including manifestless Claude default-layout bundles.
- Config changes require a gateway restart.
allow: optional allowlist (only listed plugins load).denywins.plugins.entries.<id>.apiKey: plugin-level API key convenience field (when supported by the plugin).plugins.entries.<id>.env: plugin-scoped env var map.plugins.entries.<id>.hooks.allowPromptInjection: whenfalse, core blocksbefore_prompt_buildand ignores prompt-mutating fields from legacybefore_agent_start, while preserving legacymodelOverrideandproviderOverride. Applies to native plugin hooks and supported bundle-provided hook directories.plugins.entries.<id>.subagent.allowModelOverride: explicitly trust this plugin to request per-runproviderandmodeloverrides for background subagent runs.plugins.entries.<id>.subagent.allowedModels: optional allowlist of canonicalprovider/modeltargets for trusted subagent overrides. Use"*"only when you intentionally want to allow any model.plugins.entries.<id>.config: plugin-defined config object (validated by native OpenClaw plugin schema when available).plugins.entries.firecrawl.config.webFetch: Firecrawl web-fetch provider settings.apiKey: Firecrawl API key (accepts SecretRef). Falls back toplugins.entries.firecrawl.config.webSearch.apiKey, legacytools.web.fetch.firecrawl.apiKey, orFIRECRAWL_API_KEYenv var.baseUrl: Firecrawl API base URL (default:https://api.firecrawl.dev).onlyMainContent: extract only the main content from pages (default:true).maxAgeMs: maximum cache age in milliseconds (default:172800000/ 2 days).timeoutSeconds: scrape request timeout in seconds (default:60).
plugins.entries.xai.config.xSearch: xAI X Search (Grok web search) settings.enabled: enable the X Search provider.model: Grok model to use for search (e.g."grok-4-1-fast").
plugins.entries.memory-core.config.dreaming: memory dreaming settings. See Dreaming for phases and thresholds.enabled: master dreaming switch (defaultfalse).frequency: cron cadence for each full dreaming sweep ("0 3 * * *"by default).- phase policy and thresholds are implementation details (not user-facing config keys).
- Full memory config lives in Memory configuration reference:
agents.defaults.memorySearch.*memory.backendmemory.citationsmemory.qmd.*plugins.entries.memory-core.config.dreaming
- Enabled Claude bundle plugins can also contribute embedded Pi defaults from
settings.json; OpenClaw applies those as sanitized agent settings, not as raw OpenClaw config patches. plugins.slots.memory: pick the active memory plugin id, or"none"to disable memory plugins.plugins.slots.contextEngine: pick the active context engine plugin id; defaults to"legacy"unless you install and select another engine.plugins.installs: CLI-managed install metadata used byopenclaw plugins update.- Includes
source,spec,sourcePath,installPath,version,resolvedName,resolvedVersion,resolvedSpec,integrity,shasum,resolvedAt,installedAt. - Treat
plugins.installs.*as managed state; prefer CLI commands over manual edits.
- Includes
Browser
evaluateEnabled: falsedisablesact:evaluateandwait --fn.ssrfPolicy.dangerouslyAllowPrivateNetworkis disabled when unset, so browser navigation stays strict by default.- Set
ssrfPolicy.dangerouslyAllowPrivateNetwork: trueonly when you intentionally trust private-network browser navigation. - In strict mode, remote CDP profile endpoints (
profiles.*.cdpUrl) are subject to the same private-network blocking during reachability/discovery checks. ssrfPolicy.allowPrivateNetworkremains supported as a legacy alias.- In strict mode, use
ssrfPolicy.hostnameAllowlistandssrfPolicy.allowedHostnamesfor explicit exceptions. - Remote profiles are attach-only (start/stop/reset disabled).
profiles.*.cdpUrlacceptshttp://,https://,ws://, andwss://. Use HTTP(S) when you want OpenClaw to discover/json/version; use WS(S) when your provider gives you a direct DevTools WebSocket URL.existing-sessionprofiles use Chrome MCP instead of CDP and can attach on the selected host or through a connected browser node.existing-sessionprofiles can setuserDataDirto target a specific Chromium-based browser profile such as Brave or Edge.existing-sessionprofiles keep the current Chrome MCP route limits: snapshot/ref-driven actions instead of CSS-selector targeting, one-file upload hooks, no dialog timeout overrides, nowait --load networkidle, and noresponsebody, PDF export, download interception, or batch actions.- Local managed
openclawprofiles auto-assigncdpPortandcdpUrl; only setcdpUrlexplicitly for remote CDP. - Auto-detect order: default browser if Chromium-based → Chrome → Brave → Edge → Chromium → Chrome Canary.
- Control service: loopback only (port derived from
gateway.port, default18791). extraArgsappends extra launch flags to local Chromium startup (for example--disable-gpu, window sizing, or debug flags).
UI
seamColor: accent color for native app UI chrome (Talk Mode bubble tint, etc.).assistant: Control UI identity override. Falls back to active agent identity.
Gateway
Gateway field details
Gateway field details
mode:local(run gateway) orremote(connect to remote gateway). Gateway refuses to start unlesslocal.port: single multiplexed port for WS + HTTP. Precedence:--port>OPENCLAW_GATEWAY_PORT>gateway.port>18789.bind:auto,loopback(default),lan(0.0.0.0),tailnet(Tailscale IP only), orcustom.- Legacy bind aliases: use bind mode values in
gateway.bind(auto,loopback,lan,tailnet,custom), not host aliases (0.0.0.0,127.0.0.1,localhost,::,::1). - Docker note: the default
loopbackbind listens on127.0.0.1inside the container. With Docker bridge networking (-p 18789:18789), traffic arrives oneth0, so the gateway is unreachable. Use--network host, or setbind: "lan"(orbind: "custom"withcustomBindHost: "0.0.0.0") to listen on all interfaces. - Auth: required by default. Non-loopback binds require gateway auth. In practice that means a shared token/password or an identity-aware reverse proxy with
gateway.auth.mode: "trusted-proxy". Onboarding wizard generates a token by default. - If both
gateway.auth.tokenandgateway.auth.passwordare configured (including SecretRefs), setgateway.auth.modeexplicitly totokenorpassword. Startup and service install/repair flows fail when both are configured and mode is unset. gateway.auth.mode: "none": explicit no-auth mode. Use only for trusted local loopback setups; this is intentionally not offered by onboarding prompts.gateway.auth.mode: "trusted-proxy": delegate auth to an identity-aware reverse proxy and trust identity headers fromgateway.trustedProxies(see Trusted Proxy Auth). This mode expects a non-loopback proxy source; same-host loopback reverse proxies do not satisfy trusted-proxy auth.gateway.auth.allowTailscale: whentrue, Tailscale Serve identity headers can satisfy Control UI/WebSocket auth (verified viatailscale whois). HTTP API endpoints do not use that Tailscale header auth; they follow the gateway’s normal HTTP auth mode instead. This tokenless flow assumes the gateway host is trusted. Defaults totruewhentailscale.mode = "serve".gateway.auth.rateLimit: optional failed-auth limiter. Applies per client IP and per auth scope (shared-secret and device-token are tracked independently). Blocked attempts return429+Retry-After.- On the async Tailscale Serve Control UI path, failed attempts for the same
{scope, clientIp}are serialized before the failure write. Concurrent bad attempts from the same client can therefore trip the limiter on the second request instead of both racing through as plain mismatches. gateway.auth.rateLimit.exemptLoopbackdefaults totrue; setfalsewhen you intentionally want localhost traffic rate-limited too (for test setups or strict proxy deployments).
- On the async Tailscale Serve Control UI path, failed attempts for the same
- Browser-origin WS auth attempts are always throttled with loopback exemption disabled (defense-in-depth against browser-based localhost brute force).
- On loopback, those browser-origin lockouts are isolated per normalized
Originvalue, so repeated failures from one localhost origin do not automatically lock out a different origin. tailscale.mode:serve(tailnet only, loopback bind) orfunnel(public, requires auth).controlUi.allowedOrigins: explicit browser-origin allowlist for Gateway WebSocket connects. Required when browser clients are expected from non-loopback origins.controlUi.dangerouslyAllowHostHeaderOriginFallback: dangerous mode that enables Host-header origin fallback for deployments that intentionally rely on Host-header origin policy.remote.transport:ssh(default) ordirect(ws/wss). Fordirect,remote.urlmust bews://orwss://.OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1: client-side break-glass override that allows plaintextws://to trusted private-network IPs; default remains loopback-only for plaintext.gateway.remote.token/.passwordare remote-client credential fields. They do not configure gateway auth by themselves.gateway.push.apns.relay.baseUrl: base HTTPS URL for the external APNs relay used by official/TestFlight iOS builds after they publish relay-backed registrations to the gateway. This URL must match the relay URL compiled into the iOS build.gateway.push.apns.relay.timeoutMs: gateway-to-relay send timeout in milliseconds. Defaults to10000.- Relay-backed registrations are delegated to a specific gateway identity. The paired iOS app fetches
gateway.identity.get, includes that identity in the relay registration, and forwards a registration-scoped send grant to the gateway. Another gateway cannot reuse that stored registration. OPENCLAW_APNS_RELAY_BASE_URL/OPENCLAW_APNS_RELAY_TIMEOUT_MS: temporary env overrides for the relay config above.OPENCLAW_APNS_RELAY_ALLOW_HTTP=true: development-only escape hatch for loopback HTTP relay URLs. Production relay URLs should stay on HTTPS.gateway.channelHealthCheckMinutes: channel health-monitor interval in minutes. Set0to disable health-monitor restarts globally. Default:5.gateway.channelStaleEventThresholdMinutes: stale-socket threshold in minutes. Keep this greater than or equal togateway.channelHealthCheckMinutes. Default:30.gateway.channelMaxRestartsPerHour: maximum health-monitor restarts per channel/account in a rolling hour. Default:10.channels.<provider>.healthMonitor.enabled: per-channel opt-out for health-monitor restarts while keeping the global monitor enabled.channels.<provider>.accounts.<accountId>.healthMonitor.enabled: per-account override for multi-account channels. When set, it takes precedence over the channel-level override.- Local gateway call paths can use
gateway.remote.*as fallback only whengateway.auth.*is unset. - If
gateway.auth.token/gateway.auth.passwordis explicitly configured via SecretRef and unresolved, resolution fails closed (no remote fallback masking). trustedProxies: reverse proxy IPs that terminate TLS or inject forwarded-client headers. Only list proxies you control. Loopback entries are still valid for same-host proxy/local-detection setups (for example Tailscale Serve or a local reverse proxy), but they do not make loopback requests eligible forgateway.auth.mode: "trusted-proxy".allowRealIpFallback: whentrue, the gateway acceptsX-Real-IPifX-Forwarded-Foris missing. Defaultfalsefor fail-closed behavior.gateway.tools.deny: extra tool names blocked for HTTPPOST /tools/invoke(extends default deny list).gateway.tools.allow: remove tool names from the default HTTP deny list.
OpenAI-compatible endpoints
- Chat Completions: disabled by default. Enable with
gateway.http.endpoints.chatCompletions.enabled: true. - Responses API:
gateway.http.endpoints.responses.enabled. - Responses URL-input hardening:
gateway.http.endpoints.responses.maxUrlPartsgateway.http.endpoints.responses.files.urlAllowlistgateway.http.endpoints.responses.images.urlAllowlistEmpty allowlists are treated as unset; usegateway.http.endpoints.responses.files.allowUrl=falseand/orgateway.http.endpoints.responses.images.allowUrl=falseto disable URL fetching.
- Optional response hardening header:
gateway.http.securityHeaders.strictTransportSecurity(set only for HTTPS origins you control; see Trusted Proxy Auth)
Multi-instance isolation
Run multiple gateways on one host with unique ports and state dirs:--dev (uses ~/.openclaw-dev + port 19001), --profile <name> (uses ~/.openclaw-<name>).
See Multiple Gateways.
gateway.tls
enabled: enables TLS termination at the gateway listener (HTTPS/WSS) (default:false).autoGenerate: auto-generates a local self-signed cert/key pair when explicit files are not configured; for local/dev use only.certPath: filesystem path to the TLS certificate file.keyPath: filesystem path to the TLS private key file; keep permission-restricted.caPath: optional CA bundle path for client verification or custom trust chains.
gateway.reload
mode: controls how config edits are applied at runtime."off": ignore live edits; changes require an explicit restart."restart": always restart the gateway process on config change."hot": apply changes in-process without restarting."hybrid"(default): try hot reload first; fall back to restart if required.
debounceMs: debounce window in ms before config changes are applied (non-negative integer).deferralTimeoutMs: maximum time in ms to wait for in-flight operations before forcing a restart (default:300000= 5 minutes).
Hooks
Authorization: Bearer <token> or x-openclaw-token: <token>.
Query-string hook tokens are rejected.
Validation and safety notes:
hooks.enabled=truerequires a non-emptyhooks.token.hooks.tokenmust be distinct fromgateway.auth.token; reusing the Gateway token is rejected.hooks.pathcannot be/; use a dedicated subpath such as/hooks.- If
hooks.allowRequestSessionKey=true, constrainhooks.allowedSessionKeyPrefixes(for example["hook:"]). - If a mapping or preset uses a templated
sessionKey, sethooks.allowedSessionKeyPrefixesandhooks.allowRequestSessionKey=true. Static mapping keys do not require that opt-in.
POST /hooks/wake→{ text, mode?: "now"|"next-heartbeat" }POST /hooks/agent→{ message, name?, agentId?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }sessionKeyfrom request payload is accepted only whenhooks.allowRequestSessionKey=true(default:false).
POST /hooks/<name>→ resolved viahooks.mappings- Template-rendered mapping
sessionKeyvalues are treated as externally supplied and also requirehooks.allowRequestSessionKey=true.
- Template-rendered mapping
Mapping details
Mapping details
match.pathmatches sub-path after/hooks(e.g./hooks/gmail→gmail).match.sourcematches a payload field for generic paths.- Templates like
{{messages[0].subject}}read from the payload. transformcan point to a JS/TS module returning a hook action.transform.modulemust be a relative path and stays withinhooks.transformsDir(absolute paths and traversal are rejected).
agentIdroutes to a specific agent; unknown IDs fall back to default.allowedAgentIds: restricts explicit routing (*or omitted = allow all,[]= deny all).defaultSessionKey: optional fixed session key for hook agent runs without explicitsessionKey.allowRequestSessionKey: allow/hooks/agentcallers and template-driven mapping session keys to setsessionKey(default:false).allowedSessionKeyPrefixes: optional prefix allowlist for explicitsessionKeyvalues (request + mapping), e.g.["hook:"]. It becomes required when any mapping or preset uses a templatedsessionKey.deliver: truesends final reply to a channel;channeldefaults tolast.modeloverrides LLM for this hook run (must be allowed if model catalog is set).
Gmail integration
- The built-in Gmail preset uses
sessionKey: "hook:gmail:{{messages[0].id}}". - If you keep that per-message routing, set
hooks.allowRequestSessionKey: trueand constrainhooks.allowedSessionKeyPrefixesto match the Gmail namespace, for example["hook:", "hook:gmail:"]. - If you need
hooks.allowRequestSessionKey: false, override the preset with a staticsessionKeyinstead of the templated default.
- Gateway auto-starts
gog gmail watch serveon boot when configured. SetOPENCLAW_SKIP_GMAIL_WATCHER=1to disable. - Don’t run a separate
gog gmail watch servealongside the Gateway.
Canvas host
- Serves agent-editable HTML/CSS/JS and A2UI over HTTP under the Gateway port:
http://<gateway-host>:<gateway.port>/__openclaw__/canvas/http://<gateway-host>:<gateway.port>/__openclaw__/a2ui/
- Local-only: keep
gateway.bind: "loopback"(default). - Non-loopback binds: canvas routes require Gateway auth (token/password/trusted-proxy), same as other Gateway HTTP surfaces.
- Node WebViews typically don’t send auth headers; after a node is paired and connected, the Gateway advertises node-scoped capability URLs for canvas/A2UI access.
- Capability URLs are bound to the active node WS session and expire quickly. IP-based fallback is not used.
- Injects live-reload client into served HTML.
- Auto-creates starter
index.htmlwhen empty. - Also serves A2UI at
/__openclaw__/a2ui/. - Changes require a gateway restart.
- Disable live reload for large directories or
EMFILEerrors.
Discovery
mDNS (Bonjour)
minimal(default): omitcliPath+sshPortfrom TXT records.full: includecliPath+sshPort.- Hostname defaults to
openclaw. Override withOPENCLAW_MDNS_HOSTNAME.
Wide-area (DNS-SD)
~/.openclaw/dns/. For cross-network discovery, pair with a DNS server (CoreDNS recommended) + Tailscale split DNS.
Setup: openclaw dns setup --apply.
Environment
env (inline env vars)
- Inline env vars are only applied if the process env is missing the key.
.envfiles: CWD.env+~/.openclaw/.env(neither overrides existing vars).shellEnv: imports missing expected keys from your login shell profile.- See Environment for full precedence.
Env var substitution
Reference env vars in any config string with${VAR_NAME}:
- Only uppercase names matched:
[A-Z_][A-Z0-9_]*. - Missing/empty vars throw an error at config load.
- Escape with
$${VAR}for a literal${VAR}. - Works with
$include.
Secrets
Secret refs are additive: plaintext values still work.SecretRef
Use one object shape:
providerpattern:^[a-z][a-z0-9_-]{0,63}$source: "env"id pattern:^[A-Z][A-Z0-9_]{0,127}$source: "file"id: absolute JSON pointer (for example"/providers/openai/apiKey")source: "exec"id pattern:^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$source: "exec"ids must not contain.or..slash-delimited path segments (for examplea/../bis rejected)
Supported credential surface
- Canonical matrix: SecretRef Credential Surface
secrets applytargets supportedopenclaw.jsoncredential paths.auth-profiles.jsonrefs are included in runtime resolution and audit coverage.
Secret providers config
fileprovider supportsmode: "json"andmode: "singleValue"(idmust be"value"in singleValue mode).execprovider requires an absolutecommandpath and uses protocol payloads on stdin/stdout.- By default, symlink command paths are rejected. Set
allowSymlinkCommand: trueto allow symlink paths while validating the resolved target path. - If
trustedDirsis configured, the trusted-dir check applies to the resolved target path. execchild environment is minimal by default; pass required variables explicitly withpassEnv.- Secret refs are resolved at activation time into an in-memory snapshot, then request paths read the snapshot only.
- Active-surface filtering applies during activation: unresolved refs on enabled surfaces fail startup/reload, while inactive surfaces are skipped with diagnostics.
Auth storage
- Per-agent profiles are stored at
<agentDir>/auth-profiles.json. auth-profiles.jsonsupports value-level refs (keyRefforapi_key,tokenReffortoken) for static credential modes.- OAuth-mode profiles (
auth.profiles.<id>.mode = "oauth") do not support SecretRef-backed auth-profile credentials. - Static runtime credentials come from in-memory resolved snapshots; legacy static
auth.jsonentries are scrubbed when discovered. - Legacy OAuth imports from
~/.openclaw/credentials/oauth.json. - See OAuth.
- Secrets runtime behavior and
audit/configure/applytooling: Secrets Management.
auth.cooldowns
billingBackoffHours: base backoff in hours when a profile fails due to true billing/insufficient-credit errors (default:5). Explicit billing text can still land here even on401/403responses, but provider-specific text matchers stay scoped to the provider that owns them (for example OpenRouterKey limit exceeded). Retryable HTTP402usage-window or organization/workspace spend-limit messages stay in therate_limitpath instead.billingBackoffHoursByProvider: optional per-provider overrides for billing backoff hours.billingMaxHours: cap in hours for billing backoff exponential growth (default:24).authPermanentBackoffMinutes: base backoff in minutes for high-confidenceauth_permanentfailures (default:10).authPermanentMaxMinutes: cap in minutes forauth_permanentbackoff growth (default:60).failureWindowHours: rolling window in hours used for backoff counters (default:24).overloadedProfileRotations: maximum same-provider auth-profile rotations for overloaded errors before switching to model fallback (default:1). Provider-busy shapes such asModelNotReadyExceptionland here.overloadedBackoffMs: fixed delay before retrying an overloaded provider/profile rotation (default:0).rateLimitedProfileRotations: maximum same-provider auth-profile rotations for rate-limit errors before switching to model fallback (default:1). That rate-limit bucket includes provider-shaped text such asToo many concurrent requests,ThrottlingException,concurrency limit reached,workers_ai ... quota limit exceeded, andresource exhausted.
Logging
- Default log file:
/tmp/openclaw/openclaw-YYYY-MM-DD.log. - Set
logging.filefor a stable path. consoleLevelbumps todebugwhen--verbose.maxFileBytes: maximum log file size in bytes before writes are suppressed (positive integer; default:524288000= 500 MB). Use external log rotation for production deployments.
Diagnostics
enabled: master toggle for instrumentation output (default:true).flags: array of flag strings enabling targeted log output (supports wildcards like"telegram.*"or"*").stuckSessionWarnMs: age threshold in ms for emitting stuck-session warnings while a session remains in processing state.otel.enabled: enables the OpenTelemetry export pipeline (default:false).otel.endpoint: collector URL for OTel export.otel.protocol:"http/protobuf"(default) or"grpc".otel.headers: extra HTTP/gRPC metadata headers sent with OTel export requests.otel.serviceName: service name for resource attributes.otel.traces/otel.metrics/otel.logs: enable trace, metrics, or log export.otel.sampleRate: trace sampling rate0–1.otel.flushIntervalMs: periodic telemetry flush interval in ms.cacheTrace.enabled: log cache trace snapshots for embedded runs (default:false).cacheTrace.filePath: output path for cache trace JSONL (default:$OPENCLAW_STATE_DIR/logs/cache-trace.jsonl).cacheTrace.includeMessages/includePrompt/includeSystem: control what is included in cache trace output (all default:true).
Update
channel: release channel for npm/git installs —"stable","beta", or"dev".checkOnStart: check for npm updates when the gateway starts (default:true).auto.enabled: enable background auto-update for package installs (default:false).auto.stableDelayHours: minimum delay in hours before stable-channel auto-apply (default:6; max:168).auto.stableJitterHours: extra stable-channel rollout spread window in hours (default:12; max:168).auto.betaCheckIntervalHours: how often beta-channel checks run in hours (default:1; max:24).
ACP
enabled: global ACP feature gate (default:false).dispatch.enabled: independent gate for ACP session turn dispatch (default:true). Setfalseto keep ACP commands available while blocking execution.backend: default ACP runtime backend id (must match a registered ACP runtime plugin).defaultAgent: fallback ACP target agent id when spawns do not specify an explicit target.allowedAgents: allowlist of agent ids permitted for ACP runtime sessions; empty means no additional restriction.maxConcurrentSessions: maximum concurrently active ACP sessions.stream.coalesceIdleMs: idle flush window in ms for streamed text.stream.maxChunkChars: maximum chunk size before splitting streamed block projection.stream.repeatSuppression: suppress repeated status/tool lines per turn (default:true).stream.deliveryMode:"live"streams incrementally;"final_only"buffers until turn terminal events.stream.hiddenBoundarySeparator: separator before visible text after hidden tool events (default:"paragraph").stream.maxOutputChars: maximum assistant output characters projected per ACP turn.stream.maxSessionUpdateChars: maximum characters for projected ACP status/update lines.stream.tagVisibility: record of tag names to boolean visibility overrides for streamed events.runtime.ttlMinutes: idle TTL in minutes for ACP session workers before eligible cleanup.runtime.installCommand: optional install command to run when bootstrapping an ACP runtime environment.
CLI
cli.banner.taglineModecontrols banner tagline style:"random"(default): rotating funny/seasonal taglines."default": fixed neutral tagline (All your chats, one OpenClaw.)."off": no tagline text (banner title/version still shown).
- To hide the entire banner (not just taglines), set env
OPENCLAW_HIDE_BANNER=1.
Wizard
Metadata written by CLI guided setup flows (onboard, configure, doctor):
Identity
Seeagents.list identity fields under Agent defaults.
Bridge (legacy, removed)
Current builds no longer include the TCP bridge. Nodes connect over the Gateway WebSocket.bridge.* keys are no longer part of the config schema (validation fails until removed; openclaw doctor --fix can strip unknown keys).
Legacy bridge config (historical reference)
Legacy bridge config (historical reference)
Cron
sessionRetention: how long to keep completed isolated cron run sessions before pruning fromsessions.json. Also controls cleanup of archived deleted cron transcripts. Default:24h; setfalseto disable.runLog.maxBytes: max size per run log file (cron/runs/<jobId>.jsonl) before pruning. Default:2_000_000bytes.runLog.keepLines: newest lines retained when run-log pruning is triggered. Default:2000.webhookToken: bearer token used for cron webhook POST delivery (delivery.mode = "webhook"), if omitted no auth header is sent.webhook: deprecated legacy fallback webhook URL (http/https) used only for stored jobs that still havenotify: true.
cron.retry
maxAttempts: maximum retries for one-shot jobs on transient errors (default:3; range:0–10).backoffMs: array of backoff delays in ms for each retry attempt (default:[30000, 60000, 300000]; 1–10 entries).retryOn: error types that trigger retries —"rate_limit","overloaded","network","timeout","server_error". Omit to retry all transient types.
cron.failureAlert
enabled: enable failure alerts for cron jobs (default:false).after: consecutive failures before an alert fires (positive integer, min:1).cooldownMs: minimum milliseconds between repeated alerts for the same job (non-negative integer).mode: delivery mode —"announce"sends via a channel message;"webhook"posts to the configured webhook.accountId: optional account or channel id to scope alert delivery.
cron.failureDestination
- Default destination for cron failure notifications across all jobs.
mode:"announce"or"webhook"; defaults to"announce"when enough target data exists.channel: channel override for announce delivery."last"reuses the last known delivery channel.to: explicit announce target or webhook URL. Required for webhook mode.accountId: optional account override for delivery.- Per-job
delivery.failureDestinationoverrides this global default. - When neither global nor per-job failure destination is set, jobs that already deliver via
announcefall back to that primary announce target on failure. delivery.failureDestinationis only supported forsessionTarget="isolated"jobs unless the job’s primarydelivery.modeis"webhook".
Media model template variables
Template placeholders expanded intools.media.models[].args:
| Variable | Description |
|---|---|
{{Body}} | Full inbound message body |
{{RawBody}} | Raw body (no history/sender wrappers) |
{{BodyStripped}} | Body with group mentions stripped |
{{From}} | Sender identifier |
{{To}} | Destination identifier |
{{MessageSid}} | Channel message id |
{{SessionId}} | Current session UUID |
{{IsNewSession}} | "true" when new session created |
{{MediaUrl}} | Inbound media pseudo-URL |
{{MediaPath}} | Local media path |
{{MediaType}} | Media type (image/audio/document/…) |
{{Transcript}} | Audio transcript |
{{Prompt}} | Resolved media prompt for CLI entries |
{{MaxChars}} | Resolved max output chars for CLI entries |
{{ChatType}} | "direct" or "group" |
{{GroupSubject}} | Group subject (best effort) |
{{GroupMembers}} | Group members preview (best effort) |
{{SenderName}} | Sender display name (best effort) |
{{SenderE164}} | Sender phone number (best effort) |
{{Provider}} | Provider hint (whatsapp, telegram, discord, etc.) |
Config includes ($include)
Split config into multiple files:
- Single file: replaces the containing object.
- Array of files: deep-merged in order (later overrides earlier).
- Sibling keys: merged after includes (override included values).
- Nested includes: up to 10 levels deep.
- Paths: resolved relative to the including file, but must stay inside the top-level config directory (
dirnameofopenclaw.json). Absolute/../forms are allowed only when they still resolve inside that boundary. - OpenClaw-owned writes that change only one top-level section backed by a single-file include write through to that included file. For example,
plugins installupdatesplugins: { $include: "./plugins.json5" }inplugins.json5and leavesopenclaw.jsonintact. - Root includes, include arrays, and includes with sibling overrides are read-only for OpenClaw-owned writes; those writes fail closed instead of flattening the config.
- Errors: clear messages for missing files, parse errors, and circular includes.
Related: Configuration · Configuration Examples · Doctor