OAuth·for·Agents

Delegated access in the agentic era

Agents need to log in to things.

Not with your API key. Not with a copy of your password. With an identity of their own, permission you actually granted, and a trail you can read afterwards.

Almost all of that machinery already exists — already shipped, already deployed at scale. It's OAuth. What has been missing is a picture of how the pieces fit together for software that decides at runtime what it's going to touch. This is that picture: seven scenarios, each adding a single piece to the one before it.

First, who's in the room

Four parties, and one of them is new.

Before any of the protocol makes sense, it's worth being precise about the parties, because one of them is new and it changes where the credentials must not go.

What an agent actually does
  1. User or SystemAgent

    Optional. Someone hands the agent a task — a person, a batch job, or another agent. It may also have no instruction at all and simply run.

  2. AgentModel

    The agent gives the model the context it has: the request, its system prompt, the tools available to it, and whatever earlier tool output it has accumulated.

  3. ModelAgent

    The model returns output that determines which tool, service or resource gets called next. This is the step where a task becomes a decision about what to touch.

  4. AgentTools · Services · Resources

    The agent calls one or more external endpoints. This is the arrow the rest of this site is about. Any of these endpoints may itself be another agent.

  5. Tools · Services · ResourcesAgent

    Results come back, become more context, and steps 2–5 run again — until the agent decides it's finished.

  6. AgentUser or System

    Optional. It answers, or asks for more input, or reports intermediate progress.

Two things fall out of this picture that are easy to miss.

The model is a protected resource too. Step 2 is an authenticated API call to somebody's inference endpoint, and it needs the same treatment as any other: an identity for the caller, a scoped token, an audit trail. It's drawn in resource colour above for exactly that reason. Meanwhile tools, services and resources are one category — from an authorization standpoint there's no useful difference between an API, an MCP server, and another agent wearing a tool's clothes.

The model must never be able to reach a credential. Not the agent's own, and not any token it holds for a tool. Steps 2 and 3 are a loop through a component that reads untrusted input and can be talked into printing things, so a credential anywhere in that context window is a credential you have published. This is the one rule on this page with no exceptions, and it's the strongest argument for credentials the agent never has to hold on disk at all.

The honest version

Software changed. Five assumptions broke.

OAuth was designed around a world where integrations were decided by people, in advance, and written down. Agents don't work that way — and the friction everyone is feeling right now is real.

The old shape

A developer decides their app will integrate with a service. They read the docs, register the app, get a client_id, pick their scopes, and ship. A user clicks "Connect," sees a consent screen in a browser, and approves. The app holds a token and uses it for months.

The new shape

An agent is handed a task and works out which services it needs while it is running. It may meet a server nobody has ever registered with. It acts at 3am while its user is asleep. It calls another agent, which calls an API at a different company. Nothing about that was written down in advance.

01

Nobody registered the client

OAuth's registration step assumes a human filled out a form on a developer portal and got an identifier back. An agent that discovers a server mid-task has no such identifier, and neither side wants a manual step in the middle of a conversation.

Closed by Client ID Metadata Documents — the client publishes its own metadata at a URL, and that URL is the client ID.

02

There's no browser, and no one is watching

Consent was designed as a redirect: a person, in front of a screen, reading a page. Agents run in terminals, in CI, on a server, at night. The moment a decision is needed, the human may be hours away — and "pending" was never treated as a legitimate state to sit in.

Closed by the device grant, CIBA, and the transaction authorization challenge — asynchronous approval, with polling, as a first-class flow.

03

"Read your email" is not a permission

Scopes name categories of capability. Agents take specific actions: move this $4,000, delete that repository, email these forty people. A scope can't tell a user which of those is about to happen, so the consent they give is much broader than the act they'd approve.

Closed by Rich Authorization Requests — structured authorization details describing the actual operation, not the category.

04

A bearer token is a bearer token

The whole security model of a bearer token is "don't let it leak." Agents copy credentials into prompts, logs, sandboxes and third-party runtimes. The blast radius of a leak is the entire lifetime of the token, on any machine on earth.

Closed by DPoP and mTLS — the token is bound to a key the agent holds, so a stolen copy is inert.

05

By hop four, nobody knows who asked

