AI agentsidentityauthorizationOAuthmandatesmulti-agent

Agent identity is not user identity

9 min read

The identity assumption hiding in plain sight

Every authorization framework makes an assumption about the shape of the entity it is authorizing. OAuth 2.0 assumes there is a human at the authorization step who is present, identifiable, and capable of consenting to a list of scopes. Service accounts assume the caller is a machine with a well-defined, bounded role, issuing requests as itself. API keys assume the holder of the secret is the same entity that was issued the secret.

None of these assumptions hold for an AI agent acting on behalf of a human principal.

The agent is not a user. It did not click the authorize button. It may be running hours after the human who started it has closed their laptop. It is not a service account either - it is executing arbitrary intent on behalf of a specific person, not performing a bounded mechanical function. And the "holder of the secret" property breaks entirely once you realize the same agent might be acting for dozens of different principals at once, all sharing the same runtime, the same process, the same credential store.

This is not a minor gap you can patch with a slightly longer scope string. It is a structural mismatch between what existing identity models were built for and what multi-agent systems actually need.

What user identity assumes

OAuth's authorization code flow is built around a moment: the user is redirected to an authorization server, they authenticate, they review a list of requested scopes, they click approve, and they are sent back to the application with a token that reflects that deliberate act.

That moment is load-bearing. It is when consent happens. The token that flows from it derives its legitimacy from the fact that a real human, with a real identity, made a real decision to grant a specific set of permissions to a specific application. The access token is a record of that consent, bounded by expiry and scope.

When an agent acts, there is no such moment. There was a prompt, earlier, where a human expressed intent - "book me a hotel in Amsterdam for next Thursday, under €180 a night." That expression of intent is not the same as an OAuth consent screen. It named a goal; it did not enumerate the specific API calls, the exact provider, the precise action, or the confirmed price. Everything the agent does from that point forward is an interpretation of intent, not a fresh explicit consent.

If you hand an agent a delegated OAuth token from the user's session, you have two problems. First, the token has far more scope than the single action the agent is taking right now - granting bookings:write authorises every booking action until expiry, not the specific room the principal had in mind. Second, and more fundamentally, the user consented to giving the application access, not to every specific action an AI model might choose to take while using that access. The model's judgment is inside the token's blast radius, but outside the user's consent.

Service accounts: the other failure mode

The other common approach is to skip user delegation entirely and give the agent a service account credential. This sidesteps the user-consent problem by not pretending there is user consent - the agent authenticates as itself, a machine identity, with its own permissions.

This works well for bounded automation: a CI pipeline that deploys code, a cron job that archives logs, a webhook handler that routes events. These actors have no human principal. They are doing mechanical work on behalf of the system, not acting on behalf of a specific person with specific preferences, limits, and accountability.

An AI agent is different. It is not doing mechanical work on behalf of the system. It is interpreting and executing the intent of a specific human principal. When that agent books a hotel room, the booking is not made by "the agent service account" - it is made by Alice, who told the agent to find her somewhere to stay. The provider should know it is acting for Alice. Alice should be able to see and audit every action taken on her behalf. If something goes wrong, the accountability chain has to run back to Alice, not to an anonymous service credential.

A service account erases the principal. It tells the provider that a machine called the API; it says nothing about the human that machine was acting for. That is not just a privacy problem - it is an authorization problem. The provider cannot apply per-principal limits, preferences, or fraud detection if they cannot see the principal. The principal cannot dispute a charge if there is no record of their involvement. The audit trail answers "what service account called the API?" but not "what did Alice actually authorize?"

The multi-agent principal problem

Single-agent architectures are hard enough. Multi-agent systems - where an orchestrator spawns sub-agents, or where a chain of specialized models passes context down a pipeline - introduce a question that existing identity models cannot answer at all: who is the principal when there are five agents in the call chain?

Consider the sequence: a planning agent decomposes a travel request, hands off to a hotel search agent, which calls a booking agent, which invokes a payment agent, which finally calls the hotel provider's API. Each hop in that chain is a legitimate delegation. Each agent is acting for the one that called it. But none of them is the human principal. The human principal is Alice, at the top of the chain, who asked for a trip to Amsterdam.

OAuth does not model this. Service accounts do not model this. The standard patterns give you a credential that represents the caller - but in a multi-agent chain, "the caller" is the payment agent, whose caller is the booking agent, whose caller is the search agent, whose caller is the planner, whose caller is Alice. The provider's API receives a request from the payment agent. It has no way to know Alice exists.

  • Scope inflation - each hop in the chain needs permission to delegate to the next. Without a principled delegation model, the practical answer is to give every agent in the chain broad credentials, because you do not know in advance what the sub-agent will need. Scope inflates toward "everything" at every delegation boundary.
  • Principal erasure - by the time the call reaches the provider, the original human principal is invisible. If the payment agent's service account is compromised, you will see a spike in anomalous charges from the payment service; you will not see that those charges correspond to one compromised principal or ten thousand.
  • Audit collapse - the audit trail at each service shows the immediate caller. Reconstructing "what did Alice's original intent produce?" requires joining logs across every service in the chain, which may span systems you do not control and retain logs on different schedules.

The prompt injection angle

In a multi-agent chain, prompt injection is a principal-spoofing attack. A crafted payload in a retrieved document can instruct a sub-agent to take actions the original principal never intended, and without a principal identity carried through the chain, the provider has no way to distinguish a legitimately-delegated call from an injected one. The original principal's identity and scope are the only thing that can bound what an injected payload can cause.

Three identities in every agentic call

To design a better model you first have to be precise about what "identity" means in an agentic call. There are three distinct things conflated under that word:

  • The model identity - which language model is executing. Relevant for capability and audit, but not for authorization - you do not grant permissions to GPT-4o; you grant them to the principal on whose behalf it is acting.
  • The agent identity - which orchestrating code or agent runtime is making the call. This is the service-account-style identity. It matters for rate limiting, abuse detection, and operational monitoring. It does not say anything about whose intent is being executed.
  • The principal identity - the human whose intent the call is executing, whose spend cap applies, who can be held accountable, and who can audit or dispute the action. This is what existing models mostly do not carry.

Getting authorization right for agents requires treating all three as distinct, carrying the principal identity through every hop in the delegation chain, and scoping each action to the specific intent of that principal at that moment - not to the broad capabilities of the agent runtime.

What a mandate carries that a token cannot

A mandate is a credential scoped to a specific action, signed by the principal's private key, with an expiry measured in seconds. It does not represent the principal's general authority over a category of operations - it represents their specific intent to invoke one action at one provider at one moment.

The structural difference from a token: a token is issued once and used many times; a mandate is minted fresh for each call. The token carries "this principal hasbookings:write"; the mandate carries "this principal has authorizedbook_room at Lux Hotels, right now, up to €180." They are different claims. The first is a standing grant of capability. The second is a cryptographic record of a specific act of authorization.

This distinction matters because it closes the gap between what the principal intended and what the agent can do. A standing scope grant grows stale immediately after it is issued - the principal intended one booking, not the authority to make any booking indefinitely. A per-action mandate reflects the specific intent at the specific moment it was formed.

The principal survives delegation

Because a mandate is signed by the principal's private key, the principal identity is cryptographically embedded in the credential itself. It does not matter how many agents are in the delegation chain between the principal and the provider - the mandate at the end of the chain was signed by Alice, and the provider can verify that without calling back to any identity service.

In a multi-agent chain, each sub-agent presents the same mandate that was signed at the top of the chain. The mandate cannot be re-signed by an intermediate agent - it was minted by the wallet sidecar, on behalf of Alice, at the moment Alice's intent was captured. The payment agent at the bottom of the chain is presenting Alice's authorization, not its own service account credential. The provider always knows whose intent they are executing.

Scope is a commitment, not a capability list

OAuth scopes are additive and static: a token carries a list of permissions that were granted at authorization time and remain valid until expiry. They describe what the caller is allowed to do, across any number of calls, to any resource the scope covers.

A mandate's scope is a commitment to a specific action at a specific target. An IntentMandate for book_room at Lux Hotels cannot be used for cancel_room, cannot be replayed against a different provider, and cannot be used twice. Scope is not a string that can be interpreted broadly by an agent looking for wiggle room; it is a cryptographic binding to exactly one call.

This means the agent cannot scope-escalate. Even if a model reasons its way to a broader interpretation of the principal's intent - "they said 'book somewhere nice,' so I can also upgrade the room" - the mandate it holds authorizes the specific action it was minted for, and the gateway rejects anything outside that. The model's judgment is bounded by the principal's actual authorization, not by what a sufficiently creative interpretation of a scope string might permit.

Spend is part of identity

One property of principal identity that existing models never carry: the principal's willingness to pay. When Alice says "find me a hotel under €180," that ceiling is part of her intent. It is not a separate configuration setting; it is a constraint on what she has authorized.

