Tool policy
Tool policy is the hard stop that controls what an agent can do.deny always wins. If allow is non-empty, every unlisted tool is blocked. Configuration layers from global → per-agent → exec approvals file — stricter always wins.
Profiles
A profile is a predefined baseline that enables a curated tool set:
Profiles are a starting point. Add specific tools with
alsoAllow, or remove them with deny.
Allow and deny
Explicit allowlist
allow is set and non-empty, every tool not listed is blocked, including tools from any profile. Use deny on top of allow if you want belt-and-suspenders blocking even for listed tools.
Tool name reference
Entry values are exact strings — no glob syntax:
Plugin tools use the form
<plugin-id>/<tool-name>. List available names with openclaw tools list.
Per-provider overrides
Restrict tool access by which AI provider is active for a given turn:"anthropic") or a "provider/model" pair for model-specific rules.
Global vs per-agent
Global tool config
tools.* applies to all agents unless overridden:
Per-agent override
agents.list[*].tools applies only to that agent and takes precedence over the global config:
Per-agent tool config is not a full replacement of global — it is evaluated alongside global. The policy resolver uses the more specific scope (per-agent) when both define the same setting.
deny from either scope wins.Where per-agent config cannot appear
Per-agenttools supports allow, alsoAllow, deny, profile, byProvider, and exec.* — but does not expose the web, media, links, message, agentToAgent, sessions, or subagents sub-objects (those are global-only).
Exec security
tools.exec controls whether and how the agent can run shell commands.
security modes
ask modes
Safe bins
Safe bins are binaries the agent can run without an approval prompt inallowlist or full mode. They must match a known-safe argument profile.
jq, cut, uniq, head, tail, tr, wc.
Default trusted directories for path resolution: /bin, /usr/bin only. Binaries in /usr/local/bin, /opt/homebrew/bin, etc. require adding those dirs to safeBinTrustedDirs.
Additional exec keys
Exec approvals file
The exec approvals file (~/.openclaw/exec-approvals.json) is the host-local persistent record of approved binaries. It exists independently of openclaw.json and is written by the runtime when a user approves an exec prompt.
Allowlist entry format
- Glob patterns matched against the resolved binary path (symlinks followed).
- Basename-only entries are ignored — patterns must resolve to an absolute path or glob.
- Per-agent: scoped under
agents.<agentId>.allowlist. - Valid examples:
/usr/local/bin/rg,~/Projects/**/bin/*,/opt/homebrew/bin/*.
Config vs approvals file — precedence
The effective policy is always the stricter of the two sources:
Examples:
- Config
security: "full"+ approvalssecurity: "deny"→ effective:"deny" - Config
ask: "off"+ approvalsask: "always"→ effective:"always"
agents.<id> overrides defaults; per-agent is more specific.
The approvals file is owned by the host process. In multi-user or shared-gateway setups, each user’s gateway process has its own approvals file. Config-level
tools.exec.security is the shared baseline; the approvals file is the per-user additive record.Skill allowlist
Global bundled skill filter
allowBundled controls which bundled (built-in) skills are active. Workspace skills loaded from load.extraDirs and managed skills are not affected — control those via skills.entries.<name>.enabled.
Per-agent skill filter
agents.list[*].skills is a simple string array of skill names. It takes precedence over global config for that agent. An empty array ([]) disables all skills.
Skills can only be restricted here — you cannot add a skill to an agent that is not already globally available. If a skill is disabled globally via
skills.entries.<name>.enabled: false, per-agent config cannot re-enable it.Per-skill config
Individual skills can be toggled and configured underskills.entries:
Config hierarchy and implications
Settings cascade from most general to most specific. More specific always wins — except fordeny, which wins everywhere.
What happens when a key is set in one place but not another
Common footguns
allow and alsoAllow in the same scope
allow and alsoAllow in the same scope
Using both
allow and alsoAllow at the same config level is a schema validation error. If you want to extend a profile, use alsoAllow. If you want an explicit list, use allow alone.Per-agent allow does not merge with global allow
Per-agent allow does not merge with global allow
If global sets
tools.allow: ["exec", "read"] and a per-agent sets tools.allow: ["write"], the per-agent has only write. The lists do not merge — per-agent allow replaces the global allow for that agent.Global deny always applies — even when per-agent allow lists the tool
Global deny always applies — even when per-agent allow lists the tool
tools.deny: ["exec"] globally blocks exec for all agents even if agents.list.dev.tools.allow: ["exec"]. deny is evaluated after all allow resolution and wins.exec-approvals.json can be stricter than config, but not looser
exec-approvals.json can be stricter than config, but not looser
If you set
tools.exec.security: "full" in config but the approvals file for that agent says security: "deny", the agent cannot run exec. The approvals file cannot grant permissions that config has not already given — it can only restrict.skills: [] on an agent disables skills, but skill hooks still fire
skills: [] on an agent disables skills, but skill hooks still fire
Setting
agents.list[*].skills: [] removes skills from the agent’s prompt context and disables skill invocation — but plugin-registered hook handlers for skill events still run. This is expected behaviour.