auth.md and AID: Complementary Layers, Not Competitors
WorkOS launched auth.md two days ago — an open protocol for agents to register themselves with services. It's a thoughtful design, anchored in real IETF standards. It also makes one architectural choice that's directly opposite to AID: the agent never has its own cryptographic identity. After spending a day with the spec and the reference implementation, my read is that auth.md and AID aren't really competitors. They answer different questions at different layers, and the cleanest future is one where they compose.
What Each Protocol Actually Is
auth.md is an open protocol from WorkOS that lets a service publish a markdown file at https://yourservice.com/auth.md describing how agents can register. Agents fetch the file, follow the recipe, and either present a signed identity assertion (an ID-JAG from a trusted agent provider) or go through an email-OTP claim ceremony. The wire format is JSON over /agent/auth, with discovery via RFC 9728 Protected Resource Metadata. The reference implementation is TypeScript. The spec was published on May 21, 2026.
AID (Agent Identity) is what we've been building at 23blocks. Each agent has its own Ed25519 keypair. Registration is a one-time human-approved binding between that keypair and a role on an auth server. From then on, every token request is a signed proof of possession over a custom OAuth 2.0 grant type, urn:aid:agent-identity. Reference implementation is bash + curl + jq + openssl. Already in production.
Both protocols use Ed25519 and OAuth 2.0 at the core. Both require human authorization before agents can operate. Both are MIT-licensed. After that, the philosophies diverge sharply.
The Fundamental Architectural Split
Read auth.md's agent-provider guide closely and you'll find a striking sentence: "The document does not establish cryptographic identity for the agent itself." The agent provider has keys. The agent — the thing actually making requests — does not. It operates inside a user's session and presents a signed assertion that says "this user, on this provider, consented to this audience." The provider holds the private key.
AID flips this. The agent is the identity. It has its own Ed25519 keypair, its own address (support-bot@acme.local), its own role, its own scopes. There's no "provider" intermediary — the agent's signature is sufficient because the auth server has, at registration time, recorded the agent's public key as a first-class principal.
This isn't a small detail. It changes what's auditable, what's blast-radius-contained, what's revocable, and what fits which deployment shape. Two examples to make it concrete:
Logs show agent_address=support-bot@acme.local. If two agents act under one user's authority, you can tell them apart. Per-agent rate limits become trivial.
Logs show iss=provider-X, sub=user-Y. Two agents acting for the same user on the same provider are indistinguishable. Per-agent attribution requires a separate channel.
Side-by-Side Comparison
| Dimension | auth.md | AID |
|---|---|---|
| Who holds the private key | Agent provider | The agent itself |
| Primary principal | End user (agent acts "on behalf of") | The agent (first-class) |
| Trust anchor | Service-maintained allowlist of provider JWKSs | Per-service per-agent registration |
| Discovery | RFC 9728 PRM + /auth.md | RFC 9728 + aid_grant block (just shipped) |
| Onboarding flows | Three (ID-JAG, verified email, anonymous + OTP) | Two (admin-initiated, agent-requests-pending) |
| Wire format | JSON body POST to /agent/auth | OAuth 2.0 grant urn:aid:agent-identity |
| Revocation | Push: provider→service backchannel | Pull: RFC 7662 introspection |
| Credential formats | JWT or opaque API key | RS256 JWT (opaque on roadmap) |
| PII in the protocol | Yes (email, phone) | No (agent address + fingerprint only) |
| Reference impl | TypeScript / Node | Bash + jq + curl + openssl |
| Status | Public release (2026-05-21) | v1.0, in production |
| License | MIT | MIT |
Where auth.md Wins
Standards lineage. auth.md anchors itself in RFC 9728, the ID-JAG IETF draft, and OIDC backchannel logout. That's a one-Slack-message sell to enterprise security teams. Until last week, AID's standards story was thinner. We've since added an RFC anchoring table to the spec and discovery is now RFC 9728/8414-shaped, but auth.md has more standards-shaped depth out of the gate.
Friction laddering. auth.md's anonymous-start flow is genuinely clever. An agent that has no identity assertion can still register, get a low-scope API key immediately, and earn more scopes later through an email OTP claim. AID is binary — approved or not. The auth.md design lowers activation friction for consumer-AI shapes.
Scale via the provider model. One agent provider (Anthropic, OpenAI, Google) can vouch for millions of agents. AID would need every service to register every agent individually. For the "Claude-acting-for-Jane" scenario where Claude has never seen Acme Corp's API before, the provider model scales beautifully.
Consumer-AI fit. The user is the principal; the agent is ephemeral; identity assertions carry user context. This matches how ChatGPT-style assistants actually deploy today.
Distribution and authorship. WorkOS-backed launch. Garrett Galow shepherding the spec. ID-JAG co-authored by Aaron Parecki and Karl McGuinness — the same people who wrote PKCE and FAPI. That's a credibility tailwind.
Where AID Wins
Per-agent auditability. Logs show which agent did which thing. With auth.md you log (provider X, user Y) — you cannot distinguish two agents acting for the same user under the same provider. For SOC 2 audit trails, fraud investigation, and per-agent rate limiting, this matters.
Per-agent least privilege. AID roles are bound to the agent, not the user. A user with admin rights can run a read-only agent. With auth.md, scope decisions are mediated by the provider and the service's PRM — the agent has no independent scope envelope.
Proof-of-possession by the agent. AID's aid-token-exchange\n<ts>\n<oidc_issuer> signed proof binds each token request to the holder of the key. auth.md doesn't prove the agent holds anything — it proves the provider did.
Provider-compromise blast radius. In auth.md, compromise of one provider's signing key compromises every delegation it ever issued, until services rotate their trusted-provider lists. WorkOS's own docs flag this as "security-critical configuration." AID has no providers — compromise of one agent's key compromises one agent.
Real-time revocation without provider cooperation. RFC 7662 introspection works whether or not anyone pushes events. auth.md's revocation depends on the provider's willingness and ability to push. Push-based revocation also has its own subtle reliability story (retries, ordering, idempotency by jti) — pull-based is simpler.
Headless deployments. AID is bash + curl + jq + openssl. No runtime. No SDK. Works inside a Dockerfile RUN line. Drop it into a CI job, a cron, a sidecar.
No PII in the protocol. Important for compliance and for B2B/server-to-server cases. Agents don't have emails or phones. They have addresses and fingerprints.
The Convergence Opportunity
Here's the clearest framing: auth.md and AID solve different layers of the same problem.
- auth.md answers: "How does a fresh agent discover a service and bootstrap a registration?"
- AID answers: "How does a registered agent prove it's the holder of a specific identity on every subsequent request?"
These are stackable. An auth.md agent_auth block could advertise urn:aid:agent-identity as one of its assertion_types_supported. The agent's Ed25519 public key becomes the registration artifact. AID's token-exchange grant takes over for ongoing token issuance. You get auth.md's discoverable bootstrap and AID's per-agent identity in the same flow.
This week we shipped the prerequisite on AID's side. The new aid_grant block lives at /.well-known/oauth-authorization-server and is intentionally shaped to sit side-by-side with auth.md's agent_auth block on the same metadata document:
{
"issuer": "https://auth.acme.com/zoom",
"token_endpoint": "https://auth.acme.com/zoom/oauth/token",
"grant_types_supported": [
"urn:aid:agent-identity",
"client_credentials"
],
"aid_grant": {
"aid_version": "1.0",
"registration_endpoint": "...",
"registration_request_endpoint": "...",
"key_algorithms_supported": ["Ed25519"]
},
"agent_auth": {
"register_uri": "...",
"identity_types_supported": ["anonymous", "identity_assertion"]
}
}
A single auth server can support both protocols. An agent that knows it has an Ed25519 identity uses the AID path. An agent that only has a user-delegation context uses the auth.md path. Nothing forces a choice. We're going to open an issue on workos/auth.md proposing this composition — Garrett's blog explicitly invites community feedback (authmd@workos.com) and the architectural surface is small.
Adoption Snapshot
Where each protocol sits in the broader landscape today:
- auth.md: Days old, ~40 stars on GitHub, WorkOS distribution, ID-JAG IETF momentum. Likely to grow fast in consumer-AI.
- ID-JAG: IETF OAuth WG draft-03. Strong signal.
- DCR (RFC 7591) + MCP: The MCP team has pivoted to DCR after running into the limits of manual registration. There's real market pull for something here.
- Other proposals (AAuth, Agent Auth, x402): all early-stage. See API Changelog's roundup.
- AID: niche but architecturally distinct. The "agent has its own identity" position is unoccupied in the public landscape. Every other proposal models the agent as either a client (DCR), a session (auth.md/ID-JAG), or a wallet (x402).
The market is clearly looking for an answer. The question is whether the answer is one protocol or a layered stack. We think it's the stack.
The Bottom Line
auth.md is the better answer for consumer AI: ChatGPT acts for Jane, hits a service that's never seen Jane before, both sides discover each other through standard well-known URLs, and the agent provider's JWKS provides the trust anchor. The user is the principal; the agent is the proxy.
AID is the better answer for autonomous, long-lived, audited agents: support-bot has its own keys, its own role, its own scopes, its own audit trail. It runs in a server. It doesn't act for a particular user — it acts for itself, with permissions an admin granted explicitly. The agent is the principal.
The interesting near-future is composing them. An auth server publishes both aid_grant and agent_auth blocks. A multi-modal agent — say, Claude with a registered Ed25519 identity and a user-delegation context — uses whichever path fits the request. That's a future worth building toward.
Disclosure: This article is written by the AID team. We've tried to be fair about both protocols and link to the primary sources throughout. auth.md is open source at github.com/workos/auth.md. AID is open source at github.com/agentmessaging/agent-identity.