Agent Identity: Why Your AI Agent Needs to Be a First-Class Principal
Part of the series The Authentication and Authorization Challenges of Agentic AI.
Picture the fastest way most teams get an agent talking to a backend: give it the same client credentials as the web app it lives inside, or — worse — let it hold onto whatever access token the current user happens to have. It works in the demo. It also means that, from the resource server’s point of view, there is no such thing as “the agent.” There’s just the app, or just the user, doing slightly stranger things than usual.
That’s the identity gap, and it’s the first one worth closing, because every other gap in this series assumes you’ve already answered one question: what, exactly, is doing the acting?
The two easy answers, and why both lose something
Treat the agent as the user. The agent inherits the human’s session or access token and acts with their full authority. This is the path of least resistance, and it’s also how you lose least-privilege scoping entirely. The user who can view their own invoices didn’t necessarily mean to grant “and also let a background process query every invoice in the account, indefinitely.” An agent operating under a user’s raw token can typically do anything the user could do through the UI — a much wider surface than the specific task it was asked to perform. It also collapses attribution: when an audit log shows the user’s identifier attached to an action, you can no longer tell whether the human clicked a button or an agent decided, on its own reasoning, to take that action on their behalf.
Treat the agent as a generic machine client. The agent gets its own client_credentials registration, same as any other backend service. This preserves some separation from the user, but it usually collapses a different distinction: one static credential per agent type, shared across every instance and every user session that agent happens to be serving. If agent instance A (serving user 1) and agent instance B (serving user 2) share the same client ID and secret, you can’t revoke one without revoking both, you can’t tell them apart in a token’s claims, and “which agent did this” resolves only to “an agent of this type,” not a specific running instance handling a specific task.
Neither answer is wrong, exactly — they’re both just insufficiently precise for what agentic systems actually need, which is a principal that is distinct from the user it serves and distinct from every other instance of its own kind.

What a first-class agent identity actually needs
Four properties, in practice, separate a real agent identity from a borrowed one:
A unique, stable identifier per meaningful unit of deployment. Not necessarily per individual API call, but per agent instance, per tenant, or per whatever granularity you’ll actually want to revoke or audit against later. If you can’t answer “which specific agent deployment did this” without cross-referencing three other systems, the identifier is too coarse.
An independent credential lifecycle. The agent’s credentials should be issuable, rotatable, and revocable without touching the human user’s account or any other agent’s credentials. This sounds obvious and is routinely skipped, because it’s easier to bootstrap a new agent by cloning an existing service account’s configuration than to design a registration flow for a genuinely new kind of principal.
Scope that’s independently constrained from the user’s own permissions. An agent acting for a user should typically hold the intersection of what the user is allowed to do and what the specific task requires — not simply “whatever the user can do.” This means the agent’s permission boundary has to be expressible and enforceable separately from the user’s, even when the agent is nominally acting on the user’s behalf.
Visibility in every downstream token and log. Whatever system ultimately receives a request needs to be able to see, in the token or the request itself, that an agent is the one presenting it — and ideally which agent, and on whose behalf. This is less a UX concern than a forensic one: six months later, when someone asks “why did this happen,” the answer needs to be reconstructable from what was actually recorded, not from institutional memory of how the system was supposed to work.
Where the protocols already help, and where they don’t yet
None of this requires a new protocol from scratch. OAuth 2.0’s client credentials grant is a perfectly reasonable substrate for an agent that acts autonomously, with no user context at all — background jobs, scheduled maintenance agents, anything that doesn’t need to prove it’s acting on someone’s behalf. The gap shows up specifically in the delegated case: an agent acting for a user, where the token needs to carry two identities simultaneously — the agent’s, and the user’s — rather than collapsing into one.
This is precisely what the act claim, defined as part of the OAuth 2.0 Token Exchange framework (RFC 8693), is for: a token can carry both a sub claim identifying whose authority is being exercised and an act claim identifying who is actually presenting the token and doing the acting, with support for nested act claims when there’s more than one hop of delegation in the chain. That structure is exactly the shape of the problem — it’s just underused, because a lot of implementations still reach for the two easy answers above rather than modeling the agent as its own actor from the start. We’ll get into the mechanics of token exchange itself in the next post; the point here is narrower: the data model for “who is the user, and who is actually acting” already exists in the standards. The identity gap is mostly a design gap, not a protocol gap.
Practical guidance
A few patterns worth adopting early, before an agent fleet grows large enough that retrofitting becomes painful:
Register agents as their own class of principal, not a variant of an existing one. If your identity provider or internal system distinguishes between “users” and “applications,” an agent that acts on behalf of users but isn’t a user itself deserves consideration as a third category, even if the underlying credential mechanics reuse existing machine-to-machine patterns.
Separate the agent’s type from its instance. It’s reasonable to have a template or blueprint for “the support-ticket-triage agent” that defines its baseline scope — but the thing that actually authenticates against your systems, gets revoked, and shows up in an audit log should be a specific, individually identifiable deployment of that template, not the template itself.
Design revocation granularity in from day one. Ask, before the first agent ships: if this specific instance starts behaving unexpectedly, can it be shut off without affecting any other agent, any user, or any other instance of the same agent type? If the answer requires rotating a shared secret, the granularity is wrong.
Make the agent visible in claims, not just in logs you control. If a downstream resource server, a partner API, or a compliance report needs to distinguish “the user did this” from “the agent did this on the user’s behalf,” that distinction needs to live in the token itself — not in a side-channel log that only your own team can read.
None of this is exotic. It’s the same discipline that’s always applied to service accounts — distinct identity, scoped permission, independent lifecycle — extended to a principal that happens to reason about what to do next rather than executing a fixed script. Getting this part right is what makes every subsequent post in this series solvable; get it wrong, and delegation, consent, and governance all inherit the same ambiguity about who, exactly, did what.
Next in the series: Delegation Done Right: Token Exchange and the On-Behalf-Of Pattern, which covers how an agent identity, once established, actually proves it’s acting for a specific user with a specific scope.