Three-axis agent governance
Every governance vendor in the agent space pitches roughly the same thing: tool allowlists, audit logs, identity attribution. Look closer at the policy models, though, and you find a quiet collapse: “agent” is treated as either the API key holding it (the user axis) or the MCP server it calls (the tool axis). The agent itself — what kind of agent, what it’s instructed to do, what its trust profile is — disappears.
That collapse is why per-agent policies in most products either don’t exist or only work for registered agents the platform already knows about. Detected agents (Claude Code sessions, CrewAI runs, raw gsk_ API keys) become anonymous traffic.
The model
Agentic Control Plane treats governance as a three-axis ABAC problem with agent as a distinct, first-class axis:
| Axis | Asks the question | Examples |
|---|---|---|
| Tool | What action is being taken? | “Disallow github.repos.delete workspace-wide” |
| Agent | Who or what is taking the action? | “Claude Code subagents can’t write files; the Explore subagent specifically gets a $0.50 budget cap” |
| User | Who authorized it? | “Alice can invoke Stripe-touching agents; Bob cannot” |
Every tool call is governed by the intersection of all three plus a workspace baseline. Most-specific override wins at the leaf level. The merge happens server-side in the gateway’s getEffectivePolicy function; the dashboard exposes it as three tabs with identical UX patterns.
Where this lives in the product
- Tools tab — discovered tool list. Click a tool, set rules per agent tier.
- Agents tab — workspace tier defaults + per-(client, tier, name) overrides. Targets specific detected-agent shapes like
Claude Code::subagent::ExploreorCrewAI::api::researcher. - Users tab — role defaults + per-user overrides.
The four-layer merge order at runtime:
workspace defaults ← the floor — what's allowed by default
↓ override at leaf
role defaults ← per role (owner / admin / member)
↓ override at leaf
agentType policy ← most-specific (client::tier::name) wins
↓ override at leaf
user override ← final say for that human
↓
final policy → applied to every tool call
What it unlocks that single-axis governance can’t
Lock down a specific subagent without restricting the parent. Claude Code’s Explore subagent makes web requests, reads files, runs searches. You want it sandboxed differently from your interactive Claude Code session. Without an agent axis: impossible without breaking the parent. With it: Claude Code::subagent::Explore → no Bash, $0.50 budget. Done.
Set per-framework policy without per-user pain. “Every CrewAI researcher across the org gets a 30-call rate limit” — one rule, hits everyone running that crew. Without an agent axis: you’d write that rule on every user.
Explainable denials. When a call is denied, the audit log shows which axis denied it. “This call was denied because the AGENT policy for Claude Code subagent says deny on github.repos.delete, even though the USER policy allows it and the TOOL policy doesn’t restrict it.” Debuggable, defensible to compliance.
Detected agents are governable, not just observable. Most products show you Claude Code traffic in a dashboard but can’t apply policy to it without you “registering” the agent first. ACP treats detected agents as policy subjects from the moment traffic appears.
Comparison
| Tool axis | Agent axis | User axis | Runtime intersection | |
|---|---|---|---|---|
| MintMCP | yes (allowlist) | partial — per-MCP-server only | yes (RBAC) | partial |
| Obot AI | yes (ACLs) | partial — MCP-server level | yes (Okta/Entra) | partial |
| TrueFoundry | yes (per-server) | not modeled distinctly | yes (federated) | no |
| Lunar.dev | yes (DLP, risk eval) | tool-risk-focused, not agent-typed | yes (identity attribution) | no |
| Composio | yes (they own the tools) | not modeled | basic | no |
| Gravitee MCP | yes (per-method ACL) | not modeled | API-key only | no |
| Cloudflare Enterprise MCP | yes (WAF, AI for Apps) | not modeled — sees IPs and identities | yes (Access) | no |
| ACP | yes | yes — first-class, with delegation chain | yes | yes — canonical 3-axis ABAC |
How it composes with delegation chains
The agent axis is what makes agent-to-agent delegation chains actually governable. When the PR Reviewer delegates to the Security Scanner:
- The PR Reviewer’s tier (e.g.
interactive) and name match its agent-axis policy - The Security Scanner’s tier (
subagent) and name (security-scanner) match a different agent-axis policy - As the chain narrows scopes hop-by-hop, each hop’s policy is independently enforced
- The audit log shows the full chain with the policy that fired at each step
Without an agent axis, you’d be stuck with one policy for the whole chain — defeating the entire point of delegation.
Try it
Three places this story shows up in the product:
cloud.agenticcontrolplane.com/agents— see every detected agent in your workspacecloud.agenticcontrolplane.com/policies— three tabs, set rules per axiscloud.agenticcontrolplane.com/activity— every tool call logged with the policy decision
Or read the deeper architecture pieces:
- Agent-to-Agent governance — the delegation chain spec
- Integration guides — wire any agent framework through ACP
- What is an Agentic Control Plane? — the category definition