Policies
A policy decides what an agent’s tool calls are allowed to do — allow, deny, rate-limit, or redact — and whether the workspace is enforcing those decisions or just watching. These endpoints read and write that policy from code. They write the same documents the console does; the console is just another client.
https://api.agenticcontrolplane.com/<workspace>/admin
Governance endpoints carry your workspace slug in the path (it must match the slug in your key). Writes require a key created by an owner or admin of the workspace.
The four layers
Policy is evaluated in layers, most-specific wins. Each layer overrides the one below it:
| Layer | Endpoint | Scope |
|---|---|---|
| Workspace | /admin/workspacePolicy |
The baseline for everything in the workspace. |
| Role | /admin/rolePolicies/{role} |
Per-role overrides — owner, admin, member. |
| Agent type | /admin/agentTypePolicies/{key} |
Per-agent-identity overrides, keyed client::tier::name. |
| User | /admin/userPolicies/{uid} |
Per-user overrides — including stricter rules a user sets on themselves. |
At request time ACP merges the layers that apply to the caller and the agent, and the strictest decision holds. This page documents the workspace layer in full; the other three take the same body shape at their own paths.
The policy object
{
"mode": "enforce",
"defaults": {
"interactive": { "permission": "allow", "rateLimit": 100, "transform": "log" },
"subagent": { "permission": "allow", "rateLimit": 60, "transform": "redact" },
"background": { "permission": "deny" },
"api": { "permission": "allow", "rateLimit": 30, "transform": "redact" }
},
"tools": {
"github.create_issue": {
"interactive": { "permission": "allow", "rateLimit": 10, "transform": "log" }
}
}
}
| Field | Type | Description |
|---|---|---|
mode |
"enforce" | "audit" |
enforce applies decisions; audit logs what would have happened without blocking anything. Start in audit, watch the logs, then flip to enforce. |
defaults |
object | Per-tier rules applied to every tool unless a tools entry overrides them. Tiers: interactive, subagent, background, api. |
tools |
object | Per-tool overrides, each keyed by tool name, then by tier. |
Each rule is:
| Field | Type | Description |
|---|---|---|
permission |
"allow" | "deny" |
Whether the call may proceed. |
rateLimit |
number | Optional. Max calls per window before the call is throttled. |
transform |
"log" | "redact" |
log records the call as-is; redact strips detected secrets/PII from what’s logged and passed on. |
The tiers describe how the agent is running, not who wrote it: interactive (a human in the loop), subagent (a delegated sub-task), background (autonomous/scheduled), api (driven by an API trigger). Governing by tier lets you, say, allow a tool interactively but deny it to a background run.
Read the workspace policy
GET /<workspace>/admin/workspacePolicy
Readable by any member.
curl -s "$ACP/acme/admin/workspacePolicy" \
-H "Authorization: Bearer $ACP_KEY"
Returns the policy object, or {} if none is set (defaults apply).
Write the workspace policy
PUT /<workspace>/admin/workspacePolicy
A merge update — send only what you want to change; unset fields are left intact. Owner/admin only.
curl -sX PUT "$ACP/acme/admin/workspacePolicy" \
-H "Authorization: Bearer $ACP_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "enforce",
"defaults": {
"background": { "permission": "deny" },
"interactive": { "permission": "allow", "transform": "log" }
}
}'
{ "ok": true }
A common rollout: set "mode": "audit", run your agents, read the audit log to see which tools they actually touch, codify rules for those, then PUT { "mode": "enforce" }.
Clear the workspace policy
DELETE /<workspace>/admin/workspacePolicy
Removes the workspace layer entirely; the built-in defaults apply at the next call. Useful for resetting a test workspace. Owner/admin only.
curl -sX DELETE "$ACP/acme/admin/workspacePolicy" \
-H "Authorization: Bearer $ACP_KEY"
The other three layers
rolePolicies, agentTypePolicies, and userPolicies take the same body shape at their own paths, with the layer’s key as the last path segment:
# Per-role: tighten what members can do
curl -sX PUT "$ACP/acme/admin/rolePolicies/member" \
-H "Authorization: Bearer $ACP_KEY" -H "Content-Type: application/json" \
-d '{ "defaults": { "interactive": { "permission": "allow", "rateLimit": 50 } } }'
# Per-agent-type: rein in one agent identity (client::tier::name)
curl -sX PUT "$ACP/acme/admin/agentTypePolicies/Claude%20Code::background::" \
-H "Authorization: Bearer $ACP_KEY" -H "Content-Type: application/json" \
-d '{ "tools": { "shell.exec": { "background": { "permission": "deny" } } } }'
# Per-user: a user can set stricter rules on themselves
curl -sX PUT "$ACP/acme/admin/userPolicies/uid_123" \
-H "Authorization: Bearer $ACP_KEY" -H "Content-Type: application/json" \
-d '{ "mode": "enforce", "defaults": { "api": { "permission": "deny" } } }'
Each layer supports GET, PUT, and DELETE the same way the workspace layer does. userPolicies allows self-edits (a member tightening their own rules) in addition to admin edits.
The conceptual model
This is the reference. For why the layers merge the way they do, the tier model, and the detection passes behind redact, read Policies & scopes and the governance model.