Most published AI security failures do not come from a novel exploit against the model. They come from an agent doing something it was technically permitted to do, and should not have been. The model behaved unremarkably — it produced a plausible next action — and the surrounding system executed it because nothing said no.
That is excessive agency, catalogued as LLM06 in the OWASP Top 10 for LLM applications. It is unusual among the entries because it is not really an attack. It is an architectural property of your deployment that determines how much damage every other entry on the list can do.
The Three Components
OWASP separates excessive agency into three parts, and the separation is operationally useful because each has a distinct fix.
Excessive functionality. The agent has access to tools it does not need for its task. An agent that summarizes support tickets is connected to an MCP server exposing forty tools, of which it uses three. The remaining thirty-seven are attack surface. Often this happens because the server was integrated wholesale rather than tool-by-tool, or because the tool list was appropriate for an earlier version of the task and never pruned.
Excessive permissions. The tools the agent legitimately needs are configured with more authority than the task requires. The document-reading tool holds credentials with write and delete. The database tool connects as a role with access to every schema. The agent needs one table and one verb, and holds the whole surface.
Excessive autonomy. The agent executes consequential, hard-to-reverse actions without a verification step. Nothing distinguishes "post a draft to a scratch channel" from "issue a refund" or "delete a production record." Both flow through the same unconditional execution path.
These compound. An agent with all three is one confused decision away from an incident. An agent with narrow functionality, minimal permissions, and approval gates on irreversible actions can be wrong repeatedly with bounded consequences — which is the only realistic design target, because models will be wrong.
Cutting Excessive Functionality
Start from the tools actually invoked, not the tools available. Instrument tool calls in staging or in observe-only mode in production, collect two weeks of real traffic, and produce the actual invocation set per agent. In most deployments the used fraction is small — commonly under a quarter of what is exposed.
Then invert the default. Tools are denied unless explicitly allowed for that agent, and the allow-list is per agent, not per server. Connecting to an MCP server should not implicitly grant its whole tool catalog; the grant should enumerate individual tools. Scoping MCP tool permissions covers the enumeration mechanics, and how to monitor MCP tool calls covers the instrumentation that tells you what to keep.
Two details matter more than they appear to. First, tool descriptions are part of the surface: a tool the agent cannot call but whose description is in context still influences behavior and still leaks information about your environment. Remove denied tools from the context, do not merely reject their invocation. Second, dynamic tool discovery — where an agent enumerates available tools at runtime — must be filtered by the same allow-list, or you have rebuilt the wide surface at a different layer.
Cutting Excessive Permissions
Least privilege for agents is not a role assignment problem. Roles aggregate permissions for human convenience, and every role broad enough to be reusable is broader than any single agent task needs.
The unit that works is the connection: a specific agent to a specific resource, carrying explicitly enumerated verbs and a scoped credential. The same agent may hold several connections with different scopes, and its effective authority is the union of narrow grants rather than the span of a role. See how to implement least privilege for agents and governed agent resource connections.
Beyond verb scoping, three constraints repay their configuration cost:
- Row and record scoping. Not just "read the customers table" but "read customer records belonging to the tenant on whose behalf this task runs." Tenant scoping enforced at the data layer rather than in the prompt is what prevents cross-tenant leakage when the agent is confused. See tenant isolation with row-level security.
- Volume ceilings. A read-only agent that pulls the entire table is an exfiltration event even though every individual read was permitted. Per-call and per-task result-size caps convert unlimited read into bounded read.
- Credential lifetime. Short-lived, audience-restricted tokens rather than standing keys, so a leaked credential expires rather than persisting. See key rotation for agent credentials.
Cutting Excessive Autonomy
The wrong way to scope autonomy is by agent trustworthiness or task category. The right axis is the action's own properties: is it reversible, and how large is its blast radius?
A practical four-tier split:
- Auto-execute. Reversible, small radius, low cost. Reads, drafts, internal notes. No gate; log and move on.
- Auto-execute with notification. Reversible but externally visible. Sending an internal message, creating a ticket. Execute, but emit a notification so a human sees it happened.
- Approval required. Irreversible or externally consequential. Payments, customer-facing communication, permission changes, deletions. A human authorizes before execution, with the proposed action and its parameters shown in full.
- Prohibited. Never available to an agent regardless of approval. Modifying audit records, changing its own permissions, disabling guardrails. These belong outside the agent's reachable surface entirely, not behind a gate.
The failure mode here is approval fatigue. If tier three catches hundreds of actions a day, humans will approve reflexively within two weeks and the gate becomes theater. Keep the approval tier small enough that each item genuinely gets read — which means being disciplined about what is truly irreversible. Human-in-the-loop approvals for agents covers the queue design; break-glass and emergency access covers the exception path.
A kill switch belongs alongside this: a single control that halts a specific agent, an agent class, or all agents, taking effect on in-flight requests rather than only on new ones. See rogue AI agents and kill switches.
Why Constraints Need Recorded Decisions
A constraint you cannot evidence is a constraint you cannot rely on. Configuration drifts, deployments diverge, someone widens a scope for a demo and it stays widened. The only durable answer to "was this agent restricted at the time of the incident?" is a record produced by the enforcement point at the moment of the decision.
That record should carry the agent, the connection, the tool and parameters, the policy evaluated, the outcome, and the timestamp — including for allowed calls, not only blocked ones. Allow decisions are what let you demonstrate that the constraint was live and evaluating rather than misconfigured into permissiveness. Hash-chaining the sequence makes the record hard to edit after the fact, which is what makes it useful in an investigation or an audit. See tamper-evident audit logs.
Common questions
How is excessive agency different from over-permissioning in ordinary software?
The permissions component is the same problem. The differences are the functionality and autonomy components. Conventional software calls the APIs its code calls — the functionality surface is fixed at build time and reviewable in a diff. An agent chooses at runtime from everything it can reach, and that choice is influenced by untrusted content in its context. So the exposed surface, not the used surface, is the security-relevant one, and it must be constrained by configuration rather than by code review.
If I have strong guardrails, do I still need to reduce tool scope?
Yes, and in the opposite priority order to how most teams sequence it. Guardrails are probabilistic content controls: they inspect prompts and outputs and make judgment calls, and they will have false negatives. Scope reduction is deterministic: a tool that is not connected cannot be called, regardless of how convincing the injected instruction is. Guardrails handle what scope reduction cannot express; they do not substitute for it. Guardrails versus policies draws the line.
Our agents need broad access to be useful. How do we reconcile that?
Usually the requirement is broad coverage rather than broad authority per action — the agent must be able to reach many systems, but any single task touches one or two. That decomposes into many narrow connections rather than one wide role, with the task-time scope determined by the principal being served. Where genuinely broad authority is unavoidable, constrain the invocation side instead: restrict who can trigger the agent, prevent user input from influencing its targets, and drive it from fixed configuration rather than free-form prompts.
Where should the enforcement point live?
Between the agent and the tool, not inside the agent. Enforcement implemented as instructions in a system prompt is advisory — the same context window that carries the instruction carries the attacker's content. Enforcement implemented in the proxy or gateway that mediates tool calls holds regardless of what the model was persuaded to attempt. See what is an AI control plane.
How Praesidia approaches excessive agency
Praesidia constrains all three components at the connection layer. Tool access is allow-listed per agent rather than inherited from an MCP server registration, so the exposed surface matches the used surface. Each connection carries its own enumerated scopes, trust-level requirement, guardrails, and spend ceiling, so effective authority is a union of narrow grants. Actions can be gated for human approval, and a kill switch halts an agent or agent class including in-flight work.
Every evaluation — allowed and blocked alike — is written to a tamper-evident audit record with full attribution, so the constraints are demonstrable rather than assumed. For the full risk framing see the OWASP LLM Top 10 for agents and the Praesidia documentation.