A request starts with a person, passes through an agent, an MCP server, a partner's API and three internal services. Somewhere in there the original identity turns into "trust me, I'm the backend." When something goes wrong, the log says a service did it.

Closed by Token Exchange, Identity Chaining and Transaction Tokens — the actor chain travels with the request across every hop.

Notice what isn't on this list

Not one of these is a flaw in OAuth's core idea: that a resource owner can grant a piece of software narrow, revocable, auditable access without handing over a credential. That idea is exactly what agents need. What broke are the assumptions layered on top of it, and every one of them has a spec-shaped answer that's in progress or already exists.

The ladder

Seven scenarios, each one piece bigger than the last.

Start with an agent that has no user at all and just needs to call an API. Add a person. Add a service nobody registered with. Add precision, then absence, then a company boundary, then your own internals. Every rung reuses everything below it and adds exactly one new idea.

The agent acts as itself

A nightly job summarizes yesterday's support tickets. There's no user in the loop — the agent is the one being authorized. Today this is a long-lived API key pasted into an environment variable, copied into three deployment configs, and rotated never.

Adds: an identity for the agent that isn't a shared secret — a key it holds, a short-lived token it earns, and a token that's useless if it leaks.

Replace the API key

The agent acts for a person

Now the agent reads your calendar. The API has to know two things at once: which software is asking, and whose data it's allowed to touch. These are different questions, and conflating them is how you end up with an agent that can read everyone's calendar.

Adds: delegation — a token that names the user and the agent acting for them, so the audit log has both.

Add the human

The agent meets a service nobody registered with

Mid-conversation, the agent is pointed at an MCP server it has never seen, run by a company that has never heard of it. There is no developer portal step available, and there is no human to go do one. The two sides have to bootstrap trust from a URL.

Adds: runtime discovery and registration-free clients — protected resource metadata, and a client ID that is a URL you can fetch.

Bootstrap from a URL

The agent says exactly what it's about to do

"This agent may send email on your behalf" is a promise with no edges. What the user wants to approve is "send this draft to these recipients." The gap between those two sentences is where most of the fear about agents actually lives.

Adds: structured intent — authorization details that describe the operation, so consent and the audit record are about the act, not the category.

Get specific

Nobody's watching and it needs permission

The agent has been running for forty minutes and hits the one step that needs a person: a refund above the limit, a production deploy, a payment. Its user is asleep. Failing is wrong, and guessing is much worse.

Adds: asynchronous authorization — the resource issues a challenge, a human approves it out-of-band, and the agent waits without holding anything sensitive.

Wait for the human

The work crosses a company boundary

An agent inside your SaaS vendor's product needs to read a document in your company's storage. Your IdP knows the user. The storage API does not trust your vendor's tokens, and shouldn't have to learn a new issuer for every vendor you buy.

Adds: identity chaining — a short-lived, audience-bound grant that lets each domain keep issuing its own tokens while the user's identity survives the crossing.

Cross the boundary

The request fans out inside your own walls

One agent call becomes eleven internal service calls. The outermost token was audience-bound to the edge and shouldn't go further, but every service downstream still needs to know it's acting for a specific person, under a specific authorization, in a specific request.

Adds: transaction tokens — a per-request, internally-scoped credential carrying immutable call context through the whole fan-out.

Follow it inward

Before the first request

Something has to decide what to ask for.

A user says "chase up our overdue invoices." Somewhere between that sentence and an authorization request containing an amount and an account number, a decomposition happens. That step is the agent's mission, and it's worth naming, because naming it is what lets you draw a line around it.

A mission is the objective an agent is handed — by a person, a system, or another agent. It arrives in natural language, it is usually broader than any single API call, and turning it into concrete access requests is a planning problem, not a protocol one. No specification is going to tell you how to get from "chase up our overdue invoices" to a list of resources. That work happens inside the agent, before it asks for anything.

Which is precisely why the boundary matters. Mission decomposition is performed by the least trustworthy component in the system — the one reading untrusted invoices, untrusted email and untrusted web pages. Its output is a plan, and a plan is a request, and a request is not an authorization. Everything below is about keeping those three things distinct.

01

Don't decompose the whole thing up front

