# OAuth for machines and people

> How a human signs in, and how a machine client registers, authorizes, and calls an agent with a scoped token.

HTML version: https://agentbag.ai/docs/oauth-for-machines — updated 2026-10-05.

People sign in with Google at `https://agents.agentbag.ai/login`. Machines never sign in — they complete an OAuth 2.0 flow and hold a scoped token the owner can revoke.

## The discovery chain

OAuth endpoints live on the host that serves the agent — the product host, not this apex. For the retail tenant that is `https://agents.agentbag.ai`; on a custom domain it is the agent’s own host. Tokens are tenant-bound: run the whole chain on the host the user’s workspace lives on. The chain, on that host:

1. `GET https://agents.agentbag.ai/.well-known/oauth-protected-resource/<resource-path>` — which authorization server protects a resource (e.g. an agent’s MCP endpoint).
2. `GET https://agents.agentbag.ai/.well-known/oauth-authorization-server` — the issuer metadata: register, authorize, token, and revocation endpoints.
3. `POST https://agents.agentbag.ai/api/oauth/register` — dynamic client registration: name your client, get a `client_id`.
4. `GET https://agents.agentbag.ai/api/oauth/authorize` — the consent redirect (PKCE required); the owner or the audience level decides what is granted.
5. `POST https://agents.agentbag.ai/api/oauth/token` — exchange the code for an access token; `POST https://agents.agentbag.ai/api/oauth/revoke` to retire it.

## Audience levels

- Public — anonymous calls; the agent answers from public leaves only.
- Authenticated (`vwr_` envelope) — a signed-in viewer sees the leaves the owner granted them.
- Owner-approved — write actions and gated content, behind explicit grants.

> Envelopes are tenant-bound. A token minted for one workspace names that tenant in `aud` and is refused everywhere else — the tenant label, never the hostname, is what is compared.

## Endpoint limits

The OAuth endpoints carry their own per-caller windows: registration is capped at 10/hour, token exchange at 60/minute, revocation at 30/minute. A `429` answers with `retry-after` and `x-ratelimit-*` headers — honor them rather than retrying into the wall. Register once and reuse the `client_id`; scripted re-registration is the pattern the limit exists to refuse.

