304 lines
10 KiB
YAML
304 lines
10 KiB
YAML
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
|
|
openapi: 3.1.0
|
|
info:
|
|
title: agent-call Executor Control API
|
|
version: 1.0.0
|
|
description: >-
|
|
Internal control, query, replay, and recording hand-off API. Call execution
|
|
enters through RabbitMQ, not HTTP.
|
|
servers:
|
|
- url: https://executor.internal
|
|
security:
|
|
- bearerAuth: []
|
|
paths:
|
|
/internal/v1/outbound/tasks/{task_id}/controls:
|
|
post:
|
|
operationId: controlTask
|
|
summary: Persist a pause, resume, or stop barrier
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- $ref: '#/components/parameters/RequestId'
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
- $ref: '#/components/parameters/TaskId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ControlRequest'
|
|
responses:
|
|
'202':
|
|
description: Reliably persisted, not yet necessarily applied
|
|
headers:
|
|
Location:
|
|
schema: {type: string}
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ControlAccepted'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'403': {$ref: '#/components/responses/Forbidden'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/internal/v1/outbound/commands/{command_id}:
|
|
get:
|
|
operationId: getCommand
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- $ref: '#/components/parameters/RequestId'
|
|
- $ref: '#/components/parameters/CommandId'
|
|
responses:
|
|
'200':
|
|
description: Command snapshot
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Command'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/internal/v1/outbound/calls/{call_id}:
|
|
get:
|
|
operationId: getCall
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- $ref: '#/components/parameters/RequestId'
|
|
- $ref: '#/components/parameters/CallId'
|
|
responses:
|
|
'200':
|
|
description: Call snapshot
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Call'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/internal/v1/outbound/calls/{call_id}/replays:
|
|
post:
|
|
operationId: replayCall
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- $ref: '#/components/parameters/RequestId'
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
- $ref: '#/components/parameters/CallId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ReplayRequest'}
|
|
responses:
|
|
'202':
|
|
description: Replay persisted for bounded broker delivery
|
|
headers:
|
|
Location: {schema: {type: string}}
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ReplayAccepted'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'410': {$ref: '#/components/responses/ReplayExpired'}
|
|
/internal/v1/outbound/commands/{source_command_id}/replays:
|
|
post:
|
|
operationId: replayCommand
|
|
parameters:
|
|
- $ref: '#/components/parameters/TenantId'
|
|
- $ref: '#/components/parameters/RequestId'
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
- $ref: '#/components/parameters/SourceCommandId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ReplayRequest'}
|
|
responses:
|
|
'202':
|
|
description: Replay persisted for bounded broker delivery
|
|
headers:
|
|
Location: {schema: {type: string}}
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ReplayAccepted'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'410': {$ref: '#/components/responses/ReplayExpired'}
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
parameters:
|
|
TenantId:
|
|
name: X-Tenant-ID
|
|
in: header
|
|
required: true
|
|
schema: {type: string}
|
|
RequestId:
|
|
name: X-Request-ID
|
|
in: header
|
|
required: true
|
|
schema: {type: string}
|
|
IdempotencyKey:
|
|
name: Idempotency-Key
|
|
in: header
|
|
required: true
|
|
schema: {type: string}
|
|
TaskId:
|
|
name: task_id
|
|
in: path
|
|
required: true
|
|
schema: {$ref: '#/components/schemas/Id'}
|
|
CommandId:
|
|
name: command_id
|
|
in: path
|
|
required: true
|
|
schema: {$ref: '#/components/schemas/Id'}
|
|
SourceCommandId:
|
|
name: source_command_id
|
|
in: path
|
|
required: true
|
|
schema: {$ref: '#/components/schemas/Id'}
|
|
CallId:
|
|
name: call_id
|
|
in: path
|
|
required: true
|
|
schema: {$ref: '#/components/schemas/Id'}
|
|
schemas:
|
|
Id:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 128
|
|
pattern: '^[^\s/\\]+$'
|
|
ControlRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [command_id, action, expected_task_revision, reason]
|
|
properties:
|
|
command_id: {$ref: '#/components/schemas/Id'}
|
|
action: {type: string, enum: [pause, resume, stop]}
|
|
expected_task_revision: {type: integer, minimum: 1}
|
|
active_call_policy: {type: string, enum: [drain, hangup]}
|
|
reason: {type: string, minLength: 1, maxLength: 512}
|
|
ControlAccepted:
|
|
type: object
|
|
required:
|
|
- command_id
|
|
- tenant_id
|
|
- tenant_key
|
|
- task_id
|
|
- status
|
|
- requested_task_revision
|
|
- accepted_at
|
|
properties:
|
|
command_id: {$ref: '#/components/schemas/Id'}
|
|
tenant_id: {type: string}
|
|
tenant_key: {type: string}
|
|
task_id: {$ref: '#/components/schemas/Id'}
|
|
status: {const: accepted}
|
|
requested_task_revision: {type: integer}
|
|
accepted_at: {type: string, format: date-time}
|
|
ReplayRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [command_id, reason]
|
|
properties:
|
|
command_id: {$ref: '#/components/schemas/Id'}
|
|
reason: {type: string, minLength: 1, maxLength: 512}
|
|
ReplayAccepted:
|
|
type: object
|
|
required: [command_id, status, snapshot_cutoff]
|
|
properties:
|
|
command_id: {$ref: '#/components/schemas/Id'}
|
|
status: {const: accepted}
|
|
snapshot_cutoff: {type: string, format: date-time}
|
|
Command:
|
|
type: object
|
|
required:
|
|
- command_id
|
|
- command_type
|
|
- tenant_id
|
|
- tenant_key
|
|
- status
|
|
- aggregate_version
|
|
properties:
|
|
command_id: {$ref: '#/components/schemas/Id'}
|
|
command_type: {type: string}
|
|
tenant_id: {type: string}
|
|
tenant_key: {type: string}
|
|
task_id: {type: [string, 'null']}
|
|
execution_id: {type: [string, 'null']}
|
|
call_id: {type: [string, 'null']}
|
|
status: {type: string}
|
|
reason_code: {type: [string, 'null']}
|
|
wait_reason_code: {type: [string, 'null']}
|
|
accepted_at: {type: [string, 'null'], format: date-time}
|
|
waiting_since: {type: [string, 'null'], format: date-time}
|
|
admission_deadline: {type: [string, 'null'], format: date-time}
|
|
requested_task_revision: {type: [integer, 'null']}
|
|
applied_task_revision: {type: [integer, 'null']}
|
|
task_state: {type: [string, 'null']}
|
|
updated_at: {type: string, format: date-time}
|
|
aggregate_version: {type: integer, minimum: 1}
|
|
Call:
|
|
type: object
|
|
required:
|
|
- call_id
|
|
- execution_id
|
|
- call_state
|
|
- call_version
|
|
- attempts
|
|
- transcript
|
|
- recordings
|
|
- delivery
|
|
- snapshot_at
|
|
properties:
|
|
call_id: {type: string}
|
|
execution_id: {type: string}
|
|
task_id: {type: string}
|
|
task_item_id: {type: string}
|
|
call_state: {type: string}
|
|
call_version: {type: integer}
|
|
reason_code: {type: [string, 'null']}
|
|
outcome: {type: [string, 'null']}
|
|
started_at: {type: [string, 'null'], format: date-time}
|
|
ended_at: {type: [string, 'null'], format: date-time}
|
|
duration_ms: {type: [integer, 'null']}
|
|
attempts: {type: array, items: {type: object}}
|
|
transcript: {type: object}
|
|
recordings: {type: array, items: {type: object}}
|
|
delivery: {type: object}
|
|
snapshot_at: {type: string, format: date-time}
|
|
responses:
|
|
Unauthorized:
|
|
description: Unauthorized
|
|
content:
|
|
application/problem+json:
|
|
schema: {$ref: '#/components/schemas/Problem'}
|
|
Forbidden:
|
|
description: Forbidden
|
|
content:
|
|
application/problem+json:
|
|
schema: {$ref: '#/components/schemas/Problem'}
|
|
NotFound:
|
|
description: Not found without cross-tenant enumeration
|
|
content:
|
|
application/problem+json:
|
|
schema: {$ref: '#/components/schemas/Problem'}
|
|
Conflict:
|
|
description: Idempotency or revision conflict
|
|
content:
|
|
application/problem+json:
|
|
schema: {$ref: '#/components/schemas/Problem'}
|
|
ReplayExpired:
|
|
description: Retention window expired
|
|
content:
|
|
application/problem+json:
|
|
schema: {$ref: '#/components/schemas/Problem'}
|
|
Problem:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [type, title, status, code, detail, request_id, retryable]
|
|
properties:
|
|
type: {type: string, format: uri-reference}
|
|
title: {type: string}
|
|
status: {type: integer}
|
|
code: {type: string}
|
|
detail: {type: string}
|
|
request_id: {type: string}
|
|
retryable: {type: boolean}
|