Multi-Agent Sandbox and Tool Restrictions: Configuration and Precedence
Learn how to configure per-agent sandbox and tool policies in multi-agent environments, including rule precedence and practical examples. Essential for developers managing agent isolation and security.
Each agent within a multi-agent environment has the ability to override the sandbox and tool policies that apply globally. This document explains how to configure these settings on a per-agent basis, the order in which rules take effect, and provides practical examples.
-
Sandboxing, A complete guide to backends and modes.
-
Sandbox vs tool policy vs elevated, Helps you figure out why something is being blocked.
-
Elevated mode, Allows trusted senders to use elevated execution.
Warning
Authentication is tied to each agent individually: every agent maintains its own
agentDirauth store located in~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite. Do not shareagentDirbetween agents. When an agent lacks a local auth profile, it can fall back to the default or main agent's profiles, but OAuth refresh tokens are never copied into secondary agent stores. If you transfer credentials by hand, only portable staticapi_keyortokenprofiles should be duplicated.
Configuration examples
Example 1: Personal + restricted family agent
{
"agents": {
"entries": {
"main": {
"default": true,
"name": "Personal Assistant",
"workspace": "~/.openclaw/workspace",
"sandbox": { "mode": "off" }
},
"family": {
"name": "Family Bot",
"workspace": "~/.openclaw/workspace-family",
"sandbox": {
"mode": "all",
"scope": "agent"
},
"tools": {
"allow": ["read", "message"],
"deny": ["exec", "write", "edit", "apply_patch", "process", "browser"],
"message": {
"crossContext": {
"allowWithinProvider": false,
"allowAcrossProviders": false
}
}
}
}
}
},
"bindings": [
{
"agentId": "family",
"match": {
"channel": "whatsapp",
"accountId": "*",
"peer": {
"kind": "group",
"id": "120363424282127706@g.us"
}
}
}
]
}
Outcome:
- The
mainagent executes on the host machine with unrestricted tool access. - The
familyagent runs inside the designated container sandbox backend, with one container created per agent, and is limited toreadplus message sends within the current conversation.
Example 2: Work agent with shared sandbox
{
"agents": {
"entries": {
"personal": {
"default": true,
"workspace": "~/.openclaw/workspace-personal",
"sandbox": { "mode": "off" }
},
"work": {
"workspace": "~/.openclaw/workspace-work",
"sandbox": {
"mode": "all",
"scope": "shared",
"workspaceRoot": "/tmp/work-sandboxes"
},
"tools": {
"allow": ["read", "write", "apply_patch", "exec"],
"deny": ["browser", "gateway", "discord"]
}
}
}
}
}
Example 2b: Global coding profile + messaging-only agent
{
"tools": { "profile": "coding" },
"agents": {
"entries": {
"main": {
"default": true
},
"support": {
"tools": { "profile": "messaging", "allow": ["slack"] }
}
}
}
}
Outcome:
- Default agents are given coding tools.
- The
supportagent only handles messaging, along with the Slack tool.
Example 3: Different sandbox modes per agent
{
"agents": {
"defaults": {
"sandbox": {
"mode": "non-main",
"scope": "session"
}
},
"entries": {
"main": {
"default": true,
"workspace": "~/.openclaw/workspace",
"sandbox": {
"mode": "off"
}
},
"public": {
"workspace": "~/.openclaw/workspace-public",
"sandbox": {
"mode": "all",
"scope": "agent"
},
"tools": {
"allow": ["read"],
"deny": ["exec", "write", "edit", "apply_patch"]
}
}
}
}
}
Configuration precedence
When both a global configuration (agents.defaults.*) and an agent-specific one (agents.entries.*.*) are present:
Sandbox config
Agent-specific settings take priority over global ones:
agents.entries.*.sandbox.mode > agents.defaults.sandbox.mode
agents.entries.*.sandbox.scope > agents.defaults.sandbox.scope
agents.entries.*.sandbox.workspaceRoot > agents.defaults.sandbox.workspaceRoot
agents.entries.*.sandbox.workspaceAccess > agents.defaults.sandbox.workspaceAccess
agents.entries.*.sandbox.docker.* > agents.defaults.sandbox.docker.*
agents.entries.*.sandbox.browser.* > agents.defaults.sandbox.browser.*
agents.entries.*.sandbox.prune.* > agents.defaults.sandbox.prune.*
Note
For that particular agent,
agents.entries.*.sandbox.{docker,browser,prune}.*takes precedence overagents.defaults.sandbox.{docker,browser,prune}.*and is disregarded when the sandbox scope resolves to"shared". Thedockerblock is responsible for configuring both built-in container backends.
Tool restrictions
The sequence of filtering is:
Tool profile
Either tools.profile or agents.entries.*.tools.profile.
Provider tool profile
Either tools.byProvider[provider].profile or agents.entries.*.tools.byProvider[provider].profile.
Global tool policy
tools.allow or tools.deny.
Provider tool policy
tools.byProvider[provider].allow/deny.
Agent-specific tool policy
agents.entries.*.tools.allow/deny.
Agent provider policy
agents.entries.*.tools.byProvider[provider].allow/deny.
Sandbox tool policy
Either tools.sandbox.tools or agents.entries.*.tools.sandbox.tools.
Subagent tool policy
tools.subagents.tools, when it applies.
Precedence rules
- Each level is allowed to further restrict tools, but cannot restore tools that were denied at an earlier level.
- When
agents.entries.*.tools.sandbox.toolsis configured, it replacestools.sandbox.toolsfor that agent. - When
agents.entries.*.tools.profileis configured, it takes precedence overtools.profilefor that agent. - Provider tool keys accept either
provider(for example,anthropic) orprovider/model(for example,openai/gpt-5.4).
Empty allowlist behavior
If any explicit allowlist in that chain leaves the run with no callable tools, OpenClaw stops before submitting the prompt to the model. This is intentional: an agent configured with a missing tool such as agents.entries.*.tools.allow: ["query_db"] should fail loudly until the plugin that registers query_db is enabled, not continue as a text-only agent.
Tool policies support group:* shorthands that expand to multiple tools. See Tool groups for the full list.
Per-agent elevated overrides (agents.entries.*.tools.elevated) can further restrict elevated exec for specific agents. See Elevated mode for details.
Migration from single agent
Before (single agent)
{
"agents": {
"defaults": {
"workspace": "~/.openclaw/workspace",
"sandbox": {
"mode": "non-main"
}
}
},
"tools": {
"sandbox": {
"tools": {
"allow": ["read", "write", "apply_patch", "exec"],
"deny": []
}
}
}
}
After (multi-agent)
{
"agents": {
"entries": {
"main": {
"default": true,
"workspace": "~/.openclaw/workspace",
"sandbox": { "mode": "off" }
}
}
}
}
Note
Legacy
agents.listrosters and retired per-agent keys (such assandbox.perSession,agentRuntime, andembeddedPi) are migrated byopenclaw doctor; preferagents.defaults+agents.entriesgoing forward.
Tool restriction examples
Read-only agent
{
"tools": {
"allow": ["read"],
"deny": ["exec", "write", "edit", "apply_patch", "process"]
}
}
Shell execution with filesystem tools disabled
{
"tools": {
"allow": ["read", "exec", "process"],
"deny": ["write", "edit", "apply_patch", "browser", "gateway"]
}
}
Warning
This policy disables OpenClaw filesystem tools, but
execis still a shell and can write files wherever the selected host or sandbox filesystem allows. For a read-only agent, denyexecandprocess, or combine shell access with sandbox filesystem controls such asagents.defaults.sandbox.workspaceAccess: "ro"or"none".
Communication-only
{
"tools": {
"sessions": { "visibility": "tree" },
"allow": ["sessions_list", "sessions_send", "sessions_history", "session_status"],
"deny": ["exec", "write", "edit", "apply_patch", "read", "browser"]
}
}
sessions_history in this profile still returns a bounded, sanitized recall view rather than a raw transcript dump. Assistant recall strips thinking tags, <relevant-memories> scaffolding, plain-text tool-call XML payloads (including <tool_call>...</tool_call>, <function_call>...</function_call>, <tool_calls>...</tool_calls>, <function_calls>...</function_calls>, and truncated tool-call blocks), downgraded tool-call scaffolding, leaked ASCII/full-width model control tokens, and malformed MiniMax tool-call XML before redaction/truncation.
Common pitfall: "non-main"
Warning
agents.defaults.sandbox.mode: "non-main"checks the session key against the main session key (always"main";session.mainKeyis not user-configurable, and OpenClaw warns and ignores any other value), not the agent id. Group/channel sessions always get their own keys, so they are treated as non-main and will be sandboxed. If you want an agent to never sandbox, setagents.entries.*.sandbox.mode: "off".
Testing
After configuring multi-agent sandbox and tools:
Check agent resolution
openclaw agents list --bindings
Verify sandbox containers
docker ps --filter "name=openclaw-sbx-"
Test tool restrictions
- Send a message requiring restricted tools.
- Verify the agent cannot use denied tools.
Monitor logs
openclaw logs --follow | grep -E "routing|sandbox|tools"
Troubleshooting
Agent not sandboxed despite mode: 'all'
- Check if there's a global
agents.defaults.sandbox.modethat overrides it. - Agent-specific config takes precedence, so set
agents.entries.*.sandbox.mode: "all".
Tools still available despite deny list
- Check the full filtering order: profile → provider profile → global policy → provider policy → agent policy → agent provider policy → sandbox → subagent.
- Each level can only further restrict, not grant back.
- See Sandbox vs tool policy vs elevated for step-by-step debugging.
Container not isolated per agent
- Default
scopeis"agent"(one container per agent id). - Set
scope: "session"for one container per session, orscope: "shared"to reuse one container across agents.
Related
- Elevated mode
- Multi-agent routing
- Sandbox configuration
- Sandbox vs tool policy vs elevated, troubleshooting "why is this blocked?"
- Sandboxing, complete sandbox guide (modes, scopes, backends, images)
- Session management