Where AID Fits with auth.md
WorkOS auth.md gives agents a way to register with a service after they reach it. AID gives that flow a DNS-first, optionally key-proven first hop.
Where AID Fits with auth.md
WorkOS published auth.md this week. I think it is one of the more useful agent-auth proposals out there because it solves a real workflow without trying to become the whole identity stack.
The short version:
auth.md tells an agent how to register with a service once the agent has reached it. AID answers the earlier question: given a domain, where should the agent start, and can that endpoint prove it is the one the domain published?
That distinction is the whole composition.
If it helps the framing: AID is the DKIM for agents. A DNS-published key, an endpoint that signs to prove control of it. Same shape applied to agents instead of email. The PKA post goes deeper on where the analogy holds and where it breaks.
The rest of this post is the receipts.
The handoff rule is short:
- If the agent already has the protected resource URL from a connector, SDK, registry, docs, cache, or user instruction, start with auth.md and OAuth metadata.
- If the agent only has a domain, start with AID.
- If AID returns PKA key material, verify the endpoint before sending identity material.
- Then continue into the normal auth.md flow.
AID does not replace auth.md. It removes the requirement that the agent already knows the protected resource URL through a registry, connector catalog, SDK, documentation, search, or previous integration. It makes auth.md reachable from a bare domain, and it gives the agent a place to verify the endpoint before sending an ID-JAG, an email address, a claim token, or a bearer credential.
What auth.md Does
auth.md is a registration path for agents.
WorkOS describes it as both a Markdown document and a protocol. The document is hosted at https://yourservice.com/auth.md. The protocol is a small registration surface around endpoints like /agent/auth, /agent/auth/claim, and /agent/auth/claim/complete.
The machine-readable center of the design is not the Markdown file itself. The current WorkOS docs say the Protected Resource Metadata document at /.well-known/oauth-protected-resource is the source of truth. That document points at one or more OAuth Authorization Servers. The Authorization Server metadata then carries an agent_auth block with fields like:
{
"agent_auth": {
"skill": "https://service.com/auth.md",
"register_uri": "https://auth.service.com/agent/auth",
"claim_uri": "https://auth.service.com/agent/auth/claim",
"revocation_uri": "https://auth.service.com/agent/auth/revoke",
"identity_types_supported": ["anonymous", "identity_assertion"],
"anonymous": {
"credential_types_supported": ["api_key"]
},
"identity_assertion": {
"assertion_types_supported": [
"urn:ietf:params:oauth:token-type:id-jag",
"verified_email"
],
"credential_types_supported": ["access_token", "api_key"]
}
}
}From there the agent picks one of the supported registration methods.
In the agent-verified flow, a trusted agent provider signs an ID-JAG asserting that the agent is acting for a user. The service checks the issuer against its trusted-provider list, verifies the JWT against the provider's JWKS, validates aud, jti, iat, exp, and a verified contact claim, then returns a scoped credential.
In the user-claimed flow, the service runs an OTP ceremony. The agent can start with a verified email and wait for the user to read back a code. In some deployments it registers anonymously first with reduced scopes and lets the user claim the credential later.
That closes a real gap. Sign-up forms and ordinary OAuth flows were built around humans clicking through screens. auth.md gives agents an explicit registration path without asking every service to invent a bespoke one.
The Earlier Question
auth.md begins after the agent has found a protected resource or already received a 401 with:
WWW-Authenticate: Bearer resource_metadata="https://api.service.com/.well-known/oauth-protected-resource"That is the right shape for OAuth. It also assumes the client already knows which API or service URL to call. That URL might come from a first-party SDK, an MCP registry, an enterprise connector catalog, documentation, search, a previous session, or a direct instruction. Those paths are real. They all require some prior knowledge that does not come from auth.md, because the auth.md discovery chain starts after the agent has reached the protected resource or its metadata.
That starting condition is not always there. A user may tell an agent, "book this through opentable.com." A partner agent may claim to represent acme.com. An enterprise workflow may start with a domain, not an API base URL. In those cases, the agent should not guess between the marketing site, the dashboard origin, the API host, an MCP server, or some agent-specific gateway. Before it fetches Protected Resource Metadata, reads an agent_auth block, or posts an ID-JAG, it needs the first hop:
Given this domain, what is the agent endpoint, and which protocol should I speak?
That is the narrow question AID answers.
_agent.example.com. 300 IN TXT "v=aid1;p=mcp;u=https://api.example.com/mcp;a=oauth2_code"AID maps a domain to an initial agent endpoint, a protocol token, an optional auth hint, optional docs and deprecation metadata, and optional PKA key material. It does not describe the service's scopes. It does not register the agent. It does not issue credentials. It does not decide whether a user has authorized an action.
It gives the client a starting point that is domain-owned, cheap to publish, and independent of any one application framework. Once the client has that starting point, auth.md and OAuth metadata take over.
The Clean Composition
Read as a layered flow, the two systems fit cleanly.
| Hop | Question | Mechanism |
|---|---|---|
| 1 | Given a domain, where do I start? | AID DNS record at _agent.<domain> |
| 2 | Is this the endpoint and key the domain published? | Optional AID PKA endpoint proof |
| 3 | Given the service URL, where is its OAuth metadata? | RFC 9728 Protected Resource Metadata |
| 4 | Given the Authorization Server, does it support agent registration? | Authorization Server metadata with agent_auth |
| 5 | Given an accepted registration method, how does the agent get a credential? | auth.md /agent/auth flows |
| 6 | Given a credential, how is access constrained and revoked? | Service-issued bearer credential, scopes, audit, revocation |
End-to-end:
- Agent is asked to work with
example.com. - Agent resolves
_agent.example.com. - AID returns
p=mcp,u=https://api.example.com/mcp,a=oauth2_code. - If
kis present, the endpoint proves possession of the DNS-published key. - Agent calls the endpoint.
- Endpoint returns
401withresource_metadata. - Agent fetches the RFC 9728 Protected Resource Metadata.
- Agent fetches Authorization Server metadata and reads
agent_auth. - Agent follows auth.md: ID-JAG, verified-email claim, or anonymous registration.
- Service issues a scoped credential.
The important part is not the exact example. It is the boundary. AID owns the first-contact domain-to-endpoint hop. auth.md owns the registration and credential hop.
Here is the same handoff as a compact wire example. An agent is asked: "set up access for example.com."
AID resolves:
_agent.example.com. 300 IN TXT "v=aid1;p=openapi;u=https://api.example.com;a=oauth2_code"The agent calls the discovered endpoint and gets an OAuth discovery hint:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource"The Protected Resource Metadata points to the service's Authorization Server, which advertises agent registration:
{
"issuer": "https://auth.example.com",
"agent_auth": {
"skill": "https://example.com/auth.md",
"register_uri": "https://auth.example.com/agent/auth",
"identity_types_supported": ["identity_assertion"],
"identity_assertion": {
"assertion_types_supported": [
"urn:ietf:params:oauth:token-type:id-jag"
],
"credential_types_supported": ["access_token"]
}
}
}The agent asks its provider for an audience-scoped ID-JAG and exchanges it at the register URI for a scoped credential. AID did not register the agent. It found the right starting endpoint. auth.md and OAuth metadata handled registration and credential issuance.
For a service implementing both, the recipe is short:
- Publish
_agent.example.comwith the service's agent endpoint. - Serve that endpoint over HTTPS.
- If using PKA, make the endpoint sign the first response before identity material is sent.
- Return RFC 9728
resource_metadatafrom the protected resource. - Publish Authorization Server Metadata with
agent_auth. - Keep auth.md as the human-and-agent-readable runbook for the same flow.
- Issue only scoped, revocable credentials from the auth.md registration endpoint.
What This Means for auth.md
auth.md makes the agent registration path legible once the agent has reached the service. AID makes the service reachable from the public name the user or agent probably started with.
That is not a theoretical nicety. Without a first-hop mechanism, agents still learn service URLs through documentation, search, hardcoded integrations, SDK hints, central registries, or a failed request that returns WWW-Authenticate. Those paths are useful. They are not the same as asking the domain itself.
For a service implementing both, the win shows up in one extra DNS record. The service becomes discoverable from a domain without changing its registration protocol. The registration surface stays exactly as auth.md defines it.
Agents get something concrete too. Before sending an ID-JAG, an email address, a claim token, or a bearer credential into an auth.md flow, the PKA mechanism lets the agent verify it reached the domain-published endpoint and not a misdirected or impersonating service. PKA is currently defined as an RFC 9421 HTTP Message Signatures handshake. The AID v2 explained draft puts the boundary sharply:
PKA proves that the endpoint reached at the discovered URI controls the private key corresponding to the public key currently published in the selected AID record.
That is deliberately narrow. It does not prove an ID-JAG is valid. It does not prove an OAuth token is authorized. It does not prove SPIFFE trust-domain membership, WIMSE hop re-binding, human approval, reputation, or policy approval. It is enough to verify the endpoint before identity material leaves the agent.
The smallest useful ask for the auth.md team is this: document AID as the "starting from a domain" preflight. Services that already support auth.md do not have to redesign anything. They publish one DNS record, support PKA when they publish key material, and let the existing auth.md machinery continue from the discovered endpoint.
Where the Boundary Stays Clean
The tempting mistake would be to stuff auth.md into DNS. Do not do that.
AID should not publish agent_auth blocks, ID-JAG issuer lists, scopes, credential types, provider trust lists, revocation endpoints, SPIFFE bundle endpoints, WIMSE trust-domain mappings, or registration payloads in the DNS record. That information changes too often, is too large for the first-hop record, and belongs in OAuth metadata, service documentation, policy systems, and registration protocols.
The current AID v2 plan says this directly. AID v2 core supports auth.md through a non-normative OAuth handoff note, not by importing auth.md fields into the core record. The existing a=oauth2_code hint is enough to say "expect an OAuth-style layer next." The details should come from RFC 9728, RFC 8414, and agent_auth.
The trusted-provider list is the most important place this matters. In the agent-verified auth.md flow, a service decides whether to accept an ID-JAG from iss=https://provider.example by checking that issuer against a trust list it maintains. WorkOS is explicit that this list is security-critical configuration. AID should not silently replace it. A DNS first-hop record tells the agent where to start. It does not tell the service which ID-JAG issuers to trust.
Keeping the boundary clean means:
- AID does not become an authorization server.
- auth.md does not have to become a DNS discovery protocol.
- DNS carries the stable first-hop pointer and optional key.
- HTTP metadata carries the richer registration and authorization surface.
A later AID profile may explore whether a DNS-published key should attest to accepted issuers, JWKS locations, or provider metadata. Those are profile questions, not first-hop DNS record questions.
Why the Layers Matter
The agent stack is separating into layers because it has to.
Discovery is not registration. Registration is not authorization. Authorization is not endpoint proof. Endpoint proof is not user consent. User consent is not workload federation.
Treating those as one problem is how you end up with DNS records that try to be JWT issuers, or registration endpoints that quietly take over endpoint verification. Each piece stays useful by being clear about where it stops. AID stops at the first hop and the optional endpoint proof. auth.md stops at registration and credential issuance. OAuth stops at the authorization grant. Each one is small enough to reason about because the next one picks up where it ends.
Concrete Next Steps
For AID, the next step is modest. Add a non-normative auth.md handoff note to the v2 spec draft. It should say that after AID resolves and verifies an endpoint when PKA is present, clients continue into RFC 9728 Protected Resource Metadata, RFC 8414 Authorization Server Metadata, and an agent_auth registration flow where present.
For auth.md implementers, the AID integration recipe is:
- If a client starts from a domain, resolve
_agent.<domain>first. - If the selected AID record has PKA key material, verify the endpoint before sending identity assertions or credentials.
- Then proceed with the normal auth.md flow.
For the WorkOS docs, this fits as a short "Starting from a domain" section rather than a major dependency:
If the agent begins with only a domain, use AID to discover the service endpoint: _agent.<domain> → endpoint URL → optional PKA proof → RFC 9728 PRM → agent_auth.
That lets WorkOS embrace AID without making auth.md depend on AID. Services that do not publish AID still work. Services that do publish AID become easier for agents to find and safer to approach.
For reviewers, the thing to watch is overreach. AID can make auth.md safer at the first-contact boundary. It should not claim to verify auth.md itself, replace provider trust lists, or prove that an agent is authorized for a user action.
The composition works because the boundary is clean.
Sources: auth.md, WorkOS auth.md announcement, workos/auth.md reference implementation, RFC 9728, RFC 8414, ID-JAG draft, OAuth Client ID Metadata Document draft, AID v1.2 specification, AID v2 explained draft, and the AID v2 planning branch.