openapi: 3.0.3 info: title: SentryAgent.ai — Agent Registry Service version: 1.0.0 description: | The Agent Registry Service provides full lifecycle management for AI agent identities on the SentryAgent.ai AgentIdP platform. Every AI agent is treated as a first-class non-human identity, aligned with the AGNTCY standard (Linux Foundation). Agents receive unique, immutable identifiers (UUIDs), typed capabilities, and lifecycle status management. The registry is the authoritative source of truth for all registered agent identities. **Free Tier Limits**: - Max 100 registered agents per account - API rate limit: 100 requests/minute servers: - url: http://localhost:3000/api/v1 description: Local development server - url: https://api.sentryagent.ai/v1 description: Production server tags: - name: Agent Registry description: CRUD operations for AI agent identities components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: | JWT access token obtained via the OAuth 2.0 Client Credentials flow (`POST /token`). Include in the `Authorization` header as: `Authorization: Bearer ` schemas: AgentType: type: string description: The functional classification of the AI agent. enum: - screener - classifier - orchestrator - extractor - summarizer - router - monitor - custom example: screener DeploymentEnv: type: string description: The target deployment environment for the agent. enum: - development - staging - production example: production AgentStatus: type: string description: | Lifecycle status of the agent. - `active`: Agent is operational and can authenticate. - `suspended`: Agent is temporarily disabled; credentials cannot be used. - `decommissioned`: Agent is permanently retired; soft-deleted record remains. enum: - active - suspended - decommissioned example: active Agent: type: object description: Full representation of a registered AI agent identity. required: - agentId - email - agentType - version - capabilities - owner - deploymentEnv - status - createdAt - updatedAt properties: agentId: type: string format: uuid description: > Immutable, system-assigned unique identifier for the agent. Assigned at registration and never changes. readOnly: true example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" email: type: string format: email description: > Unique email-format identifier for the agent. Acts as the human-readable stable name for this agent identity. example: "screener-001@sentryagent.ai" agentType: $ref: '#/components/schemas/AgentType' version: type: string description: Semantic version string of the agent software. pattern: '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$' example: "1.4.2" capabilities: type: array description: > List of capability strings representing what this agent is permitted to do. Uses a `resource:action` convention. items: type: string pattern: '^[a-z0-9_-]+:[a-z0-9_*-]+$' minItems: 1 example: - "resume:read" - "email:send" - "candidate:score" owner: type: string description: Team or organisation that owns and is responsible for this agent. minLength: 1 maxLength: 128 example: "talent-acquisition-team" deploymentEnv: $ref: '#/components/schemas/DeploymentEnv' status: $ref: '#/components/schemas/AgentStatus' createdAt: type: string format: date-time description: ISO 8601 timestamp when the agent was first registered. readOnly: true example: "2026-03-28T09:00:00.000Z" updatedAt: type: string format: date-time description: ISO 8601 timestamp of the most recent update to this agent record. readOnly: true example: "2026-03-28T11:30:00.000Z" CreateAgentRequest: type: object description: Request body for registering a new AI agent identity. required: - email - agentType - version - capabilities - owner - deploymentEnv properties: email: type: string format: email description: > Unique email-format identifier for the agent. Must be unique across all registered agents in the system. example: "screener-001@sentryagent.ai" agentType: $ref: '#/components/schemas/AgentType' version: type: string description: Semantic version string of the agent software. pattern: '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$' example: "1.0.0" capabilities: type: array description: List of capability strings for this agent. items: type: string pattern: '^[a-z0-9_-]+:[a-z0-9_*-]+$' minItems: 1 example: - "resume:read" - "email:send" owner: type: string description: Team or organisation that owns this agent. minLength: 1 maxLength: 128 example: "talent-acquisition-team" deploymentEnv: $ref: '#/components/schemas/DeploymentEnv' UpdateAgentRequest: type: object description: > Request body for updating agent metadata. All fields are optional; only provided fields are updated. `agentId`, `email`, and `createdAt` are immutable and cannot be changed. minProperties: 1 properties: agentType: $ref: '#/components/schemas/AgentType' version: type: string description: Updated semantic version string. pattern: '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$' example: "1.5.0" capabilities: type: array description: Updated list of capability strings. Replaces the full list. items: type: string pattern: '^[a-z0-9_-]+:[a-z0-9_*-]+$' minItems: 1 example: - "resume:read" - "email:send" - "candidate:score" - "report:write" owner: type: string description: Updated owner team or organisation. minLength: 1 maxLength: 128 example: "platform-team" deploymentEnv: $ref: '#/components/schemas/DeploymentEnv' status: $ref: '#/components/schemas/AgentStatus' PaginatedAgentsResponse: type: object description: Paginated list of agent identities. required: - data - total - page - limit properties: data: type: array items: $ref: '#/components/schemas/Agent' total: type: integer description: Total number of agents matching the query filters. example: 47 page: type: integer description: Current page number (1-based). example: 1 limit: type: integer description: Number of items per page. example: 20 ErrorResponse: type: object description: Standard error response envelope used across all SentryAgent.ai APIs. required: - code - message properties: code: type: string description: > Machine-readable error code. Use this field for programmatic error handling. example: "AGENT_NOT_FOUND" message: type: string description: Human-readable description of the error. example: "Agent with the specified ID was not found." details: type: object description: > Optional structured details providing additional context about the error, such as field-level validation failures. additionalProperties: true example: field: "email" reason: "Email address is already registered to another agent." 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: The requested resource was not found. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "AGENT_NOT_FOUND" message: "Agent with the specified ID was not found." TooManyRequests: description: Rate limit exceeded. Retry after the reset time. headers: X-RateLimit-Limit: schema: type: integer description: Maximum number of requests allowed per minute. example: 100 X-RateLimit-Remaining: schema: type: integer description: Number of requests remaining in the current window. example: 0 X-RateLimit-Reset: schema: type: integer description: Unix timestamp (seconds) when the rate limit window resets. example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "RATE_LIMIT_EXCEEDED" message: "Too many requests. Please retry after the rate limit window resets." InternalServerError: description: Unexpected server error. Contact support if the issue persists. 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: /agents: post: operationId: registerAgent tags: - Agent Registry summary: Register a new AI agent description: | Creates a new AI agent identity in the SentryAgent.ai registry. A unique immutable `agentId` (UUID) is system-assigned on creation. The `email` must be unique across all registered agents. **Free Tier**: Maximum 100 registered agents per account. Attempting to register beyond this limit returns `403 Forbidden` with code `FREE_TIER_LIMIT_EXCEEDED`. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateAgentRequest' example: email: "screener-001@sentryagent.ai" agentType: "screener" version: "1.0.0" capabilities: - "resume:read" - "email:send" owner: "talent-acquisition-team" deploymentEnv: "production" responses: '201': description: Agent registered successfully. headers: X-RateLimit-Limit: schema: type: integer example: 100 X-RateLimit-Remaining: schema: type: integer example: 99 X-RateLimit-Reset: schema: type: integer example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/Agent' example: agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" email: "screener-001@sentryagent.ai" agentType: "screener" version: "1.0.0" capabilities: - "resume:read" - "email:send" owner: "talent-acquisition-team" deploymentEnv: "production" status: "active" createdAt: "2026-03-28T09:00:00.000Z" updatedAt: "2026-03-28T09:00:00.000Z" '400': description: Invalid request body. Check `details` for field-level errors. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "VALIDATION_ERROR" message: "Request validation failed." details: field: "email" reason: "Must be a valid email address." '401': $ref: '#/components/responses/Unauthorized' '403': description: Forbidden. Either insufficient permissions or free tier limit reached. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: insufficientPermissions: summary: Insufficient permissions value: code: "FORBIDDEN" message: "You do not have permission to register agents." freeTierLimit: summary: Free tier agent limit reached value: code: "FREE_TIER_LIMIT_EXCEEDED" message: "Free tier limit of 100 registered agents has been reached." details: limit: 100 current: 100 '409': description: An agent with the provided email address is already registered. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "AGENT_ALREADY_EXISTS" message: "An agent with this email address is already registered." details: email: "screener-001@sentryagent.ai" '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' get: operationId: listAgents tags: - Agent Registry summary: List registered agents description: | Returns a paginated list of all registered AI agent identities accessible to the authenticated caller. Results can be filtered by `owner`, `agentType`, and/or `status`. Results are ordered by `createdAt` descending (most recent first). parameters: - name: page in: query description: Page number (1-based). Defaults to `1`. required: false schema: type: integer minimum: 1 default: 1 example: 1 - name: limit in: query description: Number of results per page. Defaults to `20`, maximum `100`. required: false schema: type: integer minimum: 1 maximum: 100 default: 20 example: 20 - name: owner in: query description: Filter agents by owner name (exact match). required: false schema: type: string example: "talent-acquisition-team" - name: agentType in: query description: Filter agents by type. required: false schema: $ref: '#/components/schemas/AgentType' - name: status in: query description: Filter agents by lifecycle status. required: false schema: $ref: '#/components/schemas/AgentStatus' responses: '200': description: Paginated list of agents returned successfully. headers: X-RateLimit-Limit: schema: type: integer example: 100 X-RateLimit-Remaining: schema: type: integer example: 95 X-RateLimit-Reset: schema: type: integer example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/PaginatedAgentsResponse' example: data: - agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" email: "screener-001@sentryagent.ai" agentType: "screener" version: "1.4.2" capabilities: - "resume:read" - "email:send" - "candidate:score" owner: "talent-acquisition-team" deploymentEnv: "production" status: "active" createdAt: "2026-03-01T08:00:00.000Z" updatedAt: "2026-03-28T09:00:00.000Z" - agentId: "b2c3d4e5-f6a7-8901-bcde-f12345678901" email: "classifier-002@sentryagent.ai" agentType: "classifier" version: "2.1.0" capabilities: - "document:classify" - "label:write" owner: "talent-acquisition-team" deploymentEnv: "staging" status: "active" createdAt: "2026-03-10T10:00:00.000Z" updatedAt: "2026-03-10T10:00:00.000Z" total: 47 page: 1 limit: 20 '400': description: Invalid query parameters. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "VALIDATION_ERROR" message: "Invalid query parameter value." details: field: "limit" reason: "Must be an integer between 1 and 100." '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' /agents/{agentId}: parameters: - name: agentId in: path description: The unique UUID identifier of the agent. required: true schema: type: string format: uuid example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" get: operationId: getAgentById tags: - Agent Registry summary: Get agent by ID description: | Retrieves the full identity record for a single AI agent by its immutable `agentId`. responses: '200': description: Agent record returned successfully. headers: X-RateLimit-Limit: schema: type: integer example: 100 X-RateLimit-Remaining: schema: type: integer example: 94 X-RateLimit-Reset: schema: type: integer example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/Agent' example: agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" email: "screener-001@sentryagent.ai" agentType: "screener" version: "1.4.2" capabilities: - "resume:read" - "email:send" - "candidate:score" owner: "talent-acquisition-team" deploymentEnv: "production" status: "active" createdAt: "2026-03-01T08:00:00.000Z" updatedAt: "2026-03-28T09:00:00.000Z" '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' patch: operationId: updateAgent tags: - Agent Registry summary: Update agent metadata description: | Partially updates the metadata for an existing agent. Only the fields provided in the request body are updated. Omitted fields are left unchanged. The following fields are immutable and cannot be updated: `agentId`, `email`, `createdAt`. Setting `status` to `decommissioned` is a one-way operation — a decommissioned agent cannot be reactivated. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateAgentRequest' example: version: "1.5.0" capabilities: - "resume:read" - "email:send" - "candidate:score" - "report:write" deploymentEnv: "production" responses: '200': description: Agent updated successfully. Returns the full updated agent record. headers: X-RateLimit-Limit: schema: type: integer example: 100 X-RateLimit-Remaining: schema: type: integer example: 93 X-RateLimit-Reset: schema: type: integer example: 1743155400 content: application/json: schema: $ref: '#/components/schemas/Agent' example: agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" email: "screener-001@sentryagent.ai" agentType: "screener" version: "1.5.0" capabilities: - "resume:read" - "email:send" - "candidate:score" - "report:write" owner: "talent-acquisition-team" deploymentEnv: "production" status: "active" createdAt: "2026-03-01T08:00:00.000Z" updatedAt: "2026-03-28T11:30:00.000Z" '400': description: Invalid request body or attempt to modify an immutable field. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: validationError: summary: Validation failure value: code: "VALIDATION_ERROR" message: "Request validation failed." details: field: "version" reason: "Must be a valid semantic version string." immutableField: summary: Attempt to modify immutable field value: code: "IMMUTABLE_FIELD" message: "The field 'email' cannot be modified after registration." details: field: "email" '401': $ref: '#/components/responses/Unauthorized' '403': description: Forbidden. Insufficient permissions or agent is decommissioned. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: forbidden: summary: Insufficient permissions value: code: "FORBIDDEN" message: "You do not have permission to update this agent." decommissioned: summary: Agent is decommissioned value: code: "AGENT_DECOMMISSIONED" message: "Decommissioned agents cannot be updated." details: agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' delete: operationId: deactivateAgent tags: - Agent Registry summary: Deactivate (soft-delete) an agent description: | Permanently decommissions an AI agent. This is a **soft delete** — the agent record is retained in the database for audit purposes, but the agent's status is set to `decommissioned`. **Effects of decommissioning**: - All active credentials for this agent are immediately revoked. - The agent can no longer authenticate or obtain tokens. - The agent record remains visible in the registry with status `decommissioned`. - This operation is **irreversible**. responses: '204': description: Agent decommissioned successfully. No response body. headers: X-RateLimit-Limit: schema: type: integer example: 100 X-RateLimit-Remaining: schema: type: integer example: 92 X-RateLimit-Reset: schema: type: integer example: 1743155400 '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': description: Agent is already decommissioned. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: code: "AGENT_ALREADY_DECOMMISSIONED" message: "This agent has already been decommissioned." details: agentId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError'