Gateway
Configuration — per-agent entries and multi-agent routing
Per-agent overrides under agents.entries and the multiAgent bindings that decide which agent answers a message.
agents.entries (per-agent overrides)
Use agents.entries.*.tts to give an agent its own TTS provider, voice, model,
style, or auto-TTS mode. The agent block deep-merges over global
tts, so shared credentials can stay in one place while individual
agents override only the voice or provider fields they need. The active agent's
override applies to automatic spoken replies, /tts audio, /tts status, and
the tts agent tool. See Text-to-speech
for provider examples and precedence.
{ agents: { entries: { main: { name: "Main Agent", workspace: "~/.openclaw/workspace", agentDir: "~/.openclaw/agents/main/agent", model: "anthropic/claude-opus-4-6", // or { primary, fallbacks } utilityModel: "openai/gpt-5.4-mini", thinkingDefault: "high", // per-agent thinking level override reasoningDefault: "on", // per-agent reasoning visibility override fastModeDefault: false, // per-agent fast mode override params: { cacheRetention: "none" }, // overrides matching defaults.models params by key tts: { providers: { elevenlabs: { speakerVoiceId: "EXAVITQu4vr4xnSDxMaL" }, }, }, skills: ["docs-search"], // replaces agents.defaults.skills when set identity: { name: "Samantha", theme: "helpful sloth", emoji: "🦥", avatar: "avatars/samantha.png", }, groupChat: { mentionPatterns: ["@openclaw"] }, sandbox: { mode: "off" }, runtime: { type: "acp", acp: { agent: "codex", backend: "acpx", mode: "persistent", // persistent | oneshot cwd: "/workspace/openclaw", }, }, subagents: { allowAgents: ["*"] }, tools: { profile: "coding", allow: ["browser"], deny: ["canvas"], elevated: { enabled: true }, }, }, }, },}- The
agents.entriesobject key is the stable agent id. cwd: optional working directory for reply runs, separate fromworkspace. Overridesagents.defaults.cwd; see Working directory for precedence and sandbox restrictions.defaultis retired. Exactly one configured agent resolves implicitly; multi-agent operations require a binding, surfaceagentIdtarget, scoped session/store owner, or explicit--agent/request field.model: string form sets a strict per-agent primary with no model fallback; object form{ primary }is also strict unless you addfallbacks. Use{ primary, fallbacks: [...] }to opt that agent into fallback, or{ primary, fallbacks: [] }to make strict behavior explicit. Cron jobs that only overrideprimarystill inherit default fallbacks unless you setfallbacks: [].utilityModel: optional per-agent override for short internal tasks such as generated session and thread titles. Falls back toagents.defaults.utilityModel, then the effective session provider's declared small-model default. Dashboard titles retry once with the effective regular session model. An empty string skips the alternate utility route for this agent without disabling dashboard title generation.params: agent-wide stream params merged over shared and agent-specific per-model params. Use this for overrides likecacheRetention,temperature, ormaxTokensthat should apply across the agent's models.tts: optional per-agent text-to-speech overrides. The block deep-merges overtts, so keep shared provider credentials and fallback policy inttsand set only persona-specific values such as provider, voice, model, style, or auto mode here.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. The selected provider/model profile controls which values are valid; for Google Gemini,adaptivekeeps provider-owned dynamic thinking (thinkingLevelomitted on Gemini 3/3.1,thinkingBudget: -1on Gemini 2.5).reasoningDefault: optional per-agent default reasoning visibility (on | off | stream). Overridesagents.defaults.reasoningDefaultfor this agent when no per-message or session reasoning override is set.fastModeDefault: optional per-agent default for fast mode ("auto" | true | false). Overridesagents.defaults.fastModeDefaultfor this agent when no per-message or session fast-mode override is set.models: optional per-agent model settings keyed by fullprovider/modelids. Usemodels["provider/model"].paramsfor model-specific request settings andmodels["provider/model"].agentRuntimefor runtime exceptions.models["provider/model"].codeModeacceptstrueorfalseand takes precedence over the agent'stools.codeModeactivation, the shared model override, and the global default. Omit it to inherit; it does not affect Codex native Code Mode.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.- Local workspace-relative
identity.avatarimage files are limited to 2 MB.http(s)URLs anddata:URIs are not checked against the local file-size limit. identityderives defaults:ackReactionfromemoji,mentionPatternsfromname/emoji.subagents.allowAgents: allowlist of configured agent ids for explicitsessions_spawn.agentIdtargets (["*"]= any configured target; default: same agent only). Include the requester id when self-targetedagentIdcalls should be allowed. Stale entries whose agent config was deleted are rejected bysessions_spawnand omitted fromagents_list; runopenclaw doctor --fixto clean them up, or add a minimalagents.entries.*entry if that target should remain spawnable while inheriting defaults.- 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).subagents.maxConcurrent: max concurrent child-agent runs across subagent execution. Default:8.subagents.maxChildrenPerAgent: max active children a single agent session can spawn. Default:5.subagents.maxSpawnDepth: max nesting depth for sub-agent spawning (1-5). Default:5; set1to make direct children leaves.subagents.archiveAfterMinutes: age before completed subagent state is archived. Default:60.
Multi-agent routing
Run multiple isolated agents inside one Gateway. See Multi-Agent.
{ agents: { ownership: "explicit", defaults: { heartbeat: { agentId: "home" }, systemAgent: { agentId: "home" } }, entries: { home: { workspace: "~/.openclaw/workspace-home" }, work: { workspace: "~/.openclaw/workspace-work" }, }, }, bindings: [ { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } }, { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } }, ], talk: { agentId: "home" },}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)session(optional; route bindings only):{ dmScope, groupScope }overrides session routing for matched peersacp(optional; only fortype: "acp"):{ mode, label, cwd, backend }
Deterministic match order:
match.peermatch.guildIdmatch.teamIdmatch.accountId(exact, no peer/guild/team)match.accountId: "*"(channel-wide)- Sole-agent fallback (only when exactly one agent is configured; explicit multi-agent fleets without a matching binding fail closed)
Within each tier, the first matching 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)
{agents: { entries: { personal: { workspace: "~/.openclaw/workspace-personal", sandbox: { mode: "off" }, }, },},}Read-only tools + workspace
{agents: { entries: { family: { workspace: "~/.openclaw/workspace-family", sandbox: { mode: "all", scope: "agent", workspaceAccess: "ro" }, tools: { allow: [ "read", "sessions_list", "sessions_history", "sessions_send", "sessions_spawn", "session_status", ], deny: ["write", "edit", "apply_patch", "exec", "process", "browser"], }, }, },},}No filesystem access (messaging only)
{agents: { entries: { public: { workspace: "~/.openclaw/workspace-public", sandbox: { mode: "all", scope: "agent", workspaceAccess: "none" }, tools: { allow: [ "sessions_list", "sessions_history", "sessions_send", "sessions_spawn", "session_status", "whatsapp", "telegram", "slack", "discord", "gateway", ], deny: [ "read", "write", "edit", "apply_patch", "exec", "process", "browser", "canvas", "nodes", "cron", "gateway", "image", ], }, }, },},}See Multi-Agent Sandbox & Tools for precedence details.