Agent Registration
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 |
Your choice of identity type depends on your application’s data model:
- If entities are owned by users (e.g. a user’s documents, personal settings), enable only
service_auth. This ensures every agent is bound to a specific user through the claim ceremony before it can act on their behalf. - If the resource owner is an organization (e.g. shared team resources, org-wide data),
anonymousregistrations work well – agents can begin interacting with organization-scoped resources immediately and optionally bind to a user later.
When enabling anonymous, assign it a restricted set of untrusted permissions suitable for exploration only. Sensitive operations should require trusted (post-claim) permissions so that anonymous agents cannot perform them. See Trust levels and scopes for details.
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 discover your registration endpoints through a standards-based chain defined by RFC 9728:
- Your API returns a
WWW-Authenticateheader with aresource_metadataparameter pointing to your Protected Resource Metadata document. - The agent fetches
/.well-known/oauth-protected-resourceand reads theauthorization_serversarray. - The agent fetches the Authorization Server metadata, which includes an
agent_authblock with registration endpoints.
Set up the link between your protected resource and your authorization server in the WorkOS Dashboard under Authentication → Agents → Configuration → OAuth well-known discovery.
The skill field in the AS metadata 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://example.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:
For Cloudflare Enterprise, skip the worker and use a URL rewrite rule instead.
Replace authkit_domain with your environment’s AuthKit domain. The Dashboard provides the exact source URL and configuration snippets for your environment.
auth.md URL is public – agents can access it directly without a reverse proxy. You can test the full registration flow without setting up hosting first.
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.
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:
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:
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:
The response includes attempt.verification_uri – a URL for the user.
The agent presents the verification_uri to the user. When they open it:
- They sign in to AuthKit (if not already authenticated)
- The page reveals a short
user_code - The user reads this code back to the agent
The agent submits the code along with its claim token:
On success, the response contains identity.assertion and identity.refresh_token – the agent’s trusted credentials.
By default, the claim ceremony sends the user to AuthKit’s hosted verification page to sign in and view their user_code. With the standalone claim ceremony, you keep the user in your own UI: your server links the user to the claim attempt and retrieves the user_code, which you display yourself – no redirect to AuthKit required. You still rely on WorkOS for the underlying claim; only the verification screen moves into your app.
Use the link claim attempt admin API endpoint when you want to:
- Render the claim ceremony in your own UI instead of AuthKit’s hosted verification page.
- Link a user to an agent registration server-side, without a browser redirect.
- Control how and where the
user_codeis presented to the user.
In the standard claim ceremony, the user opens a verification_uri that points to a hosted AuthKit page, signs in, and sees the user_code. With the standalone approach, your server handles that step instead:
- Agent starts a claim attempt – same as the standard flow. The agent receives a
claim_tokenand anattempt.verification_uri. - Your server links the user – instead of the user opening the verification URI, your backend calls the admin API with the
claim_attempt_tokenand the user’s identity. The API returns theuser_code. - Your app displays the code – show the
user_codeto the user in your own UI so they can relay it to the agent. - Agent completes the claim – same as the standard flow. The agent submits the
user_codeto finalize the binding.
user_code. AuthKit’s hosted verification page signs the user in first; when you move that step into your own UI, you take on that responsibility. Only reveal the code to a user your application has already signed in – otherwise anyone who can reach your UI could claim the agent. WorkOS still enforces that the email you pass matches the email bound to the claim attempt, but it cannot verify that the person viewing your UI is that user.
Call PATCH /agents/claims/attempts with your WorkOS API key, the claim_attempt_token from the agent’s registration, and the user’s identity:
The user.external_id identifies the user in your system. If no WorkOS user exists with that external ID, one is created automatically. If a user already exists and the email does not match, the request is rejected.
The response includes the user_code the agent needs to complete the claim:
When the user belongs to multiple organizations, include organization_id to specify which organization the agent should act within:
If the user belongs to multiple organizations and no organization_id is provided, the API returns a 409 error with code organization_selection_required and the list of available organizations in the response. Use one of the returned organization IDs to retry the request.
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:
The credential type (access token or API key) and its lifetime are configured per environment in the WorkOS Dashboard.
Agent access tokens include the following claims:
| Claim | Description |
|---|---|
iss |
The issuer URL for the environment |
aud |
The audience – the environment’s client_id, or the resource URI if one was requested |
sub |
The agent registration ID (e.g. agent_reg_01ABC...) |
org_id |
The organization the agent is acting within |
scope |
Space-separated list of granted permissions |
act |
Delegation claim identifying the user who authorized the agent (e.g. {"sub": "user_01DEF..."}) |
jti |
Unique token identifier |
iat |
Issued-at timestamp |
exp |
Expiration timestamp |
The act claim follows the RFC 8693 delegation pattern and is present only after a successful claim ceremony binds a user to the registration.
Once an agent has exchanged its assertion for a credential, your application needs to validate that credential on incoming requests.
Access tokens – For short-lived access tokens, you can validate the JWT locally by verifying the signature and checking expiration. This avoids a network round-trip on every request. If you need to check whether a token has been revoked before expiry, call the validate credential endpoint.
API keys – API keys must be validated server-side. Use the validate credential endpoint to confirm the key is still active and retrieve its associated registration.
To see full details about the agent behind a credential – its identity, organization, claim status, and timestamps – use the get registration endpoint with the registration ID from the access token’s sub claim.
Agent Registration uses two trust levels to control API access:
- Untrusted (pre-claim) – the default for anonymous registrations before a claim ceremony. Grants limited scopes suitable for exploration.
- Trusted (post-claim) – granted after a successful claim ceremony. Grants full scopes.
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 Registrations tab lists all agent registrations created against your environment, including their current status (unverified, verified, expired, revoked), the associated user, and the organization.
Enable the identity types agents can use to register:
- Service auth – agents register on behalf of a user, confirming identity through a claim ceremony
- Anonymous – agents register instantly with no credentials; users claim ownership when ready
Each method can be independently enabled or disabled.
Credential settings
Set the credential type and lifetime for all agent registrations:
- Credential type – choose whether the token exchange mints an access token (short-lived, re-mintable) or an API key (durable, persisted by the agent)
- Credential expiration – the lifetime of issued credentials
Trust level permissions
Define which permissions are available at each trust level:
- Trusted permissions – granted after a successful claim ceremony. These are the full set of permissions for verified agents.
- Untrusted permissions – granted to anonymous registrations before a claim. Use these for limited, exploratory access.
Only permissions that are enabled for organization API keys appear here. To add a permission to the list, enable it under Authorization > Configuration > Organization API key permissions in the Dashboard.
Discovery
The Discovery section shows:
- Host auth.md – the source URL for your environment’s generated
auth.mdskill document, with a configuration dialog showing reverse-proxy setup for Nginx, Next.js, Vercel, and Cloudflare (see Hosting auth.md above) - OAuth well-known discovery – the authorization server metadata URL that agents use to locate your registration endpoints
Once your environment is configured, test the full flow by prompting any AI agent:
The agent will follow the instructions in auth.md to register and exchange its identity assertion for credentials it can use to call your API. The agent will also guide the user through the claim flow if necessary.