Skip to main content
Control-plane tokens support least-privilege scopes. An agent that only reads the model catalogue should not hold a credential that can also cancel the subscription and drain the wallet.
Scopes are opt-in. A token minted without a scopes array is issued with * and behaves exactly as before, so every credential already in use keeps working. Nothing here is a breaking change.

Requesting a scoped token

Send a scopes array on login:
The response echoes the granted scopes:
An unknown scope is rejected with 422 rather than silently dropped, so you never receive a token wider than the one you asked for.

Available scopes

The list is also available unauthenticated at GET /api/agents/v1/auth/scopes and in scopes_supported at /.well-known/oauth-authorization-server, so an agent can read it before it holds a credential.

Working out the minimum set

Every operation in agents-openapi.json declares the scope it requires as x-required-scope. You can compute the exact set your workflow needs before authenticating:

When a call is out of scope

The response is 403, and the required scope is named in both the body and the WWW-Authenticate header (RFC 6750):
Re-authenticate requesting that scope. Do not retry the same call.

Two rules worth knowing

POST /api/agents/v1/auth/switch-account issues a token for another account in your team. The scopes it grants are the intersection of what you ask for and what the token performing the switch already holds, so a context switch can never be used as a privilege-escalation path. Ask for more than you hold and you get 403 insufficient_scope.
POST /api/agents/v1/auth/logout revokes the token making the call, and works on any token however narrow. A credential you can only destroy by holding a wider one is a credential you cannot safely hand out.logout-all and DELETE /auth/tokens/{id} act on other tokens and do require tokens:write.