Agent to Agent Trust
Multi-agent systems reintroduce a vulnerability that systems security named in 1988. A confused deputy is a privileged component tricked into misusing its authority on behalf of a less privileged caller. It happens whenever authority is ambient, meaning a component uses whatever access it happens to hold rather than access tied to the request.
In an agentic system, it happens when a specialist agent acts with its own credentials, detached from the requester's identity.
The failure
A supervisor agent, running as a service account with broad access, delegates to a research agent. The research agent, also running as a service account, calls a tool that reads customer records. The original request came from a user who should only see their own records. Nobody in the chain checked, because each agent trusted the one before it, and each acted with its own standing authority.
The result: a user obtained data through a chain of agents that no single agent would have given them directly.
Identity is a parameter
The fix is that identity travels with the request as an explicit value, and every agent and every tool authorizes against that value.
type AgentRequest<T> = { principal: Principal; // who initiated this, all the way back delegationChain: AgentId[]; // every agent that touched it capabilities: Capability[]; // what this request may do, attenuated per hop payload: T;}; // A tool never checks "can this agent do X".// It checks "can this principal do X, via this chain".async function readCustomer(req: AgentRequest<{ id: string }>) { authorize(req.principal, "customer:read", req.payload.id); return db.customers.get(req.payload.id);}The delegation chain is the audit trail, and it is what lets you answer "how did agent C end up with authority to do this" after the fact.
Attenuation, never amplification
Each hop in a delegation chain may narrow capabilities. It may never widen them.
If the supervisor holds customer:read scoped to one tenant, the research agent it delegates to holds at most that. It can't hold customer:read across tenants because its own service identity happens to. Capabilities flow down and shrink. If a specialist agent needs more authority than its caller had, that's a design error. Don't configure around it.
Trust the chain, verify the principal
Two mistakes look similar and are opposite.
Trusting the previous agent's identity is fine. You need to know the request came from your own supervisor and not from an injected instruction pretending to be one. Sign the handoff.
Trusting the previous agent's authority claims is the vulnerability. The research agent doesn't get to assert "the supervisor said this is allowed." It gets a signed principal and a signed capability set, and it verifies both at its own boundary. The mechanisms exist: OAuth 2.0 Token Exchange (RFC 8693) for delegation, or attenuable tokens such as macaroons or Biscuit, which were designed for exactly this kind of narrowing.
The tool layer is the last line
Tools should not know or care which agent called them. They authorize the principal against the resource, every call. An agent that is confused, compromised, or buggy gets stopped at the resource, because the resource only ever granted anything to the principal.
What to log
Every delegation: from which agent, to which agent, with which principal, with which capabilities, and whether attenuation occurred. When something reaches a resource it should not have, this log is the only way to find which hop lost the plot.
An agent never acts on its own authority for someone else. It acts on their behalf, with less authority than they had, and proves it at every boundary.
Working on something like this?
Start a Conversation