# A2A Delegation Agent-to-Agent (A2A) delegation lets one agent grant another agent a subset of its OAuth 2.0 scopes for a defined period. This is the foundation for building secure multi-agent pipelines where an orchestrator agent coordinates specialist sub-agents. --- ## Prerequisites - A running AgentIdP instance - Two registered agents: the delegator (has a Bearer token) and the delegatee (knows its `agentId`) - The delegator's scopes must be a superset of the scopes it wants to delegate --- ## How delegation works ``` Delegator agent Delegatee agent | | |-- POST /oauth2/token/delegate ----------->| (creates chain server-side) |<-- { delegationToken, chainId, scopes } --| | | |-- passes delegationToken out-of-band ---->| | | | POST /oauth2/token/verify-delegation | <-- { valid: true, scopes, expiresAt } | | | (optional) DELETE /oauth2/token/delegate/{chainId} ``` --- ## Step 1 — Create a delegation chain The delegator agent creates the chain by specifying the delegatee's `agentId`, the scopes to delegate (must be a strict subset of the delegator's own scopes), and the TTL in seconds. ```bash curl -s -X POST http://localhost:3000/api/v1/oauth2/token/delegate \ -H "Authorization: Bearer $DELEGATOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "delegateeAgentId": "'$DELEGATEE_AGENT_ID'", "scopes": ["agents:read"], "ttlSeconds": 3600 }' | jq . ``` Response (`201 Created`): ```json { "delegationToken": "sa_del_a1b2c3d4e5f6...", "chainId": "d4e5f6a7-b8c9-0123-def0-123456789abc", "delegatorAgentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "delegateeAgentId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "scopes": ["agents:read"], "expiresAt": "2026-04-04T10:00:00.000Z" } ``` Save the `delegationToken` and `chainId`: ```bash export DELEGATION_TOKEN="sa_del_a1b2c3d4e5f6..." export CHAIN_ID="d4e5f6a7-b8c9-0123-def0-123456789abc" ``` **TTL constraints**: minimum 60 seconds, maximum 86400 seconds (24 hours). Choose the minimum TTL that covers the delegatee's task. --- ## Step 2 — Pass the delegation token to the delegatee Pass `DELEGATION_TOKEN` to the delegatee agent out-of-band. This can be via a shared queue, a direct API call to the sub-agent, or any other channel. The token is a signed opaque string — do not parse it; treat it as an opaque credential. --- ## Step 3 — Verify the delegation token The delegatee (or any agent checking the delegation) calls the verify endpoint. This confirms the chain is valid and not expired or revoked. ```bash curl -s -X POST http://localhost:3000/api/v1/oauth2/token/verify-delegation \ -H "Authorization: Bearer $DELEGATEE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "delegationToken": "'$DELEGATION_TOKEN'" }' | jq . ``` Response (`200 OK` — valid delegation): ```json { "valid": true, "chainId": "d4e5f6a7-b8c9-0123-def0-123456789abc", "delegatorAgentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "delegateeAgentId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "scopes": ["agents:read"], "issuedAt": "2026-04-04T09:00:00.000Z", "expiresAt": "2026-04-04T10:00:00.000Z", "revokedAt": null } ``` Response (`200 OK` — expired delegation): ```json { "valid": false, "chainId": "d4e5f6a7-b8c9-0123-def0-123456789abc", "delegatorAgentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "delegateeAgentId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "scopes": ["agents:read"], "issuedAt": "2026-04-03T09:00:00.000Z", "expiresAt": "2026-04-03T10:00:00.000Z", "revokedAt": null } ``` > The verify endpoint always returns `200 OK`. Check the `valid` field — it is never an error > response for an expired or revoked token. --- ## Step 4 — (Optional) Revoke the delegation early If the delegatee has completed its task and you want to revoke the delegation before it expires, the delegator calls: ```bash curl -s -X DELETE "http://localhost:3000/api/v1/oauth2/token/delegate/$CHAIN_ID" \ -H "Authorization: Bearer $DELEGATOR_TOKEN" \ -o /dev/null -w "%{http_code}\n" ``` Expected response: `204` (no body). After revocation, verify requests for this chain return `{ "valid": false, "revokedAt": "" }`. --- ## Scope rules - Delegated scopes must be a strict subset of the delegator's own token scopes - You cannot delegate scopes you do not have - You cannot delegate to yourself (delegateeAgentId must differ from delegatorAgentId) - Delegation is not transitive — a delegatee cannot re-delegate to a third agent --- ## Common errors ### `400 VALIDATION_ERROR` — scope not a subset The delegator attempted to delegate a scope it does not hold. Check `GET /api/v1/token/introspect` to confirm which scopes your token carries. ### `400 VALIDATION_ERROR` — ttlSeconds out of range Min: 60, Max: 86400. Values outside this range return a validation error.