Policies & scopes
The hook sends each tool call to the gateway before it runs, and ACP decides allow / flag / ask / deny for it based on three layered policy axes. Redaction is a separate transform on tool output, covered below. This page is the mental model — the console is where you actually configure the rules.
The four outcomes
allow— the tool runs. The terminal prints nothing; the row appears on Activity (or in~/.acp/audit.jsonlwith--local).flag— the tool runs, and the row is marked for review.ask— the call is held for a human. The agent sees[ACP] Approval required: <reason>; the request appears on the Approvals page and the workspace owner gets an email. Approving grants a single retry within the grant window; unanswered requests expire and count as denied. Details on Approvals.deny— the call is blocked. The agent sees[ACP] Denied by policy: <reason>.
Rules are per tool — a prefix like Bash.rm, Bash.git-push, or WebFetch.<host> — and per agent tier: interactive, subagent, background, api.
The three axes
Every /govern/tool-use call is evaluated against three axes of policy, in this order:
1. Tool policies — workspace-wide defaults
Dashboard → Policies → Tool Policies. Workspace-wide allowlists and required scopes per tool. The question these answer: “Is anyone in this workspace allowed to call github.repos.delete? What scope do they need?”
This is the first-class way to disable a dangerous tool for everyone, or require a sensitive scope (github.admin) before a tool can be called.
2. Agent policies — per-tier rules
Dashboard → Policies → Agent Policies. Rules per agent tier: interactive, subagent, background, api. The question these answer: “What can a background cron agent do that my interactive Claude Code session can’t?”
Typical pattern: lock down background agents tightly (read-only, rate-limited, no destructive ops), leave interactive agents permissive, keep subagents in between.
3. User policies — per-identity overrides
Dashboard → Policies → User Policies. Overrides per user identity. The question these answer: “Alice gets to run stripe.charge.* because she’s in finance; Bob does not.”
Use these for carve-outs, not broad strokes. If you’re writing user policies for most of your team, the rule probably belongs in tool or agent policies instead.
Most-restrictive-wins
The layers intersect. For any one tool and tier, the effective permission is the most restrictive one any applicable layer sets — workspace, role, agent type, or user — so tightening at any layer tightens the result and no layer can loosen what another has denied. Within a layer, a more specific tool entry (Bash.curl) decides over a broader one (Bash), so you can allow a family and deny one member of it.
| Workspace | Agent type | User | Result |
|---|---|---|---|
| allow | allow | allow | allow |
| allow | allow | deny | deny (the user tightened it) |
| allow | deny | — | deny (the agent type tightened it) |
| deny | allow | — | deny (workspace deny holds; a layer cannot loosen it) |
| allow | ask | allow | ask (the strictest of the three) |
Above every layer sit the two floors that nothing can loosen: the hardline catastrophe list (rm -rf /, disk wipes, force-push to a protected branch, and the like) and policy tamper (any write to the files that control the agent).
Scopes
Scopes are short strings that describe tool capabilities (github.pr.write, slack.read, stripe.charge.*). They serve two jobs:
- Required on the tool side. The tool policy says “
github.pr.createrequires scopegithub.pr.write.” - Granted to the caller. The JWT (or the agent’s tier configuration) carries a set of scopes. If the caller’s scopes don’t cover the tool’s required scope, the call is denied.
Scopes support wildcards: github.* covers github.pr.write, github.issue.create, etc. * covers everything — use with care.
For delegation chains (agent calling agent calling tool), scopes narrow at each hop. See agent-to-agent control for details.
Audit mode vs. enforce mode
A workspace is in one of two modes:
- Audit mode — where every new workspace starts. Everything is recorded, nothing is blocked. Shadow evaluation shows
[ACP shadow] That was <tool> — <why>in the agent transcript for calls the starter policy would have paused, so you see what enforce would do before it does it. - Enforce mode — decisions are honored.
askholds the call,denyblocks it and returns the reason to the agent. Switch on the Policies page.
Recommended rollout: stay in audit mode for a few days. Read the shadow notices and the rows on Activity. Adjust the rules until the false-positive rate is where you want it. Then switch to enforce.
This is how you avoid the common failure mode where a well-meaning tightening of policy takes down half your agent fleet because the rules didn’t match reality.
Set a rule from a row
From any row on Activity or Sessions, choose Ask next time, Deny next time, or Allow always. That writes a standing rule for that tool and tier — no policy editor needed. Agents can also propose a rule from a denial they hit (acp_propose_rule); proposals wait on the Policies page until you confirm them.
Ran ungoverned
When the gateway is unreachable, interactive calls proceed with a loud [ACP] ⚠ UNGOVERNED notice in the terminal, and the row is marked ran ungoverned in Activity. Unattended tiers (subagent, background, api) stay blocked until the gateway answers.
PII, prompt injection, and secrets
These are handled by the content-scanning layer, which runs on the tool’s output (and optionally its input). Unlike allow/deny, the primary decision type here is redact — the output is rewritten with sensitive strings replaced.
The three detectors today:
- PII. Six high-precision types: emails, phone numbers, SSNs, credit-card numbers, IBANs, IP addresses. Default policy:
detect(SSN and credit card are hard-blocked regardless of policy);redactis a policy you enable. - Prompt injection. Heuristic match against known injection patterns in tool output (especially web fetches). Default policy:
flag(log but pass through); set toredactordenyfor high-stakes agents. - Secrets. API keys, tokens, private keys in tool output. Default policy:
redact.
Each detector has per-agent-tier policy. A researcher bot reading public docs can have lax settings; a customer-service bot touching real records should redact aggressively.
What you won’t find here
This page is conceptual. For field-level details — exact JSON schema of policy objects, scope inheritance rules, the API for bulk-importing policies — see the API reference. The Activity log is the source of truth for what policies actually did on a given call.
Related
- How a call is decided — how policy fits into the per-call pipeline.
- Approvals — what a held call looks like, the grant window, expiry.
- Agent-to-agent control — scope narrowing across delegation chains.
- Rules by tool, tier, and user — the broader identity / policy / observability frame.
Run agents? ACP lets you see, control, and price every tool call they make — allow/ask/deny policy, per-session cost, and a full audit log for Claude Code, Cursor, Codex, and OpenClaw, in one command:
curl -sf https://agenticcontrolplane.com/install.sh | bash
Getting started → · see your first governed call → · free up to 5 agents · prefer fully on-device? add --local