The mission isn't fully knowable at the start — that's what makes it a mission rather than a script. So the temptation is to ask for everything it might need, which produces the broadest consent request in the system at the moment the user understands least about what's coming.

Ask late and ask narrowly. Authorization per resource, at the moment the agent reaches it, is cheap when discovery is a 401 and two well-known documents away.

02

Let the resource tell the agent what's askable

Decomposition doesn't have to be a guess. Protected resource metadata publishes the scopes that exist; an authorization server can publish which authorization details types and fields it will accept. The agent can find out what a legitimate request looks like instead of inferring it.

This is what turns planning into a negotiation with the resource rather than an educated guess — and it's why RAR metadata and error remediation matters more for agents than for anyone else.

03

The output should be an act, not a category

The leaves of a decomposed mission are specific: pay this invoice, email these people. If the plan collapses back into payments.write before it reaches the authorization server, everything the decomposition knew has been thrown away at the last step.

Closed by Rich Authorization Requests. Structured authorization details are, in effect, the wire format for a decomposed mission.

04

The plan must not decide when a human is asked

If the agent's own decomposition determines which steps need approval, then whoever controls the agent's input determines which steps need approval. That is the whole game, lost in one line of application logic.

The resource sets the bar and issues the challenge; the authorization server enforces it. See rung 04 — the agent is a courier, not a judge.

05

Tie the whole mission together

One mission becomes many grants, tokens and calls across several services. If nothing connects them, your audit trail is a pile of unrelated authorizations and "what did this task actually do" is an afternoon of log archaeology.

A correlation identifier carried through every hop — which is exactly what a transaction token's txn claim is for. See rung 06.

The honest part

Mission decomposition itself is out of scope for every specification here, and should be — it's application logic, and it will be different for every agent. What isn't out of scope, and isn't solved, is naming the mission on the wire: there's no interoperable way to say "this authorization was obtained in service of that objective," so you can't yet revoke or audit a mission across parties. It's on the list below.

The other direction

Sometimes the agent is the one being called.

Every rung above puts the agent on the left-hand side of the arrow, asking for access. Flip it: a batch job invokes your agent, or another company's agent does. Now your agent is the protected resource, and it has to make the decisions the APIs above were making.

The good news is that this needs nothing new. An agent that accepts calls is an OAuth resource server: it publishes protected resource metadata, it validates audience-restricted tokens issued by an authorization server it trusts, it checks proof of possession, and it decides what the caller is allowed to ask for. A tool endpoint that happens to be implemented by an agent is still just a tool endpoint. That is the whole point of treating tools, services, resources and agents as one category — the protocol doesn't need to care which one is on the other end.

What does need saying is what happens next, because there's one mistake that gets made almost every time.

Don't forward the token you were given

Your agent receives an access token, needs to call three services to do the work, and the token it's holding is right there. Sending it onward is the single most tempting shortcut in this entire document, and it hands every downstream service a credential minted for you — replayable against you, and against anything else in that token's audience.

Exchange it instead. Token Exchange inside your own domain, identity chaining when the next service is behind a different authorization server, and transaction tokens for the internal fan-out. Each of those preserves who asked and who is acting — the act chain nests, so "this agent, for that agent, for this person" survives — while giving each hop a credential that only works for that hop.

Agent-to-agent, then, is not a sixth rung so much as the ladder read in both directions at once: your agent climbing it as a client on one side, and standing at the top of it as a resource on the other.

The parts bin

None of this is speculative.

Everything in the seven scenarios is a published RFC or an active IETF draft. Here are the load-bearing ones. The full reference has the rest, with what each is for and where it stands as of August 2026.

DPoP RFC 9449

Binds an access token to a key the client holds. A copied token is worthless without the private key — which is what makes a token safe to hand to a runtime you don't fully control.

Protected Resource Metadata RFC 9728

Lets an API say, in a machine-readable document, which authorization server protects it. This is the discovery step that makes "meet a server you've never seen" possible at all.

Client ID Metadata Document WG draft

A client's ID is an HTTPS URL that serves its own metadata. No registration call, no portal, no shared secret — and the identifier means the same thing at every server that fetches it.

Rich Authorization Requests RFC 9396

Replaces a scope string with a structured description of the operation being requested. The difference between "can send mail" and "send this message to these people."

Token Exchange RFC 8693

Trades one token for another, and carries an act claim naming the actor operating on the subject's behalf. This is where "the agent, for the user" becomes a thing a token can say.

Transaction Tokens WG draft

A short-lived token scoped to one call chain inside a trust domain, carrying immutable context so every internal hop can make its own decision without re-deriving who asked.

Not a sales pitch

What's actually missing.

A page that claims everything is solved is a page you shouldn't trust. Some things genuinely aren't standardized yet. They're worth naming precisely, because the size of the remaining gap is the whole question of whether this needs a new ecosystem or a few more drafts.

  • Naming the individual agent instance

    A client_id names a piece of software, not the copy of it that is currently running. You can bind a token to a per-instance key, but what you can't yet do in a standard way is put "this is instance abc-123, spawned at 14:02, by this parent" into a token so a resource can reason about it, revoke just that one, and show it in a list to a user.

    The naming half of this has answers outside OAuth — identifiers for individual running instances of software are well-trodden ground, and have been deployed at scale for years in infrastructure that has nothing to do with agents. Composing them with OAuth is the open work, and AI Agent Authentication and Authorization is where that composition is being written down.

    Closest thing today: DPoP's key thumbprint as a de-facto instance handle, plus a private claim. Interoperable, no. Workable, yes.

  • How deep delegation is allowed to go

    Token Exchange's may_act says who may act for whom. It doesn't express "this agent may sub-delegate to one more agent and no further," or "this delegation dies when the parent task ends." Agents calling agents makes that a live question rather than a theoretical one.

    Closest thing today: nested act chains plus local policy at each authorization server.

  • Showing a person what they're approving

    Rich Authorization Requests can express an operation exactly. Nothing standardizes how an authorization server should render an unfamiliar authorization details type to a human, or what to do when it receives one it doesn't understand. Precision the user can't read isn't consent.

    Closest thing today: the RAR metadata and error remediation draft, which is exactly this problem being worked on.

  • Revocation that actually propagates

    "Kill this agent's access everywhere, now" spans an IdP, three authorization servers and a partner. The machinery exists — the Shared Signals Framework, with CAEP and RISC as its profiles — and the obligation is not really in doubt either: a party that receives a revocation signal has to drop its cached tokens and decisions rather than run them to expiry. What's missing is deployment. Until subscribing is ordinary, an agent's access dies at the speed of the longest token lifetime in the chain.

    Closest thing today: short token lifetimes and the refresh token expiration draft — blunt, but it works.

  • Naming the mission on the wire

    An agent is given an objective and turns it into a dozen authorizations across several services. Nothing standard lets a token say "this was obtained in service of that mission" in a form another party can act on — so you can't revoke a mission, you can't audit one end-to-end across companies, and you can't ask an authorization server to refuse anything that isn't part of one. The planning step is rightly out of scope; the identifier for it shouldn't be.

    Closest thing today: a transaction token's txn claim inside one trust domain, and a shared request identifier by convention outside it. Works if everyone involved agreed in advance.

  • Vouching for what an agent is, to a stranger

    Inside a platform this already works, and it has a name: posture assessment at the moment a credential is issued. Whatever starts the agent evaluates signals about it first — what build this is, where it's running, and where the hardware allows it, measurements from a TPM or an enclave — and those signals decide whether the agent gets a credential at all, what it says, and how long it lasts.

    The gap is portability. A client ID metadata document tells you what a client claims to be, and posture assessment only convinces the platform that did the assessing. Neither gives an API on the other side of the internet — with no relationship to that platform — anything it can check about where this agent came from.

    Closest thing today: attestation-based client authentication and SPIFFE client authentication where the authorization server sits inside the same trust domain, plus reputation on the client ID URL itself.

The shape of the gap

A claim here. A metadata field there. A rendering convention. These are draft-sized problems, being worked on in the open by the people who will have to implement them — and each one lands in an ecosystem that already has authorization servers, libraries, audit pipelines and security review behind it.

That's the case for building on what's here: not that OAuth is perfect for agents, but that the distance from where it is to where agents need it is genuinely short, and the distance from zero is not.

Start at the bottom.

The first rung is the one almost everybody is standing on right now — an agent with an API key in an environment variable. It's also the easiest one to fix.