How agents obtain identity and credentials from an AuthKit-powered service.
Agent Registration enables AI agents and LLM-based clients to obtain identity credentials from your AuthKit-powered service. Unlike traditional OAuth flows designed for users in a browser, Agent Registration is purpose-built for programmatic clients that need machine-readable instructions, minimal interaction, and secure credential management.
Agents discover the registration surface through your service’s .well-known/oauth-authorization-server metadata, register with one of several identity types, optionally bind to a user via a claim ceremony, and exchange the resulting identity assertion for an access token or API key.
Agent Registration supports three identity types, selected by the agent based on its context:
| Type | When to use | Claim ceremony |
|---|---|---|
anonymous | The agent has no user identity and wants to trial the service | Optional |
service_auth | The agent knows the user’s email and needs trusted access | Required |
refresh | The agent’s current assertion is expiring and needs rotation | Not applicable |
Agent AuthKit User │ │ │ │─── POST /agent/identity ─────────────────────►│ │ │ (type: service_auth) │ │ │◄── claim.token + attempt ─────────────────────│ │ │ (includes verification_uri) │ │ │ │ │ │─── "Open this link and read back the code" ──────────────────────────────►│ │ │◄── signs in, views code ──│ │◄── user reads code back ──────────────────────────────────────────────────│ │ │ │ │─── POST /agent/identity/claim/complete ──────►│ │ │ (user_code) │ │ │◄── identity.assertion ────────────────────────│ │ │ │ │ │─── POST /oauth2/token ───────────────────────►│ │ │ (assertion exchange) │ │ │◄── access_token / api_key ────────────────────│ │ │ │ │
verification_uri. The separate POST /agent/identity/claim endpoint is only needed if the initial attempt expires and the agent needs to start a new one.
Agents find the registration endpoints through your AuthKit domain’s OAuth Authorization Server metadata. When Agent Registration is enabled, the metadata includes an agent_auth block:
curl https://authkit_domain/.well-known/oauth-authorization-server | jq .agent_auth { "skill": "https://authkit_domain/agent/auth.md", "identity_endpoint": "https://authkit_domain/agent/identity", "claim_endpoint": "https://authkit_domain/agent/identity/claim", "identity_types_supported": ["anonymous", "service_auth"] }
The skill field points to a generated auth.md document – a step-by-step guide with curl commands tailored to your environment’s configuration. Agents can follow it directly without needing to parse this documentation.
For agents to discover your service, host the auth.md file at the root of your domain (e.g. https://yourapp.com/auth.md). The recommended approach is to reverse-proxy the WorkOS-hosted version so it always reflects your current configuration.
Find the source URL in the WorkOS Dashboard under Authentication → Agents → Configuration → Host auth.md, then configure your server:
async rewrites() { return [{ source: '/auth.md', destination: 'https://<authkit_domain>/agent/auth.md', }]; }
{ "rewrites": [ { "source": "/auth.md", "destination": "https://<authkit_domain>/agent/auth.md" } ] }
location = /auth.md { proxy_pass https://<authkit_domain>/agent/auth.md; proxy_set_header Host <authkit_domain>; proxy_ssl_server_name on; }
export default { async fetch(request) { const url = new URL(request.url); if (url.pathname === "/auth.md") { return fetch("https://<authkit_domain>/agent/auth.md"); } return fetch(request); } }
Replace <authkit_domain> with your environment’s AuthKit domain. The Dashboard provides the exact source URL and configuration snippets for your environment.
Anonymous registration creates an identity with no user binding. The agent receives an identity assertion immediately and can optionally bind to a user later via the claim ceremony.
curl -X POST https://authkit_domain/agent/identity \ -H "Content-Type: application/json" \ -d '{"type": "anonymous"}'
The response includes:
identity.assertion – a signed JWT the agent uses for credential exchangeclaim.token – used to start a claim ceremony later (optional)scopes.pre_claim – permissions available before claiming (untrusted)scopes.post_claim – permissions available after claiming (trusted)When the agent knows the user’s email, service_auth registration initiates a mandatory claim ceremony:
curl -X POST https://authkit_domain/agent/identity \ -H "Content-Type: application/json" \ -d '{"type": "service_auth", "login_hint": "user@example.com"}'
The response includes a claim.token and claim.attempt.verification_uri – the agent presents this URI to the user to start the claim ceremony.
When an assertion is nearing expiry, the agent rotates it using the refresh token from a previous registration or claim:
curl -X POST https://authkit_domain/agent/identity \ -H "Content-Type: application/json" \ -d '{"type": "refresh", "refresh_token": "<refresh_token>"}'
The claim ceremony binds an agent registration to a user, similar to the OAuth 2.0 Device Authorization Flow. It’s required for service_auth and optional for anonymous registrations.
The agent mints a claim attempt using the claim token from registration:
curl -X POST https://authkit_domain/agent/identity/claim \ -H "Content-Type: application/json" \ -d '{ "kind": "service_auth", "token": "<claim_token>", "login_hint": "user@example.com" }'
The response includes attempt.verification_uri – a URL for the user.
The agent presents the verification_uri to the user. When they open it:
user_codeThe agent submits the code along with its claim token:
curl -X POST https://authkit_domain/agent/identity/claim/complete \ -H "Content-Type: application/json" \ -d '{ "claim_token": "<claim_token>", "user_code": "<code from user>" }'
On success, the response contains identity.assertion and identity.refresh_token – the agent’s trusted credentials.
After obtaining an identity assertion (from registration or claim completion), the agent exchanges it at the token endpoint for an access token or API key:
curl -X POST https://authkit_domain/oauth2/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \ --data-urlencode "assertion=<identity_assertion>"
The credential type (access token or API key) and its lifetime are configured per environment in the WorkOS Dashboard.
Agent Registration uses two trust levels to control API access:
Configure which scopes map to each trust level in the WorkOS Dashboard under your environment’s agent auth settings.
Configure Agent Registration in the WorkOS Dashboard under Authentication → Agents. The page has three tabs:
Enable the identity types agents can use to register:
Each method can be independently enabled or disabled.
The Configuration tab contains three sections:
Set the credential type and lifetime for all agent registrations:
Define which permissions are available at each trust level:
The Discovery section shows:
auth.md skill document, with a configuration dialog showing reverse-proxy setup for Nginx, Next.js, Vercel, and Cloudflare (see Hosting auth.md above)Agent Registration must be enabled for your environment. Contact your WorkOS account team if it is not yet available.