openapi: "3.0.3" info: title: SentryAgent.ai — A2A Delegation (Agent-to-Agent) version: 1.0.0 description: | Agent-to-Agent (A2A) delegation endpoints for the SentryAgent.ai AgentIdP platform. The delegation subsystem enables an authenticated agent (the *delegator*) to grant a subset of its own scopes to another agent (the *delegatee*) for a limited time. This creates a cryptographically-signed delegation chain, suitable for multi-agent orchestration patterns. **All endpoints require a valid Bearer JWT.** **Feature flag:** When `A2A_ENABLED=false` these routes are not registered (return 404). **Delegation rules:** - The delegatee must be in the same tenant as the delegator. - Delegated scopes must be a strict subset of the delegator's own scopes. - TTL minimum: 60 seconds; maximum: 86400 seconds (24 hours). - Each delegation chain has a unique `chainId` (UUID). - Revoking a chain is idempotent — revoking an already-revoked chain succeeds. servers: - url: http://localhost:3000/api/v1 description: Local development server - url: https://api.sentryagent.ai/v1 description: Production server tags: - name: A2A Delegation description: Agent-to-Agent delegation chain management components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: | JWT access token obtained via `POST /token`. Include as `Authorization: Bearer `. schemas: DelegationChain: type: object description: A delegation chain record as returned by the API. required: - id - tenantId - delegatorAgentId - delegateeAgentId - scopes - delegationToken - ttlSeconds - issuedAt - expiresAt - createdAt properties: id: type: string format: uuid description: Unique identifier of the delegation chain. readOnly: true example: "chain-abcd-1234-5678-ef01" tenantId: type: string format: uuid description: Organization (tenant) that owns this delegation. readOnly: true example: "org-1234-5678-abcd-ef01" delegatorAgentId: type: string format: uuid description: UUID of the agent granting authority. example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" delegateeAgentId: type: string format: uuid description: UUID of the agent receiving delegated authority. example: "b2c3d4e5-f6a7-8901-bcde-f12345678901" scopes: type: array items: type: string description: OAuth 2.0 scopes granted by this delegation chain. example: - "agents:read" delegationToken: type: string description: | Opaque delegation token string that the delegatee presents to verify authority. This token encodes the chain metadata and is HMAC-signed. example: "chain-abcd-1234-5678-ef01.1743151200.1743237600" signature: type: string description: HMAC-SHA256 signature of the delegation token payload. example: "3a7f2b9c..." ttlSeconds: type: integer description: Delegation lifetime in seconds. minimum: 60 maximum: 86400 example: 3600 issuedAt: type: string format: date-time readOnly: true example: "2026-04-07T09:00:00.000Z" expiresAt: type: string format: date-time readOnly: true example: "2026-04-07T10:00:00.000Z" revokedAt: type: string format: date-time nullable: true description: Timestamp when this chain was revoked. Null if still active or expired naturally. readOnly: true example: null createdAt: type: string format: date-time readOnly: true example: "2026-04-07T09:00:00.000Z" CreateDelegationRequest: type: object description: Request body for creating a new agent-to-agent delegation chain. required: - delegateeAgentId - scopes - ttlSeconds properties: delegateeAgentId: type: string format: uuid description: | UUID of the agent to receive delegated authority. Must be in the same tenant as the delegator (caller). example: "b2c3d4e5-f6a7-8901-bcde-f12345678901" scopes: type: array items: type: string description: | Scopes to delegate. Must be a strict subset of the delegator's current token scopes. At least one scope must be specified. minItems: 1 example: - "agents:read" ttlSeconds: type: integer description: Delegation lifetime in seconds. Minimum: 60; Maximum: 86400 (24 hours). minimum: 60 maximum: 86400 example: 3600 VerifyDelegationRequest: type: object description: Request body for verifying a delegation token. required: - delegationToken properties: delegationToken: type: string description: The delegation token string to verify. example: "chain-abcd-1234-5678-ef01.1743151200.1743237600" DelegationVerificationResult: type: object description: | Result of verifying a delegation token. Returns `valid: false` for expired or revoked tokens without throwing. required: - valid - chainId - delegatorAgentId - delegateeAgentId - scopes - issuedAt - expiresAt properties: valid: type: boolean description: Whether the delegation token is currently valid (active, not expired, not revoked). example: true chainId: type: string format: uuid description: UUID of the delegation chain. example: "chain-abcd-1234-5678-ef01" delegatorAgentId: type: string format: uuid example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" delegateeAgentId: type: string format: uuid example: "b2c3d4e5-f6a7-8901-bcde-f12345678901" scopes: type: array items: type: string example: - "agents:read" issuedAt: type: string format: date-time example: "2026-04-07T09:00:00.000Z" expiresAt: type: string format: date-time example: "2026-04-07T10:00:00.000Z" revokedAt: type: string format: date-time nullable: true example: null ErrorResponse: type: object description: Standard error response envelope. required: - code - message properties: code: type: string example: "DELEGATION_NOT_FOUND" message: type: string example: "Delegation chain with the specified ID was not found." details: type: object additionalProperties: true responses: Unauthorized: description: Missing or invalid Bearer token. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "UNAUTHORIZED" message: "A valid Bearer token is required to access this resource." Forbidden: description: Valid token but insufficient permissions. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "FORBIDDEN" message: "You do not have permission to perform this action." NotFound: description: Delegation chain not found. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "DELEGATION_NOT_FOUND" message: "Delegation chain with the specified ID was not found." InternalServerError: description: Unexpected server error. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "INTERNAL_SERVER_ERROR" message: "An unexpected error occurred. Please try again later." security: - BearerAuth: [] paths: /oauth2/token/delegate: post: operationId: createDelegation tags: - A2A Delegation summary: Create an A2A delegation chain description: | Creates a new agent-to-agent delegation chain. The authenticated agent (the *delegator*) grants a subset of its own scopes to the `delegateeAgentId`. A cryptographically-signed `delegationToken` is returned. The delegatee presents this token to `POST /oauth2/token/verify-delegation` to prove delegated authority. **Validation:** - Delegatee must be in the same organization as the delegator. - `scopes` must be a strict subset of the delegator's current token scopes. - `ttlSeconds` must be between 60 and 86400. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateDelegationRequest' example: delegateeAgentId: "b2c3d4e5-f6a7-8901-bcde-f12345678901" scopes: - "agents:read" ttlSeconds: 3600 responses: '201': description: Delegation chain created successfully. content: application/json: schema: $ref: '#/components/schemas/DelegationChain' example: id: "chain-abcd-1234-5678-ef01" tenantId: "org-1234-5678-abcd-ef01" delegatorAgentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" delegateeAgentId: "b2c3d4e5-f6a7-8901-bcde-f12345678901" scopes: - "agents:read" delegationToken: "chain-abcd-1234-5678-ef01.1743151200.1743154800" signature: "3a7f2b9c..." ttlSeconds: 3600 issuedAt: "2026-04-07T09:00:00.000Z" expiresAt: "2026-04-07T10:00:00.000Z" revokedAt: null createdAt: "2026-04-07T09:00:00.000Z" '400': description: Validation error in request body. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: scopeExceedsOwn: summary: Requested scope exceeds delegator's own scopes value: code: "SCOPE_EXCEEDS_DELEGATOR" message: "Delegated scopes must be a subset of the delegator's own token scopes." details: requested: ["agents:write"] available: ["agents:read"] invalidTtl: summary: TTL out of range value: code: "VALIDATION_ERROR" message: "ttlSeconds must be between 60 and 86400." crossTenant: summary: Delegatee in different tenant value: code: "CROSS_TENANT_DELEGATION" message: "Delegatee agent must be in the same organization as the delegator." '401': $ref: '#/components/responses/Unauthorized' '404': description: Delegatee agent not found. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "AGENT_NOT_FOUND" message: "Delegatee agent with the specified ID was not found." '500': $ref: '#/components/responses/InternalServerError' /oauth2/token/verify-delegation: post: operationId: verifyDelegation tags: - A2A Delegation summary: Verify a delegation token description: | Verifies a delegation token and returns the chain details if valid. Returns `valid: true` with full chain metadata when the token is valid (exists, not expired, not revoked). Returns `valid: false` when the token is expired or revoked. Does not throw an error for inactive tokens — always returns `200`. Requires a valid Bearer JWT (any authenticated agent may verify a delegation). requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/VerifyDelegationRequest' example: delegationToken: "chain-abcd-1234-5678-ef01.1743151200.1743154800" responses: '200': description: Delegation verification result returned. content: application/json: schema: $ref: '#/components/schemas/DelegationVerificationResult' examples: valid: summary: Valid delegation token value: valid: true chainId: "chain-abcd-1234-5678-ef01" delegatorAgentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" delegateeAgentId: "b2c3d4e5-f6a7-8901-bcde-f12345678901" scopes: - "agents:read" issuedAt: "2026-04-07T09:00:00.000Z" expiresAt: "2026-04-07T10:00:00.000Z" revokedAt: null expired: summary: Expired delegation token value: valid: false chainId: "chain-abcd-1234-5678-ef01" delegatorAgentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" delegateeAgentId: "b2c3d4e5-f6a7-8901-bcde-f12345678901" scopes: - "agents:read" issuedAt: "2026-04-06T09:00:00.000Z" expiresAt: "2026-04-06T10:00:00.000Z" revokedAt: null '400': description: Missing or malformed `delegationToken` field. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "VALIDATION_ERROR" message: "The 'delegationToken' field is required." '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalServerError' /oauth2/token/delegate/{chainId}: parameters: - name: chainId in: path required: true description: UUID of the delegation chain to revoke. schema: type: string format: uuid example: "chain-abcd-1234-5678-ef01" delete: operationId: revokeDelegation tags: - A2A Delegation summary: Revoke a delegation chain description: | Immediately revokes a delegation chain. After revocation, `POST /oauth2/token/verify-delegation` will return `valid: false` for the revoked chain's token. **Idempotent** — revoking an already-revoked chain returns `204` without error. Only the delegator agent or an admin may revoke a chain. Requires a valid Bearer JWT. responses: '204': description: Delegation chain revoked successfully (or was already revoked). No response body. '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError'