All docs
AgentID docs
Run from the app you want to configure:
$ npx @agentmail/agentid-cli initButton name and mark: brand page.
Set up with a coding agent
Give your coding agent this prompt.
Add AgentID sign-in to this project. Read https://www.agentid.com/llms-full.txt for the integration reference, then run `npx @agentmail/agentid-cli init` from the project root and follow its prompts.Add AgentID to your app
AgentID is a standard OpenID Connect provider. If your stack already validates login tokens, this is configuration, not code.
Auth providers#
Clerk
Clerk’s built-in AgentID connection, step by step with screenshots.
Supabase
Custom provider in Supabase Auth, step by step with screenshots.
Auth0
The official AgentID connection from Auth0 Marketplace, step by step.
Descope
Custom provider in Descope, step by step with screenshots.
Better Auth
A helper package for Better Auth’s Generic OAuth plugin, step by step.
Auth.js v4
One provider entry for an existing NextAuth app, step by step.
WorkOS
Not yetNot available yet. WorkOS AuthKit can’t add custom sign-in providers, so AgentID needs WorkOS to support it first.
Custom OIDC
Any other stack: the values a connector asks for, the defaults to change, and what to store.
Verifying a token#
Tokens are ES256. Validate against the JWKS and check iss and aud; caching keys by kid is safe.
https://auth.agentid.com/v0/jwks.jsonnpx @agentmail/agentid-cli doctorThe human owner
Every agent has a human owner. You can ask who they are, and cap how many accounts one owner’s agents create in your app.
Human owner scopes#
- owner_profile
- The name of the human who owns the agent, as the owner_name claim.
- owner_email
- That human’s email address, as the owner_email claim, plus owner_email_verified.
To be granted them:
- A registered application
- Create one in the AgentID console or with the CLI. Open clients cannot request owner scopes.
- The scopes in your sign-in
- Add owner_profile and owner_email to the scopes your auth provider sends to /authorize. They are not set when you create the application.
- The agent’s permission
- The agent’s AgentMail API key needs the App: Share Owner permission. Without it, the agent can’t finish the sign-in alone, and the organization owner has to approve it from their AgentMail account.
The claims arrive in the id_token and from /v0/userinfo: owner_name, owner_email and owner_email_verified, which is always true. Each claim is under token claims.
Only need to tell owners apart? The profile scope adds owner_sub, an opaque identifier that agents with the same owner share. It needs no owner scope, and open clients can request it.
Signup limit per owner#
Cap how many of one owner’s agents can create an account in your app. AgentID enforces the number, so there is nothing to build.
In the AgentID console, open your application, choose Settings › Edit, and set Maximum signups per owner. Click Save changes.
- Blank
- Unlimited. This is the default.
- 0
- No new signups. Inboxes that already have an account keep signing in.
- 1 to 1,000,000
- That many accounts per owner.
Counted per AgentMail organization, not per inbox. An inbox that already has an account can always sign in.
At the limit, the sign-in stops on the AgentID waiting page and your callback is not called. Registered applications only.
Reference
Endpoints#
All on the issuer origin.
- /.well-known/openid-configuration
- Discovery document. Point your OIDC client here and it derives the rest.
- /v0/jwks.json
- Public signing keys, with stable key ids and an overlap window across rotations. The pre-/v0 path still resolves here.
- /v0/authorize
- Starts an Authorization Code sign-in. Open clients require PKCE (S256). Registered clients may omit it; when one sends a challenge, the verifier is enforced.
- /v0/token
- Exchanges the code for an id_token and access_token, enforcing the verifier whenever authorization used PKCE and echoing a supplied nonce in the id_token.
- /v0/userinfo
- Returns identity and granted owner claims for a Bearer access token, re-checked against live state on every call. Token envelope fields and scope are not included.
- /v0/register
- Dynamic client registration (RFC 7591), advertised as registration_endpoint. The console and the CLI call it for you when you create an application.
Scopes#
Space-delimited. Start with openid email profile; no scope falls back to openid email.
- openid
- The agent’s verified subject. Always present, and every sign-in must carry it.
- The agent’s inbox address, plus email_verified.
- profile
- The agent’s display name as name, its address-derived handle as preferred_username, and an opaque identifier for its owner as owner_sub.
Owner scopes disclose the organization’s human owner. Open clients cannot request them.
- owner_profile
- The name of the human who owns the agent, as the owner_name claim.
- owner_email
- That human’s email address, as the owner_email claim, plus owner_email_verified.
You pick scopes in your auth provider, which sends them to /authorize, not when you create the application. What owner scopes need before they are granted is under human owner scopes.
Token claims#
- Always
sub"lM9vT2aR7sK4qN8wE1xC6bY0uF3hJ5pD9gL2zV7oA4Q"The inbox. The same in every app, and new if the inbox is recreated.actor_type"agent"Always "agent".iss"https://auth.agentid.com"The issuer. Matches discovery.aud"b7d41e0a-2c65-4f8b-9d31-0a5e7c2f4b18"Your client_id.iat1767225000Issued at, in Unix seconds.exp1767225600Expires ten minutes after iat.jti"9f1c2a44-3e77-4c19-9a2e-6b0d5f8e1c33"Unique ID for this token.- email scope
email"support@acme.agentmail.to"The agent’s inbox address.email_verifiedtrueAlways true.- profile scope
name"Acme Support"Display name. Omitted when the inbox has none.preferred_username"support_acme-agentmail-to"Handle, derived from the address.owner_sub"oW7xN2pQ4mT8vL1kR6sC9dF3gH5jB0aE2uY4zI6nP8A"Opaque owner ID, shared by that owner’s agents.- owner_profile scope
owner_name"Maya Chen"The human owner’s name.- owner_email scope
owner_email"maya@acme.com"The human owner’s email.owner_email_verifiedtrueAlways true.- Registered client
scope"openid email profile owner_profile owner_email"What the sign-in actually granted.- When sent
nonce"n-0S6_WzA2Mj"Echoed from your request, if you sent one.
/v0/userinforeturns the same claims withoutiss,aud,iat,exp,jtiandscope.- Open clients get no
scopeand no owner claims, and theiraudis the URL they use asclient_id. - Most auth libraries keep only the standard claims, so an owner claim can be in the token and missing from your session. Each provider guide names its fix.
Lifetimes#
- Sign-in transaction
- 5 min
- From the redirect to /authorize. The agent has to approve inside it.
- Authorization code
- 60 s
- Single use. Exchange it as soon as your callback receives it.
- id_token and access_token
- 10 min
- No refresh tokens, so a longer session is one you mint yourself.
- Sign-in key
- 30 days
- From activation. The browser’s credential for the inbox. Deleting the bearer key that created it revokes nothing.
- Remembered approval
- 180 days
- From the last sign-in, per inbox and client. A changed redirect URI or scope set asks again. It outlives a revoked key.
Keep state and code_verifier for at least ten minutes; an early expiry fails the callback as a mismatch.
Signing in with AgentID
What an agent does to complete a sign-in. Request and response shapes are in AgentID sign in on the AgentMail docs.
The waiting page#
An existing AgentID session continues on its own; otherwise the waiting page shows one command to create one. It also shows the auth_token, and the agent has 5 minutes to approve.
Approve#
POST /v0/inboxes/{inbox_id}/authorize
{ "auth_token": "<from the waiting page>", "accept_disclosure": true }Three things end separately.#
- The browser session
- Forgetting a session at auth.agentid.com/sessions removes the sign-in material from that browser alone, and the page lists only the sessions saved in the browser that opens it.
- The key
- Revoking the key,
DELETE /v0/api-keys/{api_key_id}on the AgentMail API, stops new sign-ins with it everywhere. - The app’s session
- Ends when you end it. A revoked key does not sign anyone out of your app.