Why Agents Need Their Own Cryptographic Identity
Survey the agent-authentication proposals out today — WorkOS auth.md, ID-JAG, AAuth, x402, OAuth Dynamic Client Registration — and you'll notice something. Every single one models the agent as something else: a session, a client, a wallet, a delegated user. None of them give the agent an identity of its own. That gap costs you auditability, blast-radius containment, and a coherent answer to "who did this?" Here's why it matters, and when it's worth the extra weight.
The Four Ways Agents Get Authenticated Today
Look at every public agent-authentication proposal and you can sort them into four buckets. Each one models the agent as a different abstraction borrowed from a pre-agent era.
OAuth 2.0 Dynamic Client Registration (RFC 7591). The agent registers itself as an OAuth client — same shape as a mobile app or third-party integration. Trust anchor: the client_id + secret pair the auth server issues. MCP recently adopted this.
WorkOS auth.md, ID-JAG. The agent operates inside a user's authenticated session. An agent provider mints a short-lived assertion on user consent. Trust anchor: the agent provider's JWKS.
AAuth, "Agent Auth" (Dick Hardt). The agent identifies the user through PII — name, email, credit card, medical ID. Then it can act with that user's scoped permissions. Trust anchor: the PII matching the auth server's user record.
x402 (Coinbase). The agent pays per request with USDC, signing transfers under a user-defined spending mandate. Trust anchor: the blockchain. Identity is implicit in the wallet address.
Notice what's missing? Across all four, the agent itself is not the principal. It's a client, a session, a proxy, a wallet. Its actions are always attributable to something else — the OAuth client registration, the upstream user, the credit card, the public key. None of them ask the question: what if the agent is the thing we want to identify?
That's the position AID takes. Each agent has its own Ed25519 keypair. It's not borrowed from a user, not proxied through a provider, not derived from a wallet balance. The agent's signature is the agent's identity. Full stop.
What You Lose When the Agent Has No Identity
Three concrete losses:
1. Auditability collapses to the next layer up. Your access logs read user=jane.doe@acme.com, client=openai-chatgpt. Two different ChatGPT conversations Jane had today, doing two different things, are indistinguishable. The user did it. The agent provider mediated. The actual agent that made the call is invisible. For security incident response, fraud investigation, and SOC 2 audit trails, this isn't enough.
2. Least privilege defaults to the user's privilege. If the agent operates as the user, its maximum scope is the user's scope. You can scope down at the assertion layer (auth.md does this well), but you can't easily scope up for the agent specifically. And the inverse fails completely: there's no way to give an agent a permission the user doesn't have, even when that's the right design — a customer-support agent should be able to look up any customer's order, not just orders belonging to "the user it's acting for."
3. Compromise blast radius scales with the intermediary, not the principal. Compromise an agent provider's signing key in the auth.md model, and you compromise every delegation the provider ever issued. The WorkOS docs explicitly flag this as security-critical configuration. Compromise an OAuth client registration in the DCR model, and every agent using that registration is compromised. With per-agent keys, compromise of one agent's key compromises that one agent. Containment is automatic.
A Concrete Scenario: The Refund Audit
Imagine you're running a customer-support platform. You have two agents:
- tier1-triage: reads tickets, classifies them, can refund up to $50
- fraud-review: reads tickets, can read customer purchase history, can not refund
Both agents are operated by the same admin user, Sarah. A $48 refund just went out for a customer claiming they didn't receive an order. Months later, the customer files a chargeback claiming the refund never reached them. Compliance asks: which agent processed this?
Your log says user=sarah, scope=refunds:write. You know Sarah's agent did it. You don't know which one. Both have valid sessions because they both operate under Sarah. You go check internal correlation IDs, hope you logged the conversation ID, hope it's still in your trace store. Maybe you find it. Maybe you don't.
Your log says agent=tier1-triage@acme.local. You know exactly which agent. You can also know — without checking — that it wasn't fraud-review, because fraud-review's role doesn't include refunds:write at all. Token introspection at the time of the call would have denied it.
This isn't a contrived example. It's the exact shape of every agent-attribution incident response that's coming in the next two years. Per-agent identity isn't a luxury — it's the audit log you didn't realize you were going to need.
What "Agent Has Its Own Identity" Means in Practice
In AID, "the agent has its own identity" is four concrete things:
- An Ed25519 keypair held by the agent. Generated on first run via
aid-init. The private key never leaves the agent's machine. - A human-readable address.
support-bot@acme.local,tier1-triage@acme.local. The address appears in every token, every log entry, every introspection response. - A signed proof on every token request. Not just at registration — every time the agent asks for a token, it signs a fresh timestamp + audience binding. The auth server verifies the signature against the public key it recorded at registration.
- A role-scoped envelope, set by a human at registration. The agent has scopes the user might not have, and the user can run agents with scopes narrower than their own. The two are decoupled.
The crucial property is that none of these depend on a third party. No agent provider's JWKS. No OAuth client registration shared across deployments. No wallet balance. The auth server has one row per agent in a database — that's the whole trust anchor.
This is why AID's reference implementation is four shell scripts. The model is small enough that it doesn't need a runtime.
When Delegation IS the Right Model
The honest answer: a lot of the time. We're not arguing per-agent identity is universally better — we're arguing it's the missing default, and the right model depends on deployment shape.
| Deployment | Better fit | Why |
|---|---|---|
| ChatGPT calling Acme's API for Jane | Delegation (auth.md / ID-JAG) | Acme doesn't know Jane. Provider JWKS bridges the gap. |
| Long-lived support agent inside Acme | Per-agent identity (AID) | Acme owns the agent. Admin grants scopes directly. |
| CI/CD agent deploying code | Per-agent identity | No user is involved. Service-account model. |
| Personal coding agent on a developer's laptop | Either | Per-agent identity gives clean per-laptop audit; delegation lowers setup friction. |
| Multi-tenant SaaS spawning agents per customer | Per-agent identity | Customer-level isolation is the entire product. One key per tenant agent. |
| Pay-per-call AI on the open web | Wallet (x402) | Identity is irrelevant; settlement is the contract. |
The pattern: delegation wins when the calling-party doesn't know the user; per-agent identity wins when the agent is a long-lived autonomous principal in a system the deployer controls. These are very different shapes. Picking the right one matters more than picking the "winning" protocol.
Why Not Both
An agent doesn't have to pick. The interesting near-future is composition. Imagine an agent with:
- A long-lived Ed25519 identity (AID). Its own keypair, its own role on the auth server, used for autonomous actions that don't involve a user.
- A short-lived user-delegation context (auth.md / ID-JAG). Acquired when a user explicitly hands the agent permission to do something on their behalf.
When the agent acts autonomously — running its scheduled jobs, processing its inbox, doing the work a human granted it — its AID identity authenticates the call. When it acts on a user's request — "go book me a flight" — it presents both. The token carries both agent_address and delegating_user. Audit logs show both. Authorization can be either's intersection, depending on policy.
This isn't science fiction. The aid_grant block we just shipped sits side-by-side with auth.md's agent_auth block on the same auth-server metadata document. A server that publishes both supports both. An agent that has both pulls whichever it needs. We're not trying to win — we're trying to fill the unoccupied position so the stack is complete.
Closing
The agent-authentication landscape today is rich in delegation models and impoverished in identity models. Every public proposal teaches a service how to trust an intermediary — a provider, a wallet, an OAuth registration, a user assertion. None of them teach a service how to know the agent itself.
That's the gap AID fills. It's not the right answer for every shape — ChatGPT calling random services for Jane isn't going to work this way and shouldn't. But for autonomous, long-lived, audited agents inside systems we control, the agent-has-its-own-identity model is the missing default. The audit log you're going to wish you had built. The blast-radius containment you're going to wish you had picked.
Build for both. The agent that has its own keys and can carry user-delegation context is the agent that fits the most deployments. That's where the standards stack should land.