Skip to main content

Agent Auth (OAuth 2.1)

OAuth 2.1 identity service for autonomous agents. Supports client credentials flow, token introspection (RFC 7662), revocation (RFC 7009), and delegated token exchange for agent-to-agent authentication.

Base path: /api/v1/cloud/auth

POST /clients​

Create an OAuth 2.1 client for a registered agent. The client_secret is returned only once.

agent_registration_id accepts the agent_id returned by POST /cloud/agents/register (e.g. agent-a1b2c3d4e5f6) — it's resolved to the registration's internal id automatically, so the only identifier the Registry ever gives you just works here (Refs #9301).

curl -X POST https://api.ainative.studio/api/v1/cloud/auth/clients \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_registration_id": "agent-a1b2c3d4e5f6",
"scopes": ["agent.register", "memory.recall", "memory.store"],
"token_ttl_seconds": 3600
}'

Response (201):

{
"id": "client-uuid",
"client_id": "agt_abc123def456",
"client_secret": "sk_agent_xxxxxxxxxxxx",
"scopes": ["agent.register", "memory.recall", "memory.store"],
"token_ttl_seconds": 3600
}

POST /token​

Client credentials grant. Exchange client_id + client_secret for an access token.

grant_type must be client_credentials — this is the only grant type implemented for agent OAuth. Any other value (e.g. authorization_code) returns 400 Bad Request with "Unsupported grant_type: ... Only 'client_credentials' is supported.".

curl -X POST https://api.ainative.studio/api/v1/cloud/auth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=agt_abc123&client_secret=sk_agent_xxx&scope=agent.register memory.recall"

Response:

{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "agent.register memory.recall"
}

POST /token/introspect​

Validate a token per RFC 7662. Use this to verify tokens from other agents.

curl -X POST https://api.ainative.studio/api/v1/cloud/auth/token/introspect \
-H "Content-Type: application/json" \
-d '{"token": "eyJ..."}'

Response:

{
"active": true,
"client_id": "agt_abc123def456",
"scope": "agent.register memory.recall",
"exp": 1712200000,
"iat": 1712196400
}

POST /token/revoke​

Revoke a token per RFC 7009.

curl -X POST https://api.ainative.studio/api/v1/cloud/auth/token/revoke \
-H "Content-Type: application/json" \
-d '{"token": "eyJ..."}'

POST /token/delegate​

Delegated token exchange for agent-to-agent auth. Agent A can request a scoped token to act on behalf of a user when calling Agent B.

curl -X POST https://api.ainative.studio/api/v1/cloud/auth/token/delegate \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"parent_token": "eyJ...",
"target_agent_id": "agent-target-xyz",
"scopes": ["memory.recall"]
}'

parent_token is the calling agent's own access token — the delegated token's scopes must be a subset of the parent's. There is no ttl_seconds field; the delegated token's lifetime is fixed server-side.

Response:

{
"access_token": "eyJ...",
"token_type": "bearer",
"expires_in": 600,
"scope": "memory.recall"
}

Available Scopes​

The canonical scope taxonomy lives in AgentOAuthService.VALID_SCOPES — passing any scope outside this list returns a real 400 Invalid scopes.

ScopeDescription
agent.registerRegister a new agent
agent.delegateRequest a delegated token to act on behalf of another agent
memory.recallRecall memories, search vectors
memory.storeStore memories, add vectors
memory.forgetDelete memories
zerodb.readRead ZeroDB tables/vectors
zerodb.writeWrite ZeroDB tables/vectors
zerodb.adminAdminister ZeroDB projects
chat.completeChat completions
chat.streamStreaming chat completions
stream.ingestIngest into a live stream
stream.readRead from a live stream
file.uploadUpload files
file.downloadDownload files
mcp.connectConnect to an MCP server
mcp.executeExecute MCP tool calls