On-Behalf-Of: how agents act on a person's verified identity
An agent acting under its own identity holds the union of everyone's permissions. On-Behalf-Of delegation binds every call to the person who actually asked.
Josh van Leeuwen
Software Engineer
Giving agents their own identity is step one. Letting them act on your behalf, without becoming you, is the next step. That is what On-Behalf-Of delegation is for.
AI agents do not have one identity problem. They have two.
Earlier this year we argued that agents need their own cryptographic identity. That argument stands. An agent with no verifiable identity of its own is a security incident waiting to happen, and runtime-issued workload identity is table stakes. But the identity of the agent is not the identity of the requester, and a lot of the interesting damage lives in the gap between the two.
Open your audit log after something unexpected happens: a record deleted, a refund issued, a pull request merged. The log will tell you the agent did it. Of course the agent did it. The agent does everything. The question you actually need answered is who asked it to, and on that the log is silent.
One convenient abstraction, two real gaps
When an agent acts under its own identity, every downstream system sees the agent and only the agent. That single design decision opens two gaps which tend to get discussed as one.
The first is the attribution gap. The agent is a shared actor: ten people asked it to do ten different things this afternoon, and every one of those actions arrived at your downstream systems using the same passport; the agent identity. The original human evaporated at the first hop. For anything you need to audit, prove, or explain to a regulator, that is unacceptable.
The second is the authorisation gap, and it is the more dangerous of the two. To be useful to many users, the agent accumulates broad standing access: it can read every customer record, touch every repo, call every tool, because someone might need it to. Its permissions are the union of everyone's permissions. Now consider where an agent's instructions actually come from: a support email, a ticket description, a page it retrieved, the output of a tool it called, and so on. Any of those can carry an instruction, and a prompt injection buried in untrusted input executes with the agent's full authority, not the authority of whoever happened to be in the loop.
This failure mode has had a name for forty years: the confused deputy. A privileged program is tricked into misusing its own authority on behalf of someone who never had that authority in the first place. Give an agent broad standing credentials and point it at untrusted input, and you have built a textbook confused deputy and wired it to production.

The requester disappears at the first hop. The target only ever sees agent B, with agent B's rights.
The two obvious fixes, and why both are wrong
The first instinct is to lean harder into the service account: scope agent B's identity above as tightly as possible and move on. Necessary, but not sufficient. This is because the agent's permissions must remain a superset of what any individual user should be able to do. It has to serve all of them. However tightly you scope it, the blast radius of an injection is still the union of everyone's access, when it should be bounded by one real user.
The second instinct is impersonation: let the agent become the user. Mint a token that says the agent is Alice and let it act as Alice. This closes the authorisation gap, since the action is now bounded by Alice's real permissions, however it reopens the attribution gap and adds a worse one. An impersonation token tells the target it is speaking to Alice. It does not tell the target that an agent is in the room. If the action was wrong, was it Alice at her keyboard, or an injection riding Alice's identity through a compromised agent? The token cannot say, because you deliberately erased the distinction.
The real requirement is stricter than either instinct allows: keep both identities. The human, so authorisation is bounded by what that specific person may do. The agent, so you always know a machine acted, and which one.

