Agent identity
An agent is a first-class client type. Registering one through the management API gives it an org-bound identity, a specific set of tool scopes, and — optionally — a DID it can prove with a verifiable credential.
This is the difference between an agent and a dynamically registered client: agents are provisioned by someone holding an API key, so they can be bound to an organization and granted tool scopes. Anonymous registration can do neither.
Register an agent
Section titled “Register an agent”Requires agents:write.
POST /v1/organizations/org_01J…/agentsAuthorization: Bearer sk_live_…
{ "name": "Research bot", "scopes": ["tool:search", "tool:weather"], "agent_did": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"}{ "client_id": "agent_8f3b2c…", "client_secret": "cs_…", "scopes": ["tool:search", "tool:weather"], "agent_did": "did:key:z6Mk…", "token_endpoint": "https://acme.oauth.work/token", "grant_type": "client_credentials"}The client_secret is shown once.
Scopes must be tool scopes — mcp:*, tool:*, or a2a:*. Anything else is refused:
{ "error": "invalid_scope", "detail": "invalid agent scopes: admin (allowed: mcp:*, tool:*, a2a:*)" }Omitting scopes defaults to ["mcp:tools"], which is broad — it satisfies every tool on the demo
MCP server. Name the specific tools an agent needs instead. That list is the whole of what the agent
can ever be authorized for: it bounds not only its own tokens but also what it can receive through
delegation.
agent_did is optional. When set, it becomes the token sub and the subject of any
agent identity credential the agent mints.
Get a token
Section titled “Get a token”Agents use the client-credentials grant with client_secret_basic:
POST /tokenAuthorization: Basic <base64(agent_8f3b2c…:cs_…)>Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&scope=tool:search&resource=https://tools.acme.com/mcp{ "access_token": "eyJ…", "token_type": "Bearer", "expires_in": 3600, "scope": "tool:search"}Requesting more scopes than the agent holds narrows to the intersection rather than failing, so read
scope in the response. Requesting a resource the agent is not allowed fails with
invalid_target.
The token’s actor_type is agent, and sub is the agent’s DID when it has one, otherwise its
client id — so a resource server can tell an agent’s token from a user’s without inspecting the
client registry.
Add a DPoP proof to the token request and the resulting token is key-bound, which is worth doing for anything that will be passed between services.
For a stronger credential than a shared secret, register with private_key_jwt instead — see
client authentication.
Rotating a secret
Section titled “Rotating a secret”POST /v1/organizations/org_01J…/agents/agent_8f3b2c…/rotate_secretAuthorization: Bearer sk_live_…{ "client_id": "agent_8f3b2c…", "client_secret": "cs_…" }The old secret stops working immediately — there is no overlap window. Deploy the new secret before rotating, or plan for the gap. Already-issued access tokens are unaffected and remain valid until they expire; rotation prevents new ones from being minted, it does not revoke old ones. To cut those off too, revoke them.
Writes an agent_secret_rotated audit event.
Listing and deleting
Section titled “Listing and deleting”GET /v1/organizations/:orgId/agents # agents:readDELETE /v1/organizations/:orgId/agents/:clientId # agents:writeListing never returns secrets. Deleting stops the agent from obtaining new tokens.
Agent identity credentials
Section titled “Agent identity credentials”An agent’s token can mint a verifiable credential attesting to what it is — useful when the agent has to prove its identity to a party that does not share your authorization server.
POST /credentials/issueAuthorization: Bearer <agent access token>
{ "format": "sd-jwt-vc" }The platform recognizes the token’s actor_type and issues an AgentIdentityCredential rather than
a Work Credential:
{ "agentId": "agent_8f3b2c…", "actorType": "agent", "organization": "org_01J…", "scope": "tool:search"}It is signed by the tenant’s key and resolves through the tenant’s did:web document. Pass
holderDid to bind it to a did:key the agent holds, so the agent can prove possession rather than
merely presenting a bearer document.
A token that came from delegation mints a DelegationCredential instead, attesting that the
actor chain may act for the original subject.
See verifiable credentials for formats and verification.
Per-agent enforcement
Section titled “Per-agent enforcement”The platform hosts a demo MCP resource server at /mcp that enforces these scopes per tool, so you
can exercise the whole path before pointing agents at your own servers:
GET /mcp/tools{ "tools": [ { "name": "search", "description": "Search the (mock) knowledge base", "required_scope": "tool:search" }, { "name": "weather", "description": "Get the (mock) weather", "required_scope": "tool:weather" }, { "name": "email.send", "description": "Send a (mock) email", "required_scope": "tool:email.send" } ]}Calling a tool requires a token that is audience-bound to the resource and carries the tool’s scope. See MCP authorization.