A mandate-based identity model binds the spend cap to the principal's credential at mandate-mint time. The gateway enforces that cap on every call, independent of what the provider charges or how many retries the model attempts. The cap is not a soft guideline the model is expected to honor; it is a hard limit enforced by infrastructure that the model cannot override.

For the transactional flow, the mandate also includes a price lock: the provider signs a CartMandate committing to an exact total before the agent confirms. The agent then signs a PaymentMandate for that exact amount. No charge can occur that the principal did not explicitly confirm, at a price they explicitly saw. User identity never carried this property, because it did not need to - a human clicking "confirm booking" is performing that act themselves. An agent performing it on their behalf needs the infrastructure to enforce the same guarantees the click-flow provides.

What providers see differently

From the provider's perspective, the shift is from answering "who is this service account?" to answering "who is this human, and what did they specifically authorize?"

A provider receiving a mandate-backed call can answer four questions that a key- or token-based call cannot:

  • Who - the principal's identity, verified cryptographically, regardless of how many agents are in the delegation chain between them and this call.
  • What - the exact action that was authorized, not a scope string that needs to be interpreted. If the mandate is for book_room, that is the only action it covers.
  • How much - the exact price the principal confirmed, and the maximum they are willing to spend. No post-hoc billing ambiguity.
  • When - a mandate is valid for seconds. If the call arrives outside that window, it is rejected. There is no "valid until manually rotated" problem.

These are the questions that underpin fraud detection, per-principal rate limiting, dispute resolution, and regulatory accountability. They are not answerable from a service account credential or a shared API key. They require a credential designed to carry principal identity, not just caller identity.

The authorization chain, end to end

The full flow is worth making concrete. Alice asks her travel agent to find and book a hotel. The travel agent - an orchestrating model, possibly with sub-agents - discovers the Lux Hotels provider through the registry, reads the spec, and identifies book_room as the target action.

Before calling, the agent uses the wallet sidecar to mint an IntentMandate. The sidecar holds Alice's private key. It produces a short-lived JWT signed by Alice's key, naming Lux Hotels as the merchant and book_room as the action. The agent cannot mint its own mandate; only the sidecar can, and only within Alice's configured spend cap.

The agent calls the gateway with the IntentMandate. The gateway verifies the signature (Alice's key), checks the scope (matches the target action), and checks the expiry (seconds, not hours). The gateway asks Lux Hotels for a CartMandate - a signed price commitment. The agent signs a PaymentMandate for that exact total. The gateway confirms the total is within Alice's cap. The call proceeds.

At every step, the provider and the gateway can see Alice's identity. At every step, the scope is bound to the specific action, not a category. The audit record shows Alice authorized this specific action at this exact price at this moment - not that a service account made an API call that fell within a valid scope.

The agent runtime is still visible

Mandate-based identity does not erase the agent identity layer - it adds the principal identity layer on top. The gateway still sees which agent runtime made the call, which is useful for operational monitoring and abuse detection. The two layers are additive: you know both whose intent is being executed and which process is executing it. That combination is what makes it possible to detect, for example, a compromised agent runtime acting on behalf of many principals - both the anomalous service-level behavior and the per-principal impact are visible.

Why this matters beyond security

The argument for mandate-based identity is not purely about preventing misuse. It is about enabling a class of actions that businesses will not grant to agents under any other model.

A business will give a service account read access to their catalog without much deliberation. It will give an agent a write scope with more caution. It will not - and should not - give an agent the authority to commit purchase orders, book venues, or trigger settlements unless it has a way to know, cryptographically, that every such action was explicitly authorized by an identified human principal, within a confirmed spend cap, for a specific action at a specific price.

User identity models cannot provide that guarantee because they were designed around a human who is present and acting directly. Service account models cannot provide it because they are designed around machines with no human principal at all. The gap between those two models is exactly the space that autonomous agents occupy.

Mandate-based identity is designed for that space. The credential is not a standing grant of capability on behalf of a broadly-trusted service, and it is not a direct expression of a present human's click. It is a verifiable record that a specific human, identified by their key, authorized a specific action, at a specific price, for a specific provider, in a window that has since closed. That is a new identity primitive. It is the one multi-agent systems actually need.

Further reading

The mechanics of how API keys fall short compared to mandates are covered in detail in Why API keys are the wrong auth primitive for AI agents. For how mandate verification sits on top of the MCP tool-calling layer, see MCP gives agents tools. What gives agents trust?.