Under its own identity, the agent authorises with its own broad permissions and the log names only the service account.
Delegation, not impersonation
This is not a new problem and it does not need a new standard. The prior art is RFC 8693, OAuth 2.0 Token Exchange, and the distinction it draws is exactly the one above: impersonation versus delegation.
An impersonation token says "I am Alice" and nothing else. A delegation token says "this is Alice's request, currently being carried out by this agent". The mechanism is a claim called act (actor): the token's subject stays the human, and the act claim names the agent doing the carrying. Both parties remain identifiable, in the same token, at every point downstream.
That is the whole idea behind On-Behalf-Of (OBO). A human interacts with an agent. Rather than acting as itself or pretending to be the human, the agent exchanges the human's verified identity for a short-lived OBO token: subject is the human, actor is the agent, scoped narrowly, minted just before it is needed and expired shortly after. The target verifies the human's identity and the human's permissions before it acts.
The human rides along. Authorisation is bounded by what the user may do, and the log records both the user and the agent that acted.
The agent no longer carries ambient authority to be tricked into misusing, because every outbound call is bound by the invoking user's rights rather than the agent's superset. An injection that convinces the agent to delete every customer record fails, for the boring reason that the person it is acting for cannot delete every customer record. The worst an injection can do is act within one user's least privilege, and every attempt is attributable. The deputy stops being confused because it stopped holding authority that was not tied to a specific request.
A token is only worth the trust behind it
A token is a claim, and a claim is worth exactly as much as the target's willingness to believe it. So the second half of the problem is not minting tokens; it is getting the systems you already run to trust them- trust distribution.
Here too there is plenty of prior art, because this is the same primitive that already runs your infrastructure. AWS IRSA, Azure Federated Identity Credentials and GCP Workload Identity Federation all work the same way: a workload presents a short-lived OIDC token from its own issuer, and the target is configured to trust that issuer, validating the signature against the issuer's published public keys and checking subject and audience. No long-lived shared secret. Just a configured trust relationship between an issuer and a consumer.
The mapping back to agents is one-to-one. The workload is the agent. The issuer is the platform the agent runs on. The target is whatever the agent is calling: a tool, an MCP server, an internal API. The only thing that changes is what rides inside the token. Cloud federation stops at proving which machine is calling. An OBO token proves that too, and then answers the harder question: which human asked it to.
Catalyst's identity plane, issued by Sentry, is an OIDC issuer of exactly this kind. Because the OBO tokens are standards-compliant JWTs, an external service trusts Sentry the same way it would trust any other identity provider. Federate the trust once, and every agent on the platform can present verifiable, delegated, human-scoped identity to that service. And because they are ordinary JWTs with the right audience, they interoperate across clouds: an OBO token can be exchanged onward for an AWS, Azure or GCP credential through those same federation mechanisms.

One trust anchor, many consumers. Federate Sentry once; every agent inherits verifiable, human-scoped identity everywhere.
None of this asks your organisation to adopt a new identity silo; it plugs into the IAM you already have.
Chains, and the answer the auditor actually wanted
Remember that real agentic systems are not one agent and one target. An agent calls another agent, which calls a tool, which calls a service. If the human's identity survives only the first hop, you are back where you started three hops later.
RFC 8693 handles this by nesting: each delegation wraps a new act claim around the previous one. The outermost actor is whoever is acting right now; peel the layers back and you reach the original human at the centre. The result is not just a token but a chain of custody: this person asked, this agent carried it, which asked this agent, which finally called this tool.

Attribution survives every hop. The subject stays the human; each delegation nests the actor before it.
This is where delegation meets durable execution. Agentic workflows on Catalyst run with verifiable execution: the history is signed and tamper-evident. Combine that with delegated identity and the audit story stops being "the agent did it". It becomes a signed, replayable record of which human initiated an action and every agent that carried it, across a workflow that may have suspended and resumed on a different machine hours later. That is the record you wanted when you opened the log at the top of this post.
Not everything speaks OIDC
Not everything downstream understands tokens. A database does not read an act claim, and plenty of legacy systems have never heard of OIDC and never will.
For those, the claims still have to be made to authenticate something. The answer is a policy layer in front of the resource that authorises the action from the OBO token's claims: take the verified human identity out of the token, evaluate it against policy (a policy engine such as Rego is the natural fit), and allow or deny. The resource never learns what delegation is. The layer in front of it does, and enforces the human's rights on the resource's behalf.
Catalyst can act as that layer. The claims Catalyst Sentry (platform identity provider) mints into the OBO token are the same claims the policy evaluates, so the rules that govern an agent's tool calls and the rules that guard a legacy database are written against one vocabulary: who asked, which agent is acting, and what that person is allowed to do. Your database does not need to learn about delegation, just exposed and routed via Catalyst.
An agent should never be more powerful than the person who asked it
An agent acting under its own identity is, by construction, more powerful than any individual who uses it, and that over privileged power is precisely what an injection reaches for and what an auditor wouldn't be able to trace. Delegation removes this gap; the agent acts with the requester's identity and the requester's permissions, no more, and the record shows both the human and the machine at every hop.
So ask the question of your own stack: when your agent acts, whose identity does the target see? If the answer is "the agent's", you do not have delegation. You have a very capable stranger holding keys to the castle, taking instructions from anyone who can reach its inbox.


