feat: Phase 1 MVP — complete AgentIdP implementation
Implements all P0 features per OpenSpec change phase-1-mvp-implementation: - Agent Registry Service (CRUD) — full lifecycle management - OAuth 2.0 Token Service (Client Credentials flow) - Credential Management (generate, rotate, revoke) - Immutable Audit Log Service Tech: Node.js 18+, TypeScript 5.3+ strict, Express 4.18+, PostgreSQL 14+, Redis 7+ Standards: OpenAPI 3.0 specs, DRY/SOLID, zero `any` types Quality: 18 unit test suites, 244 tests passing, 97%+ coverage OpenAPI: 4 complete specs (14 endpoints total) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
816
docs/openapi/agent-registry.yaml
Normal file
816
docs/openapi/agent-registry.yaml
Normal file
@@ -0,0 +1,816 @@
|
||||
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 <token>`
|
||||
|
||||
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'
|
||||
Reference in New Issue
Block a user