On this page

On this page

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.

json5
{  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.entries object key is the stable agent id.
  • cwd: optional working directory for reply runs, separate from workspace. Overrides agents.defaults.cwd; see Working directory for precedence and sandbox restrictions.
  • default is retired. Exactly one configured agent resolves implicitly; multi-agent operations require a binding, surface agentId target, 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 add fallbacks. Use { primary, fallbacks: [...] } to opt that agent into fallback, or { primary, fallbacks: [] } to make strict behavior explicit. Cron jobs that only override primary still inherit default fallbacks unless you set fallbacks: [].
  • utilityModel: optional per-agent string, alias, or { primary, fallbacks } override for short internal tasks such as generated session and thread titles. An omitted setting inherits agents.defaults.utilityModel. A fallback-only object inherits the default primary; an explicit primary without fallbacks, or fallbacks: [], clears inherited utility fallbacks. Utility fallback lists are independent of model.fallbacks and use the same retry, alias resolution, and model-selection policy as configured model fallbacks. With no explicit or inherited utility primary, automatic utility selection applies; if no automatic route is available, the first utility fallback starts the chain. Dashboard titles retry once with the effective regular session model after the utility chain is exhausted. 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 like cacheRetention, temperature, or maxTokens that should apply across the agent's models.
  • tts: optional per-agent text-to-speech overrides. The block deep-merges over tts, so keep shared provider credentials and fallback policy in tts and 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 inherits agents.defaults.skills when 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 | ultra). Takes precedence over agent-specific and shared model params.thinking settings and agents.defaults.thinkingDefault when no per-message or session override is set. The selected provider/model profile controls which values are valid; for Google Gemini, adaptive keeps provider-owned dynamic thinking (thinkingLevel omitted on Gemini 3/3.1, thinkingBudget: -1 on Gemini 2.5). See thinking resolution order.
  • reasoningDefault: optional per-agent default reasoning visibility (on | off | stream). Overrides agents.defaults.reasoningDefault for this agent when no per-message or session reasoning override is set.
  • fastModeDefault: optional per-agent default for fast mode ("auto" | true | false). Overrides agents.defaults.fastModeDefault for this agent when no per-message or session fast-mode override is set.
  • verboseDefault: optional per-agent default verbose level ("off" | "on" | "full"). Overrides agents.defaults.verboseDefault for this agent when no per-message or session verbose override is set.
  • models: optional per-agent model settings keyed by full provider/model ids. Use models["provider/model"].params for model-specific request settings and models["provider/model"].agentRuntime for runtime exceptions. models["provider/model"].codeMode accepts true or false and takes precedence over the agent's tools.codeMode activation, the shared model override, and the global default. Omit it to inherit; it does not affect Codex native Code Mode.
  • nativeRuntimeConsent: optional list of harness IDs, such as ["muse"], remembered during setup. Applies only to this agent; it has no global or defaults inheritance. An administrator selecting a remembered harness or creating a chat with it automatically uses Full access with the optional sandbox disabled. This promotion uses the same permission-change lifecycle as explicit settings changes and refuses changes during an active run. Non-admin clients cannot use remembered consent to raise a chat's permissions; their existing restrictions still apply. Mandatory sandbox and workspace boundaries still reject the runtime. Each turn checks the current list, current session identity, Full access, sandbox off, and absence of tool allowlists, disabled tools, or swarm collection. The current live configuration is checked again immediately before native dispatch, so removing consent also blocks queued or prepared work that relied on it. Remove an ID in Settings under Remembered native runtime permissions to revoke it for every chat relying on remembered consent. Explicit Continue for this chat consent remains unchanged. The field is additive and requires no migration.
  • runtime: optional per-agent runtime descriptor. Use type: "acp" with runtime.acp defaults (agent, backend, mode, cwd) when the agent should default to ACP harness sessions.
  • identity.avatar: workspace-relative path, http(s) URL, or data: URI.
  • Local workspace-relative identity.avatar image files are limited to 2 MB. http(s) URLs and data: URIs are not checked against the local file-size limit.
  • identity derives defaults: ackReaction from emoji, mentionPatterns from name/emoji.
  • subagents.allowAgents: allowlist of configured agent ids for explicit sessions_spawn.agentId targets (["*"] = any configured target; default: same agent only). Include the requester id when self-targeted agentId calls should be allowed. Stale entries whose agent config was deleted are rejected by sessions_spawn and omitted from agents_list; run openclaw doctor --fix to clean them up, or add a minimal agents.entries.* entry if that target should remain spawnable while inheriting defaults.
  • tools.agentToAgent.send: optional outgoing target agent IDs or * patterns for sessions_send. Omit to keep global policy and visibility checks; [] denies ordinary cross-agent sends. Matches permit send-only access under narrow visibility without granting history, search, list, status, or session controls. Global agent-to-agent policy and sandbox clamps still apply; same-agent and requester-owned child rules are unchanged. See send-only configuration.
  • Sandbox inheritance guard: if the requester session is sandboxed, sessions_spawn rejects targets that would run unsandboxed.
  • subagents.requireAgentId: when true, block sessions_spawn calls that omit agentId (forces explicit profile selection; default: false).
  • subagents.maxConcurrent: max concurrent child-agent runs per immediate spawning/controller session. Default: 8; independent sessions have independent budgets. Codex-native subagents use Codex's separate scheduler and limits.
  • subagents.maxChildrenPerAgent: separate admission limit on active children a single agent session can spawn. Default: 5.
  • subagents.maxSpawnDepth: max nesting depth for sub-agent spawning (1-5). Default: 5; set 1 to 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.

json5
{  agents: {    ownership: "explicit",    defaults: { 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): route for normal routing (missing type defaults to route), acp for 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 peers
  • acp (optional; only for type: "acp"): { mode, label, cwd, backend }

Fixed match order:

  1. match.peer
  2. match.guildId
  3. match.teamId
  4. match.accountId (exact, no peer/guild/team)
  5. match.accountId: "*" (channel-wide)
  6. Sole-agent fallback (only when exactly one agent is configured; explicit multi-agent fleets without a matching binding reject the request)

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)
json5
{  agents: {    entries: {      personal: {        workspace: "~/.openclaw/workspace-personal",        sandbox: { mode: "off" },      },    },  },}
Read-only tools + workspace
json5
{  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)
json5
{  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.

Was this useful?