diff --git a/README.md b/README.md index 7d978e0..b235447 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ main(); | Resource | Operations | |----------|------------| -| Agents | Create, list, get, update, archive | +| Agents | Create, list, get, update, archive, version, diff, fork, rollback | | Sessions | Create, list, get, update, delete, cancel | | Messages | Create, list | | Events | Poll, stream (SSE) | diff --git a/openapi/openapi.json b/openapi/openapi.json index 525e657..03a5c1d 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -648,67 +648,40 @@ } } }, - "/v1/apps/{app_id}/a2a/{channel_id}": { - "post": { + "/v1/agents/{agent_id}/versions": { + "get": { "tags": [ - "apps" + "agents" ], - "summary": "POST /v1/apps/{app_id}/a2a/{channel_id}", - "operationId": "invoke_a2a", + "summary": "GET /v1/agents/{agent_id}/versions - List saved agent versions", + "operationId": "list_agent_versions", "parameters": [ { - "name": "app_id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "channel_id", + "name": "agent_id", "in": "path", - "description": "A2A channel ID", + "description": "Agent ID (prefixed) or name", "required": true, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": {} - } - }, - "required": true - }, "responses": { "200": { - "description": "JSON-RPC 2.0 response (success or A2A error envelope)" - }, - "401": { - "description": "Missing or invalid API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "App is not published or channel disabled", + "description": "Saved agent versions", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/AgentVersion" + } } } } }, "404": { - "description": "App or channel not found", + "description": "Agent not found or agent_versions disabled", "content": { "application/json": { "schema": { @@ -718,41 +691,57 @@ } } } - } - }, - "/v1/apps/{app_id}/a2a/{channel_id}/.well-known/agent-card.json": { - "get": { + }, + "post": { "tags": [ - "apps" + "agents" ], - "summary": "GET /v1/apps/{app_id}/a2a/{channel_id}/.well-known/agent-card.json", - "operationId": "agent_card", + "summary": "POST /v1/agents/{agent_id}/versions - Save the current agent configuration as a version", + "operationId": "create_agent_version", "parameters": [ { - "name": "app_id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "channel_id", + "name": "agent_id", "in": "path", - "description": "A2A channel ID", + "description": "Agent ID (prefixed) or name", "required": true, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAgentVersionRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Agent Card JSON" + "description": "Agent version created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AgentVersion" + } + } + } + }, + "400": { + "description": "Invalid request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, "404": { - "description": "App or channel not found / unpublished / disabled", + "description": "Agent not found or agent_versions disabled", "content": { "application/json": { "schema": { @@ -764,26 +753,18 @@ } } }, - "/v1/apps/{app_id}/webhooks/{channel_id}": { + "/v1/agents/{agent_id}/versions/default": { "post": { "tags": [ - "apps" + "agents" ], - "operationId": "invoke_webhook", + "summary": "POST /v1/agents/{agent_id}/versions/default - Set the default version for an agent", + "operationId": "set_default_agent_version", "parameters": [ { - "name": "app_id", - "in": "path", - "description": "App ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "channel_id", + "name": "agent_id", "in": "path", - "description": "Webhook channel ID", + "description": "Agent ID (prefixed) or name", "required": true, "schema": { "type": "string" @@ -792,27 +773,27 @@ ], "requestBody": { "content": { - "application/octet-stream": { + "application/json": { "schema": { - "type": "string" + "$ref": "#/components/schemas/SetDefaultAgentVersionRequest" } } }, "required": true }, "responses": { - "202": { - "description": "Webhook accepted", + "200": { + "description": "Default version updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WebhookInvocationResponse" + "$ref": "#/components/schemas/WithUrls_Agent" } } } }, - "401": { - "description": "Invalid or missing webhook token", + "400": { + "description": "Invalid request", "content": { "application/json": { "schema": { @@ -821,8 +802,8 @@ } } }, - "403": { - "description": "App is not published or channel disabled", + "404": { + "description": "Agent or version not found, or agent_versions disabled", "content": { "application/json": { "schema": { @@ -830,19 +811,59 @@ } } } + } + } + } + }, + "/v1/agents/{agent_id}/versions/{from_version_id}/diff/{to_version_id}": { + "get": { + "tags": [ + "agents" + ], + "summary": "GET /v1/agents/{agent_id}/versions/{from_version_id}/diff/{to_version_id} - Diff two agent versions", + "operationId": "diff_agent_versions", + "parameters": [ + { + "name": "agent_id", + "in": "path", + "description": "Agent ID (prefixed) or name", + "required": true, + "schema": { + "type": "string" + } }, - "404": { - "description": "App or channel not found", + { + "name": "from_version_id", + "in": "path", + "description": "Base agent version ID", + "required": true, + "schema": { + "$ref": "#/components/schemas/agentverId" + } + }, + { + "name": "to_version_id", + "in": "path", + "description": "Comparison agent version ID", + "required": true, + "schema": { + "$ref": "#/components/schemas/agentverId" + } + } + ], + "responses": { + "200": { + "description": "Agent version diff", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/AgentVersionDiffResponse" } } } }, - "500": { - "description": "Internal server error", + "404": { + "description": "Agent or version not found, or agent_versions disabled", "content": { "application/json": { "schema": { @@ -854,59 +875,56 @@ } } }, - "/v1/capabilities": { - "get": { + "/v1/agents/{agent_id}/versions/{version_id}/fork": { + "post": { "tags": [ - "capabilities" + "agents" ], - "summary": "GET /v1/capabilities - List available capabilities with pagination", - "operationId": "list_capabilities", + "summary": "POST /v1/agents/{agent_id}/versions/{version_id}/fork - Create a new agent from a saved version", + "operationId": "fork_agent_version", "parameters": [ { - "name": "search", - "in": "query", - "description": "Search by name/description", - "required": false, + "name": "agent_id", + "in": "path", + "description": "Source agent ID (prefixed) or name", + "required": true, "schema": { "type": "string" } }, { - "name": "offset", - "in": "query", - "description": "Pagination offset (default: 0)", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "limit", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, + "name": "version_id", + "in": "path", + "description": "Agent version ID", + "required": true, "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 + "$ref": "#/components/schemas/agentverId" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForkAgentVersionRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Paginated list of capabilities", + "description": "Agent fork created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PaginatedResponse_WithUrls_CapabilityInfo" + "$ref": "#/components/schemas/WithUrls_Agent" } } } }, "400": { - "description": "Invalid query parameters", + "description": "Invalid request", "content": { "application/json": { "schema": { @@ -915,8 +933,8 @@ } } }, - "500": { - "description": "Internal server error", + "404": { + "description": "Agent or version not found, or agent_versions disabled", "content": { "application/json": { "schema": { @@ -928,37 +946,56 @@ } } }, - "/v1/capabilities/{capability_id}": { - "get": { + "/v1/agents/{agent_id}/versions/{version_id}/rollback": { + "post": { "tags": [ - "capabilities" + "agents" ], - "summary": "GET /v1/capabilities/{capability_id} - Get a specific capability", - "operationId": "get_capability", + "summary": "POST /v1/agents/{agent_id}/versions/{version_id}/rollback - Restore an agent from a saved version", + "operationId": "rollback_agent_version", "parameters": [ { - "name": "capability_id", + "name": "agent_id", "in": "path", - "description": "Capability ID", + "description": "Agent ID (prefixed) or name", "required": true, "schema": { "type": "string" } + }, + { + "name": "version_id", + "in": "path", + "description": "Agent version ID", + "required": true, + "schema": { + "$ref": "#/components/schemas/agentverId" + } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RollbackAgentVersionRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Capability found", + "description": "Agent rolled back", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_CapabilityInfo" + "$ref": "#/components/schemas/WithUrls_Agent" } } } }, - "404": { - "description": "Capability not found", + "400": { + "description": "Invalid request", "content": { "application/json": { "schema": { @@ -967,8 +1004,8 @@ } } }, - "500": { - "description": "Internal server error", + "404": { + "description": "Agent or version not found, or agent_versions disabled", "content": { "application/json": { "schema": { @@ -980,20 +1017,29 @@ } } }, - "/v1/durable/config": { - "get": { + "/v1/agents/{agent_id}/voice/sessions": { + "post": { "tags": [ - "durable" + "voice" ], - "summary": "GET /v1/durable/config - Durable policy results for UI gating.", - "operationId": "durable_config", + "operationId": "create_agent_voice_session", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceCallRequest" + } + } + }, + "required": true + }, "responses": { - "200": { - "description": "Resource config for durable surfaces", + "201": { + "description": "Agent session and realtime call created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResourceConfigResponse" + "$ref": "#/components/schemas/VoiceSessionResponse_VoiceCallResponse" } } } @@ -1001,41 +1047,67 @@ } } }, - "/v1/durable/executions/{execution_id}": { - "get": { + "/v1/apps/{app_id}/a2a/{channel_id}": { + "post": { "tags": [ - "durable-schedules" + "apps" ], - "summary": "GET /v1/durable/executions/:execution_id - Get execution details", - "operationId": "get_execution", + "summary": "POST /v1/apps/{app_id}/a2a/{channel_id}", + "operationId": "invoke_a2a", "parameters": [ { - "name": "execution_id", + "name": "app_id", "in": "path", - "description": "Execution ID", + "description": "App ID", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" + } + }, + { + "name": "channel_id", + "in": "path", + "description": "A2A channel ID", + "required": true, + "schema": { + "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": {} + } + }, + "required": true + }, "responses": { "200": { - "description": "Execution details", + "description": "JSON-RPC 2.0 response. For message/send and tasks/* the body is a single JSON envelope; for message/stream the body is text/event-stream of JSON-RPC envelopes. tasks/get and tasks/cancel surface -32001 Task not found for unknown task ids." + }, + "401": { + "description": "Missing or invalid API key", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScheduleExecutionResponse" + "$ref": "#/components/schemas/ErrorResponse" } } } }, - "401": { - "description": "Authentication required" + "403": { + "description": "App is not published or channel disabled", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, "404": { - "description": "Execution not found", + "description": "App or channel not found", "content": { "application/json": { "schema": { @@ -1044,8 +1116,8 @@ } } }, - "500": { - "description": "Internal server error", + "429": { + "description": "SSE connection limit reached for the org/session", "content": { "application/json": { "schema": { @@ -1057,71 +1129,39 @@ } } }, - "/v1/durable/schedules": { + "/v1/apps/{app_id}/a2a/{channel_id}/.well-known/agent-card.json": { "get": { "tags": [ - "durable-schedules" + "apps" ], - "summary": "GET /v1/durable/schedules - List schedules", - "operationId": "list_schedules", + "summary": "GET /v1/apps/{app_id}/a2a/{channel_id}/.well-known/agent-card.json", + "operationId": "agent_card", "parameters": [ { - "name": "enabled", - "in": "query", - "description": "Filter by enabled status", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "target_type", - "in": "query", - "description": "Filter by target type", - "required": false, + "name": "app_id", + "in": "path", + "description": "App ID", + "required": true, "schema": { "type": "string" } }, { - "name": "offset", - "in": "query", - "description": "Pagination offset", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "limit", - "in": "query", - "description": "Pagination limit", - "required": false, + "name": "channel_id", + "in": "path", + "description": "A2A channel ID", + "required": true, "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 + "type": "string" } } ], "responses": { "200": { - "description": "List of schedules", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SchedulesListResponse" - } - } - } - }, - "401": { - "description": "Authentication required" + "description": "Agent Card JSON" }, - "500": { - "description": "Internal server error", + "404": { + "description": "App or channel not found / unpublished / disabled", "content": { "application/json": { "schema": { @@ -1131,36 +1171,57 @@ } } } - }, + } + }, + "/v1/apps/{app_id}/webhooks/{channel_id}": { "post": { "tags": [ - "durable-schedules" + "apps" + ], + "operationId": "invoke_webhook", + "parameters": [ + { + "name": "app_id", + "in": "path", + "description": "App ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "channel_id", + "in": "path", + "description": "Webhook channel ID", + "required": true, + "schema": { + "type": "string" + } + } ], - "summary": "POST /v1/durable/schedules - Create a new schedule", - "operationId": "create_schedule", "requestBody": { "content": { - "application/json": { + "application/octet-stream": { "schema": { - "$ref": "#/components/schemas/CreateScheduleRequest" + "type": "string" } } }, "required": true }, "responses": { - "201": { - "description": "Schedule created", + "202": { + "description": "Webhook accepted", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScheduleResponse" + "$ref": "#/components/schemas/WebhookInvocationResponse" } } } }, - "400": { - "description": "Invalid request", + "401": { + "description": "Invalid or missing webhook token", "content": { "application/json": { "schema": { @@ -1169,11 +1230,18 @@ } } }, - "401": { - "description": "Authentication required" + "403": { + "description": "App is not published or channel disabled", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, - "409": { - "description": "Schedule name already exists", + "404": { + "description": "App or channel not found", "content": { "application/json": { "schema": { @@ -1195,41 +1263,59 @@ } } }, - "/v1/durable/schedules/{schedule_id}": { + "/v1/capabilities": { "get": { "tags": [ - "durable-schedules" + "capabilities" ], - "summary": "GET /v1/durable/schedules/:schedule_id - Get schedule details", - "operationId": "get_schedule", + "summary": "GET /v1/capabilities - List available capabilities with pagination", + "operationId": "list_capabilities", "parameters": [ { - "name": "schedule_id", - "in": "path", - "description": "Schedule ID", - "required": true, + "name": "search", + "in": "query", + "description": "Search by name/description", + "required": false, "schema": { - "type": "string", - "format": "uuid" + "type": "string" + } + }, + { + "name": "offset", + "in": "query", + "description": "Pagination offset (default: 0)", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + }, + { + "name": "limit", + "in": "query", + "description": "Page size (default: 20, max: 100)", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 } } ], "responses": { "200": { - "description": "Schedule details", + "description": "Paginated list of capabilities", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScheduleResponse" + "$ref": "#/components/schemas/PaginatedResponse_WithUrls_CapabilityInfo" } } } }, - "401": { - "description": "Authentication required" - }, - "404": { - "description": "Schedule not found", + "400": { + "description": "Invalid query parameters", "content": { "application/json": { "schema": { @@ -1250,107 +1336,35 @@ } } }, - "delete": { + "post": { "tags": [ - "durable-schedules" - ], - "summary": "DELETE /v1/durable/schedules/:schedule_id - Delete schedule", - "operationId": "delete_schedule", - "parameters": [ - { - "name": "schedule_id", - "in": "path", - "description": "Schedule ID", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } - ], - "responses": { - "204": { - "description": "Schedule deleted" - }, - "401": { - "description": "Authentication required" - }, - "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - }, - "patch": { - "tags": [ - "durable-schedules" - ], - "summary": "PATCH /v1/durable/schedules/:schedule_id - Update schedule", - "operationId": "update_schedule", - "parameters": [ - { - "name": "schedule_id", - "in": "path", - "description": "Schedule ID", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - } + "capabilities" ], + "summary": "POST /v1/capabilities - Create a persisted declarative capability.", + "operationId": "create_declarative_capability", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateScheduleRequest" + "$ref": "#/components/schemas/CreateDeclarativeCapabilityRequest" } } }, "required": true }, "responses": { - "200": { - "description": "Schedule updated", + "201": { + "description": "Declarative capability created. Response id uses cap_<32-hex>; capability_id uses declarative:.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScheduleResponse" + "$ref": "#/components/schemas/WithUrls_DeclarativeCapability" } } } }, "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Authentication required" - }, - "404": { - "description": "Schedule not found", + "description": "Invalid declarative capability definition, name, limits, file mount, skill, or MCP server configuration.", "content": { "application/json": { "schema": { @@ -1359,8 +1373,8 @@ } } }, - "500": { - "description": "Internal server error", + "409": { + "description": "A declarative capability with the same unique name already exists.", "content": { "application/json": { "schema": { @@ -1372,86 +1386,61 @@ } } }, - "/v1/durable/schedules/{schedule_id}/executions": { + "/v1/capabilities/declarative": { "get": { "tags": [ - "durable-schedules" + "capabilities" ], - "summary": "GET /v1/durable/schedules/:schedule_id/executions - List schedule executions", - "operationId": "list_schedule_executions", + "summary": "GET /v1/capabilities/declarative - List persisted declarative resources.", + "operationId": "list_declarative_capabilities", "parameters": [ { - "name": "schedule_id", - "in": "path", - "description": "Schedule ID", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "status", + "name": "search", "in": "query", - "description": "Filter by status", + "description": "Search by unique name, display name, or description", "required": false, "schema": { "type": "string" } }, { - "name": "offset", - "in": "query", - "description": "Pagination offset", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "limit", + "name": "include_archived", "in": "query", - "description": "Pagination limit", + "description": "Include archived declarative capabilities", "required": false, "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 + "type": "boolean" } } ], "responses": { "200": { - "description": "List of executions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScheduleExecutionsListResponse" - } - } - } - }, - "401": { - "description": "Authentication required" - }, - "404": { - "description": "Schedule not found", + "description": "Persisted declarative capability resources", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/ListResponse_WithUrls_DeclarativeCapability" } } } - }, - "500": { - "description": "Internal server error", + } + } + } + }, + "/v1/capabilities/declarative/config": { + "get": { + "tags": [ + "capabilities" + ], + "summary": "GET /v1/capabilities/declarative/config", + "operationId": "declarative_capabilities_config", + "responses": { + "200": { + "description": "Resource config for declarative capabilities", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/ResourceConfigResponse" } } } @@ -1459,51 +1448,37 @@ } } }, - "/v1/durable/schedules/{schedule_id}/pause": { - "post": { + "/v1/capabilities/declarative/{capability_id}": { + "get": { "tags": [ - "durable-schedules" + "capabilities" ], - "summary": "POST /v1/durable/schedules/:schedule_id/pause - Pause schedule", - "operationId": "pause_schedule", + "summary": "GET /v1/capabilities/declarative/{capability_id} - Get a declarative resource.", + "operationId": "get_declarative_capability", "parameters": [ { - "name": "schedule_id", + "name": "capability_id", "in": "path", - "description": "Schedule ID", + "description": "Public declarative capability resource ID, e.g. cap_01933b5a000070008000000000000001", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" } } ], "responses": { "200": { - "description": "Schedule paused", + "description": "Declarative capability resource", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScheduleResponse" + "$ref": "#/components/schemas/WithUrls_DeclarativeCapability" } } } }, - "401": { - "description": "Authentication required" - }, "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", + "description": "Declarative capability not found", "content": { "application/json": { "schema": { @@ -1513,53 +1488,30 @@ } } } - } - }, - "/v1/durable/schedules/{schedule_id}/resume": { - "post": { + }, + "delete": { "tags": [ - "durable-schedules" + "capabilities" ], - "summary": "POST /v1/durable/schedules/:schedule_id/resume - Resume schedule", - "operationId": "resume_schedule", + "summary": "DELETE /v1/capabilities/declarative/{capability_id} - Archive a declarative resource.", + "operationId": "delete_declarative_capability", "parameters": [ { - "name": "schedule_id", + "name": "capability_id", "in": "path", - "description": "Schedule ID", + "description": "Public declarative capability resource ID", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" } } ], "responses": { "200": { - "description": "Schedule resumed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScheduleResponse" - } - } - } - }, - "401": { - "description": "Authentication required" + "description": "Declarative capability archived" }, "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", + "description": "Declarative capability not found", "content": { "application/json": { "schema": { @@ -1569,43 +1521,47 @@ } } } - } - }, - "/v1/durable/schedules/{schedule_id}/stats": { - "get": { + }, + "patch": { "tags": [ - "durable-schedules" + "capabilities" ], - "summary": "GET /v1/durable/schedules/:schedule_id/stats - Get schedule statistics", - "operationId": "get_schedule_stats", + "summary": "PATCH /v1/capabilities/declarative/{capability_id} - Update a declarative resource.", + "operationId": "update_declarative_capability", "parameters": [ { - "name": "schedule_id", + "name": "capability_id", "in": "path", - "description": "Schedule ID", + "description": "Public declarative capability resource ID", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateDeclarativeCapabilityRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Schedule statistics", + "description": "Declarative capability updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ScheduleStatsResponse" + "$ref": "#/components/schemas/WithUrls_DeclarativeCapability" } } } }, - "401": { - "description": "Authentication required" - }, - "404": { - "description": "Schedule not found", + "400": { + "description": "Invalid update payload or declarative capability definition", "content": { "application/json": { "schema": { @@ -1614,8 +1570,8 @@ } } }, - "500": { - "description": "Internal server error", + "409": { + "description": "A declarative capability with the same unique name already exists", "content": { "application/json": { "schema": { @@ -1627,41 +1583,72 @@ } } }, - "/v1/durable/schedules/{schedule_id}/trigger": { + "/v1/capabilities/declarative/{capability_id}/delete": { "post": { "tags": [ - "durable-schedules" + "capabilities" ], - "summary": "POST /v1/durable/schedules/:schedule_id/trigger - Manually trigger schedule", - "operationId": "trigger_schedule", + "summary": "POST /v1/capabilities/declarative/{capability_id}/delete - Permanently delete archived resource.", + "operationId": "destroy_declarative_capability", "parameters": [ { - "name": "schedule_id", + "name": "capability_id", "in": "path", - "description": "Schedule ID", + "description": "Public declarative capability resource ID", "required": true, "schema": { - "type": "string", - "format": "uuid" + "type": "string" } } ], "responses": { "200": { - "description": "Schedule triggered", + "description": "Archived declarative capability permanently deleted" + }, + "404": { + "description": "Declarative capability not found or not archived", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TriggerResponse" + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/capabilities/{capability_id}": { + "get": { + "tags": [ + "capabilities" + ], + "summary": "GET /v1/capabilities/{capability_id} - Get a specific capability", + "operationId": "get_capability", + "parameters": [ + { + "name": "capability_id", + "in": "path", + "description": "Capability ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Capability found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_CapabilityInfo" } } } - }, - "401": { - "description": "Authentication required" }, "404": { - "description": "Schedule not found", + "description": "Capability not found", "content": { "application/json": { "schema": { @@ -1683,23 +1670,20 @@ } } }, - "/v1/harness-examples": { + "/v1/durable/config": { "get": { "tags": [ - "harness-examples" + "durable" ], - "summary": "GET /v1/harness-examples — list all available harness examples.", - "operationId": "list_examples", + "summary": "GET /v1/durable/config - Durable policy results for UI gating.", + "operationId": "durable_config", "responses": { "200": { - "description": "List of harness examples", + "description": "Resource config for durable surfaces", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/HarnessExample" - } + "$ref": "#/components/schemas/ResourceConfigResponse" } } } @@ -1707,69 +1691,148 @@ } } }, - "/v1/harnesses": { + "/v1/durable/executions/{execution_id}": { "get": { "tags": [ - "harnesses" + "durable-schedules" ], - "summary": "GET /v1/harnesses", - "operationId": "list_harnesses", + "summary": "GET /v1/durable/executions/:execution_id - Get execution details", + "operationId": "get_execution", "parameters": [ { - "name": "search", + "name": "execution_id", + "in": "path", + "description": "Execution ID", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Execution details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScheduleExecutionResponse" + } + } + } + }, + "401": { + "description": "Authentication required" + }, + "404": { + "description": "Execution not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/durable/schedules": { + "get": { + "tags": [ + "durable-schedules" + ], + "summary": "GET /v1/durable/schedules - List schedules", + "operationId": "list_schedules", + "parameters": [ + { + "name": "enabled", "in": "query", - "description": "Search by name or description (case-insensitive substring match).", + "description": "Filter by enabled status", "required": false, "schema": { - "type": [ - "string", - "null" - ] + "type": "boolean" } }, { - "name": "include_archived", + "name": "target_type", "in": "query", - "description": "Include archived harnesses. Deleted harnesses never appear in lists.", + "description": "Filter by target type", "required": false, "schema": { - "type": [ - "boolean", - "null" - ] + "type": "string" + } + }, + { + "name": "offset", + "in": "query", + "description": "Pagination offset", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + }, + { + "name": "limit", + "in": "query", + "description": "Pagination limit", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 } } ], "responses": { "200": { - "description": "List of harnesses", + "description": "List of schedules", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_WithUrls_ResourceWithCounts_Harness" + "$ref": "#/components/schemas/SchedulesListResponse" } } } }, - "403": { - "description": "Forbidden" + "401": { + "description": "Authentication required" }, "500": { - "description": "Internal server error" + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } }, "post": { "tags": [ - "harnesses" + "durable-schedules" ], - "summary": "POST /v1/harnesses", - "operationId": "create_harness", + "summary": "POST /v1/durable/schedules - Create a new schedule", + "operationId": "create_schedule", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateHarnessRequest" + "$ref": "#/components/schemas/CreateScheduleRequest" } } }, @@ -1777,17 +1840,17 @@ }, "responses": { "201": { - "description": "Harness created", + "description": "Schedule created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_Harness" + "$ref": "#/components/schemas/ScheduleResponse" } } } }, "400": { - "description": "Invalid input", + "description": "Invalid request", "content": { "application/json": { "schema": { @@ -1796,8 +1859,11 @@ } } }, - "403": { - "description": "Forbidden", + "401": { + "description": "Authentication required" + }, + "409": { + "description": "Schedule name already exists", "content": { "application/json": { "schema": { @@ -1819,60 +1885,41 @@ } } }, - "/v1/harnesses/config": { + "/v1/durable/schedules/{schedule_id}": { "get": { "tags": [ - "harnesses" - ], - "summary": "GET /v1/harnesses/config", - "description": "Returns which harness policies the caller satisfies.\nUI uses this to show/hide controls (e.g. delete button).", - "operationId": "harness_config", - "responses": { - "200": { - "description": "Resource config for harnesses", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResourceConfigResponse" - } - } - } - } - } - } - }, - "/v1/harnesses/import": { - "post": { - "tags": [ - "harnesses" + "durable-schedules" ], - "summary": "POST /v1/harnesses/import - Adopt a harness example as a regular org-owned harness.", - "description": "Creates a normal harness (`is_built_in = false`) from a code-defined\nexample. The new harness inherits from the org's `generic` harness by\nname — no UUIDs are hardcoded. Capabilities and other config flow through\nthe same validation paths as `POST /v1/harnesses`.\n\nReturns 201 on creation. If the example name collides with an existing\nharness in the org, a random alphanumeric suffix is appended (parity with\nagent example import).", - "operationId": "import_harness", + "summary": "GET /v1/durable/schedules/:schedule_id - Get schedule details", + "operationId": "get_schedule", "parameters": [ { - "name": "from-example", - "in": "query", - "description": "Import from a built-in harness example by name (e.g. `data-analyst`).\nRequired: the only currently supported import mode is from-example.", + "name": "schedule_id", + "in": "path", + "description": "Schedule ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { - "201": { - "description": "Harness adopted from example", + "200": { + "description": "Schedule details", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_Harness" + "$ref": "#/components/schemas/ScheduleResponse" } } } }, - "400": { - "description": "Invalid input or missing capabilities", + "401": { + "description": "Authentication required" + }, + "404": { + "description": "Schedule not found", "content": { "application/json": { "schema": { @@ -1881,59 +1928,8 @@ } } }, - "404": { - "description": "Example not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/v1/harnesses/preview": { - "post": { - "tags": [ - "harnesses" - ], - "summary": "POST /v1/harnesses/preview", - "operationId": "preview_harness", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PreviewHarnessRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Harness preview generated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HarnessPreviewResponse" - } - } - } - }, - "500": { - "description": "Internal server error", + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { @@ -1943,98 +1939,69 @@ } } } - } - }, - "/v1/harnesses/{harness_id}": { - "get": { + }, + "delete": { "tags": [ - "harnesses" + "durable-schedules" ], - "summary": "GET /v1/harnesses/{harness_id}", - "description": "Accepts either a harness ID (e.g. `harness_01933b5a...`) or a\nname (e.g. `generic`). The virtual name `default` resolves to the org's\nconfigured default harness. Names are resolved within the caller's org.", - "operationId": "get_harness", + "summary": "DELETE /v1/durable/schedules/:schedule_id - Delete schedule", + "operationId": "delete_schedule", "parameters": [ { - "name": "harness_id", + "name": "schedule_id", "in": "path", - "description": "Harness ID (prefixed) or name", + "description": "Schedule ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { - "200": { - "description": "Harness found", + "204": { + "description": "Schedule deleted" + }, + "401": { + "description": "Authentication required" + }, + "404": { + "description": "Schedule not found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_ResourceWithCounts_Harness" + "$ref": "#/components/schemas/ErrorResponse" } } } }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Harness not found" - }, "500": { - "description": "Internal server error" - } - } - }, - "delete": { - "tags": [ - "harnesses" - ], - "summary": "DELETE /v1/harnesses/{harness_id}", - "operationId": "delete_harness", - "parameters": [ - { - "name": "harness_id", - "in": "path", - "description": "Harness ID (prefixed)", - "required": true, - "schema": { - "type": "string" + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } } } - ], - "responses": { - "204": { - "description": "Harness archived" - }, - "400": { - "description": "Invalid harness ID" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Harness not found" - }, - "500": { - "description": "Internal server error" - } } }, "patch": { "tags": [ - "harnesses" + "durable-schedules" ], - "summary": "PATCH /v1/harnesses/{harness_id}", - "operationId": "update_harness", + "summary": "PATCH /v1/durable/schedules/:schedule_id - Update schedule", + "operationId": "update_schedule", "parameters": [ { - "name": "harness_id", + "name": "schedule_id", "in": "path", - "description": "Harness ID (prefixed)", + "description": "Schedule ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], @@ -2042,7 +2009,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateHarnessRequest" + "$ref": "#/components/schemas/UpdateScheduleRequest" } } }, @@ -2050,17 +2017,17 @@ }, "responses": { "200": { - "description": "Harness updated", + "description": "Schedule updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_Harness" + "$ref": "#/components/schemas/ScheduleResponse" } } } }, "400": { - "description": "Invalid input", + "description": "Invalid request", "content": { "application/json": { "schema": { @@ -2069,18 +2036,11 @@ } } }, - "403": { - "description": "Forbidden", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "401": { + "description": "Authentication required" }, "404": { - "description": "Harness not found", + "description": "Schedule not found", "content": { "application/json": { "schema": { @@ -2102,58 +2062,72 @@ } } }, - "/v1/harnesses/{harness_id}/copy": { - "post": { + "/v1/durable/schedules/{schedule_id}/executions": { + "get": { "tags": [ - "harnesses" + "durable-schedules" ], - "summary": "POST /v1/harnesses/{harness_id}/copy - Copy a harness", - "description": "Creates a new harness with the same configuration as the source harness.\nThe new harness's name will be \"{original name} (copy)\".", - "operationId": "copy_harness", + "summary": "GET /v1/durable/schedules/:schedule_id/executions - List schedule executions", + "operationId": "list_schedule_executions", "parameters": [ { - "name": "harness_id", + "name": "schedule_id", "in": "path", - "description": "Source harness ID to copy", + "description": "Schedule ID", "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "description": "Filter by status", + "required": false, "schema": { "type": "string" } + }, + { + "name": "offset", + "in": "query", + "description": "Pagination offset", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + }, + { + "name": "limit", + "in": "query", + "description": "Pagination limit", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } } ], "responses": { - "201": { - "description": "Harness copied successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WithUrls_Harness" - } - } - } - }, - "400": { - "description": "Invalid harness ID", + "200": { + "description": "List of executions", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/ScheduleExecutionsListResponse" } } } }, - "403": { - "description": "Forbidden", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "401": { + "description": "Authentication required" }, "404": { - "description": "Source harness not found", + "description": "Schedule not found", "content": { "application/json": { "schema": { @@ -2175,47 +2149,41 @@ } } }, - "/v1/harnesses/{harness_id}/stats": { - "get": { + "/v1/durable/schedules/{schedule_id}/pause": { + "post": { "tags": [ - "harnesses" + "durable-schedules" ], - "summary": "GET /v1/harnesses/{harness_id}/stats - Get aggregate usage stats for a harness", - "operationId": "get_harness_stats", + "summary": "POST /v1/durable/schedules/:schedule_id/pause - Pause schedule", + "operationId": "pause_schedule", "parameters": [ { - "name": "harness_id", + "name": "schedule_id", "in": "path", - "description": "Harness ID (prefixed) or name", + "description": "Schedule ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { "200": { - "description": "Harness aggregate stats", + "description": "Schedule paused", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResourceStatsResponse" + "$ref": "#/components/schemas/ScheduleResponse" } } } }, - "403": { - "description": "Forbidden", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "401": { + "description": "Authentication required" }, "404": { - "description": "Harness not found", + "description": "Schedule not found", "content": { "application/json": { "schema": { @@ -2237,218 +2205,210 @@ } } }, - "/v1/images": { - "get": { + "/v1/durable/schedules/{schedule_id}/resume": { + "post": { "tags": [ - "images" + "durable-schedules" ], - "summary": "GET /v1/images - List images", - "operationId": "list_images", + "summary": "POST /v1/durable/schedules/:schedule_id/resume - Resume schedule", + "operationId": "resume_schedule", "parameters": [ { - "name": "limit", - "in": "query", - "description": "Max items to return (default 50)", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "offset", - "in": "query", - "description": "Items to skip", - "required": false, + "name": "schedule_id", + "in": "path", + "description": "Schedule ID", + "required": true, "schema": { - "type": "integer", - "format": "int64" + "type": "string", + "format": "uuid" } } ], "responses": { "200": { - "description": "List of images", + "description": "Schedule resumed", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ImageInfo" - } + "$ref": "#/components/schemas/ScheduleResponse" } } } }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "images" - ], - "summary": "POST /v1/images - Upload an image", - "operationId": "upload_image", - "parameters": [ - { - "name": "session_id", - "in": "query", - "description": "Optional: session ID stored as metadata for tracking (not required for upload)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "description": "Multipart form data with 'file' field", - "content": { - "multipart/form-data": { - "schema": { - "type": "string" - } - } + "401": { + "description": "Authentication required" }, - "required": true - }, - "responses": { - "201": { - "description": "Image uploaded successfully", + "404": { + "description": "Schedule not found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ImageUploadResponse" + "$ref": "#/components/schemas/ErrorResponse" } } } }, - "400": { - "description": "Invalid request (bad format, size exceeded, etc.)" - }, "500": { - "description": "Internal server error" + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } } }, - "/v1/images/{image_id}": { + "/v1/durable/schedules/{schedule_id}/stats": { "get": { "tags": [ - "images" + "durable-schedules" ], - "summary": "GET /v1/images/{image_id} - Get image (returns binary data)", - "operationId": "get_image", + "summary": "GET /v1/durable/schedules/:schedule_id/stats - Get schedule statistics", + "operationId": "get_schedule_stats", "parameters": [ { - "name": "image_id", + "name": "schedule_id", "in": "path", - "description": "Image ID (prefixed, e.g., img_...)", + "description": "Schedule ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { "200": { - "description": "Image binary data", + "description": "Schedule statistics", "content": { - "image/*": {} + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScheduleStatsResponse" + } + } } }, - "400": { - "description": "Invalid image ID" + "401": { + "description": "Authentication required" }, "404": { - "description": "Image not found" + "description": "Schedule not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, "500": { - "description": "Internal server error" + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } - }, - "delete": { + } + }, + "/v1/durable/schedules/{schedule_id}/trigger": { + "post": { "tags": [ - "images" + "durable-schedules" ], - "summary": "DELETE /v1/images/{image_id} - Delete an image", - "operationId": "delete_image", + "summary": "POST /v1/durable/schedules/:schedule_id/trigger - Manually trigger schedule", + "operationId": "trigger_schedule", "parameters": [ { - "name": "image_id", + "name": "schedule_id", "in": "path", - "description": "Image ID (prefixed, e.g., img_...)", + "description": "Schedule ID", "required": true, "schema": { - "type": "string" + "type": "string", + "format": "uuid" } } ], "responses": { - "204": { - "description": "Image deleted" + "200": { + "description": "Schedule triggered", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TriggerResponse" + } + } + } }, - "400": { - "description": "Invalid image ID" + "401": { + "description": "Authentication required" }, "404": { - "description": "Image not found" + "description": "Schedule not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, "500": { - "description": "Internal server error" + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } } }, - "/v1/images/{image_id}/thumbnail": { + "/v1/harness-examples": { "get": { "tags": [ - "images" - ], - "summary": "GET /v1/images/{image_id}/thumbnail - Get image thumbnail", - "operationId": "get_thumbnail", - "parameters": [ - { - "name": "image_id", - "in": "path", - "description": "Image ID (prefixed, e.g., img_...)", - "required": true, - "schema": { - "type": "string" - } - } + "harness-examples" ], + "summary": "GET /v1/harness-examples — list all available harness examples.", + "operationId": "list_examples", "responses": { "200": { - "description": "Thumbnail binary data", + "description": "List of harness examples", "content": { - "image/jpeg": {} + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HarnessExample" + } + } + } } - }, - "400": { - "description": "Invalid image ID" - }, - "404": { - "description": "Image not found or no thumbnail" - }, - "500": { - "description": "Internal server error" } } } }, - "/v1/knowledge-bases": { + "/v1/harnesses": { "get": { "tags": [ - "knowledge_bases" + "harnesses" ], - "operationId": "list_kbs", + "summary": "GET /v1/harnesses", + "operationId": "list_harnesses", "parameters": [ { "name": "search", "in": "query", + "description": "Search by name or description (case-insensitive substring match).", "required": false, "schema": { "type": [ @@ -2460,6 +2420,7 @@ { "name": "include_archived", "in": "query", + "description": "Include archived harnesses. Deleted harnesses never appear in lists.", "required": false, "schema": { "type": [ @@ -2471,27 +2432,34 @@ ], "responses": { "200": { - "description": "List knowledge bases", + "description": "List of harnesses", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_KnowledgeBaseResponse" + "$ref": "#/components/schemas/ListResponse_WithUrls_ResourceWithCounts_Harness" } } } + }, + "403": { + "description": "Forbidden" + }, + "500": { + "description": "Internal server error" } } }, "post": { "tags": [ - "knowledge_bases" + "harnesses" ], - "operationId": "create_kb", + "summary": "POST /v1/harnesses", + "operationId": "create_harness", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateKnowledgeBaseRequest" + "$ref": "#/components/schemas/CreateHarnessRequest" } } }, @@ -2499,11 +2467,11 @@ }, "responses": { "201": { - "description": "Knowledge base created", + "description": "Harness created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KnowledgeBaseResponse" + "$ref": "#/components/schemas/WithUrls_Harness" } } } @@ -2518,8 +2486,18 @@ } } }, - "409": { - "description": "Duplicate knowledge base name", + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { @@ -2531,17 +2509,41 @@ } } }, - "/v1/knowledge-bases/{kb_id}": { + "/v1/harnesses/config": { "get": { "tags": [ - "knowledge_bases" + "harnesses" ], - "operationId": "get_kb", + "summary": "GET /v1/harnesses/config", + "description": "Returns which harness policies the caller satisfies.\nUI uses this to show/hide controls (e.g. delete button).", + "operationId": "harness_config", + "responses": { + "200": { + "description": "Resource config for harnesses", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResourceConfigResponse" + } + } + } + } + } + } + }, + "/v1/harnesses/import": { + "post": { + "tags": [ + "harnesses" + ], + "summary": "POST /v1/harnesses/import - Adopt a harness example as a regular org-owned harness.", + "description": "Creates a normal harness (`is_built_in = false`) from a code-defined\nexample. The new harness inherits from the org's `generic` harness by\nname — no UUIDs are hardcoded. Capabilities and other config flow through\nthe same validation paths as `POST /v1/harnesses`.\n\nReturns 201 on creation. If the example name collides with an existing\nharness in the org, a random alphanumeric suffix is appended (parity with\nagent example import).", + "operationId": "import_harness", "parameters": [ { - "name": "kb_id", - "in": "path", - "description": "Knowledge base ID", + "name": "from-example", + "in": "query", + "description": "Import from a built-in harness example by name (e.g. `data-analyst`).\nRequired: the only currently supported import mode is from-example.", "required": true, "schema": { "type": "string" @@ -2549,18 +2551,38 @@ } ], "responses": { - "200": { - "description": "Knowledge base found", + "201": { + "description": "Harness adopted from example", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KnowledgeBaseResponse" + "$ref": "#/components/schemas/WithUrls_Harness" + } + } + } + }, + "400": { + "description": "Invalid input or missing capabilities", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { - "description": "Knowledge base not found", + "description": "Example not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { @@ -2570,17 +2592,62 @@ } } } - }, - "delete": { + } + }, + "/v1/harnesses/preview": { + "post": { "tags": [ - "knowledge_bases" + "harnesses" ], - "operationId": "delete_kb", + "summary": "POST /v1/harnesses/preview", + "operationId": "preview_harness", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PreviewHarnessRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Harness preview generated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HarnessPreviewResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/harnesses/{harness_id}": { + "get": { + "tags": [ + "harnesses" + ], + "summary": "GET /v1/harnesses/{harness_id}", + "description": "Accepts either a harness ID (e.g. `harness_01933b5a...`) or a\nname (e.g. `generic`). The virtual name `default` resolves to the org's\nconfigured default harness. Names are resolved within the caller's org.", + "operationId": "get_harness", "parameters": [ { - "name": "kb_id", + "name": "harness_id", "in": "path", - "description": "Knowledge base ID", + "description": "Harness ID (prefixed) or name", "required": true, "schema": { "type": "string" @@ -2588,31 +2655,73 @@ } ], "responses": { - "204": { - "description": "Knowledge base archived" - }, - "404": { - "description": "Knowledge base not found", + "200": { + "description": "Harness found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/WithUrls_ResourceWithCounts_Harness" } } } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Harness not found" + }, + "500": { + "description": "Internal server error" + } + } + }, + "delete": { + "tags": [ + "harnesses" + ], + "summary": "DELETE /v1/harnesses/{harness_id}", + "operationId": "delete_harness", + "parameters": [ + { + "name": "harness_id", + "in": "path", + "description": "Harness ID (prefixed)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Harness archived" + }, + "400": { + "description": "Invalid harness ID" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Harness not found" + }, + "500": { + "description": "Internal server error" } } }, "patch": { "tags": [ - "knowledge_bases" + "harnesses" ], - "operationId": "update_kb", + "summary": "PATCH /v1/harnesses/{harness_id}", + "operationId": "update_harness", "parameters": [ { - "name": "kb_id", + "name": "harness_id", "in": "path", - "description": "Knowledge base ID", + "description": "Harness ID (prefixed)", "required": true, "schema": { "type": "string" @@ -2623,7 +2732,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeBaseRequest" + "$ref": "#/components/schemas/UpdateHarnessRequest" } } }, @@ -2631,11 +2740,11 @@ }, "responses": { "200": { - "description": "Knowledge base updated", + "description": "Harness updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KnowledgeBaseResponse" + "$ref": "#/components/schemas/WithUrls_Harness" } } } @@ -2650,8 +2759,18 @@ } } }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, "404": { - "description": "Knowledge base not found", + "description": "Harness not found", "content": { "application/json": { "schema": { @@ -2660,8 +2779,8 @@ } } }, - "409": { - "description": "Duplicate knowledge base name", + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { @@ -2673,58 +2792,38 @@ } } }, - "/v1/knowledge-bases/{kb_id}/entries": { - "get": { + "/v1/harnesses/{harness_id}/copy": { + "post": { "tags": [ - "knowledge_bases" + "harnesses" ], - "operationId": "list_entries", + "summary": "POST /v1/harnesses/{harness_id}/copy - Copy a harness", + "description": "Creates a new harness with the same configuration as the source harness.\nThe new harness's name will be \"{original name} (copy)\".", + "operationId": "copy_harness", "parameters": [ { - "name": "kb_id", + "name": "harness_id", "in": "path", - "description": "Knowledge base ID", + "description": "Source harness ID to copy", "required": true, "schema": { "type": "string" } - }, - { - "name": "search", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "kind", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } } ], "responses": { - "200": { - "description": "List entries", + "201": { + "description": "Harness copied successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_KnowledgeEntryResponse" + "$ref": "#/components/schemas/WithUrls_Harness" } } } }, - "404": { - "description": "Knowledge base not found", + "400": { + "description": "Invalid harness ID", "content": { "application/json": { "schema": { @@ -2732,48 +2831,19 @@ } } } - } - } - }, - "post": { - "tags": [ - "knowledge_bases" - ], - "operationId": "create_entry", - "parameters": [ - { - "name": "kb_id", - "in": "path", - "description": "Knowledge base ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateKnowledgeEntryRequest" - } - } }, - "required": true - }, - "responses": { - "201": { - "description": "Entry created", + "403": { + "description": "Forbidden", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KnowledgeEntryResponse" + "$ref": "#/components/schemas/ErrorResponse" } } } }, - "400": { - "description": "Invalid input", + "404": { + "description": "Source harness not found", "content": { "application/json": { "schema": { @@ -2782,8 +2852,8 @@ } } }, - "404": { - "description": "Knowledge base not found", + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { @@ -2795,26 +2865,18 @@ } } }, - "/v1/knowledge-bases/{kb_id}/entries/{entry_id}": { + "/v1/harnesses/{harness_id}/stats": { "get": { "tags": [ - "knowledge_bases" + "harnesses" ], - "operationId": "get_entry", + "summary": "GET /v1/harnesses/{harness_id}/stats - Get aggregate usage stats for a harness", + "operationId": "get_harness_stats", "parameters": [ { - "name": "kb_id", - "in": "path", - "description": "Knowledge base ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "entry_id", + "name": "harness_id", "in": "path", - "description": "Entry ID", + "description": "Harness ID (prefixed) or name", "required": true, "schema": { "type": "string" @@ -2823,17 +2885,37 @@ ], "responses": { "200": { - "description": "Entry found", + "description": "Harness aggregate stats", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KnowledgeEntryResponse" + "$ref": "#/components/schemas/ResourceStatsResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { - "description": "Entry not found", + "description": "Harness not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { @@ -2843,222 +2925,151 @@ } } } - }, - "delete": { + } + }, + "/v1/images": { + "get": { "tags": [ - "knowledge_bases" + "images" ], - "operationId": "delete_entry", + "summary": "GET /v1/images - List images", + "operationId": "list_images", "parameters": [ { - "name": "kb_id", - "in": "path", - "description": "Knowledge base ID", - "required": true, + "name": "limit", + "in": "query", + "description": "Max items to return (default 50)", + "required": false, "schema": { - "type": "string" + "type": "integer", + "format": "int64" } }, { - "name": "entry_id", - "in": "path", - "description": "Entry ID", - "required": true, + "name": "offset", + "in": "query", + "description": "Items to skip", + "required": false, "schema": { - "type": "string" + "type": "integer", + "format": "int64" } } ], "responses": { - "204": { - "description": "Entry deleted" - }, - "404": { - "description": "Entry not found", + "200": { + "description": "List of images", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/ImageInfo" + } } } } + }, + "500": { + "description": "Internal server error" } } }, - "patch": { + "post": { "tags": [ - "knowledge_bases" + "images" ], - "operationId": "update_entry", + "summary": "POST /v1/images - Upload an image", + "operationId": "upload_image", "parameters": [ { - "name": "kb_id", - "in": "path", - "description": "Knowledge base ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "entry_id", - "in": "path", - "description": "Entry ID", - "required": true, + "name": "session_id", + "in": "query", + "description": "Optional: session ID stored as metadata for tracking (not required for upload)", + "required": false, "schema": { "type": "string" } } ], "requestBody": { + "description": "Multipart form data with 'file' field", "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/UpdateKnowledgeEntryRequest" + "type": "string" } } }, "required": true }, "responses": { - "200": { - "description": "Entry updated", + "201": { + "description": "Image uploaded successfully", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KnowledgeEntryResponse" + "$ref": "#/components/schemas/ImageUploadResponse" } } } }, "400": { - "description": "Invalid input", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "description": "Invalid request (bad format, size exceeded, etc.)" }, - "404": { - "description": "Entry not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "500": { + "description": "Internal server error" } } } }, - "/v1/llm-models": { + "/v1/images/{image_id}": { "get": { "tags": [ - "llm-models" + "images" ], - "summary": "List all models across all providers", - "operationId": "list_all_models", + "summary": "GET /v1/images/{image_id} - Get image (returns binary data)", + "operationId": "get_image", "parameters": [ { - "name": "source", - "in": "query", - "description": "Filter by model source (manual, discovered, predefined)", - "required": false, + "name": "image_id", + "in": "path", + "description": "Image ID (prefixed, e.g., img_...)", + "required": true, "schema": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/LlmModelSource" - } - ] - } - }, - { - "name": "include_stale", - "in": "query", - "description": "Include models that are stale (not seen in recent sync). Default: true", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "favorites_only", - "in": "query", - "description": "Only return favorite models. Default: false", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of all models", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListResponse_WithUrls_LlmModelWithProvider" - } - } - } - } - } - } - }, - "/v1/llm-models/{id}": { - "get": { - "tags": [ - "llm-models" - ], - "summary": "Get a specific model with provider info and profile", - "operationId": "get_model", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Model ID (prefixed, e.g., mod_...)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Model found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WithUrls_LlmModelWithProvider" - } - } + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Image binary data", + "content": { + "image/*": {} } }, "400": { - "description": "Invalid model ID" + "description": "Invalid image ID" }, "404": { - "description": "Model not found" + "description": "Image not found" + }, + "500": { + "description": "Internal server error" } } }, "delete": { "tags": [ - "llm-models" + "images" ], - "summary": "Delete a model", - "operationId": "delete_model", + "summary": "DELETE /v1/images/{image_id} - Delete an image", + "operationId": "delete_image", "parameters": [ { - "name": "id", + "name": "image_id", "in": "path", - "description": "Model ID (prefixed, e.g., mod_...)", + "description": "Image ID (prefixed, e.g., img_...)", "required": true, "schema": { "type": "string" @@ -3067,77 +3078,94 @@ ], "responses": { "204": { - "description": "Model deleted" + "description": "Image deleted" }, "400": { - "description": "Invalid model ID" + "description": "Invalid image ID" }, "404": { - "description": "Model not found" + "description": "Image not found" + }, + "500": { + "description": "Internal server error" } } - }, - "patch": { + } + }, + "/v1/images/{image_id}/thumbnail": { + "get": { "tags": [ - "llm-models" + "images" ], - "summary": "Update a model", - "operationId": "update_model", + "summary": "GET /v1/images/{image_id}/thumbnail - Get image thumbnail", + "operationId": "get_thumbnail", "parameters": [ { - "name": "id", + "name": "image_id", "in": "path", - "description": "Model ID (prefixed, e.g., mod_...)", + "description": "Image ID (prefixed, e.g., img_...)", "required": true, "schema": { "type": "string" } } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateLlmModelRequest" - } - } - }, - "required": true - }, "responses": { "200": { - "description": "Model updated", + "description": "Thumbnail binary data", "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WithUrls_LlmModel" - } - } + "image/jpeg": {} } }, "400": { - "description": "Invalid model ID" + "description": "Invalid image ID" }, "404": { - "description": "Model not found" + "description": "Image not found or no thumbnail" + }, + "500": { + "description": "Internal server error" } } } }, - "/v1/llm-providers": { + "/v1/knowledge-bases": { "get": { "tags": [ - "llm-providers" + "knowledge_bases" + ], + "operationId": "list_kbs", + "parameters": [ + { + "name": "search", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "include_archived", + "in": "query", + "required": false, + "schema": { + "type": [ + "boolean", + "null" + ] + } + } ], - "summary": "List all LLM providers", - "operationId": "list_providers", "responses": { "200": { - "description": "List of providers", + "description": "List knowledge bases", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_WithUrls_LlmProvider" + "$ref": "#/components/schemas/ListResponse_KnowledgeBaseResponse" } } } @@ -3146,15 +3174,14 @@ }, "post": { "tags": [ - "llm-providers" + "knowledge_bases" ], - "summary": "Create a new LLM provider", - "operationId": "create_provider", + "operationId": "create_kb", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateLlmProviderRequest" + "$ref": "#/components/schemas/CreateKnowledgeBaseRequest" } } }, @@ -3162,36 +3189,49 @@ }, "responses": { "201": { - "description": "Provider created", + "description": "Knowledge base created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_LlmProvider" + "$ref": "#/components/schemas/KnowledgeBaseResponse" } } } }, "400": { - "description": "Invalid request" + "description": "Invalid input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, - "500": { - "description": "Internal error" + "409": { + "description": "Duplicate knowledge base name", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } } }, - "/v1/llm-providers/{id}": { + "/v1/knowledge-bases/{kb_id}": { "get": { "tags": [ - "llm-providers" + "knowledge_bases" ], - "summary": "Get a specific LLM provider", - "operationId": "get_provider", + "operationId": "get_kb", "parameters": [ { - "name": "id", + "name": "kb_id", "in": "path", - "description": "Provider ID (prefixed, e.g., prov_...)", + "description": "Knowledge base ID", "required": true, "schema": { "type": "string" @@ -3200,34 +3240,37 @@ ], "responses": { "200": { - "description": "Provider found", + "description": "Knowledge base found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_LlmProvider" + "$ref": "#/components/schemas/KnowledgeBaseResponse" } } } }, - "400": { - "description": "Invalid provider ID" - }, "404": { - "description": "Provider not found" + "description": "Knowledge base not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } }, "delete": { "tags": [ - "llm-providers" + "knowledge_bases" ], - "summary": "Delete an LLM provider", - "operationId": "delete_provider", + "operationId": "delete_kb", "parameters": [ { - "name": "id", + "name": "kb_id", "in": "path", - "description": "Provider ID (prefixed, e.g., prov_...)", + "description": "Knowledge base ID", "required": true, "schema": { "type": "string" @@ -3236,27 +3279,30 @@ ], "responses": { "204": { - "description": "Provider deleted" - }, - "400": { - "description": "Invalid provider ID" + "description": "Knowledge base archived" }, "404": { - "description": "Provider not found" + "description": "Knowledge base not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } }, "patch": { "tags": [ - "llm-providers" + "knowledge_bases" ], - "summary": "Update an LLM provider", - "operationId": "update_provider", + "operationId": "update_kb", "parameters": [ { - "name": "id", + "name": "kb_id", "in": "path", - "description": "Provider ID (prefixed, e.g., prov_...)", + "description": "Knowledge base ID", "required": true, "schema": { "type": "string" @@ -3267,7 +3313,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateLlmProviderRequest" + "$ref": "#/components/schemas/UpdateKnowledgeBaseRequest" } } }, @@ -3275,162 +3321,67 @@ }, "responses": { "200": { - "description": "Provider updated", + "description": "Knowledge base updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_LlmProvider" + "$ref": "#/components/schemas/KnowledgeBaseResponse" } } } }, "400": { - "description": "Invalid provider ID" - }, - "404": { - "description": "Provider not found" - } - } - } - }, - "/v1/llm-providers/{id}/sync-models": { - "post": { - "tags": [ - "llm-providers" - ], - "summary": "Sync models from an LLM provider", - "description": "Fetches the list of available models from the provider's API and updates\nthe database. Only works for providers with standard base URLs (not custom).", - "operationId": "sync_models", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID (prefixed, e.g., prov_...)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Models synced", + "description": "Invalid input", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SyncModelsResponse" + "$ref": "#/components/schemas/ErrorResponse" } } } }, - "400": { - "description": "Invalid provider ID" - }, "404": { - "description": "Provider not found" - }, - "500": { - "description": "Sync failed" - } - } - } - }, - "/v1/llm-providers/{provider_id}/models": { - "get": { - "tags": [ - "llm-models" - ], - "summary": "List models for a specific provider", - "operationId": "list_provider_models", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID (prefixed, e.g., prov_...)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of models", + "description": "Knowledge base not found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_WithUrls_LlmModel" + "$ref": "#/components/schemas/ErrorResponse" } } } }, - "400": { - "description": "Invalid provider ID" - } - } - }, - "post": { - "tags": [ - "llm-models" - ], - "summary": "Create a new model for a provider", - "operationId": "create_model", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID (prefixed, e.g., prov_...)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateLlmModelRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Model created", + "409": { + "description": "Duplicate knowledge base name", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_LlmModel" + "$ref": "#/components/schemas/ErrorResponse" } } } - }, - "400": { - "description": "Invalid provider ID" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal error" } } } }, - "/v1/mcp-servers": { + "/v1/knowledge-bases/{kb_id}/entries": { "get": { "tags": [ - "mcp-servers" + "knowledge_bases" ], - "summary": "GET /v1/mcp-servers - List all MCP servers", - "operationId": "list_mcp_servers", + "operationId": "list_entries", "parameters": [ + { + "name": "kb_id", + "in": "path", + "description": "Knowledge base ID", + "required": true, + "schema": { + "type": "string" + } + }, { "name": "search", "in": "query", - "description": "Search by name or description (case-insensitive substring match).", "required": false, "schema": { "type": [ @@ -3440,13 +3391,12 @@ } }, { - "name": "include_archived", + "name": "kind", "in": "query", - "description": "Include archived MCP servers. Deleted MCP servers never appear in lists.", "required": false, "schema": { "type": [ - "boolean", + "string", "null" ] } @@ -3454,31 +3404,48 @@ ], "responses": { "200": { - "description": "List of MCP servers", + "description": "List entries", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_WithUrls_McpServer" + "$ref": "#/components/schemas/ListResponse_KnowledgeEntryResponse" } } } }, - "500": { - "description": "Internal server error" + "404": { + "description": "Knowledge base not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } }, "post": { "tags": [ - "mcp-servers" + "knowledge_bases" + ], + "operationId": "create_entry", + "parameters": [ + { + "name": "kb_id", + "in": "path", + "description": "Knowledge base ID", + "required": true, + "schema": { + "type": "string" + } + } ], - "summary": "POST /v1/mcp-servers - Create a new MCP server", - "operationId": "create_mcp_server", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateMcpServerRequest" + "$ref": "#/components/schemas/CreateKnowledgeEntryRequest" } } }, @@ -3486,17 +3453,17 @@ }, "responses": { "201": { - "description": "MCP server created successfully", + "description": "Entry created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_McpServer" + "$ref": "#/components/schemas/KnowledgeEntryResponse" } } } }, "400": { - "description": "Invalid input or duplicate name", + "description": "Invalid input", "content": { "application/json": { "schema": { @@ -3505,8 +3472,8 @@ } } }, - "500": { - "description": "Internal server error", + "404": { + "description": "Knowledge base not found", "content": { "application/json": { "schema": { @@ -3518,18 +3485,26 @@ } } }, - "/v1/mcp-servers/{server_id}": { + "/v1/knowledge-bases/{kb_id}/entries/{entry_id}": { "get": { "tags": [ - "mcp-servers" + "knowledge_bases" ], - "summary": "GET /v1/mcp-servers/{server_id} - Get MCP server by ID", - "operationId": "get_mcp_server", + "operationId": "get_entry", "parameters": [ { - "name": "server_id", + "name": "kb_id", "in": "path", - "description": "MCP server ID (prefixed, e.g., mcp_...)", + "description": "Knowledge base ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "entry_id", + "in": "path", + "description": "Entry ID", "required": true, "schema": { "type": "string" @@ -3538,37 +3513,46 @@ ], "responses": { "200": { - "description": "MCP server found", + "description": "Entry found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WithUrls_McpServer" + "$ref": "#/components/schemas/KnowledgeEntryResponse" } } } }, - "400": { - "description": "Invalid server ID" - }, "404": { - "description": "MCP server not found" - }, - "500": { - "description": "Internal server error" + "description": "Entry not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } } }, "delete": { "tags": [ - "mcp-servers" + "knowledge_bases" ], - "summary": "DELETE /v1/mcp-servers/{server_id} - Delete MCP server", - "operationId": "delete_mcp_server", + "operationId": "delete_entry", "parameters": [ { - "name": "server_id", + "name": "kb_id", "in": "path", - "description": "MCP server ID (prefixed, e.g., mcp_...)", + "description": "Knowledge base ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "entry_id", + "in": "path", + "description": "Entry ID", "required": true, "schema": { "type": "string" @@ -3577,30 +3561,1184 @@ ], "responses": { "204": { - "description": "MCP server deleted successfully" + "description": "Entry deleted" }, - "400": { - "description": "Invalid server ID" + "404": { + "description": "Entry not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "patch": { + "tags": [ + "knowledge_bases" + ], + "operationId": "update_entry", + "parameters": [ + { + "name": "kb_id", + "in": "path", + "description": "Knowledge base ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "entry_id", + "in": "path", + "description": "Entry ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateKnowledgeEntryRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Entry updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KnowledgeEntryResponse" + } + } + } + }, + "400": { + "description": "Invalid input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Entry not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/llm-models": { + "get": { + "tags": [ + "llm-models" + ], + "summary": "List all models across all providers", + "operationId": "list_all_models", + "parameters": [ + { + "name": "source", + "in": "query", + "description": "Filter by model source (manual, discovered, predefined)", + "required": false, + "schema": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/LlmModelSource" + } + ] + } + }, + { + "name": "include_stale", + "in": "query", + "description": "Include models that are stale (not seen in recent sync). Default: true", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "favorites_only", + "in": "query", + "description": "Only return favorite models. Default: false", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "List of all models", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_WithUrls_LlmModelWithProvider" + } + } + } + } + } + } + }, + "/v1/llm-models/{id}": { + "get": { + "tags": [ + "llm-models" + ], + "summary": "Get a specific model with provider info and profile", + "operationId": "get_model", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Model ID (prefixed, e.g., mod_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Model found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_LlmModelWithProvider" + } + } + } + }, + "400": { + "description": "Invalid model ID" + }, + "404": { + "description": "Model not found" + } + } + }, + "delete": { + "tags": [ + "llm-models" + ], + "summary": "Delete a model", + "operationId": "delete_model", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Model ID (prefixed, e.g., mod_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Model deleted" + }, + "400": { + "description": "Invalid model ID" + }, + "404": { + "description": "Model not found" + } + } + }, + "patch": { + "tags": [ + "llm-models" + ], + "summary": "Update a model", + "operationId": "update_model", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Model ID (prefixed, e.g., mod_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateLlmModelRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Model updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_LlmModel" + } + } + } + }, + "400": { + "description": "Invalid model ID" + }, + "404": { + "description": "Model not found" + } + } + } + }, + "/v1/llm-providers": { + "get": { + "tags": [ + "llm-providers" + ], + "summary": "List all LLM providers", + "operationId": "list_providers", + "responses": { + "200": { + "description": "List of providers", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_WithUrls_LlmProvider" + } + } + } + } + } + }, + "post": { + "tags": [ + "llm-providers" + ], + "summary": "Create a new LLM provider", + "operationId": "create_provider", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLlmProviderRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Provider created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_LlmProvider" + } + } + } + }, + "400": { + "description": "Invalid request" + }, + "500": { + "description": "Internal error" + } + } + } + }, + "/v1/llm-providers/{id}": { + "get": { + "tags": [ + "llm-providers" + ], + "summary": "Get a specific LLM provider", + "operationId": "get_provider", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Provider ID (prefixed, e.g., prov_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Provider found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_LlmProvider" + } + } + } + }, + "400": { + "description": "Invalid provider ID" + }, + "404": { + "description": "Provider not found" + } + } + }, + "delete": { + "tags": [ + "llm-providers" + ], + "summary": "Delete an LLM provider", + "operationId": "delete_provider", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Provider ID (prefixed, e.g., prov_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Provider deleted" + }, + "400": { + "description": "Invalid provider ID" + }, + "404": { + "description": "Provider not found" + } + } + }, + "patch": { + "tags": [ + "llm-providers" + ], + "summary": "Update an LLM provider", + "operationId": "update_provider", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Provider ID (prefixed, e.g., prov_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateLlmProviderRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Provider updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_LlmProvider" + } + } + } + }, + "400": { + "description": "Invalid provider ID" + }, + "404": { + "description": "Provider not found" + } + } + } + }, + "/v1/llm-providers/{id}/sync-models": { + "post": { + "tags": [ + "llm-providers" + ], + "summary": "Sync models from an LLM provider", + "description": "Fetches the list of available models from the provider's API and updates\nthe database. Only works for providers with standard base URLs (not custom).", + "operationId": "sync_models", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Provider ID (prefixed, e.g., prov_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Models synced", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SyncModelsResponse" + } + } + } + }, + "400": { + "description": "Invalid provider ID" + }, + "404": { + "description": "Provider not found" + }, + "500": { + "description": "Sync failed" + } + } + } + }, + "/v1/llm-providers/{provider_id}/models": { + "get": { + "tags": [ + "llm-models" + ], + "summary": "List models for a specific provider", + "operationId": "list_provider_models", + "parameters": [ + { + "name": "provider_id", + "in": "path", + "description": "Provider ID (prefixed, e.g., prov_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List of models", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_WithUrls_LlmModel" + } + } + } + }, + "400": { + "description": "Invalid provider ID" + } + } + }, + "post": { + "tags": [ + "llm-models" + ], + "summary": "Create a new model for a provider", + "operationId": "create_model", + "parameters": [ + { + "name": "provider_id", + "in": "path", + "description": "Provider ID (prefixed, e.g., prov_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLlmModelRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Model created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_LlmModel" + } + } + } + }, + "400": { + "description": "Invalid provider ID" + }, + "404": { + "description": "Provider not found" + }, + "500": { + "description": "Internal error" + } + } + } + }, + "/v1/mcp-servers": { + "get": { + "tags": [ + "mcp-servers" + ], + "summary": "GET /v1/mcp-servers - List all MCP servers", + "operationId": "list_mcp_servers", + "parameters": [ + { + "name": "search", + "in": "query", + "description": "Search by name or description (case-insensitive substring match).", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "include_archived", + "in": "query", + "description": "Include archived MCP servers. Deleted MCP servers never appear in lists.", + "required": false, + "schema": { + "type": [ + "boolean", + "null" + ] + } + } + ], + "responses": { + "200": { + "description": "List of MCP servers", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_WithUrls_McpServer" + } + } + } + }, + "500": { + "description": "Internal server error" + } + } + }, + "post": { + "tags": [ + "mcp-servers" + ], + "summary": "POST /v1/mcp-servers - Create a new MCP server", + "operationId": "create_mcp_server", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMcpServerRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "MCP server created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_McpServer" + } + } + } + }, + "400": { + "description": "Invalid input or duplicate name", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/mcp-servers/{server_id}": { + "get": { + "tags": [ + "mcp-servers" + ], + "summary": "GET /v1/mcp-servers/{server_id} - Get MCP server by ID", + "operationId": "get_mcp_server", + "parameters": [ + { + "name": "server_id", + "in": "path", + "description": "MCP server ID (prefixed, e.g., mcp_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "MCP server found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_McpServer" + } + } + } + }, + "400": { + "description": "Invalid server ID" + }, + "404": { + "description": "MCP server not found" + }, + "500": { + "description": "Internal server error" + } + } + }, + "delete": { + "tags": [ + "mcp-servers" + ], + "summary": "DELETE /v1/mcp-servers/{server_id} - Delete MCP server", + "operationId": "delete_mcp_server", + "parameters": [ + { + "name": "server_id", + "in": "path", + "description": "MCP server ID (prefixed, e.g., mcp_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "MCP server deleted successfully" + }, + "400": { + "description": "Invalid server ID" + }, + "404": { + "description": "MCP server not found" + }, + "500": { + "description": "Internal server error" + } + } + }, + "patch": { + "tags": [ + "mcp-servers" + ], + "summary": "PATCH /v1/mcp-servers/{server_id} - Update MCP server", + "operationId": "update_mcp_server", + "parameters": [ + { + "name": "server_id", + "in": "path", + "description": "MCP server ID (prefixed, e.g., mcp_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateMcpServerRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "MCP server updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WithUrls_McpServer" + } + } + } + }, + "400": { + "description": "Invalid server ID or input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "MCP server not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/memory-stores": { + "get": { + "tags": [ + "memory_stores" + ], + "operationId": "list_memory_stores", + "responses": { + "200": { + "description": "List org memory stores", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_MemoryStoreResponse" + } + } + } + } + } + }, + "post": { + "tags": [ + "memory_stores" + ], + "operationId": "create_memory_store", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMemoryStoreRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Memory store created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MemoryStoreResponse" + } + } + } + }, + "400": { + "description": "Invalid input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Duplicate name or default conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/memory-stores/{store_id}": { + "get": { + "tags": [ + "memory_stores" + ], + "operationId": "get_memory_store", + "parameters": [ + { + "name": "store_id", + "in": "path", + "description": "Memory store ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Memory store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MemoryStoreResponse" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/memory-stores/{store_id}/memories": { + "get": { + "tags": [ + "memory_stores" + ], + "operationId": "list_memories", + "parameters": [ + { + "name": "store_id", + "in": "path", + "description": "Memory store ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "query", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "kind", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "tag", + "in": "query", + "required": false, + "schema": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + } + }, + { + "name": "include_inactive", + "in": "query", + "required": false, + "schema": { + "type": [ + "boolean", + "null" + ] + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Memories", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListMemoriesResponse" + } + } + } + }, + "404": { + "description": "Store not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/memory-stores/{store_id}/memories/{memory_id}": { + "delete": { + "tags": [ + "memory_stores" + ], + "operationId": "forget_memory", + "parameters": [ + { + "name": "store_id", + "in": "path", + "description": "Memory store ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "memory_id", + "in": "path", + "description": "Memory ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Memory deactivated" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/orgs": { + "get": { + "tags": [ + "Organizations" + ], + "summary": "GET /v1/orgs - List organizations the current user belongs to", + "operationId": "list_organizations", + "responses": { + "200": { + "description": "List of organizations", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_OrganizationResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ] + }, + "post": { + "tags": [ + "Organizations" + ], + "summary": "POST /v1/orgs - Create a new organization", + "operationId": "create_organization", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateOrganizationRequest" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Organization created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationResponse" + } + } + } + }, + "400": { + "description": "Invalid input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ] + } + }, + "/v1/orgs/{org}": { + "get": { + "tags": [ + "Organizations" + ], + "summary": "GET /v1/orgs/:org - Get organization details", + "operationId": "get_organization", + "parameters": [ + { + "name": "org", + "in": "path", + "description": "Organization public ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Organization details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationResponse" + } + } + } }, "404": { - "description": "MCP server not found" + "description": "Organization not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] }, - "500": { - "description": "Internal server error" + { + "cookieAuth": [] } - } + ] }, "patch": { "tags": [ - "mcp-servers" + "Organizations" ], - "summary": "PATCH /v1/mcp-servers/{server_id} - Update MCP server", - "operationId": "update_mcp_server", + "summary": "PATCH /v1/orgs/:org - Update organization", + "operationId": "update_organization", "parameters": [ { - "name": "server_id", + "name": "org", "in": "path", - "description": "MCP server ID (prefixed, e.g., mcp_...)", + "description": "Organization public ID", "required": true, "schema": { "type": "string" @@ -3611,7 +4749,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateMcpServerRequest" + "$ref": "#/components/schemas/UpdateOrganizationRequest" } } }, @@ -3619,27 +4757,17 @@ }, "responses": { "200": { - "description": "MCP server updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WithUrls_McpServer" - } - } - } - }, - "400": { - "description": "Invalid server ID or input", + "description": "Organization updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "$ref": "#/components/schemas/OrganizationResponse" } } } }, "404": { - "description": "MCP server not found", + "description": "Organization not found", "content": { "application/json": { "schema": { @@ -3647,33 +4775,58 @@ } } } + } + }, + "security": [ + { + "bearerAuth": [] }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + { + "cookieAuth": [] } - } + ] } }, - "/v1/memory-stores": { + "/v1/payments/accounts": { "get": { "tags": [ - "memory_stores" + "payments" + ], + "operationId": "list_payment_accounts", + "parameters": [ + { + "name": "owner_type", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "owner_id", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + } ], - "operationId": "list_memory_stores", "responses": { "200": { - "description": "List org memory stores", + "description": "List payment accounts", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_MemoryStoreResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentAccount" + } } } } @@ -3682,14 +4835,14 @@ }, "post": { "tags": [ - "memory_stores" + "payments" ], - "operationId": "create_memory_store", + "operationId": "create_payment_account", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateMemoryStoreRequest" + "$ref": "#/components/schemas/CreatePaymentAccountRequest" } } }, @@ -3697,11 +4850,11 @@ }, "responses": { "201": { - "description": "Memory store created", + "description": "Payment account created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemoryStoreResponse" + "$ref": "#/components/schemas/PaymentAccount" } } } @@ -3715,31 +4868,21 @@ } } } - }, - "409": { - "description": "Duplicate name or default conflict", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } } } } }, - "/v1/memory-stores/{store_id}": { + "/v1/payments/accounts/{payment_account_id}": { "get": { "tags": [ - "memory_stores" + "payments" ], - "operationId": "get_memory_store", + "operationId": "get_payment_account", "parameters": [ { - "name": "store_id", + "name": "payment_account_id", "in": "path", - "description": "Memory store ID", + "description": "Payment account ID", "required": true, "schema": { "type": "string" @@ -3748,11 +4891,11 @@ ], "responses": { "200": { - "description": "Memory store", + "description": "Payment account", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemoryStoreResponse" + "$ref": "#/components/schemas/PaymentAccount" } } } @@ -3768,97 +4911,88 @@ } } } - } - }, - "/v1/memory-stores/{store_id}/memories": { - "get": { + }, + "delete": { "tags": [ - "memory_stores" + "payments" ], - "operationId": "list_memories", + "operationId": "disable_payment_account", "parameters": [ { - "name": "store_id", + "name": "payment_account_id", "in": "path", - "description": "Memory store ID", + "description": "Payment account ID", "required": true, "schema": { "type": "string" } + } + ], + "responses": { + "204": { + "description": "Payment account disabled" }, - { - "name": "query", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "kind", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "tag", - "in": "query", - "required": false, - "schema": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } - }, - { - "name": "include_inactive", - "in": "query", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, + } + } + }, + "patch": { + "tags": [ + "payments" + ], + "operationId": "update_payment_account", + "parameters": [ { - "name": "limit", - "in": "query", - "required": false, + "name": "payment_account_id", + "in": "path", + "description": "Payment account ID", + "required": true, "schema": { - "type": [ - "integer", - "null" - ], - "minimum": 0 + "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePaymentAccountRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Memories", + "description": "Payment account updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListMemoriesResponse" + "$ref": "#/components/schemas/PaymentAccount" + } + } + } + }, + "400": { + "description": "Invalid input", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { - "description": "Store not found", + "description": "Not found", "content": { "application/json": { "schema": { @@ -3870,42 +5004,44 @@ } } }, - "/v1/memory-stores/{store_id}/memories/{memory_id}": { - "delete": { + "/v1/payments/attempts": { + "get": { "tags": [ - "memory_stores" + "payments" ], - "operationId": "forget_memory", + "operationId": "list_payment_attempts", "parameters": [ { - "name": "store_id", - "in": "path", - "description": "Memory store ID", - "required": true, + "name": "session_id", + "in": "query", + "required": false, "schema": { - "type": "string" - } - }, - { - "name": "memory_id", - "in": "path", - "description": "Memory ID", - "required": true, + "type": [ + "string", + "null" + ] + } + }, + { + "name": "limit", + "in": "query", + "required": false, "schema": { - "type": "string" + "type": "integer", + "format": "int64" } } ], "responses": { - "204": { - "description": "Memory deactivated" - }, - "404": { - "description": "Not found", + "200": { + "description": "List payment attempts", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentAttempt" + } } } } @@ -3913,45 +5049,73 @@ } } }, - "/v1/orgs": { + "/v1/payments/policies": { "get": { "tags": [ - "Organizations" + "payments" + ], + "operationId": "list_payment_policies", + "parameters": [ + { + "name": "payment_account_id", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "subject_type", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "subject_id", + "in": "query", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + } ], - "summary": "GET /v1/orgs - List organizations the current user belongs to", - "operationId": "list_organizations", "responses": { "200": { - "description": "List of organizations", + "description": "List payment policies", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_OrganizationResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentPolicy" + } } } } } - }, - "security": [ - { - "bearerAuth": [] - }, - { - "cookieAuth": [] - } - ] + } }, "post": { "tags": [ - "Organizations" + "payments" ], - "summary": "POST /v1/orgs - Create a new organization", - "operationId": "create_organization", + "operationId": "create_payment_policy", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateOrganizationRequest" + "$ref": "#/components/schemas/CreatePaymentPolicyRequest" } } }, @@ -3959,11 +5123,11 @@ }, "responses": { "201": { - "description": "Organization created", + "description": "Payment policy created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationResponse" + "$ref": "#/components/schemas/PaymentPolicy" } } } @@ -3978,29 +5142,20 @@ } } } - }, - "security": [ - { - "bearerAuth": [] - }, - { - "cookieAuth": [] - } - ] + } } }, - "/v1/orgs/{org}": { + "/v1/payments/policies/{payment_policy_id}": { "get": { "tags": [ - "Organizations" + "payments" ], - "summary": "GET /v1/orgs/:org - Get organization details", - "operationId": "get_organization", + "operationId": "get_payment_policy", "parameters": [ { - "name": "org", + "name": "payment_policy_id", "in": "path", - "description": "Organization public ID", + "description": "Payment policy ID", "required": true, "schema": { "type": "string" @@ -4009,17 +5164,17 @@ ], "responses": { "200": { - "description": "Organization details", + "description": "Payment policy", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationResponse" + "$ref": "#/components/schemas/PaymentPolicy" } } } }, "404": { - "description": "Organization not found", + "description": "Not found", "content": { "application/json": { "schema": { @@ -4028,27 +5183,50 @@ } } } - }, - "security": [ + } + }, + "delete": { + "tags": [ + "payments" + ], + "operationId": "disable_payment_policy", + "parameters": [ { - "bearerAuth": [] + "name": "payment_policy_id", + "in": "path", + "description": "Payment policy ID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Payment policy disabled" }, - { - "cookieAuth": [] + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } - ] + } }, "patch": { "tags": [ - "Organizations" + "payments" ], - "summary": "PATCH /v1/orgs/:org - Update organization", - "operationId": "update_organization", + "operationId": "update_payment_policy", "parameters": [ { - "name": "org", + "name": "payment_policy_id", "in": "path", - "description": "Organization public ID", + "description": "Payment policy ID", "required": true, "schema": { "type": "string" @@ -4059,7 +5237,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateOrganizationRequest" + "$ref": "#/components/schemas/UpdatePaymentPolicyRequest" } } }, @@ -4067,17 +5245,17 @@ }, "responses": { "200": { - "description": "Organization updated", + "description": "Payment policy updated", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OrganizationResponse" + "$ref": "#/components/schemas/PaymentPolicy" } } } }, - "404": { - "description": "Organization not found", + "400": { + "description": "Invalid input", "content": { "application/json": { "schema": { @@ -4085,16 +5263,18 @@ } } } - } - }, - "security": [ - { - "bearerAuth": [] }, - { - "cookieAuth": [] + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } } - ] + } } }, "/v1/sessions": { @@ -4258,6 +5438,36 @@ } } }, + "/v1/sessions/chat/voice": { + "post": { + "tags": [ + "voice" + ], + "operationId": "create_chat_voice_session", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceCallRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Platform chat session and realtime call created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceSessionResponse_VoiceCallResponse" + } + } + } + } + } + } + }, "/v1/sessions/{session_id}": { "get": { "tags": [ @@ -4685,13 +5895,98 @@ "description": "Session ID (prefixed, e.g., sess_...)", "required": true, "schema": { - "type": "string" + "type": "string" + } + }, + { + "name": "since_id", + "in": "query", + "description": "Filter events with ID greater than this event ID (prefixed format: event_{32-hex})", + "required": false, + "schema": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/eventId" + } + ] + } + }, + { + "name": "types", + "in": "query", + "description": "Positive type filter (repeat key). Empty = all types.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "style": "form", + "explode": true + }, + { + "name": "exclude", + "in": "query", + "description": "Event types to exclude (repeat key); applied after `types`.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "style": "form", + "explode": true + }, + { + "name": "limit", + "in": "query", + "description": "Max events to return (backward pagination). When set, returns the last N events\n(or last N before `before_sequence`). Results are ordered oldest→newest.", + "required": false, + "schema": { + "type": [ + "integer", + "null" + ], + "format": "int32", + "maximum": 1000, + "minimum": 1 + } + }, + { + "name": "before_sequence", + "in": "query", + "description": "Cursor for backward pagination: only return events with sequence < this value.", + "required": false, + "schema": { + "type": [ + "integer", + "null" + ], + "format": "int32" + } + }, + { + "name": "after_sequence", + "in": "query", + "description": "Forward cursor: only return events with sequence > this value.", + "required": false, + "schema": { + "type": [ + "integer", + "null" + ], + "format": "int32" } }, { - "name": "since_id", + "name": "around", "in": "query", - "description": "Filter events with ID greater than this event ID (prefixed format: event_{32-hex})", + "description": "Anchor event id: returns up to `window` events on each side (default 50, max 500).\nMutually exclusive with `since_id`, `after_sequence`, and `before_sequence` — 400 if combined.", "required": false, "schema": { "oneOf": [ @@ -4699,29 +5994,90 @@ "type": "null" }, { - "$ref": "#/components/schemas/TypedId" + "$ref": "#/components/schemas/eventId" } ] } }, { - "name": "types", + "name": "window", "in": "query", - "description": "Positive type filter: only return events matching these types (can be specified multiple times).\nWhen empty, all types are returned. Example: ?types=turn.started&types=turn.completed", + "description": "Window size for `around` (events on each side). Defaults to 50, max 500.", "required": false, "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "style": "form", - "explode": true + "type": [ + "integer", + "null" + ], + "format": "int32" + } }, { - "name": "exclude", + "name": "from_ts", "in": "query", - "description": "Event types to exclude from the response (can be specified multiple times).\nApplied after `types` filter. Common delta events to exclude: output.message.delta, reason.thinking.delta", + "description": "Lower bound on `created_at` (RFC 3339, e.g. `2025-05-07T00:00:00Z`).", + "required": false, + "schema": { + "type": [ + "string", + "null" + ], + "format": "date-time" + } + }, + { + "name": "to_ts", + "in": "query", + "description": "Upper bound on `created_at`.", + "required": false, + "schema": { + "type": [ + "string", + "null" + ], + "format": "date-time" + } + }, + { + "name": "turn_id", + "in": "query", + "description": "Filter by `context.turn_id` (prefixed id, e.g. `turn_...`).", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "exec_id", + "in": "query", + "description": "Filter by `context.exec_id` (prefixed id, e.g. `exec_...`).", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "trace_id", + "in": "query", + "description": "Filter by `context.trace_id`.", + "required": false, + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "tags", + "in": "query", + "description": "Tag any-match against `events.tags` (repeat key for multiple values).", "required": false, "schema": { "type": "array", @@ -4733,31 +6089,36 @@ "explode": true }, { - "name": "limit", + "name": "tool_name", "in": "query", - "description": "Max events to return (backward pagination). When set, returns the last N events\n(or last N before `before_sequence`). Results are ordered oldest→newest.", + "description": "Filter by `data.tool_name` — useful for narrowing `tool.*` events.", "required": false, "schema": { "type": [ - "integer", + "string", "null" - ], - "format": "int32", - "maximum": 1000, - "minimum": 1 + ] } }, { - "name": "before_sequence", + "name": "q", "in": "query", - "description": "Cursor for backward pagination: only return events with sequence < this value.\nUsed with `limit` to paginate backward through event history.", + "description": "Full-text search (Postgres tsvector; substring fallback for in-memory mode).", "required": false, "schema": { "type": [ - "integer", + "string", "null" - ], - "format": "int32" + ] + } + }, + { + "name": "order_desc", + "in": "query", + "description": "When true, return newest first; default oldest first.", + "required": false, + "schema": { + "type": "boolean" } } ], @@ -4793,6 +6154,47 @@ } } }, + "/v1/sessions/{session_id}/events/summary": { + "get": { + "tags": [ + "events" + ], + "summary": "GET /v1/sessions/{session_id}/events/summary - one-shot debug summary", + "operationId": "events_summary", + "parameters": [ + { + "name": "session_id", + "in": "path", + "description": "Session ID (prefixed, e.g., sess_...)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Per-type counts and time span for the session", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventsSummaryResult" + } + } + } + }, + "400": { + "description": "Invalid session ID" + }, + "404": { + "description": "Session not found" + }, + "500": { + "description": "Internal server error" + } + } + } + }, "/v1/sessions/{session_id}/export": { "get": { "tags": [ @@ -5932,7 +7334,7 @@ "type": "null" }, { - "$ref": "#/components/schemas/TypedId" + "$ref": "#/components/schemas/eventId" } ] } @@ -5964,144 +7366,256 @@ }, "style": "form", "explode": true + } + ], + "responses": { + "200": { + "description": "Event stream. Includes 'connected' on open, domain events during streaming, and 'disconnecting' before graceful close.", + "content": { + "text/event-stream": {} + } + }, + "400": { + "description": "Invalid session ID" }, + "404": { + "description": "Session not found" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/v1/sessions/{session_id}/storage/keys": { + "get": { + "tags": [ + "session-storage" + ], + "summary": "GET /v1/sessions/{session_id}/storage/keys - List all key-value pairs", + "operationId": "list_keys", + "parameters": [ { - "name": "limit", - "in": "query", - "description": "Max events to return (backward pagination). When set, returns the last N events\n(or last N before `before_sequence`). Results are ordered oldest→newest.", - "required": false, + "name": "session_id", + "in": "path", + "description": "Session ID", + "required": true, "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "maximum": 1000, - "minimum": 1 + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List of key-value pairs", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_KeyValueInfo" + } + } } }, + "404": { + "description": "Session not found" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/v1/sessions/{session_id}/storage/secrets": { + "get": { + "tags": [ + "session-storage" + ], + "summary": "GET /v1/sessions/{session_id}/storage/secrets - List all secrets (names only)", + "operationId": "list_secrets", + "parameters": [ { - "name": "before_sequence", - "in": "query", - "description": "Cursor for backward pagination: only return events with sequence < this value.\nUsed with `limit` to paginate backward through event history.", - "required": false, + "name": "session_id", + "in": "path", + "description": "Session ID", + "required": true, "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List of secrets (names only, no values)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListResponse_SecretInfo" + } + } + } + }, + "404": { + "description": "Session not found" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/v1/sessions/{session_id}/tool-results": { + "post": { + "tags": [ + "sessions" + ], + "summary": "POST /v1/sessions/{session_id}/tool-results - Submit client-side tool results", + "description": "Accepts tool results executed by the client and resumes the agent workflow.\nSession must be in `waiting_for_tool_results` status.", + "operationId": "submit_tool_results", + "parameters": [ + { + "name": "session_id", + "in": "path", + "description": "Session ID (prefixed, e.g., session_...)", + "required": true, + "schema": { + "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubmitToolResultsRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Event stream. Includes 'connected' on open, domain events during streaming, and 'disconnecting' before graceful close.", + "description": "Tool results accepted and workflow resumed", "content": { - "text/event-stream": {} + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubmitToolResultsResponse" + } + } } }, "400": { - "description": "Invalid session ID" + "description": "Invalid session ID or request" }, "404": { "description": "Session not found" }, + "409": { + "description": "Session not in waiting_for_tool_results state" + }, "500": { "description": "Internal server error" } } } }, - "/v1/sessions/{session_id}/storage/keys": { - "get": { + "/v1/sessions/{session_id}/voice/calls": { + "post": { "tags": [ - "session-storage" + "voice" ], - "summary": "GET /v1/sessions/{session_id}/storage/keys - List all key-value pairs", - "operationId": "list_keys", + "operationId": "create_call", "parameters": [ { "name": "session_id", "in": "path", - "description": "Session ID", "required": true, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceCallRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "List of key-value pairs", + "description": "Realtime WebRTC call created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_KeyValueInfo" + "$ref": "#/components/schemas/VoiceCallResponse" } } } - }, - "404": { - "description": "Session not found" - }, - "500": { - "description": "Internal server error" } } } }, - "/v1/sessions/{session_id}/storage/secrets": { - "get": { + "/v1/sessions/{session_id}/voice/client-secret": { + "post": { "tags": [ - "session-storage" + "voice" ], - "summary": "GET /v1/sessions/{session_id}/storage/secrets - List all secrets (names only)", - "operationId": "list_secrets", + "operationId": "create_client_secret", "parameters": [ { "name": "session_id", "in": "path", - "description": "Session ID", "required": true, "schema": { "type": "string" } } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceClientSecretRequest" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "List of secrets (names only, no values)", + "description": "Realtime client secret created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListResponse_SecretInfo" + "$ref": "#/components/schemas/VoiceClientSecretResponse" } } } - }, - "404": { - "description": "Session not found" - }, - "500": { - "description": "Internal server error" } } } }, - "/v1/sessions/{session_id}/tool-results": { + "/v1/sessions/{session_id}/voice/{voice_connection_id}/attach": { "post": { "tags": [ - "sessions" + "voice" ], - "summary": "POST /v1/sessions/{session_id}/tool-results - Submit client-side tool results", - "description": "Accepts tool results executed by the client and resumes the agent workflow.\nSession must be in `waiting_for_tool_results` status.", - "operationId": "submit_tool_results", + "operationId": "attach_call", "parameters": [ { "name": "session_id", "in": "path", - "description": "Session ID (prefixed, e.g., session_...)", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "voice_connection_id", + "in": "path", "required": true, "schema": { "type": "string" @@ -6112,7 +7626,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SubmitToolResultsRequest" + "$ref": "#/components/schemas/VoiceAttachRequest" } } }, @@ -6120,26 +7634,62 @@ }, "responses": { "200": { - "description": "Tool results accepted and workflow resumed", + "description": "Realtime sideband attached", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SubmitToolResultsResponse" + "$ref": "#/components/schemas/VoiceAttachResponse" } } } + } + } + } + }, + "/v1/sessions/{session_id}/voice/{voice_connection_id}/end": { + "post": { + "tags": [ + "voice" + ], + "operationId": "end_call", + "parameters": [ + { + "name": "session_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } }, - "400": { - "description": "Invalid session ID or request" - }, - "404": { - "description": "Session not found" - }, - "409": { - "description": "Session not in waiting_for_tool_results state" + { + "name": "voice_connection_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceEndRequest" + } + } }, - "500": { - "description": "Internal server error" + "required": true + }, + "responses": { + "200": { + "description": "Realtime voice connection ended", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceEndResponse" + } + } + } } } } @@ -6903,6 +8453,14 @@ "description": "Default LLM model ID for this agent.\nCan be overridden at the session level.", "example": "model_01933b5a00007000800000000000001" }, + "default_version_id": { + "type": [ + "string", + "null" + ], + "description": "Default immutable version used by deployments that choose the default policy.", + "example": "agentver_01933b5a00007000800000000000001" + }, "deleted_at": { "type": [ "string", @@ -6925,6 +8483,22 @@ ], "description": "Human-readable display name shown in UI (e.g. \"Customer Support Agent\").\nFalls back to `name` when absent." }, + "forked_from_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Source agent for a forked agent.", + "example": "agent_01933b5a00007000800000000000001" + }, + "forked_from_version_id": { + "type": [ + "string", + "null" + ], + "description": "Source version for a forked agent.", + "example": "agentver_01933b5a00007000800000000000001" + }, "id": { "type": "string", "description": "External identifier (agent_<32-hex>). Shown as \"id\" in API.\nClient-supplied or auto-generated.", @@ -6964,6 +8538,14 @@ } ] }, + "root_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Root agent lineage identifier for grouping fork families.", + "example": "agent_01933b5a00007000800000000000001" + }, "status": { "$ref": "#/components/schemas/AgentStatus", "description": "Current lifecycle status of the agent." @@ -7022,34 +8604,153 @@ }, "AgentPreviewResponse": { "type": "object", - "description": "Response showing the final agent shape after applying capabilities", + "description": "Response showing the final agent shape after applying capabilities", + "required": [ + "system_prompt", + "tools" + ], + "properties": { + "system_prompt": { + "type": "string", + "description": "The full system prompt with capability additions prepended" + }, + "tools": { + "type": "array", + "items": { + "type": "object" + }, + "description": "All tool definitions from capabilities" + } + } + }, + "AgentStatus": { + "type": "string", + "description": "Agent lifecycle status.\n- `active`: Agent is available for use\n- `archived`: Agent is hidden from listings and cannot be modified or assigned\n- `deleted`: Agent is a tombstone kept only for historical references", + "enum": [ + "active", + "archived", + "deleted" + ] + }, + "AgentVersion": { + "type": "object", + "description": "Immutable snapshot of an Agent's authored and resolved runtime config.", + "required": [ + "id", + "agent_id", + "version_number", + "semver_major", + "semver_minor", + "semver_patch", + "version", + "change_kind", + "config_hash", + "authored_config", + "resolved_config", + "created_at" + ], + "properties": { + "agent_id": { + "type": "string", + "example": "agent_01933b5a000070008000000000000001" + }, + "authored_config": { + "type": "object" + }, + "change_kind": { + "$ref": "#/components/schemas/AgentVersionChangeKind" + }, + "config_hash": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "created_by_principal_id": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string", + "example": "agentver_01933b5a000070008000000000000001" + }, + "parent_version_id": { + "type": [ + "string", + "null" + ] + }, + "resolved_config": { + "type": "object" + }, + "semver_major": { + "type": "integer", + "format": "int32" + }, + "semver_minor": { + "type": "integer", + "format": "int32" + }, + "semver_patch": { + "type": "integer", + "format": "int32" + }, + "source_version_id": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "version": { + "type": "string" + }, + "version_number": { + "type": "integer", + "format": "int32" + } + } + }, + "AgentVersionChangeKind": { + "type": "string", + "description": "Reason a version was created. Stored as lower_snake_case text.", + "enum": [ + "manual", + "patch", + "minor", + "major", + "import", + "rollback", + "fork" + ] + }, + "AgentVersionDiffResponse": { + "type": "object", "required": [ - "system_prompt", - "tools" + "from_version_id", + "to_version_id", + "authored_diff", + "resolved_diff" ], "properties": { - "system_prompt": { - "type": "string", - "description": "The full system prompt with capability additions prepended" + "authored_diff": {}, + "from_version_id": { + "$ref": "#/components/schemas/agentverId" }, - "tools": { - "type": "array", - "items": { - "type": "object" - }, - "description": "All tool definitions from capabilities" + "resolved_diff": {}, + "to_version_id": { + "$ref": "#/components/schemas/agentverId" } } }, - "AgentStatus": { - "type": "string", - "description": "Agent lifecycle status.\n- `active`: Agent is available for use\n- `archived`: Agent is hidden from listings and cannot be modified or assigned\n- `deleted`: Agent is a tombstone kept only for historical references", - "enum": [ - "active", - "archived", - "deleted" - ] - }, "BTreeMap": { "type": "object", "additionalProperties": { @@ -7927,6 +9628,27 @@ } } }, + "CreateAgentVersionRequest": { + "type": "object", + "properties": { + "change_kind": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/AgentVersionChangeKind" + } + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + } + } + }, "CreateBranchRequest": { "type": "object", "description": "Request to create a branch", @@ -7958,6 +9680,18 @@ } } }, + "CreateDeclarativeCapabilityRequest": { + "type": "object", + "required": [ + "definition" + ], + "properties": { + "definition": { + "type": "object", + "description": "Definition for the new declarative capability. `name` must be unique per org and becomes the canonical `declarative:` capability ref." + } + } + }, "CreateFileRequest": { "type": "object", "description": "Request to create a file", @@ -8364,6 +10098,108 @@ } } }, + "CreatePaymentAccountRequest": { + "type": "object", + "required": [ + "owner_type", + "owner_id", + "rail", + "label" + ], + "properties": { + "label": { + "type": "string" + }, + "metadata": {}, + "owner_id": { + "type": "string" + }, + "owner_type": { + "type": "string" + }, + "private_key": { + "type": [ + "string", + "null" + ] + }, + "public_address": { + "type": [ + "string", + "null" + ] + }, + "rail": { + "type": "string" + } + } + }, + "CreatePaymentPolicyRequest": { + "type": "object", + "required": [ + "payment_account_id", + "subject_type", + "subject_id" + ], + "properties": { + "allowed_capabilities": { + "type": "array", + "items": { + "type": "string" + } + }, + "allowed_hosts": { + "type": "array", + "items": { + "type": "string" + } + }, + "max_amount_usd_per_day": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "max_amount_usd_per_request": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "max_amount_usd_per_turn": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "metadata": {}, + "payment_account_id": { + "type": "string" + }, + "rail_preference": { + "type": "array", + "items": { + "type": "string" + } + }, + "require_approval_above_usd": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "subject_id": { + "type": "string" + }, + "subject_type": { + "type": "string" + } + } + }, "CreateScheduleRequest": { "type": "object", "description": "Create schedule request", @@ -8619,6 +10455,80 @@ } } }, + "DeclarativeCapability": { + "type": "object", + "required": [ + "id", + "capability_id", + "name", + "description", + "status", + "definition", + "created_at", + "updated_at" + ], + "properties": { + "archived_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "capability_id": { + "type": "string", + "description": "Runtime capability reference. Agents and harnesses may use this or the plain unique name.", + "example": "declarative:research_pack" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "definition": { + "type": "object", + "description": "Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata." + }, + "deleted_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "description": { + "type": "string", + "description": "Short summary shown in pickers, search results, and API listings.", + "example": "Adds research instructions, starter files, and MCP tools." + }, + "display_name": { + "type": [ + "string", + "null" + ], + "description": "Human-facing label shown in the UI. Defaults to `name` when omitted.", + "example": "Research Pack" + }, + "id": { + "type": "string", + "description": "Public resource ID for this persisted declarative capability.", + "example": "cap_01933b5a000070008000000000000001" + }, + "name": { + "type": "string", + "description": "Stable unique name used in capability refs. Lowercase letters, numbers, and underscores.", + "example": "research_pack" + }, + "status": { + "type": "string", + "description": "Lifecycle state for the resource: active, disabled, archived, or deleted.", + "example": "active" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, "DeferrablePolicy": { "type": "string", "description": "Controls whether a tool's full schema can be deferred (tool_search).\n\nWhen tool_search is active and a model supports it, tools marked as\n`Automatic` or `Always` will have `defer_loading: true` set, meaning\nonly the name+description are sent upfront and full parameter schemas\nare loaded on-demand by the model.", @@ -8905,6 +10815,27 @@ }, { "$ref": "#/components/schemas/BudgetEventData" + }, + { + "$ref": "#/components/schemas/VoiceSessionStartedData" + }, + { + "$ref": "#/components/schemas/VoiceTranscriptData" + }, + { + "$ref": "#/components/schemas/VoiceTranscriptData" + }, + { + "$ref": "#/components/schemas/VoiceTranscriptData" + }, + { + "$ref": "#/components/schemas/VoiceTranscriptData" + }, + { + "$ref": "#/components/schemas/VoiceSessionEndedData" + }, + { + "$ref": "#/components/schemas/VoiceSessionFailedData" } ], "title": "EventData", @@ -8917,6 +10848,71 @@ } } }, + "EventTypeCountOut": { + "type": "object", + "required": [ + "event_type", + "count" + ], + "properties": { + "count": { + "type": "integer", + "format": "int64" + }, + "event_type": { + "type": "string" + } + } + }, + "EventsSummaryResult": { + "type": "object", + "required": [ + "total", + "by_type", + "turn_count", + "error_count" + ], + "properties": { + "by_type": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EventTypeCountOut" + }, + "description": "Per-type count, sorted by event_type asc." + }, + "error_count": { + "type": "integer", + "format": "int64", + "description": "Convenience: count of failure-shaped event types\n(`turn.failed`, `tool.failed`, `*.error`, `subagent.failed`)." + }, + "first_ts": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Earliest event timestamp, if any." + }, + "last_ts": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Latest event timestamp, if any." + }, + "total": { + "type": "integer", + "format": "int64", + "description": "Total event count across all types." + }, + "turn_count": { + "type": "integer", + "format": "int64", + "description": "Convenience: count of `turn.started` events." + } + } + }, "ExecutionPhase": { "type": "string", "description": "Execution phase for assistant messages in multi-step tool-calling flows.\n\nProviders that natively support phases (OpenAI GPT-5.x) send the phase value\ndirectly in the API request. For providers without native support (Anthropic,\nGemini), the phase is still tracked internally and derived from state in the\nReasonAtom, but is not sent to the provider API.\n\nSerialized as lowercase strings for backward compatibility with existing\npersisted messages: `\"commentary\"` and `\"final_answer\"`.\n\nLegacy values `\"in_progress\"` and `\"completed\"` are accepted during\ndeserialization for backward compatibility.", @@ -9073,10 +11069,33 @@ "type": "string", "description": "File path within the session filesystem (normalized, e.g. \"/reports/summary.md\")." }, - "size_bytes": { - "type": "integer", - "format": "int64", - "description": "File size in bytes after write." + "size_bytes": { + "type": "integer", + "format": "int64", + "description": "File size in bytes after write." + } + } + }, + "ForkAgentVersionRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "display_name": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" } } }, @@ -10247,6 +12266,14 @@ "description": "Default LLM model ID for this agent.\nCan be overridden at the session level.", "example": "model_01933b5a00007000800000000000001" }, + "default_version_id": { + "type": [ + "string", + "null" + ], + "description": "Default immutable version used by deployments that choose the default policy.", + "example": "agentver_01933b5a00007000800000000000001" + }, "deleted_at": { "type": [ "string", @@ -10269,6 +12296,22 @@ ], "description": "Human-readable display name shown in UI (e.g. \"Customer Support Agent\").\nFalls back to `name` when absent." }, + "forked_from_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Source agent for a forked agent.", + "example": "agent_01933b5a00007000800000000000001" + }, + "forked_from_version_id": { + "type": [ + "string", + "null" + ], + "description": "Source version for a forked agent.", + "example": "agentver_01933b5a00007000800000000000001" + }, "id": { "type": "string", "description": "External identifier (agent_<32-hex>). Shown as \"id\" in API.\nClient-supplied or auto-generated.", @@ -10308,6 +12351,14 @@ } ] }, + "root_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Root agent lineage identifier for grouping fork families.", + "example": "agent_01933b5a00007000800000000000001" + }, "status": { "$ref": "#/components/schemas/AgentStatus", "description": "Current lifecycle status of the agent." @@ -11561,6 +13612,120 @@ } } }, + "ListResponse_WithUrls_DeclarativeCapability": { + "type": "object", + "description": "Response wrapper for list endpoints.\nAll list endpoints return responses wrapped in a `data` field.", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "allOf": [ + { + "type": "object", + "required": [ + "id", + "capability_id", + "name", + "description", + "status", + "definition", + "created_at", + "updated_at" + ], + "properties": { + "archived_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "capability_id": { + "type": "string", + "description": "Runtime capability reference. Agents and harnesses may use this or the plain unique name.", + "example": "declarative:research_pack" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "definition": { + "type": "object", + "description": "Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata." + }, + "deleted_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "description": { + "type": "string", + "description": "Short summary shown in pickers, search results, and API listings.", + "example": "Adds research instructions, starter files, and MCP tools." + }, + "display_name": { + "type": [ + "string", + "null" + ], + "description": "Human-facing label shown in the UI. Defaults to `name` when omitted.", + "example": "Research Pack" + }, + "id": { + "type": "string", + "description": "Public resource ID for this persisted declarative capability.", + "example": "cap_01933b5a000070008000000000000001" + }, + "name": { + "type": "string", + "description": "Stable unique name used in capability refs. Lowercase letters, numbers, and underscores.", + "example": "research_pack" + }, + "status": { + "type": "string", + "description": "Lifecycle state for the resource: active, disabled, archived, or deleted.", + "example": "active" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + { + "type": "object", + "required": [ + "self_url", + "view_url", + "ui_link" + ], + "properties": { + "self_url": { + "type": "string", + "description": "Full API endpoint URL for this resource." + }, + "ui_link": { + "type": "string", + "description": "Alias for `view_url`, used by command and MCP outputs." + }, + "view_url": { + "type": "string", + "description": "Full UI URL for viewing this resource." + } + } + } + ], + "description": "Wrapper that adds API and UI links to a serialized resource.\n\nUses `self_url` (not `url`) for the API link to avoid collision with\nresources that already have a `url` field (e.g. McpServer)." + }, + "description": "Array of items returned by the list operation." + } + } + }, "ListResponse_WithUrls_LlmModel": { "type": "object", "description": "Response wrapper for list endpoints.\nAll list endpoints return responses wrapped in a `data` field.", @@ -13893,6 +16058,14 @@ "description": "Optional resident agent identity for unattended/background execution.", "example": "identity_01933b5a00007000800000000000001" }, + "agent_version_id": { + "type": [ + "string", + "null" + ], + "description": "Immutable agent version captured when the session was created or rebound.", + "example": "agentver_01933b5a00007000800000000000001" + }, "blueprint_config": { "description": "Validated config passed by host at blueprint spawn time." }, @@ -14395,6 +16568,14 @@ "description": "Default LLM model ID for this agent.\nCan be overridden at the session level.", "example": "model_01933b5a00007000800000000000001" }, + "default_version_id": { + "type": [ + "string", + "null" + ], + "description": "Default immutable version used by deployments that choose the default policy.", + "example": "agentver_01933b5a00007000800000000000001" + }, "deleted_at": { "type": [ "string", @@ -14417,6 +16598,22 @@ ], "description": "Human-readable display name shown in UI (e.g. \"Customer Support Agent\").\nFalls back to `name` when absent." }, + "forked_from_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Source agent for a forked agent.", + "example": "agent_01933b5a00007000800000000000001" + }, + "forked_from_version_id": { + "type": [ + "string", + "null" + ], + "description": "Source version for a forked agent.", + "example": "agentver_01933b5a00007000800000000000001" + }, "id": { "type": "string", "description": "External identifier (agent_<32-hex>). Shown as \"id\" in API.\nClient-supplied or auto-generated.", @@ -14456,6 +16653,14 @@ } ] }, + "root_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Root agent lineage identifier for grouping fork families.", + "example": "agent_01933b5a00007000800000000000001" + }, "status": { "$ref": "#/components/schemas/AgentStatus", "description": "Current lifecycle status of the agent." @@ -14619,6 +16824,14 @@ "description": "Optional resident agent identity for unattended/background execution.", "example": "identity_01933b5a00007000800000000000001" }, + "agent_version_id": { + "type": [ + "string", + "null" + ], + "description": "Immutable agent version captured when the session was created or rebound.", + "example": "agentver_01933b5a00007000800000000000001" + }, "blueprint_config": { "description": "Validated config passed by host at blueprint spawn time." }, @@ -14900,26 +17113,289 @@ }, "description": "Array of items returned by the list operation." }, - "limit": { - "type": "integer", - "format": "int32", - "description": "Maximum number of items per page.", - "minimum": 0 + "limit": { + "type": "integer", + "format": "int32", + "description": "Maximum number of items per page.", + "minimum": 0 + }, + "offset": { + "type": "integer", + "format": "int32", + "description": "Current offset (starting position).", + "minimum": 0 + }, + "total": { + "type": "integer", + "format": "int32", + "description": "Total number of items matching the query (across all pages).", + "minimum": 0 + } + } + }, + "PaymentAccount": { + "type": "object", + "required": [ + "id", + "organization_id", + "owner_type", + "owner_id", + "rail", + "label", + "status", + "metadata", + "created_at", + "updated_at" + ], + "properties": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "id": { + "$ref": "#/components/schemas/payacctId" + }, + "label": { + "type": "string" + }, + "metadata": {}, + "organization_id": { + "type": "string" + }, + "owner_id": { + "type": "string" + }, + "owner_type": { + "$ref": "#/components/schemas/PaymentOwnerType" + }, + "public_address": { + "type": [ + "string", + "null" + ] + }, + "rail": { + "$ref": "#/components/schemas/PaymentRail" + }, + "status": { + "$ref": "#/components/schemas/PaymentStatus" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + "PaymentAttempt": { + "type": "object", + "required": [ + "id", + "organization_id", + "capability", + "operation", + "amount_usd", + "currency", + "target_url", + "status", + "receipt", + "created_at", + "updated_at" + ], + "properties": { + "amount_usd": { + "type": "number", + "format": "double" + }, + "capability": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "currency": { + "type": "string" + }, + "error_message": { + "type": [ + "string", + "null" + ] + }, + "id": { + "$ref": "#/components/schemas/payattId" + }, + "operation": { + "type": "string" + }, + "organization_id": { + "type": "string" + }, + "payment_account_id": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/payacctId" + } + ] + }, + "rail": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/components/schemas/PaymentRail" + } + ] }, - "offset": { - "type": "integer", - "format": "int32", - "description": "Current offset (starting position).", - "minimum": 0 + "receipt": {}, + "request_hash": { + "type": [ + "string", + "null" + ] }, - "total": { - "type": "integer", - "format": "int32", - "description": "Total number of items matching the query (across all pages).", - "minimum": 0 + "session_id": { + "type": [ + "string", + "null" + ] + }, + "status": { + "$ref": "#/components/schemas/PaymentStatus" + }, + "target_url": { + "type": "string" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + "PaymentOwnerType": { + "type": "string", + "description": "Principal class that owns a payment account.", + "enum": [ + "user", + "agent_identity", + "organization" + ] + }, + "PaymentPolicy": { + "type": "object", + "required": [ + "id", + "organization_id", + "payment_account_id", + "subject_type", + "subject_id", + "allowed_capabilities", + "allowed_hosts", + "rail_preference", + "status", + "metadata", + "created_at", + "updated_at" + ], + "properties": { + "allowed_capabilities": { + "type": "array", + "items": { + "type": "string" + } + }, + "allowed_hosts": { + "type": "array", + "items": { + "type": "string" + } + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "id": { + "$ref": "#/components/schemas/paypolId" + }, + "max_amount_usd_per_day": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "max_amount_usd_per_request": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "max_amount_usd_per_turn": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "metadata": {}, + "organization_id": { + "type": "string" + }, + "payment_account_id": { + "$ref": "#/components/schemas/payacctId" + }, + "rail_preference": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentRail" + } + }, + "require_approval_above_usd": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "status": { + "$ref": "#/components/schemas/PaymentStatus" + }, + "subject_id": { + "type": "string" + }, + "subject_type": { + "type": "string" + }, + "updated_at": { + "type": "string", + "format": "date-time" } } }, + "PaymentRail": { + "type": "string", + "description": "Payment rail used to settle a machine payment.", + "enum": [ + "mpp_tempo", + "x402_base" + ] + }, + "PaymentStatus": { + "type": "string", + "enum": [ + "active", + "disabled", + "pending", + "succeeded", + "failed", + "released" + ] + }, "PreviewAgentRequest": { "type": "object", "description": "Request to preview the final agent shape with capabilities applied", @@ -15102,13 +17578,13 @@ "type": "null" }, { - "$ref": "#/components/schemas/TypedId", + "$ref": "#/components/schemas/agentId", "description": "Agent ID being used (optional)" } ] }, "harness_id": { - "$ref": "#/components/schemas/TypedId", + "$ref": "#/components/schemas/harnessId", "description": "Harness ID being used" }, "metadata": { @@ -15382,6 +17858,20 @@ "high" ] }, + "RollbackAgentVersionRequest": { + "type": "object", + "properties": { + "save_version": { + "type": "boolean" + }, + "summary": { + "type": [ + "string", + "null" + ] + } + } + }, "ScheduleExecutionResponse": { "type": "object", "description": "Schedule execution response", @@ -15741,6 +18231,14 @@ "description": "Optional resident agent identity for unattended/background execution.", "example": "identity_01933b5a00007000800000000000001" }, + "agent_version_id": { + "type": [ + "string", + "null" + ], + "description": "Immutable agent version captured when the session was created or rebound.", + "example": "agentver_01933b5a00007000800000000000001" + }, "blueprint_config": { "description": "Validated config passed by host at blueprint spawn time." }, @@ -16274,6 +18772,17 @@ "paused" ] }, + "SetDefaultAgentVersionRequest": { + "type": "object", + "required": [ + "version_id" + ], + "properties": { + "version_id": { + "$ref": "#/components/schemas/agentverId" + } + } + }, "Skill": { "type": "object", "description": "Skill entity (API response type)", @@ -17287,12 +19796,6 @@ } } }, - "TypedId": { - "type": "string", - "description": "Prefixed identifier with 'agent' prefix", - "example": "agent_01933b5a00007000800000000000001", - "pattern": "^agent_[0-9a-f]{32}$" - }, "UpdateAgentRequest": { "type": "object", "description": "Request to update an agent. Only provided fields will be updated.", @@ -17433,6 +19936,23 @@ } } }, + "UpdateDeclarativeCapabilityRequest": { + "type": "object", + "properties": { + "definition": { + "type": "object", + "description": "Replacement declarative definition. Changing `name` updates the canonical capability ref after uniqueness validation." + }, + "status": { + "type": [ + "string", + "null" + ], + "description": "Optional lifecycle state update. Use `disabled` to hide from runtime selection without archiving.", + "example": "disabled" + } + } + }, "UpdateFileRequest": { "type": "object", "description": "Request to update a file", @@ -17832,16 +20352,113 @@ "string", "null" ], - "description": "Default LLM model for this organization. Must be an enabled model.", - "example": "model_01933b5a00007000800000000000001" + "description": "Default LLM model for this organization. Must be an enabled model.", + "example": "model_01933b5a00007000800000000000001" + }, + "name": { + "type": [ + "string", + "null" + ], + "description": "The display name of the organization.", + "example": "Acme Corporation" + } + } + }, + "UpdatePaymentAccountRequest": { + "type": "object", + "properties": { + "label": { + "type": [ + "string", + "null" + ] + }, + "metadata": {}, + "private_key": { + "type": [ + "string", + "null" + ] + }, + "public_address": { + "type": [ + "string", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + } + } + }, + "UpdatePaymentPolicyRequest": { + "type": "object", + "properties": { + "allowed_capabilities": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "allowed_hosts": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "max_amount_usd_per_day": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "max_amount_usd_per_request": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "max_amount_usd_per_turn": { + "type": [ + "number", + "null" + ], + "format": "double" + }, + "metadata": {}, + "rail_preference": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "require_approval_above_usd": { + "type": [ + "number", + "null" + ], + "format": "double" }, - "name": { + "status": { "type": [ "string", "null" - ], - "description": "The display name of the organization.", - "example": "Acme Corporation" + ] } } }, @@ -17994,7 +20611,316 @@ "null" ] }, - "name": { + "name": { + "type": [ + "string", + "null" + ] + } + } + }, + "User": { + "type": "object", + "description": "User response for listing", + "required": [ + "id", + "email", + "name", + "roles", + "created_at" + ], + "properties": { + "auth_provider": { + "type": [ + "string", + "null" + ] + }, + "avatar_url": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "ValidateSkillRequest": { + "type": "object", + "description": "Request to validate a SKILL.md", + "required": [ + "skill_md" + ], + "properties": { + "skill_md": { + "type": "string", + "description": "SKILL.md content to validate" + } + } + }, + "VoiceAttachRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/VoiceSessionOptions" + }, + { + "type": "object", + "required": [ + "provider_call_id" + ], + "properties": { + "provider_call_id": { + "type": "string" + } + } + } + ] + }, + "VoiceAttachResponse": { + "type": "object", + "required": [ + "voice_connection_id", + "provider_call_id", + "provider", + "model", + "voice", + "reasoning_effort", + "expires_at" + ], + "properties": { + "expires_at": { + "type": "string", + "format": "date-time" + }, + "model": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_call_id": { + "type": "string" + }, + "reasoning_effort": { + "type": "string" + }, + "voice": { + "type": "string" + }, + "voice_connection_id": { + "type": "string" + } + } + }, + "VoiceCallRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/VoiceSessionOptions" + }, + { + "type": "object", + "required": [ + "sdp" + ], + "properties": { + "sdp": { + "type": "string" + } + } + } + ] + }, + "VoiceCallResponse": { + "type": "object", + "required": [ + "voice_connection_id", + "provider", + "model", + "voice", + "reasoning_effort", + "expires_at", + "answer_sdp" + ], + "properties": { + "answer_sdp": { + "type": "string" + }, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "model": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_call_id": { + "type": [ + "string", + "null" + ] + }, + "reasoning_effort": { + "type": "string" + }, + "voice": { + "type": "string" + }, + "voice_connection_id": { + "type": "string" + } + } + }, + "VoiceClientSecretRequest": { + "allOf": [ + { + "$ref": "#/components/schemas/VoiceSessionOptions" + } + ] + }, + "VoiceClientSecretResponse": { + "type": "object", + "required": [ + "voice_connection_id", + "provider", + "model", + "voice", + "reasoning_effort", + "expires_at", + "client_secret" + ], + "properties": { + "client_secret": {}, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "model": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "reasoning_effort": { + "type": "string" + }, + "voice": { + "type": "string" + }, + "voice_connection_id": { + "type": "string" + } + } + }, + "VoiceEndRequest": { + "type": "object", + "properties": { + "reason": { + "type": [ + "string", + "null" + ] + } + } + }, + "VoiceEndResponse": { + "type": "object", + "required": [ + "voice_connection_id", + "status" + ], + "properties": { + "status": { + "type": "string" + }, + "voice_connection_id": { + "type": "string" + } + } + }, + "VoiceSessionEndedData": { + "type": "object", + "description": "Data for voice.session.ended.", + "required": [ + "voice_connection_id" + ], + "properties": { + "duration_ms": { + "type": [ + "integer", + "null" + ], + "format": "int64", + "minimum": 0 + }, + "reason": { + "type": [ + "string", + "null" + ] + }, + "voice_connection_id": { + "type": "string" + } + } + }, + "VoiceSessionFailedData": { + "type": "object", + "description": "Data for voice.session.failed.", + "required": [ + "voice_connection_id", + "error" + ], + "properties": { + "error": { + "type": "string" + }, + "voice_connection_id": { + "type": "string" + } + } + }, + "VoiceSessionOptions": { + "type": "object", + "properties": { + "instructions": { + "type": [ + "string", + "null" + ] + }, + "model": { + "type": [ + "string", + "null" + ] + }, + "reasoning_effort": { + "type": [ + "string", + "null" + ] + }, + "voice": { "type": [ "string", "null" @@ -18002,60 +20928,122 @@ } } }, - "User": { + "VoiceSessionResponse_VoiceCallResponse": { "type": "object", - "description": "User response for listing", "required": [ - "id", - "email", - "name", - "roles", - "created_at" + "session", + "voice" ], "properties": { - "auth_provider": { - "type": [ - "string", - "null" - ] - }, - "avatar_url": { - "type": [ - "string", - "null" - ] + "session": { + "$ref": "#/components/schemas/Session" }, - "created_at": { - "type": "string", - "format": "date-time" + "voice": { + "type": "object", + "required": [ + "voice_connection_id", + "provider", + "model", + "voice", + "reasoning_effort", + "expires_at", + "answer_sdp" + ], + "properties": { + "answer_sdp": { + "type": "string" + }, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "model": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_call_id": { + "type": [ + "string", + "null" + ] + }, + "reasoning_effort": { + "type": "string" + }, + "voice": { + "type": "string" + }, + "voice_connection_id": { + "type": "string" + } + } + } + } + }, + "VoiceSessionStartedData": { + "type": "object", + "description": "Data for voice.session.started.", + "required": [ + "voice_connection_id", + "model", + "voice", + "reasoning_effort", + "transport" + ], + "properties": { + "model": { + "type": "string" }, - "email": { + "reasoning_effort": { "type": "string" }, - "id": { + "transport": { "type": "string" }, - "name": { + "voice": { "type": "string" }, - "roles": { - "type": "array", - "items": { - "type": "string" - } + "voice_connection_id": { + "type": "string" } } }, - "ValidateSkillRequest": { + "VoiceTranscriptData": { "type": "object", - "description": "Request to validate a SKILL.md", + "description": "Data for voice transcript delta/completed events.", "required": [ - "skill_md" + "voice_connection_id", + "accumulated" ], "properties": { - "skill_md": { - "type": "string", - "description": "SKILL.md content to validate" + "accumulated": { + "type": "string" + }, + "delta": { + "type": "string" + }, + "item_id": { + "type": [ + "string", + "null" + ] + }, + "phase": { + "type": [ + "string", + "null" + ] + }, + "response_id": { + "type": [ + "string", + "null" + ] + }, + "voice_connection_id": { + "type": "string" } } }, @@ -18170,6 +21158,14 @@ "description": "Default LLM model ID for this agent.\nCan be overridden at the session level.", "example": "model_01933b5a00007000800000000000001" }, + "default_version_id": { + "type": [ + "string", + "null" + ], + "description": "Default immutable version used by deployments that choose the default policy.", + "example": "agentver_01933b5a00007000800000000000001" + }, "deleted_at": { "type": [ "string", @@ -18192,6 +21188,22 @@ ], "description": "Human-readable display name shown in UI (e.g. \"Customer Support Agent\").\nFalls back to `name` when absent." }, + "forked_from_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Source agent for a forked agent.", + "example": "agent_01933b5a00007000800000000000001" + }, + "forked_from_version_id": { + "type": [ + "string", + "null" + ], + "description": "Source version for a forked agent.", + "example": "agentver_01933b5a00007000800000000000001" + }, "id": { "type": "string", "description": "External identifier (agent_<32-hex>). Shown as \"id\" in API.\nClient-supplied or auto-generated.", @@ -18231,6 +21243,14 @@ } ] }, + "root_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Root agent lineage identifier for grouping fork families.", + "example": "agent_01933b5a00007000800000000000001" + }, "status": { "$ref": "#/components/schemas/AgentStatus", "description": "Current lifecycle status of the agent." @@ -18432,6 +21452,107 @@ ], "description": "Wrapper that adds API and UI links to a serialized resource.\n\nUses `self_url` (not `url`) for the API link to avoid collision with\nresources that already have a `url` field (e.g. McpServer)." }, + "WithUrls_DeclarativeCapability": { + "allOf": [ + { + "type": "object", + "required": [ + "id", + "capability_id", + "name", + "description", + "status", + "definition", + "created_at", + "updated_at" + ], + "properties": { + "archived_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "capability_id": { + "type": "string", + "description": "Runtime capability reference. Agents and harnesses may use this or the plain unique name.", + "example": "declarative:research_pack" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "definition": { + "type": "object", + "description": "Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata." + }, + "deleted_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "description": { + "type": "string", + "description": "Short summary shown in pickers, search results, and API listings.", + "example": "Adds research instructions, starter files, and MCP tools." + }, + "display_name": { + "type": [ + "string", + "null" + ], + "description": "Human-facing label shown in the UI. Defaults to `name` when omitted.", + "example": "Research Pack" + }, + "id": { + "type": "string", + "description": "Public resource ID for this persisted declarative capability.", + "example": "cap_01933b5a000070008000000000000001" + }, + "name": { + "type": "string", + "description": "Stable unique name used in capability refs. Lowercase letters, numbers, and underscores.", + "example": "research_pack" + }, + "status": { + "type": "string", + "description": "Lifecycle state for the resource: active, disabled, archived, or deleted.", + "example": "active" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + }, + { + "type": "object", + "required": [ + "self_url", + "view_url", + "ui_link" + ], + "properties": { + "self_url": { + "type": "string", + "description": "Full API endpoint URL for this resource." + }, + "ui_link": { + "type": "string", + "description": "Alias for `view_url`, used by command and MCP outputs." + }, + "view_url": { + "type": "string", + "description": "Full UI URL for viewing this resource." + } + } + } + ], + "description": "Wrapper that adds API and UI links to a serialized resource.\n\nUses `self_url` (not `url`) for the API link to avoid collision with\nresources that already have a `url` field (e.g. McpServer)." + }, "WithUrls_Harness": { "allOf": [ { @@ -19028,6 +22149,14 @@ "description": "Default LLM model ID for this agent.\nCan be overridden at the session level.", "example": "model_01933b5a00007000800000000000001" }, + "default_version_id": { + "type": [ + "string", + "null" + ], + "description": "Default immutable version used by deployments that choose the default policy.", + "example": "agentver_01933b5a00007000800000000000001" + }, "deleted_at": { "type": [ "string", @@ -19050,6 +22179,22 @@ ], "description": "Human-readable display name shown in UI (e.g. \"Customer Support Agent\").\nFalls back to `name` when absent." }, + "forked_from_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Source agent for a forked agent.", + "example": "agent_01933b5a00007000800000000000001" + }, + "forked_from_version_id": { + "type": [ + "string", + "null" + ], + "description": "Source version for a forked agent.", + "example": "agentver_01933b5a00007000800000000000001" + }, "id": { "type": "string", "description": "External identifier (agent_<32-hex>). Shown as \"id\" in API.\nClient-supplied or auto-generated.", @@ -19089,6 +22234,14 @@ } ] }, + "root_agent_id": { + "type": [ + "string", + "null" + ], + "description": "Root agent lineage identifier for grouping fork families.", + "example": "agent_01933b5a00007000800000000000001" + }, "status": { "$ref": "#/components/schemas/AgentStatus", "description": "Current lifecycle status of the agent." @@ -19398,6 +22551,14 @@ "description": "Optional resident agent identity for unattended/background execution.", "example": "identity_01933b5a00007000800000000000001" }, + "agent_version_id": { + "type": [ + "string", + "null" + ], + "description": "Immutable agent version captured when the session was created or rebound.", + "example": "agentver_01933b5a00007000800000000000001" + }, "blueprint_config": { "description": "Validated config passed by host at blueprint spawn time." }, @@ -19795,6 +22956,48 @@ } ], "description": "Wrapper that adds API and UI links to a serialized resource.\n\nUses `self_url` (not `url`) for the API link to avoid collision with\nresources that already have a `url` field (e.g. McpServer)." + }, + "agentId": { + "type": "string", + "description": "Prefixed identifier with 'agent' prefix", + "example": "agent_01933b5a00007000800000000000001", + "pattern": "^agent_[0-9a-f]{32}$" + }, + "agentverId": { + "type": "string", + "description": "Prefixed identifier with 'agentver' prefix", + "example": "agentver_01933b5a00007000800000000000001", + "pattern": "^agentver_[0-9a-f]{32}$" + }, + "eventId": { + "type": "string", + "description": "Prefixed identifier with 'event' prefix", + "example": "event_01933b5a00007000800000000000001", + "pattern": "^event_[0-9a-f]{32}$" + }, + "harnessId": { + "type": "string", + "description": "Prefixed identifier with 'harness' prefix", + "example": "harness_01933b5a00007000800000000000001", + "pattern": "^harness_[0-9a-f]{32}$" + }, + "payacctId": { + "type": "string", + "description": "Prefixed identifier with 'payacct' prefix", + "example": "payacct_01933b5a00007000800000000000001", + "pattern": "^payacct_[0-9a-f]{32}$" + }, + "payattId": { + "type": "string", + "description": "Prefixed identifier with 'payatt' prefix", + "example": "payatt_01933b5a00007000800000000000001", + "pattern": "^payatt_[0-9a-f]{32}$" + }, + "paypolId": { + "type": "string", + "description": "Prefixed identifier with 'paypol' prefix", + "example": "paypol_01933b5a00007000800000000000001", + "pattern": "^paypol_[0-9a-f]{32}$" } } }, @@ -19811,6 +23014,10 @@ "name": "messages", "description": "Message management endpoints" }, + { + "name": "voice", + "description": "Realtime voice session endpoints" + }, { "name": "events", "description": "Event streaming endpoints (SSE)" @@ -19886,6 +23093,10 @@ { "name": "skills", "description": "Skills registry endpoints" + }, + { + "name": "payments", + "description": "Machine payment wallet, policy, and attempt endpoints" } ] } diff --git a/python/README.md b/python/README.md index 18211d1..634d74a 100644 --- a/python/README.md +++ b/python/README.md @@ -80,6 +80,29 @@ client = Everruns() client = Everruns(api_key="evr_...", org_id="org_...") ``` +## Agent Versions + +```python +version = await client.agents.create_version( + "agent_...", + change_kind="manual", + summary="Baseline", +) + +versions = await client.agents.list_versions("agent_...") +diff = await client.agents.diff_versions("agent_...", "agentver_1", version.id) +fork = await client.agents.fork_version( + "agent_...", + version.id, + name="forked-agent", +) +rollback = await client.agents.rollback_version( + "agent_...", + version.id, + save_version=True, +) +``` + ## License MIT diff --git a/python/everruns_sdk/__init__.py b/python/everruns_sdk/__init__.py index 793bb46..8248807 100644 --- a/python/everruns_sdk/__init__.py +++ b/python/everruns_sdk/__init__.py @@ -21,6 +21,9 @@ from everruns_sdk.models import ( Agent, AgentCapabilityConfig, + AgentVersion, + AgentVersionChangeKind, + AgentVersionDiffResponse, Budget, BudgetCheckResult, BudgetPeriod, @@ -29,11 +32,13 @@ Connection, ContentPart, Controls, + CreateAgentVersionRequest, DeleteFileResponse, Event, ExternalActor, FileInfo, FileStat, + ForkAgentVersionRequest, GrepMatch, GrepResult, InitialFile, @@ -41,8 +46,10 @@ Message, ResourceStats, ResumeSessionResponse, + RollbackAgentVersionRequest, Session, SessionFile, + SetDefaultAgentVersionRequest, SubmitToolResultsResponse, ToolCallInfo, ToolDefinition, @@ -65,21 +72,28 @@ "ValidationError", "Agent", "AgentCapabilityConfig", + "AgentVersion", + "AgentVersionChangeKind", + "AgentVersionDiffResponse", "Budget", "BudgetCheckResult", "BudgetPeriod", "CapabilityInfo", "ClientToolResult", "Connection", + "CreateAgentVersionRequest", "DeleteFileResponse", "FileInfo", "FileStat", + "ForkAgentVersionRequest", "GrepMatch", "GrepResult", "LedgerEntry", "ResumeSessionResponse", + "RollbackAgentVersionRequest", "Session", "SessionFile", + "SetDefaultAgentVersionRequest", "SubmitToolResultsResponse", "ToolDefinition", "Message", diff --git a/python/everruns_sdk/_generated/models.py b/python/everruns_sdk/_generated/models.py index 3737f1f..7dbae98 100644 --- a/python/everruns_sdk/_generated/models.py +++ b/python/everruns_sdk/_generated/models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: openapi.json -# timestamp: 2026-05-07T03:15:38+00:00 +# timestamp: 2026-05-08T05:21:25+00:00 from __future__ import annotations @@ -49,6 +49,16 @@ class AgentStatus(Enum): deleted = 'deleted' +class AgentVersionChangeKind(Enum): + manual = 'manual' + patch = 'patch' + minor = 'minor' + major = 'major' + import_ = 'import' + rollback = 'rollback' + fork = 'fork' + + class BudgetEventData(BaseModel): balance: float = Field(..., description='Current remaining balance.') budget_id: str = Field(..., description='Budget that triggered this event.') @@ -206,6 +216,11 @@ class CostTier(BaseModel): ) +class CreateAgentVersionRequest(BaseModel): + change_kind: Optional[AgentVersionChangeKind] = None + summary: Optional[str] = None + + class CreateBranchRequest(BaseModel): commit_oid: str = Field(..., description='Commit OID (hex) to point to') name: str = Field(..., description='Branch name (e.g., "feature-xyz")') @@ -217,6 +232,13 @@ class CreateDatabaseRequest(BaseModel): ) +class CreateDeclarativeCapabilityRequest(BaseModel): + definition: Dict[str, Any] = Field( + ..., + description='Definition for the new declarative capability. `name` must be unique per org and becomes the canonical `declarative:` capability ref.', + ) + + class CreateFileRequest(BaseModel): content: Optional[str] = Field( None, description='File content (text or base64-encoded)' @@ -279,6 +301,30 @@ class CreateOrganizationRequest(BaseModel): ) +class CreatePaymentAccountRequest(BaseModel): + label: str + metadata: Optional[Any] = None + owner_id: str + owner_type: str + private_key: Optional[str] = None + public_address: Optional[str] = None + rail: str + + +class CreatePaymentPolicyRequest(BaseModel): + allowed_capabilities: Optional[List[str]] = None + allowed_hosts: Optional[List[str]] = None + max_amount_usd_per_day: Optional[float] = None + max_amount_usd_per_request: Optional[float] = None + max_amount_usd_per_turn: Optional[float] = None + metadata: Optional[Any] = None + payment_account_id: str + rail_preference: Optional[List[str]] = None + require_approval_above_usd: Optional[float] = None + subject_id: str + subject_type: str + + class CreateSkillRequest(BaseModel): skill_md: str = Field( ..., @@ -300,6 +346,47 @@ class DatabaseInfoResponse(BaseModel): updated_at: str +class DeclarativeCapability(BaseModel): + archived_at: Optional[datetime] = None + capability_id: str = Field( + ..., + description='Runtime capability reference. Agents and harnesses may use this or the plain unique name.', + example='declarative:research_pack', + ) + created_at: datetime + definition: Dict[str, Any] = Field( + ..., + description='Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata.', + ) + deleted_at: Optional[datetime] = None + description: str = Field( + ..., + description='Short summary shown in pickers, search results, and API listings.', + example='Adds research instructions, starter files, and MCP tools.', + ) + display_name: Optional[str] = Field( + None, + description='Human-facing label shown in the UI. Defaults to `name` when omitted.', + example='Research Pack', + ) + id: str = Field( + ..., + description='Public resource ID for this persisted declarative capability.', + example='cap_01933b5a000070008000000000000001', + ) + name: str = Field( + ..., + description='Stable unique name used in capability refs. Lowercase letters, numbers, and underscores.', + example='research_pack', + ) + status: str = Field( + ..., + description='Lifecycle state for the resource: active, disabled, archived, or deleted.', + example='active', + ) + updated_at: datetime + + class DeferrablePolicy(Enum): never = 'never' automatic = 'automatic' @@ -355,6 +442,31 @@ class EventContext(BaseModel): ) +class EventTypeCountOut(BaseModel): + count: int + event_type: str + + +class EventsSummaryResult(BaseModel): + by_type: List[EventTypeCountOut] = Field( + ..., description='Per-type count, sorted by event_type asc.' + ) + error_count: int = Field( + ..., + description='Convenience: count of failure-shaped event types\n(`turn.failed`, `tool.failed`, `*.error`, `subagent.failed`).', + ) + first_ts: Optional[datetime] = Field( + None, description='Earliest event timestamp, if any.' + ) + last_ts: Optional[datetime] = Field( + None, description='Latest event timestamp, if any.' + ) + total: int = Field(..., description='Total event count across all types.') + turn_count: int = Field( + ..., description='Convenience: count of `turn.started` events.' + ) + + class ExecutionPhase(Enum): Commentary = 'Commentary' FinalAnswer = 'FinalAnswer' @@ -414,6 +526,12 @@ class FileWrittenData(BaseModel): size_bytes: int = Field(..., description='File size in bytes after write.') +class ForkAgentVersionRequest(BaseModel): + description: Optional[str] = None + display_name: Optional[str] = None + name: str + + class GetOrCreateChatSessionRequest(BaseModel): locale: Optional[str] = Field( None, @@ -808,6 +926,58 @@ class ListResponseVolumeResponse(BaseModel): ) +class Datum18(BaseModel): + archived_at: Optional[datetime] = None + capability_id: str = Field( + ..., + description='Runtime capability reference. Agents and harnesses may use this or the plain unique name.', + example='declarative:research_pack', + ) + created_at: datetime + definition: Dict[str, Any] = Field( + ..., + description='Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata.', + ) + deleted_at: Optional[datetime] = None + description: str = Field( + ..., + description='Short summary shown in pickers, search results, and API listings.', + example='Adds research instructions, starter files, and MCP tools.', + ) + display_name: Optional[str] = Field( + None, + description='Human-facing label shown in the UI. Defaults to `name` when omitted.', + example='Research Pack', + ) + id: str = Field( + ..., + description='Public resource ID for this persisted declarative capability.', + example='cap_01933b5a000070008000000000000001', + ) + name: str = Field( + ..., + description='Stable unique name used in capability refs. Lowercase letters, numbers, and underscores.', + example='research_pack', + ) + status: str = Field( + ..., + description='Lifecycle state for the resource: active, disabled, archived, or deleted.', + example='active', + ) + updated_at: datetime + self_url: str = Field(..., description='Full API endpoint URL for this resource.') + ui_link: str = Field( + ..., description='Alias for `view_url`, used by command and MCP outputs.' + ) + view_url: str = Field(..., description='Full UI URL for viewing this resource.') + + +class ListResponseWithUrlsDeclarativeCapability(BaseModel): + data: List[Datum18] = Field( + ..., description='Array of items returned by the list operation.' + ) + + class ListSchedulesQuery(BaseModel): enabled: Optional[bool] = Field(None, description='Filter by enabled status') limit: Optional[conint(ge=0)] = Field( @@ -1062,6 +1232,26 @@ class OutputMessageStartedData(BaseModel): ) +class PaymentOwnerType(Enum): + user = 'user' + agent_identity = 'agent_identity' + organization = 'organization' + + +class PaymentRail(Enum): + mpp_tempo = 'mpp_tempo' + x402_base = 'x402_base' + + +class PaymentStatus(Enum): + active = 'active' + disabled = 'disabled' + pending = 'pending' + succeeded = 'succeeded' + failed = 'failed' + released = 'released' + + class PrincipalKind(Enum): user = 'user' agent_identity = 'agent_identity' @@ -1163,6 +1353,11 @@ class RiskLevel(Enum): high = 'high' +class RollbackAgentVersionRequest(BaseModel): + save_version: Optional[bool] = None + summary: Optional[str] = None + + class ScheduleExecutionResponse(BaseModel): completed_at: Optional[datetime] = None created_at: datetime @@ -1600,11 +1795,15 @@ class TurnStartedData(BaseModel): ) -class TypedId(BaseModel): - __root__: constr(regex=r'^agent_[0-9a-f]{32}$') = Field( - ..., - description="Prefixed identifier with 'agent' prefix", - example='agent_01933b5a00007000800000000000001', +class UpdateDeclarativeCapabilityRequest(BaseModel): + definition: Optional[Dict[str, Any]] = Field( + None, + description='Replacement declarative definition. Changing `name` updates the canonical capability ref after uniqueness validation.', + ) + status: Optional[str] = Field( + None, + description='Optional lifecycle state update. Use `disabled` to hide from runtime selection without archiving.', + example='disabled', ) @@ -1726,6 +1925,26 @@ class UpdateOrganizationRequest(BaseModel): ) +class UpdatePaymentAccountRequest(BaseModel): + label: Optional[str] = None + metadata: Optional[Any] = None + private_key: Optional[str] = None + public_address: Optional[str] = None + status: Optional[str] = None + + +class UpdatePaymentPolicyRequest(BaseModel): + allowed_capabilities: Optional[List[str]] = None + allowed_hosts: Optional[List[str]] = None + max_amount_usd_per_day: Optional[float] = None + max_amount_usd_per_request: Optional[float] = None + max_amount_usd_per_turn: Optional[float] = None + metadata: Optional[Any] = None + rail_preference: Optional[List[str]] = None + require_approval_above_usd: Optional[float] = None + status: Optional[str] = None + + class UpdateScheduleRequest(BaseModel): catch_up_missed: Optional[bool] = Field( None, description='Catch up missed triggers' @@ -1791,6 +2010,92 @@ class ValidateSkillRequest(BaseModel): skill_md: str = Field(..., description='SKILL.md content to validate') +class VoiceAttachResponse(BaseModel): + expires_at: datetime + model: str + provider: str + provider_call_id: str + reasoning_effort: str + voice: str + voice_connection_id: str + + +class VoiceCallResponse(BaseModel): + answer_sdp: str + expires_at: datetime + model: str + provider: str + provider_call_id: Optional[str] = None + reasoning_effort: str + voice: str + voice_connection_id: str + + +class VoiceClientSecretResponse(BaseModel): + client_secret: Any + expires_at: datetime + model: str + provider: str + reasoning_effort: str + voice: str + voice_connection_id: str + + +class VoiceEndRequest(BaseModel): + reason: Optional[str] = None + + +class VoiceEndResponse(BaseModel): + status: str + voice_connection_id: str + + +class VoiceSessionEndedData(BaseModel): + duration_ms: Optional[conint(ge=0)] = None + reason: Optional[str] = None + voice_connection_id: str + + +class VoiceSessionFailedData(BaseModel): + error: str + voice_connection_id: str + + +class VoiceSessionOptions(BaseModel): + instructions: Optional[str] = None + model: Optional[str] = None + reasoning_effort: Optional[str] = None + voice: Optional[str] = None + + +class Voice(BaseModel): + answer_sdp: str + expires_at: datetime + model: str + provider: str + provider_call_id: Optional[str] = None + reasoning_effort: str + voice: str + voice_connection_id: str + + +class VoiceSessionStartedData(BaseModel): + model: str + reasoning_effort: str + transport: str + voice: str + voice_connection_id: str + + +class VoiceTranscriptData(BaseModel): + accumulated: str + delta: Optional[str] = None + item_id: Optional[str] = None + phase: Optional[str] = None + response_id: Optional[str] = None + voice_connection_id: str + + class VolumeResponse(BaseModel): archived_at: Optional[datetime] = None created_at: datetime @@ -1867,6 +2172,52 @@ class WithUrlsCapabilityInfo(BaseModel): view_url: str = Field(..., description='Full UI URL for viewing this resource.') +class WithUrlsDeclarativeCapability(BaseModel): + archived_at: Optional[datetime] = None + capability_id: str = Field( + ..., + description='Runtime capability reference. Agents and harnesses may use this or the plain unique name.', + example='declarative:research_pack', + ) + created_at: datetime + definition: Dict[str, Any] = Field( + ..., + description='Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata.', + ) + deleted_at: Optional[datetime] = None + description: str = Field( + ..., + description='Short summary shown in pickers, search results, and API listings.', + example='Adds research instructions, starter files, and MCP tools.', + ) + display_name: Optional[str] = Field( + None, + description='Human-facing label shown in the UI. Defaults to `name` when omitted.', + example='Research Pack', + ) + id: str = Field( + ..., + description='Public resource ID for this persisted declarative capability.', + example='cap_01933b5a000070008000000000000001', + ) + name: str = Field( + ..., + description='Stable unique name used in capability refs. Lowercase letters, numbers, and underscores.', + example='research_pack', + ) + status: str = Field( + ..., + description='Lifecycle state for the resource: active, disabled, archived, or deleted.', + example='active', + ) + updated_at: datetime + self_url: str = Field(..., description='Full API endpoint URL for this resource.') + ui_link: str = Field( + ..., description='Alias for `view_url`, used by command and MCP outputs.' + ) + view_url: str = Field(..., description='Full UI URL for viewing this resource.') + + class WithUrlsLlmModel(BaseModel): capabilities: List[str] created_at: datetime @@ -1998,6 +2349,62 @@ class WithUrlsSkill(BaseModel): view_url: str = Field(..., description='Full UI URL for viewing this resource.') +class AgentId(BaseModel): + __root__: constr(regex=r'^agent_[0-9a-f]{32}$') = Field( + ..., + description="Prefixed identifier with 'agent' prefix", + example='agent_01933b5a00007000800000000000001', + ) + + +class AgentverId(BaseModel): + __root__: constr(regex=r'^agentver_[0-9a-f]{32}$') = Field( + ..., + description="Prefixed identifier with 'agentver' prefix", + example='agentver_01933b5a00007000800000000000001', + ) + + +class EventId(BaseModel): + __root__: constr(regex=r'^event_[0-9a-f]{32}$') = Field( + ..., + description="Prefixed identifier with 'event' prefix", + example='event_01933b5a00007000800000000000001', + ) + + +class HarnessId(BaseModel): + __root__: constr(regex=r'^harness_[0-9a-f]{32}$') = Field( + ..., + description="Prefixed identifier with 'harness' prefix", + example='harness_01933b5a00007000800000000000001', + ) + + +class PayacctId(BaseModel): + __root__: constr(regex=r'^payacct_[0-9a-f]{32}$') = Field( + ..., + description="Prefixed identifier with 'payacct' prefix", + example='payacct_01933b5a00007000800000000000001', + ) + + +class PayattId(BaseModel): + __root__: constr(regex=r'^payatt_[0-9a-f]{32}$') = Field( + ..., + description="Prefixed identifier with 'payatt' prefix", + example='payatt_01933b5a00007000800000000000001', + ) + + +class PaypolId(BaseModel): + __root__: constr(regex=r'^paypol_[0-9a-f]{32}$') = Field( + ..., + description="Prefixed identifier with 'paypol' prefix", + example='paypol_01933b5a00007000800000000000001', + ) + + class ActStartedData(BaseModel): headline: Optional[str] = Field( None, description='Human-readable headline for the batch' @@ -2007,6 +2414,32 @@ class ActStartedData(BaseModel): ) +class AgentVersion(BaseModel): + agent_id: str = Field(..., example='agent_01933b5a000070008000000000000001') + authored_config: Dict[str, Any] + change_kind: AgentVersionChangeKind + config_hash: str + created_at: datetime + created_by_principal_id: Optional[str] = None + id: str = Field(..., example='agentver_01933b5a000070008000000000000001') + parent_version_id: Optional[str] = None + resolved_config: Dict[str, Any] + semver_major: int + semver_minor: int + semver_patch: int + source_version_id: Optional[str] = None + summary: Optional[str] = None + version: str + version_number: int + + +class AgentVersionDiffResponse(BaseModel): + authored_diff: Any + from_version_id: AgentverId + resolved_diff: Any + to_version_id: AgentverId + + class BTreeMap1(BaseModel): auth_mode: Optional[McpServerAuthMode] = Field( None, @@ -2721,7 +3154,7 @@ class ListResponseSkill(BaseModel): ) -class Datum18(BaseModel): +class Datum19(BaseModel): capabilities: List[str] created_at: datetime display_name: str @@ -2745,12 +3178,12 @@ class Datum18(BaseModel): class ListResponseWithUrlsLlmModel(BaseModel): - data: List[Datum18] = Field( + data: List[Datum19] = Field( ..., description='Array of items returned by the list operation.' ) -class Datum20(BaseModel): +class Datum21(BaseModel): api_key_set: bool = Field( ..., description='Whether an API key is configured (key is never returned)' ) @@ -2772,12 +3205,12 @@ class Datum20(BaseModel): class ListResponseWithUrlsLlmProvider(BaseModel): - data: List[Datum20] = Field( + data: List[Datum21] = Field( ..., description='Array of items returned by the list operation.' ) -class Datum21(BaseModel): +class Datum22(BaseModel): api_key_set: bool = Field( ..., description='Whether an API key has been configured.' ) @@ -2837,12 +3270,12 @@ class Datum21(BaseModel): class ListResponseWithUrlsMcpServer(BaseModel): - data: List[Datum21] = Field( + data: List[Datum22] = Field( ..., description='Array of items returned by the list operation.' ) -class Datum22(BaseModel): +class Datum23(BaseModel): archived_at: Optional[datetime] = Field( None, description='Timestamp when the harness was archived.' ) @@ -2917,12 +3350,12 @@ class Datum22(BaseModel): class ListResponseWithUrlsResourceWithCountsHarness(BaseModel): - data: List[Datum22] = Field( + data: List[Datum23] = Field( ..., description='Array of items returned by the list operation.' ) -class Datum23(BaseModel): +class Datum24(BaseModel): allowed_tools: Optional[str] = None archived_at: Optional[datetime] = None compatibility: Optional[str] = None @@ -2951,7 +3384,7 @@ class Datum23(BaseModel): class ListResponseWithUrlsSkill(BaseModel): - data: List[Datum23] = Field( + data: List[Datum24] = Field( ..., description='Array of items returned by the list operation.' ) @@ -3136,7 +3569,7 @@ class OutputMessageCompletedData(BaseModel): usage: Optional[TokenUsage] = None -class Datum25(BaseModel): +class Datum26(BaseModel): agent_count: Optional[conint(ge=0)] = Field( None, description='Number of active agents referencing this capability in the org.', @@ -3196,7 +3629,7 @@ class Datum25(BaseModel): class PaginatedResponseWithUrlsCapabilityInfo(BaseModel): - data: List[Datum25] = Field( + data: List[Datum26] = Field( ..., description='Array of items returned by the list operation.' ) limit: conint(ge=0) = Field(..., description='Maximum number of items per page.') @@ -3206,6 +3639,58 @@ class PaginatedResponseWithUrlsCapabilityInfo(BaseModel): ) +class PaymentAccount(BaseModel): + created_at: datetime + id: PayacctId + label: str + metadata: Any + organization_id: str + owner_id: str + owner_type: PaymentOwnerType + public_address: Optional[str] = None + rail: PaymentRail + status: PaymentStatus + updated_at: datetime + + +class PaymentAttempt(BaseModel): + amount_usd: float + capability: str + created_at: datetime + currency: str + error_message: Optional[str] = None + id: PayattId + operation: str + organization_id: str + payment_account_id: Optional[PayacctId] = None + rail: Optional[PaymentRail] = None + receipt: Any + request_hash: Optional[str] = None + session_id: Optional[str] = None + status: PaymentStatus + target_url: str + updated_at: datetime + + +class PaymentPolicy(BaseModel): + allowed_capabilities: List[str] + allowed_hosts: List[str] + created_at: datetime + id: PaypolId + max_amount_usd_per_day: Optional[float] = None + max_amount_usd_per_request: Optional[float] = None + max_amount_usd_per_turn: Optional[float] = None + metadata: Any + organization_id: str + payment_account_id: PayacctId + rail_preference: List[PaymentRail] + require_approval_above_usd: Optional[float] = None + status: PaymentStatus + subject_id: str + subject_type: str + updated_at: datetime + + class PreviewAgentRequest(BaseModel): capabilities: Optional[List[AgentCapabilityConfig]] = Field( None, @@ -3254,8 +3739,8 @@ class ReasonCompletedData(BaseModel): class ReasonStartedData(BaseModel): - agent_id: Optional[TypedId] = None - harness_id: TypedId = Field(..., description='Harness ID being used') + agent_id: Optional[AgentId] = None + harness_id: HarnessId = Field(..., description='Harness ID being used') metadata: Optional[ModelMetadata] = None @@ -3330,6 +3815,10 @@ class SessionResourceEntry(BaseModel): updated_at: datetime +class SetDefaultAgentVersionRequest(BaseModel): + version_id: AgentverId + + class Skill(BaseModel): allowed_tools: Optional[str] = None archived_at: Optional[datetime] = None @@ -3482,6 +3971,18 @@ class UpdateHarnessRequest(BaseModel): tags: Optional[List[str]] = None +class VoiceAttachRequest(VoiceSessionOptions): + provider_call_id: str + + +class VoiceCallRequest(VoiceSessionOptions): + sdp: str + + +class VoiceClientSecretRequest(VoiceSessionOptions): + pass + + class WithUrlsAgent(BaseModel): archived_at: Optional[datetime] = Field( None, description='Timestamp when the agent was archived.' @@ -3498,6 +3999,11 @@ class WithUrlsAgent(BaseModel): description='Default LLM model ID for this agent.\nCan be overridden at the session level.', example='model_01933b5a00007000800000000000001', ) + default_version_id: Optional[str] = Field( + None, + description='Default immutable version used by deployments that choose the default policy.', + example='agentver_01933b5a00007000800000000000001', + ) deleted_at: Optional[datetime] = Field( None, description='Timestamp when the agent was deleted.' ) @@ -3508,6 +4014,16 @@ class WithUrlsAgent(BaseModel): None, description='Human-readable display name shown in UI (e.g. "Customer Support Agent").\nFalls back to `name` when absent.', ) + forked_from_agent_id: Optional[str] = Field( + None, + description='Source agent for a forked agent.', + example='agent_01933b5a00007000800000000000001', + ) + forked_from_version_id: Optional[str] = Field( + None, + description='Source version for a forked agent.', + example='agentver_01933b5a00007000800000000000001', + ) id: str = Field( ..., description='External identifier (agent_<32-hex>). Shown as "id" in API.\nClient-supplied or auto-generated.', @@ -3527,6 +4043,11 @@ class WithUrlsAgent(BaseModel): ..., description='Name, unique per org (e.g. "customer-support").' ) network_access: Optional[NetworkAccessList] = None + root_agent_id: Optional[str] = Field( + None, + description='Root agent lineage identifier for grouping fork families.', + example='agent_01933b5a00007000800000000000001', + ) status: AgentStatus = Field( ..., description='Current lifecycle status of the agent.' ) @@ -3636,6 +4157,11 @@ class WithUrlsResourceWithCountsAgent(BaseModel): description='Default LLM model ID for this agent.\nCan be overridden at the session level.', example='model_01933b5a00007000800000000000001', ) + default_version_id: Optional[str] = Field( + None, + description='Default immutable version used by deployments that choose the default policy.', + example='agentver_01933b5a00007000800000000000001', + ) deleted_at: Optional[datetime] = Field( None, description='Timestamp when the agent was deleted.' ) @@ -3646,6 +4172,16 @@ class WithUrlsResourceWithCountsAgent(BaseModel): None, description='Human-readable display name shown in UI (e.g. "Customer Support Agent").\nFalls back to `name` when absent.', ) + forked_from_agent_id: Optional[str] = Field( + None, + description='Source agent for a forked agent.', + example='agent_01933b5a00007000800000000000001', + ) + forked_from_version_id: Optional[str] = Field( + None, + description='Source version for a forked agent.', + example='agentver_01933b5a00007000800000000000001', + ) id: str = Field( ..., description='External identifier (agent_<32-hex>). Shown as "id" in API.\nClient-supplied or auto-generated.', @@ -3665,6 +4201,11 @@ class WithUrlsResourceWithCountsAgent(BaseModel): ..., description='Name, unique per org (e.g. "customer-support").' ) network_access: Optional[NetworkAccessList] = None + root_agent_id: Optional[str] = Field( + None, + description='Root agent lineage identifier for grouping fork families.', + example='agent_01933b5a00007000800000000000001', + ) status: AgentStatus = Field( ..., description='Current lifecycle status of the agent.' ) @@ -3785,6 +4326,11 @@ class WithUrlsSession(BaseModel): description='Optional resident agent identity for unattended/background execution.', example='identity_01933b5a00007000800000000000001', ) + agent_version_id: Optional[str] = Field( + None, + description='Immutable agent version captured when the session was created or rebound.', + example='agentver_01933b5a00007000800000000000001', + ) blueprint_config: Optional[Any] = Field( None, description='Validated config passed by host at blueprint spawn time.' ) @@ -3925,6 +4471,11 @@ class Agent(BaseModel): description='Default LLM model ID for this agent.\nCan be overridden at the session level.', example='model_01933b5a00007000800000000000001', ) + default_version_id: Optional[str] = Field( + None, + description='Default immutable version used by deployments that choose the default policy.', + example='agentver_01933b5a00007000800000000000001', + ) deleted_at: Optional[datetime] = Field( None, description='Timestamp when the agent was deleted.' ) @@ -3935,6 +4486,16 @@ class Agent(BaseModel): None, description='Human-readable display name shown in UI (e.g. "Customer Support Agent").\nFalls back to `name` when absent.', ) + forked_from_agent_id: Optional[str] = Field( + None, + description='Source agent for a forked agent.', + example='agent_01933b5a00007000800000000000001', + ) + forked_from_version_id: Optional[str] = Field( + None, + description='Source version for a forked agent.', + example='agentver_01933b5a00007000800000000000001', + ) id: str = Field( ..., description='External identifier (agent_<32-hex>). Shown as "id" in API.\nClient-supplied or auto-generated.', @@ -3954,6 +4515,11 @@ class Agent(BaseModel): ..., description='Name, unique per org (e.g. "customer-support").' ) network_access: Optional[NetworkAccessList] = None + root_agent_id: Optional[str] = Field( + None, + description='Root agent lineage identifier for grouping fork families.', + example='agent_01933b5a00007000800000000000001', + ) status: AgentStatus = Field( ..., description='Current lifecycle status of the agent.' ) @@ -4132,6 +4698,11 @@ class Datum(BaseModel): description='Default LLM model ID for this agent.\nCan be overridden at the session level.', example='model_01933b5a00007000800000000000001', ) + default_version_id: Optional[str] = Field( + None, + description='Default immutable version used by deployments that choose the default policy.', + example='agentver_01933b5a00007000800000000000001', + ) deleted_at: Optional[datetime] = Field( None, description='Timestamp when the agent was deleted.' ) @@ -4142,6 +4713,16 @@ class Datum(BaseModel): None, description='Human-readable display name shown in UI (e.g. "Customer Support Agent").\nFalls back to `name` when absent.', ) + forked_from_agent_id: Optional[str] = Field( + None, + description='Source agent for a forked agent.', + example='agent_01933b5a00007000800000000000001', + ) + forked_from_version_id: Optional[str] = Field( + None, + description='Source version for a forked agent.', + example='agentver_01933b5a00007000800000000000001', + ) id: str = Field( ..., description='External identifier (agent_<32-hex>). Shown as "id" in API.\nClient-supplied or auto-generated.', @@ -4161,6 +4742,11 @@ class Datum(BaseModel): ..., description='Name, unique per org (e.g. "customer-support").' ) network_access: Optional[NetworkAccessList] = None + root_agent_id: Optional[str] = Field( + None, + description='Root agent lineage identifier for grouping fork families.', + example='agent_01933b5a00007000800000000000001', + ) status: AgentStatus = Field( ..., description='Current lifecycle status of the agent.' ) @@ -4286,7 +4872,7 @@ class LlmModelWithProvider(BaseModel): updated_at: datetime -class Datum24(BaseModel): +class Datum25(BaseModel): active_schedule_count: Optional[conint(ge=0)] = Field( None, description='Number of active (enabled) schedules for this session.\nPopulated when the session is fetched for API responses.', @@ -4301,6 +4887,11 @@ class Datum24(BaseModel): description='Optional resident agent identity for unattended/background execution.', example='identity_01933b5a00007000800000000000001', ) + agent_version_id: Optional[str] = Field( + None, + description='Immutable agent version captured when the session was created or rebound.', + example='agentver_01933b5a00007000800000000000001', + ) blueprint_config: Optional[Any] = Field( None, description='Validated config passed by host at blueprint spawn time.' ) @@ -4421,7 +5012,7 @@ class Datum24(BaseModel): class PaginatedResponseSession(BaseModel): - data: List[Datum24] = Field( + data: List[Datum25] = Field( ..., description='Array of items returned by the list operation.' ) limit: conint(ge=0) = Field(..., description='Maximum number of items per page.') @@ -4431,7 +5022,7 @@ class PaginatedResponseSession(BaseModel): ) -class Datum26(BaseModel): +class Datum27(BaseModel): archived_at: Optional[datetime] = Field( None, description='Timestamp when the agent was archived.' ) @@ -4447,6 +5038,11 @@ class Datum26(BaseModel): description='Default LLM model ID for this agent.\nCan be overridden at the session level.', example='model_01933b5a00007000800000000000001', ) + default_version_id: Optional[str] = Field( + None, + description='Default immutable version used by deployments that choose the default policy.', + example='agentver_01933b5a00007000800000000000001', + ) deleted_at: Optional[datetime] = Field( None, description='Timestamp when the agent was deleted.' ) @@ -4457,6 +5053,16 @@ class Datum26(BaseModel): None, description='Human-readable display name shown in UI (e.g. "Customer Support Agent").\nFalls back to `name` when absent.', ) + forked_from_agent_id: Optional[str] = Field( + None, + description='Source agent for a forked agent.', + example='agent_01933b5a00007000800000000000001', + ) + forked_from_version_id: Optional[str] = Field( + None, + description='Source version for a forked agent.', + example='agentver_01933b5a00007000800000000000001', + ) id: str = Field( ..., description='External identifier (agent_<32-hex>). Shown as "id" in API.\nClient-supplied or auto-generated.', @@ -4476,6 +5082,11 @@ class Datum26(BaseModel): ..., description='Name, unique per org (e.g. "customer-support").' ) network_access: Optional[NetworkAccessList] = None + root_agent_id: Optional[str] = Field( + None, + description='Root agent lineage identifier for grouping fork families.', + example='agent_01933b5a00007000800000000000001', + ) status: AgentStatus = Field( ..., description='Current lifecycle status of the agent.' ) @@ -4508,7 +5119,7 @@ class Datum26(BaseModel): class PaginatedResponseWithUrlsResourceWithCountsAgent(BaseModel): - data: List[Datum26] = Field( + data: List[Datum27] = Field( ..., description='Array of items returned by the list operation.' ) limit: conint(ge=0) = Field(..., description='Maximum number of items per page.') @@ -4518,7 +5129,7 @@ class PaginatedResponseWithUrlsResourceWithCountsAgent(BaseModel): ) -class Datum27(BaseModel): +class Datum28(BaseModel): active_schedule_count: Optional[conint(ge=0)] = Field( None, description='Number of active (enabled) schedules for this session.\nPopulated when the session is fetched for API responses.', @@ -4533,6 +5144,11 @@ class Datum27(BaseModel): description='Optional resident agent identity for unattended/background execution.', example='identity_01933b5a00007000800000000000001', ) + agent_version_id: Optional[str] = Field( + None, + description='Immutable agent version captured when the session was created or rebound.', + example='agentver_01933b5a00007000800000000000001', + ) blueprint_config: Optional[Any] = Field( None, description='Validated config passed by host at blueprint spawn time.' ) @@ -4658,7 +5274,7 @@ class Datum27(BaseModel): class PaginatedResponseWithUrlsSession(BaseModel): - data: List[Datum27] = Field( + data: List[Datum28] = Field( ..., description='Array of items returned by the list operation.' ) limit: conint(ge=0) = Field(..., description='Maximum number of items per page.') @@ -4683,6 +5299,11 @@ class Session(BaseModel): description='Optional resident agent identity for unattended/background execution.', example='identity_01933b5a00007000800000000000001', ) + agent_version_id: Optional[str] = Field( + None, + description='Immutable agent version captured when the session was created or rebound.', + example='agentver_01933b5a00007000800000000000001', + ) blueprint_config: Optional[Any] = Field( None, description='Validated config passed by host at blueprint spawn time.' ) @@ -4802,6 +5423,11 @@ class Session(BaseModel): usage: Optional[TokenUsage] = None +class VoiceSessionResponseVoiceCallResponse(BaseModel): + session: Session + voice: Voice + + class WithUrlsLlmModelWithProvider(BaseModel): capabilities: List[str] created_at: datetime @@ -4831,7 +5457,7 @@ class WithUrlsLlmModelWithProvider(BaseModel): view_url: str = Field(..., description='Full UI URL for viewing this resource.') -class Datum19(BaseModel): +class Datum20(BaseModel): capabilities: List[str] created_at: datetime display_name: str @@ -4861,7 +5487,7 @@ class Datum19(BaseModel): class ListResponseWithUrlsLlmModelWithProvider(BaseModel): - data: List[Datum19] = Field( + data: List[Datum20] = Field( ..., description='Array of items returned by the list operation.' ) @@ -4911,6 +5537,10 @@ class EventData(BaseModel): ContextCompactedData, FileWrittenData, BudgetEventData, + VoiceSessionStartedData, + VoiceTranscriptData, + VoiceSessionEndedData, + VoiceSessionFailedData, ] = Field( ..., description='Event-specific payload. The schema depends on the event type field.', diff --git a/python/everruns_sdk/client.py b/python/everruns_sdk/client.py index 31deb19..8c8957c 100644 --- a/python/everruns_sdk/client.py +++ b/python/everruns_sdk/client.py @@ -14,6 +14,9 @@ from everruns_sdk.models import ( Agent, AgentCapabilityConfig, + AgentVersion, + AgentVersionChangeKind, + AgentVersionDiffResponse, Budget, BudgetCheckResult, CapabilityInfo, @@ -22,12 +25,14 @@ ContentPart, Controls, CreateAgentRequest, + CreateAgentVersionRequest, CreateMessageRequest, CreateSessionRequest, DeleteFileResponse, Event, FileInfo, FileStat, + ForkAgentVersionRequest, GrepResult, InitialFile, LedgerEntry, @@ -36,8 +41,10 @@ MessageInput, ResourceStats, ResumeSessionResponse, + RollbackAgentVersionRequest, Session, SessionFile, + SetDefaultAgentVersionRequest, SubmitToolResultsRequest, SubmitToolResultsResponse, ToolDefinition, @@ -286,6 +293,85 @@ async def stats(self, agent_id: str) -> ResourceStats: resp = await self._client._get(f"/agents/{agent_id}/stats") return ResourceStats(**resp) + async def list_versions(self, agent_id: str) -> list[AgentVersion]: + """List saved versions for an agent.""" + resp = await self._client._get(f"/agents/{agent_id}/versions") + return [AgentVersion(**version) for version in resp] + + async def create_version( + self, + agent_id: str, + *, + change_kind: Optional[AgentVersionChangeKind] = None, + summary: Optional[str] = None, + ) -> AgentVersion: + """Save the current agent configuration as a version.""" + req = CreateAgentVersionRequest(change_kind=change_kind, summary=summary) + resp = await self._client._post( + f"/agents/{agent_id}/versions", + req.model_dump(exclude_none=True), + ) + return AgentVersion(**resp) + + async def set_default_version(self, agent_id: str, version_id: str) -> Agent: + """Set the default version for an agent.""" + req = SetDefaultAgentVersionRequest(version_id=version_id) + resp = await self._client._post( + f"/agents/{agent_id}/versions/default", + req.model_dump(exclude_none=True), + ) + return Agent(**resp) + + async def diff_versions( + self, + agent_id: str, + from_version_id: str, + to_version_id: str, + ) -> AgentVersionDiffResponse: + """Diff two saved agent versions.""" + resp = await self._client._get( + f"/agents/{agent_id}/versions/{from_version_id}/diff/{to_version_id}" + ) + return AgentVersionDiffResponse(**resp) + + async def fork_version( + self, + agent_id: str, + version_id: str, + *, + name: str, + display_name: Optional[str] = None, + description: Optional[str] = None, + ) -> Agent: + """Create a new agent from a saved version.""" + validate_agent_name(name) + req = ForkAgentVersionRequest( + name=name, + display_name=display_name, + description=description, + ) + resp = await self._client._post( + f"/agents/{agent_id}/versions/{version_id}/fork", + req.model_dump(exclude_none=True), + ) + return Agent(**resp) + + async def rollback_version( + self, + agent_id: str, + version_id: str, + *, + save_version: Optional[bool] = None, + summary: Optional[str] = None, + ) -> Agent: + """Restore an agent from a saved version.""" + req = RollbackAgentVersionRequest(save_version=save_version, summary=summary) + resp = await self._client._post( + f"/agents/{agent_id}/versions/{version_id}/rollback", + req.model_dump(exclude_none=True), + ) + return Agent(**resp) + async def create( self, name: str, diff --git a/python/everruns_sdk/models.py b/python/everruns_sdk/models.py index e08323d..9b5a2c2 100644 --- a/python/everruns_sdk/models.py +++ b/python/everruns_sdk/models.py @@ -120,6 +120,67 @@ class Agent(BaseModel): updated_at: str +AgentVersionChangeKind = Literal["manual", "patch", "minor", "major", "import", "rollback", "fork"] + + +class AgentVersion(BaseModel): + """Immutable snapshot of an agent configuration.""" + + id: str + agent_id: str + version_number: int + semver_major: int + semver_minor: int + semver_patch: int + version: str + change_kind: AgentVersionChangeKind + config_hash: str + authored_config: dict[str, Any] + resolved_config: dict[str, Any] + created_at: str + created_by_principal_id: Optional[str] = None + parent_version_id: Optional[str] = None + source_version_id: Optional[str] = None + summary: Optional[str] = None + + +class AgentVersionDiffResponse(BaseModel): + """Diff between two saved agent versions.""" + + from_version_id: str + to_version_id: str + authored_diff: Any + resolved_diff: Any + + +class CreateAgentVersionRequest(BaseModel): + """Request to save the current agent configuration as a version.""" + + change_kind: Optional[AgentVersionChangeKind] = None + summary: Optional[str] = None + + +class SetDefaultAgentVersionRequest(BaseModel): + """Request to set the default version for an agent.""" + + version_id: str + + +class ForkAgentVersionRequest(BaseModel): + """Request to create a new agent from a saved version.""" + + name: str + display_name: Optional[str] = None + description: Optional[str] = None + + +class RollbackAgentVersionRequest(BaseModel): + """Request to restore an agent from a saved version.""" + + save_version: Optional[bool] = None + summary: Optional[str] = None + + class CreateAgentRequest(BaseModel): """Request to create an agent.""" diff --git a/python/tests/test_client.py b/python/tests/test_client.py index 029ab54..bf61981 100644 --- a/python/tests/test_client.py +++ b/python/tests/test_client.py @@ -942,6 +942,122 @@ async def test_agent_stats(): assert route.called +@pytest.mark.asyncio +@respx.mock +async def test_agent_versions_methods(): + version_json = { + "id": "agentver_123", + "agent_id": "agent_123", + "version_number": 1, + "semver_major": 1, + "semver_minor": 0, + "semver_patch": 0, + "version": "1.0.0", + "change_kind": "manual", + "config_hash": "hash_123", + "authored_config": {"name": "assistant"}, + "resolved_config": {"name": "assistant"}, + "created_at": "2026-05-08T00:00:00Z", + "summary": "Initial version", + } + agent_json = { + "id": "agent_456", + "name": "forked-agent", + "description": "Forked", + "system_prompt": "Help.", + "default_model_id": None, + "tags": [], + "capabilities": [], + "tools": [], + "initial_files": [], + "status": "active", + "created_at": "2026-05-08T00:00:00Z", + "updated_at": "2026-05-08T00:00:00Z", + } + list_route = respx.get("https://custom.example.com/api/v1/agents/agent_123/versions").mock( + return_value=httpx.Response(200, json=[version_json]) + ) + create_route = respx.post("https://custom.example.com/api/v1/agents/agent_123/versions").mock( + return_value=httpx.Response(200, json=version_json) + ) + default_route = respx.post( + "https://custom.example.com/api/v1/agents/agent_123/versions/default" + ).mock(return_value=httpx.Response(200, json=agent_json)) + diff_route = respx.get( + "https://custom.example.com/api/v1/agents/agent_123/versions/agentver_1/diff/agentver_2" + ).mock( + return_value=httpx.Response( + 200, + json={ + "from_version_id": "agentver_1", + "to_version_id": "agentver_2", + "authored_diff": [{"op": "replace", "path": "/name"}], + "resolved_diff": [], + }, + ) + ) + fork_route = respx.post( + "https://custom.example.com/api/v1/agents/agent_123/versions/agentver_1/fork" + ).mock(return_value=httpx.Response(200, json=agent_json)) + rollback_route = respx.post( + "https://custom.example.com/api/v1/agents/agent_123/versions/agentver_1/rollback" + ).mock(return_value=httpx.Response(200, json=agent_json)) + + client = Everruns(api_key="evr_test_key") + try: + versions = await client.agents.list_versions("agent_123") + created = await client.agents.create_version( + "agent_123", + change_kind="manual", + summary="Initial version", + ) + default_agent = await client.agents.set_default_version("agent_123", "agentver_1") + diff = await client.agents.diff_versions("agent_123", "agentver_1", "agentver_2") + forked_agent = await client.agents.fork_version( + "agent_123", + "agentver_1", + name="forked-agent", + display_name="Forked Agent", + description="Forked", + ) + rolled_back_agent = await client.agents.rollback_version( + "agent_123", + "agentver_1", + save_version=True, + summary="Revert", + ) + finally: + await client.close() + + assert versions[0].id == "agentver_123" + assert created.summary == "Initial version" + assert default_agent.id == "agent_456" + assert diff.to_version_id == "agentver_2" + assert forked_agent.name == "forked-agent" + assert rolled_back_agent.name == "forked-agent" + assert ( + create_route.calls.last.request.content + == b'{"change_kind":"manual","summary":"Initial version"}' + ) + assert default_route.calls.last.request.content == b'{"version_id":"agentver_1"}' + assert fork_route.calls.last.request.content == ( + b'{"name":"forked-agent","display_name":"Forked Agent","description":"Forked"}' + ) + assert rollback_route.calls.last.request.content == b'{"save_version":true,"summary":"Revert"}' + assert list_route.called + assert diff_route.called + + +@pytest.mark.asyncio +async def test_fork_agent_version_validates_agent_name(): + client = Everruns(api_key="evr_test_key") + try: + with pytest.raises(ValueError): + await client.agents.fork_version("agent_123", "agentver_1", name="Invalid Name") + finally: + await client.close() + + @pytest.mark.asyncio @respx.mock async def test_capabilities_list_with_options(): diff --git a/rust/README.md b/rust/README.md index f2b797d..c2b97d6 100644 --- a/rust/README.md +++ b/rust/README.md @@ -60,6 +60,28 @@ let session = client Runnable example: [`examples/initial_files.rs`](examples/initial_files.rs) +## Agent Versions + +\`\`\`rust +use everruns_sdk::{AgentVersionChangeKind, CreateAgentVersionRequest}; + +let version = client + .agents() + .create_version( + "agent_...", + CreateAgentVersionRequest::new() + .change_kind(AgentVersionChangeKind::Manual) + .summary("Baseline"), + ) + .await?; + +let versions = client.agents().list_versions("agent_...").await?; +let diff = client + .agents() + .diff_versions("agent_...", "agentver_1", &version.id) + .await?; +\`\`\` + ## Authentication The SDK uses API key authentication. Set the \`EVERRUNS_API_KEY\` environment variable or pass the key explicitly. For API keys with access to multiple organizations, set \`EVERRUNS_ORG_ID\` or pass \`org_id\` explicitly: diff --git a/rust/src/client.rs b/rust/src/client.rs index 1d8feb0..b288d43 100644 --- a/rust/src/client.rs +++ b/rust/src/client.rs @@ -443,6 +443,76 @@ impl<'a> AgentsClient<'a> { self.client.get(&format!("/agents/{}/stats", id)).await } + /// List saved versions for an agent. + pub async fn list_versions(&self, id: &str) -> Result> { + self.client.get(&format!("/agents/{}/versions", id)).await + } + + /// Save the current agent configuration as a version. + pub async fn create_version( + &self, + id: &str, + req: CreateAgentVersionRequest, + ) -> Result { + self.client + .post(&format!("/agents/{}/versions", id), &req) + .await + } + + /// Set the default version for an agent. + pub async fn set_default_version(&self, id: &str, version_id: &str) -> Result { + let req = SetDefaultAgentVersionRequest::new(version_id); + self.client + .post(&format!("/agents/{}/versions/default", id), &req) + .await + } + + /// Diff two saved agent versions. + pub async fn diff_versions( + &self, + id: &str, + from_version_id: &str, + to_version_id: &str, + ) -> Result { + self.client + .get(&format!( + "/agents/{}/versions/{}/diff/{}", + id, from_version_id, to_version_id + )) + .await + } + + /// Create a new agent from a saved version. + pub async fn fork_version( + &self, + id: &str, + version_id: &str, + req: ForkAgentVersionRequest, + ) -> Result { + validate_agent_name(&req.name)?; + self.client + .post( + &format!("/agents/{}/versions/{}/fork", id, version_id), + &req, + ) + .await + } + + /// Restore an agent from a saved version. + pub async fn rollback_version( + &self, + id: &str, + version_id: &str, + req: RollbackAgentVersionRequest, + ) -> Result { + self.client + .post( + &format!("/agents/{}/versions/{}/rollback", id, version_id), + &req, + ) + .await + } + /// Create a new agent with a server-assigned ID. /// /// `name` is the addressable slug (e.g. `"customer-support"`), validated diff --git a/rust/src/models.rs b/rust/src/models.rs index 498ccad..3bb3773 100644 --- a/rust/src/models.rs +++ b/rust/src/models.rs @@ -199,6 +199,153 @@ pub enum AgentStatus { Archived, } +/// Reason a saved agent version was created. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum AgentVersionChangeKind { + Manual, + Patch, + Minor, + Major, + Import, + Rollback, + Fork, +} + +/// Immutable snapshot of an agent configuration. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[non_exhaustive] +pub struct AgentVersion { + pub id: String, + pub agent_id: String, + pub version_number: i32, + pub semver_major: i32, + pub semver_minor: i32, + pub semver_patch: i32, + pub version: String, + pub change_kind: AgentVersionChangeKind, + pub config_hash: String, + pub authored_config: serde_json::Value, + pub resolved_config: serde_json::Value, + pub created_at: String, + #[serde(default)] + pub created_by_principal_id: Option, + #[serde(default)] + pub parent_version_id: Option, + #[serde(default)] + pub source_version_id: Option, + #[serde(default)] + pub summary: Option, +} + +/// Diff between two saved agent versions. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[non_exhaustive] +pub struct AgentVersionDiffResponse { + pub from_version_id: String, + pub to_version_id: String, + pub authored_diff: serde_json::Value, + pub resolved_diff: serde_json::Value, +} + +/// Request to save the current agent configuration as a version. +#[derive(Debug, Clone, Default, Serialize)] +#[non_exhaustive] +pub struct CreateAgentVersionRequest { + #[serde(skip_serializing_if = "Option::is_none")] + pub change_kind: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, +} + +impl CreateAgentVersionRequest { + pub fn new() -> Self { + Self::default() + } + + pub fn change_kind(mut self, change_kind: AgentVersionChangeKind) -> Self { + self.change_kind = Some(change_kind); + self + } + + pub fn summary(mut self, summary: impl Into) -> Self { + self.summary = Some(summary.into()); + self + } +} + +/// Request to set the default version for an agent. +#[derive(Debug, Clone, Serialize)] +#[non_exhaustive] +pub struct SetDefaultAgentVersionRequest { + pub version_id: String, +} + +impl SetDefaultAgentVersionRequest { + pub fn new(version_id: impl Into) -> Self { + Self { + version_id: version_id.into(), + } + } +} + +/// Request to create a new agent from a saved version. +#[derive(Debug, Clone, Serialize)] +#[non_exhaustive] +pub struct ForkAgentVersionRequest { + pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub display_name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, +} + +impl ForkAgentVersionRequest { + pub fn new(name: impl Into) -> Self { + Self { + name: name.into(), + display_name: None, + description: None, + } + } + + pub fn display_name(mut self, display_name: impl Into) -> Self { + self.display_name = Some(display_name.into()); + self + } + + pub fn description(mut self, description: impl Into) -> Self { + self.description = Some(description.into()); + self + } +} + +/// Request to restore an agent from a saved version. +#[derive(Debug, Clone, Default, Serialize)] +#[non_exhaustive] +pub struct RollbackAgentVersionRequest { + #[serde(skip_serializing_if = "Option::is_none")] + pub save_version: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, +} + +impl RollbackAgentVersionRequest { + pub fn new() -> Self { + Self::default() + } + + pub fn save_version(mut self, save_version: bool) -> Self { + self.save_version = Some(save_version); + self + } + + pub fn summary(mut self, summary: impl Into) -> Self { + self.summary = Some(summary.into()); + self + } +} + /// Request to create an agent #[derive(Debug, Clone, Serialize)] #[non_exhaustive] diff --git a/rust/tests/client_test.rs b/rust/tests/client_test.rs index ec5806b..fe1ed4c 100644 --- a/rust/tests/client_test.rs +++ b/rust/tests/client_test.rs @@ -1,8 +1,9 @@ //! Integration tests for Everruns SDK use everruns_sdk::{ - ContentPart, CreateAgentRequest, CreateBudgetRequest, CreateSessionRequest, Everruns, - InitialFile, TopUpRequest, UpdateBudgetRequest, + AgentVersionChangeKind, ContentPart, CreateAgentRequest, CreateAgentVersionRequest, + CreateBudgetRequest, CreateSessionRequest, Everruns, ForkAgentVersionRequest, InitialFile, + RollbackAgentVersionRequest, TopUpRequest, UpdateBudgetRequest, }; use std::sync::Mutex; use wiremock::{ @@ -236,6 +237,165 @@ async fn test_create_agent_with_initial_files() { assert_eq!(agent.initial_files.len(), 1); } +#[tokio::test] +async fn test_agent_versions_methods() { + let server = MockServer::start().await; + let client = Everruns::with_base_url("evr_test_key", &server.uri()).expect("client"); + + let version_json = serde_json::json!({ + "id": "agentver_123", + "agent_id": "agent_123", + "version_number": 1, + "semver_major": 1, + "semver_minor": 0, + "semver_patch": 0, + "version": "1.0.0", + "change_kind": "manual", + "config_hash": "hash_123", + "authored_config": {"name": "assistant"}, + "resolved_config": {"name": "assistant"}, + "created_at": "2026-05-08T00:00:00Z", + "summary": "Initial version" + }); + let agent_json = serde_json::json!({ + "id": "agent_456", + "name": "forked-agent", + "description": "Forked", + "system_prompt": "Help.", + "default_model_id": null, + "tags": [], + "capabilities": [], + "initial_files": [], + "status": "active", + "created_at": "2026-05-08T00:00:00Z", + "updated_at": "2026-05-08T00:00:00Z" + }); + + Mock::given(method("GET")) + .and(path("/v1/agents/agent_123/versions")) + .respond_with( + ResponseTemplate::new(200).set_body_json(serde_json::json!([version_json.clone()])), + ) + .mount(&server) + .await; + Mock::given(method("POST")) + .and(path("/v1/agents/agent_123/versions")) + .and(body_json(serde_json::json!({ + "change_kind": "manual", + "summary": "Initial version" + }))) + .respond_with(ResponseTemplate::new(200).set_body_json(version_json.clone())) + .mount(&server) + .await; + Mock::given(method("POST")) + .and(path("/v1/agents/agent_123/versions/default")) + .and(body_json(serde_json::json!({"version_id": "agentver_1"}))) + .respond_with(ResponseTemplate::new(200).set_body_json(agent_json.clone())) + .mount(&server) + .await; + Mock::given(method("GET")) + .and(path( + "/v1/agents/agent_123/versions/agentver_1/diff/agentver_2", + )) + .respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({ + "from_version_id": "agentver_1", + "to_version_id": "agentver_2", + "authored_diff": [], + "resolved_diff": [] + }))) + .mount(&server) + .await; + Mock::given(method("POST")) + .and(path("/v1/agents/agent_123/versions/agentver_1/fork")) + .and(body_json(serde_json::json!({ + "name": "forked-agent", + "display_name": "Forked Agent", + "description": "Forked" + }))) + .respond_with(ResponseTemplate::new(200).set_body_json(agent_json.clone())) + .mount(&server) + .await; + Mock::given(method("POST")) + .and(path("/v1/agents/agent_123/versions/agentver_1/rollback")) + .and(body_json(serde_json::json!({ + "save_version": true, + "summary": "Revert" + }))) + .respond_with(ResponseTemplate::new(200).set_body_json(agent_json)) + .mount(&server) + .await; + + let versions = client + .agents() + .list_versions("agent_123") + .await + .expect("versions should list"); + let created = client + .agents() + .create_version( + "agent_123", + CreateAgentVersionRequest::new() + .change_kind(AgentVersionChangeKind::Manual) + .summary("Initial version"), + ) + .await + .expect("version should be created"); + let default_agent = client + .agents() + .set_default_version("agent_123", "agentver_1") + .await + .expect("default version should update"); + let diff = client + .agents() + .diff_versions("agent_123", "agentver_1", "agentver_2") + .await + .expect("versions should diff"); + let forked_agent = client + .agents() + .fork_version( + "agent_123", + "agentver_1", + ForkAgentVersionRequest::new("forked-agent") + .display_name("Forked Agent") + .description("Forked"), + ) + .await + .expect("version should fork"); + let rolled_back_agent = client + .agents() + .rollback_version( + "agent_123", + "agentver_1", + RollbackAgentVersionRequest::new() + .save_version(true) + .summary("Revert"), + ) + .await + .expect("version should roll back"); + + assert_eq!(versions[0].id, "agentver_123"); + assert_eq!(created.summary.as_deref(), Some("Initial version")); + assert_eq!(default_agent.id, "agent_456"); + assert_eq!(diff.to_version_id, "agentver_2"); + assert_eq!(forked_agent.name, "forked-agent"); + assert_eq!(rolled_back_agent.name, "forked-agent"); +} + +#[tokio::test] +async fn test_fork_agent_version_validates_agent_name() { + let client = Everruns::new("evr_test_key").expect("client"); + let result = client + .agents() + .fork_version( + "agent_123", + "agentver_1", + ForkAgentVersionRequest::new("Invalid Name"), + ) + .await; + + assert!(result.is_err()); +} + #[tokio::test] async fn test_create_session_with_locale() { let server = MockServer::start().await; diff --git a/specs/api-surface.md b/specs/api-surface.md index a1449d7..652d702 100644 --- a/specs/api-surface.md +++ b/specs/api-surface.md @@ -16,6 +16,12 @@ SDKs cover agents and sessions functionality. No durable execution endpoints. - `GET /v1/agents/{id}/export` - Export agent as Markdown - `POST /v1/agents/{id}/copy` - Copy an agent - `GET /v1/agents/{id}/stats` - Get aggregate usage stats for an agent +- `GET /v1/agents/{id}/versions` - List saved agent versions +- `POST /v1/agents/{id}/versions` - Save the current agent configuration as a version +- `POST /v1/agents/{id}/versions/default` - Set the default version for an agent +- `GET /v1/agents/{id}/versions/{from_version_id}/diff/{to_version_id}` - Diff two agent versions +- `POST /v1/agents/{id}/versions/{version_id}/fork` - Create a new agent from a saved version +- `POST /v1/agents/{id}/versions/{version_id}/rollback` - Restore an agent from a saved version #### Agent Names @@ -113,6 +119,39 @@ Server administration endpoints not exposed via SDK: ### Agents - `POST /v1/agents/preview` - Preview final agent shape +- `POST /v1/agents/{id}/voice/sessions` - Create agent voice session + +### Capabilities +- `POST /v1/capabilities` - Create persisted declarative capability +- `GET /v1/capabilities/declarative` - List persisted declarative capabilities +- `GET /v1/capabilities/declarative/config` - Get declarative capability config +- `GET /v1/capabilities/declarative/{id}` - Get persisted declarative capability +- `PATCH /v1/capabilities/declarative/{id}` - Update persisted declarative capability +- `DELETE /v1/capabilities/declarative/{id}` - Archive persisted declarative capability +- `POST /v1/capabilities/declarative/{id}/delete` - Permanently delete archived declarative capability + +### Events +- `GET /v1/sessions/{id}/events/summary` - One-shot debug event summary + +### Payments +- `GET /v1/payments/accounts` - List payment accounts +- `POST /v1/payments/accounts` - Create payment account +- `GET /v1/payments/accounts/{id}` - Get payment account +- `PATCH /v1/payments/accounts/{id}` - Update payment account +- `DELETE /v1/payments/accounts/{id}` - Disable payment account +- `GET /v1/payments/attempts` - List payment attempts +- `GET /v1/payments/policies` - List payment policies +- `POST /v1/payments/policies` - Create payment policy +- `GET /v1/payments/policies/{id}` - Get payment policy +- `PATCH /v1/payments/policies/{id}` - Update payment policy +- `DELETE /v1/payments/policies/{id}` - Disable payment policy + +### Voice Sessions +- `POST /v1/sessions/chat/voice` - Create chat voice session +- `POST /v1/sessions/{id}/voice/calls` - Create voice call +- `POST /v1/sessions/{id}/voice/client-secret` - Create voice client secret +- `POST /v1/sessions/{id}/voice/{connection_id}/attach` - Attach voice call +- `POST /v1/sessions/{id}/voice/{connection_id}/end` - End voice call ### Organizations - `GET /v1/orgs` - List organizations diff --git a/typescript/README.md b/typescript/README.md index 5d83d3e..d5dcedc 100644 --- a/typescript/README.md +++ b/typescript/README.md @@ -58,6 +58,24 @@ encoding: "text", Runnable example: [`examples/initial-files.ts`](examples/initial-files.ts) Run locally from this repo with `npx tsx examples/initial-files.ts`. +## Agent Versions + +\`\`\`typescript +const version = await client.agents.createVersion("agent_...", { +changeKind: "manual", +summary: "Baseline", +}); + +const versions = await client.agents.listVersions("agent_..."); +const diff = await client.agents.diffVersions("agent_...", "agentver_1", version.id); +const fork = await client.agents.forkVersion("agent_...", version.id, { +name: "forked-agent", +}); +const rollback = await client.agents.rollbackVersion("agent_...", version.id, { +saveVersion: true, +}); +\`\`\` + ## Authentication The SDK uses API key authentication. Set the \`EVERRUNS_API_KEY\` environment variable or pass the key explicitly. For API keys with access to multiple organizations, set \`EVERRUNS_ORG_ID\` or pass \`orgId\` explicitly: diff --git a/typescript/src/client.ts b/typescript/src/client.ts index 1f199e9..d56bcb5 100644 --- a/typescript/src/client.ts +++ b/typescript/src/client.ts @@ -4,18 +4,22 @@ import { ApiKey } from "./auth.js"; import { Agent, + AgentVersion, + AgentVersionDiffResponse, Budget, BudgetCheckResult, CapabilityInfo, Connection, ContentPart, CreateAgentRequest, + CreateAgentVersionRequest, CreateBudgetRequest, DeleteFileResponse, Session, CreateSessionRequest, FileInfo, FileStat, + ForkAgentVersionRequest, GrepResult, LedgerEntry, Message, @@ -25,9 +29,11 @@ import { ListResponse, ResourceStats, ResumeSessionResponse, + RollbackAgentVersionRequest, SessionFile, SubmitToolResultsResponse, StreamOptions, + SetDefaultAgentVersionRequest, TopUpRequest, UpdateBudgetRequest, validateAgentName, @@ -276,6 +282,72 @@ class AgentsClient { return this.client.fetch(`/agents/${agentId}/stats`); } + /** List saved versions for an agent. */ + async listVersions(agentId: string): Promise { + return this.client.fetch(`/agents/${agentId}/versions`); + } + + /** Save the current agent configuration as a version. */ + async createVersion( + agentId: string, + request: CreateAgentVersionRequest = {}, + ): Promise { + return this.client.fetch(`/agents/${agentId}/versions`, { + method: "POST", + body: JSON.stringify(toCreateAgentVersionBody(request)), + }); + } + + /** Set the default version for an agent. */ + async setDefaultVersion( + agentId: string, + request: SetDefaultAgentVersionRequest, + ): Promise { + return this.client.fetch(`/agents/${agentId}/versions/default`, { + method: "POST", + body: JSON.stringify({ version_id: request.versionId }), + }); + } + + /** Diff two saved agent versions. */ + async diffVersions( + agentId: string, + fromVersionId: string, + toVersionId: string, + ): Promise { + return this.client.fetch( + `/agents/${agentId}/versions/${fromVersionId}/diff/${toVersionId}`, + ); + } + + /** Create a new agent from a saved version. */ + async forkVersion( + agentId: string, + versionId: string, + request: ForkAgentVersionRequest, + ): Promise { + validateAgentName(request.name); + return this.client.fetch(`/agents/${agentId}/versions/${versionId}/fork`, { + method: "POST", + body: JSON.stringify(toForkAgentVersionBody(request)), + }); + } + + /** Restore an agent from a saved version. */ + async rollbackVersion( + agentId: string, + versionId: string, + request: RollbackAgentVersionRequest = {}, + ): Promise { + return this.client.fetch( + `/agents/${agentId}/versions/${versionId}/rollback`, + { + method: "POST", + body: JSON.stringify(toRollbackAgentVersionBody(request)), + }, + ); + } + async list(options?: { search?: string }): Promise { const query = options?.search ? `?search=${encodeURIComponent(options.search)}` @@ -909,6 +981,45 @@ function toAgentBody(request: CreateAgentRequest): Record { return body; } +function toCreateAgentVersionBody( + request: CreateAgentVersionRequest, +): Record { + const body: Record = {}; + if (request.changeKind !== undefined) { + body.change_kind = request.changeKind; + } + if (request.summary !== undefined) { + body.summary = request.summary; + } + return body; +} + +function toForkAgentVersionBody( + request: ForkAgentVersionRequest, +): Record { + const body: Record = { name: request.name }; + if (request.displayName !== undefined) { + body.display_name = request.displayName; + } + if (request.description !== undefined) { + body.description = request.description; + } + return body; +} + +function toRollbackAgentVersionBody( + request: RollbackAgentVersionRequest, +): Record { + const body: Record = {}; + if (request.saveVersion !== undefined) { + body.save_version = request.saveVersion; + } + if (request.summary !== undefined) { + body.summary = request.summary; + } + return body; +} + /** Check if the body looks like an HTML response */ function isHtmlResponse(body: string): boolean { const trimmed = body.trimStart(); diff --git a/typescript/src/generated/schema.d.ts b/typescript/src/generated/schema.d.ts index d4eb10f..25a07a0 100644 --- a/typescript/src/generated/schema.d.ts +++ b/typescript/src/generated/schema.d.ts @@ -158,6 +158,108 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/agents/{agent_id}/versions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/agents/{agent_id}/versions - List saved agent versions */ + get: operations["list_agent_versions"]; + put?: never; + /** POST /v1/agents/{agent_id}/versions - Save the current agent configuration as a version */ + post: operations["create_agent_version"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/agents/{agent_id}/versions/default": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** POST /v1/agents/{agent_id}/versions/default - Set the default version for an agent */ + post: operations["set_default_agent_version"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/agents/{agent_id}/versions/{from_version_id}/diff/{to_version_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/agents/{agent_id}/versions/{from_version_id}/diff/{to_version_id} - Diff two agent versions */ + get: operations["diff_agent_versions"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/agents/{agent_id}/versions/{version_id}/fork": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** POST /v1/agents/{agent_id}/versions/{version_id}/fork - Create a new agent from a saved version */ + post: operations["fork_agent_version"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/agents/{agent_id}/versions/{version_id}/rollback": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** POST /v1/agents/{agent_id}/versions/{version_id}/rollback - Restore an agent from a saved version */ + post: operations["rollback_agent_version"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/agents/{agent_id}/voice/sessions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["create_agent_voice_session"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/apps/{app_id}/a2a/{channel_id}": { parameters: { query?: never; @@ -218,6 +320,24 @@ export interface paths { /** GET /v1/capabilities - List available capabilities with pagination */ get: operations["list_capabilities"]; put?: never; + /** POST /v1/capabilities - Create a persisted declarative capability. */ + post: operations["create_declarative_capability"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/capabilities/declarative": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/capabilities/declarative - List persisted declarative resources. */ + get: operations["list_declarative_capabilities"]; + put?: never; post?: never; delete?: never; options?: never; @@ -225,6 +345,59 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/capabilities/declarative/config": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/capabilities/declarative/config */ + get: operations["declarative_capabilities_config"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/capabilities/declarative/{capability_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/capabilities/declarative/{capability_id} - Get a declarative resource. */ + get: operations["get_declarative_capability"]; + put?: never; + post?: never; + /** DELETE /v1/capabilities/declarative/{capability_id} - Archive a declarative resource. */ + delete: operations["delete_declarative_capability"]; + options?: never; + head?: never; + /** PATCH /v1/capabilities/declarative/{capability_id} - Update a declarative resource. */ + patch: operations["update_declarative_capability"]; + trace?: never; + }; + "/v1/capabilities/declarative/{capability_id}/delete": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** POST /v1/capabilities/declarative/{capability_id}/delete - Permanently delete archived resource. */ + post: operations["destroy_declarative_capability"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/capabilities/{capability_id}": { parameters: { query?: never; @@ -926,6 +1099,86 @@ export interface paths { patch: operations["update_organization"]; trace?: never; }; + "/v1/payments/accounts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["list_payment_accounts"]; + put?: never; + post: operations["create_payment_account"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/payments/accounts/{payment_account_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["get_payment_account"]; + put?: never; + post?: never; + delete: operations["disable_payment_account"]; + options?: never; + head?: never; + patch: operations["update_payment_account"]; + trace?: never; + }; + "/v1/payments/attempts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["list_payment_attempts"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/payments/policies": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["list_payment_policies"]; + put?: never; + post: operations["create_payment_policy"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/payments/policies/{payment_policy_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["get_payment_policy"]; + put?: never; + post?: never; + delete: operations["disable_payment_policy"]; + options?: never; + head?: never; + patch: operations["update_payment_policy"]; + trace?: never; + }; "/v1/sessions": { parameters: { query?: never; @@ -965,6 +1218,22 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/sessions/chat/voice": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["create_chat_voice_session"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/sessions/{session_id}": { parameters: { query?: never; @@ -1113,6 +1382,23 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/sessions/{session_id}/events/summary": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/sessions/{session_id}/events/summary - one-shot debug summary */ + get: operations["events_summary"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/sessions/{session_id}/export": { parameters: { query?: never; @@ -1539,25 +1825,23 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/skills": { + "/v1/sessions/{session_id}/voice/calls": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** GET /v1/skills - List all skills */ - get: operations["list_skills"]; + get?: never; put?: never; - /** POST /v1/skills - Create skill from SKILL.md */ - post: operations["create_skill"]; + post: operations["create_call"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/skills/upload": { + "/v1/sessions/{session_id}/voice/client-secret": { parameters: { query?: never; header?: never; @@ -1566,15 +1850,14 @@ export interface paths { }; get?: never; put?: never; - /** POST /v1/skills/upload - Create skill from ZIP archive */ - post: operations["upload_skill"]; + post: operations["create_client_secret"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/skills/validate": { + "/v1/sessions/{session_id}/voice/{voice_connection_id}/attach": { parameters: { query?: never; header?: never; @@ -1583,43 +1866,110 @@ export interface paths { }; get?: never; put?: never; - /** POST /v1/skills/validate - Validate SKILL.md content */ - post: operations["validate_skill"]; + post: operations["attach_call"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/skills/{skill_id}": { + "/v1/sessions/{session_id}/voice/{voice_connection_id}/end": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** GET /v1/skills/{skill_id} - Get skill by ID */ - get: operations["get_skill"]; + get?: never; put?: never; - post?: never; - /** DELETE /v1/skills/{skill_id} - Delete skill */ - delete: operations["delete_skill"]; + post: operations["end_call"]; + delete?: never; options?: never; head?: never; - /** PATCH /v1/skills/{skill_id} - Update skill */ - patch: operations["update_skill"]; + patch?: never; trace?: never; }; - "/v1/skills/{skill_id}/content": { + "/v1/skills": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** GET /v1/skills/{skill_id}/content - Get full skill content */ - get: operations["get_skill_content"]; - put?: never; + /** GET /v1/skills - List all skills */ + get: operations["list_skills"]; + put?: never; + /** POST /v1/skills - Create skill from SKILL.md */ + post: operations["create_skill"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/skills/upload": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** POST /v1/skills/upload - Create skill from ZIP archive */ + post: operations["upload_skill"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/skills/validate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** POST /v1/skills/validate - Validate SKILL.md content */ + post: operations["validate_skill"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/skills/{skill_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/skills/{skill_id} - Get skill by ID */ + get: operations["get_skill"]; + put?: never; + post?: never; + /** DELETE /v1/skills/{skill_id} - Delete skill */ + delete: operations["delete_skill"]; + options?: never; + head?: never; + /** PATCH /v1/skills/{skill_id} - Update skill */ + patch: operations["update_skill"]; + trace?: never; + }; + "/v1/skills/{skill_id}/content": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** GET /v1/skills/{skill_id}/content - Get full skill content */ + get: operations["get_skill_content"]; + put?: never; post?: never; delete?: never; options?: never; @@ -1761,6 +2111,11 @@ export interface components { * @example model_01933b5a00007000800000000000001 */ default_model_id?: string | null; + /** + * @description Default immutable version used by deployments that choose the default policy. + * @example agentver_01933b5a00007000800000000000001 + */ + default_version_id?: string | null; /** * Format: date-time * @description Timestamp when the agent was deleted. @@ -1773,6 +2128,16 @@ export interface components { * Falls back to `name` when absent. */ display_name?: string | null; + /** + * @description Source agent for a forked agent. + * @example agent_01933b5a00007000800000000000001 + */ + forked_from_agent_id?: string | null; + /** + * @description Source version for a forked agent. + * @example agentver_01933b5a00007000800000000000001 + */ + forked_from_version_id?: string | null; /** * @description External identifier (agent_<32-hex>). Shown as "id" in API. * Client-supplied or auto-generated. @@ -1788,6 +2153,11 @@ export interface components { /** @description Name, unique per org (e.g. "customer-support"). */ name: string; network_access?: null | components["schemas"]["NetworkAccessList"]; + /** + * @description Root agent lineage identifier for grouping fork families. + * @example agent_01933b5a00007000800000000000001 + */ + root_agent_id?: string | null; /** @description Current lifecycle status of the agent. */ status: components["schemas"]["AgentStatus"]; /** @@ -1836,6 +2206,50 @@ export interface components { * @enum {string} */ AgentStatus: "active" | "archived" | "deleted"; + /** @description Immutable snapshot of an Agent's authored and resolved runtime config. */ + AgentVersion: { + /** @example agent_01933b5a000070008000000000000001 */ + agent_id: string; + authored_config: Record; + change_kind: components["schemas"]["AgentVersionChangeKind"]; + config_hash: string; + /** Format: date-time */ + created_at: string; + created_by_principal_id?: string | null; + /** @example agentver_01933b5a000070008000000000000001 */ + id: string; + parent_version_id?: string | null; + resolved_config: Record; + /** Format: int32 */ + semver_major: number; + /** Format: int32 */ + semver_minor: number; + /** Format: int32 */ + semver_patch: number; + source_version_id?: string | null; + summary?: string | null; + version: string; + /** Format: int32 */ + version_number: number; + }; + /** + * @description Reason a version was created. Stored as lower_snake_case text. + * @enum {string} + */ + AgentVersionChangeKind: + | "manual" + | "patch" + | "minor" + | "major" + | "import" + | "rollback" + | "fork"; + AgentVersionDiffResponse: { + authored_diff: unknown; + from_version_id: components["schemas"]["agentverId"]; + resolved_diff: unknown; + to_version_id: components["schemas"]["agentverId"]; + }; BTreeMap: { [key: string]: { /** @description Authentication mode used when executing tools from this scoped server. */ @@ -2232,6 +2646,10 @@ export interface components { */ tools?: components["schemas"]["ToolDefinition"][]; }; + CreateAgentVersionRequest: { + change_kind?: null | components["schemas"]["AgentVersionChangeKind"]; + summary?: string | null; + }; /** @description Request to create a branch */ CreateBranchRequest: { /** @description Commit OID (hex) to point to */ @@ -2244,6 +2662,10 @@ export interface components { /** @description Database name (alphanumeric + underscores, max 64 chars) */ name: string; }; + CreateDeclarativeCapabilityRequest: { + /** @description Definition for the new declarative capability. `name` must be unique per org and becomes the canonical `declarative:` capability ref. */ + definition: Record; + }; /** @description Request to create a file */ CreateFileRequest: { /** @description File content (text or base64-encoded) */ @@ -2430,6 +2852,32 @@ export interface components { */ name: string; }; + CreatePaymentAccountRequest: { + label: string; + metadata?: unknown; + owner_id: string; + owner_type: string; + private_key?: string | null; + public_address?: string | null; + rail: string; + }; + CreatePaymentPolicyRequest: { + allowed_capabilities?: string[]; + allowed_hosts?: string[]; + /** Format: double */ + max_amount_usd_per_day?: number | null; + /** Format: double */ + max_amount_usd_per_request?: number | null; + /** Format: double */ + max_amount_usd_per_turn?: number | null; + metadata?: unknown; + payment_account_id: string; + rail_preference?: string[]; + /** Format: double */ + require_approval_above_usd?: number | null; + subject_id: string; + subject_type: string; + }; /** @description Create schedule request */ CreateScheduleRequest: { /** @description Whether to catch up missed triggers (default: false) */ @@ -2572,6 +3020,48 @@ export interface components { size_bytes: number; updated_at: string; }; + DeclarativeCapability: { + /** Format: date-time */ + archived_at?: string | null; + /** + * @description Runtime capability reference. Agents and harnesses may use this or the plain unique name. + * @example declarative:research_pack + */ + capability_id: string; + /** Format: date-time */ + created_at: string; + /** @description Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata. */ + definition: Record; + /** Format: date-time */ + deleted_at?: string | null; + /** + * @description Short summary shown in pickers, search results, and API listings. + * @example Adds research instructions, starter files, and MCP tools. + */ + description: string; + /** + * @description Human-facing label shown in the UI. Defaults to `name` when omitted. + * @example Research Pack + */ + display_name?: string | null; + /** + * @description Public resource ID for this persisted declarative capability. + * @example cap_01933b5a000070008000000000000001 + */ + id: string; + /** + * @description Stable unique name used in capability refs. Lowercase letters, numbers, and underscores. + * @example research_pack + */ + name: string; + /** + * @description Lifecycle state for the resource: active, disabled, archived, or deleted. + * @example active + */ + status: string; + /** Format: date-time */ + updated_at: string; + }; /** * @description Controls whether a tool's full schema can be deferred (tool_search). * @@ -2738,7 +3228,49 @@ export interface components { | components["schemas"]["BudgetEventData"] | components["schemas"]["BudgetEventData"] | components["schemas"]["BudgetEventData"] - | components["schemas"]["BudgetEventData"]; + | components["schemas"]["BudgetEventData"] + | components["schemas"]["VoiceSessionStartedData"] + | components["schemas"]["VoiceTranscriptData"] + | components["schemas"]["VoiceTranscriptData"] + | components["schemas"]["VoiceTranscriptData"] + | components["schemas"]["VoiceTranscriptData"] + | components["schemas"]["VoiceSessionEndedData"] + | components["schemas"]["VoiceSessionFailedData"]; + EventTypeCountOut: { + /** Format: int64 */ + count: number; + event_type: string; + }; + EventsSummaryResult: { + /** @description Per-type count, sorted by event_type asc. */ + by_type: components["schemas"]["EventTypeCountOut"][]; + /** + * Format: int64 + * @description Convenience: count of failure-shaped event types + * (`turn.failed`, `tool.failed`, `*.error`, `subagent.failed`). + */ + error_count: number; + /** + * Format: date-time + * @description Earliest event timestamp, if any. + */ + first_ts?: string | null; + /** + * Format: date-time + * @description Latest event timestamp, if any. + */ + last_ts?: string | null; + /** + * Format: int64 + * @description Total event count across all types. + */ + total: number; + /** + * Format: int64 + * @description Convenience: count of `turn.started` events. + */ + turn_count: number; + }; /** * @description Execution phase for assistant messages in multi-step tool-calling flows. * @@ -2819,6 +3351,11 @@ export interface components { */ size_bytes: number; }; + ForkAgentVersionRequest: { + description?: string | null; + display_name?: string | null; + name: string; + }; GetOrCreateChatSessionRequest: { /** @description Browser locale for seeding the global chat session (BCP 47, e.g. `uk-UA`). */ locale?: string | null; @@ -3274,6 +3811,11 @@ export interface components { * @example model_01933b5a00007000800000000000001 */ default_model_id?: string | null; + /** + * @description Default immutable version used by deployments that choose the default policy. + * @example agentver_01933b5a00007000800000000000001 + */ + default_version_id?: string | null; /** * Format: date-time * @description Timestamp when the agent was deleted. @@ -3286,6 +3828,16 @@ export interface components { * Falls back to `name` when absent. */ display_name?: string | null; + /** + * @description Source agent for a forked agent. + * @example agent_01933b5a00007000800000000000001 + */ + forked_from_agent_id?: string | null; + /** + * @description Source version for a forked agent. + * @example agentver_01933b5a00007000800000000000001 + */ + forked_from_version_id?: string | null; /** * @description External identifier (agent_<32-hex>). Shown as "id" in API. * Client-supplied or auto-generated. @@ -3301,6 +3853,11 @@ export interface components { /** @description Name, unique per org (e.g. "customer-support"). */ name: string; network_access?: null | components["schemas"]["NetworkAccessList"]; + /** + * @description Root agent lineage identifier for grouping fork families. + * @example agent_01933b5a00007000800000000000001 + */ + root_agent_id?: string | null; /** @description Current lifecycle status of the agent. */ status: components["schemas"]["AgentStatus"]; /** @@ -3841,6 +4398,62 @@ export interface components { updated_at: string; }[]; }; + /** + * @description Response wrapper for list endpoints. + * All list endpoints return responses wrapped in a `data` field. + */ + ListResponse_WithUrls_DeclarativeCapability: { + /** @description Array of items returned by the list operation. */ + data: ({ + /** Format: date-time */ + archived_at?: string | null; + /** + * @description Runtime capability reference. Agents and harnesses may use this or the plain unique name. + * @example declarative:research_pack + */ + capability_id: string; + /** Format: date-time */ + created_at: string; + /** @description Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata. */ + definition: Record; + /** Format: date-time */ + deleted_at?: string | null; + /** + * @description Short summary shown in pickers, search results, and API listings. + * @example Adds research instructions, starter files, and MCP tools. + */ + description: string; + /** + * @description Human-facing label shown in the UI. Defaults to `name` when omitted. + * @example Research Pack + */ + display_name?: string | null; + /** + * @description Public resource ID for this persisted declarative capability. + * @example cap_01933b5a000070008000000000000001 + */ + id: string; + /** + * @description Stable unique name used in capability refs. Lowercase letters, numbers, and underscores. + * @example research_pack + */ + name: string; + /** + * @description Lifecycle state for the resource: active, disabled, archived, or deleted. + * @example active + */ + status: string; + /** Format: date-time */ + updated_at: string; + } & { + /** @description Full API endpoint URL for this resource. */ + self_url: string; + /** @description Alias for `view_url`, used by command and MCP outputs. */ + ui_link: string; + /** @description Full UI URL for viewing this resource. */ + view_url: string; + })[]; + }; /** * @description Response wrapper for list endpoints. * All list endpoints return responses wrapped in a `data` field. @@ -4861,6 +5474,11 @@ export interface components { * @example identity_01933b5a00007000800000000000001 */ agent_identity_id?: string | null; + /** + * @description Immutable agent version captured when the session was created or rebound. + * @example agentver_01933b5a00007000800000000000001 + */ + agent_version_id?: string | null; /** @description Validated config passed by host at blueprint spawn time. */ blueprint_config?: unknown; /** @@ -5109,6 +5727,11 @@ export interface components { * @example model_01933b5a00007000800000000000001 */ default_model_id?: string | null; + /** + * @description Default immutable version used by deployments that choose the default policy. + * @example agentver_01933b5a00007000800000000000001 + */ + default_version_id?: string | null; /** * Format: date-time * @description Timestamp when the agent was deleted. @@ -5121,6 +5744,16 @@ export interface components { * Falls back to `name` when absent. */ display_name?: string | null; + /** + * @description Source agent for a forked agent. + * @example agent_01933b5a00007000800000000000001 + */ + forked_from_agent_id?: string | null; + /** + * @description Source version for a forked agent. + * @example agentver_01933b5a00007000800000000000001 + */ + forked_from_version_id?: string | null; /** * @description External identifier (agent_<32-hex>). Shown as "id" in API. * Client-supplied or auto-generated. @@ -5136,6 +5769,11 @@ export interface components { /** @description Name, unique per org (e.g. "customer-support"). */ name: string; network_access?: null | components["schemas"]["NetworkAccessList"]; + /** + * @description Root agent lineage identifier for grouping fork families. + * @example agent_01933b5a00007000800000000000001 + */ + root_agent_id?: string | null; /** @description Current lifecycle status of the agent. */ status: components["schemas"]["AgentStatus"]; /** @@ -5214,6 +5852,11 @@ export interface components { * @example identity_01933b5a00007000800000000000001 */ agent_identity_id?: string | null; + /** + * @description Immutable agent version captured when the session was created or rebound. + * @example agentver_01933b5a00007000800000000000001 + */ + agent_version_id?: string | null; /** @description Validated config passed by host at blueprint spawn time. */ blueprint_config?: unknown; /** @@ -5362,6 +6005,84 @@ export interface components { */ total: number; }; + PaymentAccount: { + /** Format: date-time */ + created_at: string; + id: components["schemas"]["payacctId"]; + label: string; + metadata: unknown; + organization_id: string; + owner_id: string; + owner_type: components["schemas"]["PaymentOwnerType"]; + public_address?: string | null; + rail: components["schemas"]["PaymentRail"]; + status: components["schemas"]["PaymentStatus"]; + /** Format: date-time */ + updated_at: string; + }; + PaymentAttempt: { + /** Format: double */ + amount_usd: number; + capability: string; + /** Format: date-time */ + created_at: string; + currency: string; + error_message?: string | null; + id: components["schemas"]["payattId"]; + operation: string; + organization_id: string; + payment_account_id?: null | components["schemas"]["payacctId"]; + rail?: null | components["schemas"]["PaymentRail"]; + receipt: unknown; + request_hash?: string | null; + session_id?: string | null; + status: components["schemas"]["PaymentStatus"]; + target_url: string; + /** Format: date-time */ + updated_at: string; + }; + /** + * @description Principal class that owns a payment account. + * @enum {string} + */ + PaymentOwnerType: "user" | "agent_identity" | "organization"; + PaymentPolicy: { + allowed_capabilities: string[]; + allowed_hosts: string[]; + /** Format: date-time */ + created_at: string; + id: components["schemas"]["paypolId"]; + /** Format: double */ + max_amount_usd_per_day?: number | null; + /** Format: double */ + max_amount_usd_per_request?: number | null; + /** Format: double */ + max_amount_usd_per_turn?: number | null; + metadata: unknown; + organization_id: string; + payment_account_id: components["schemas"]["payacctId"]; + rail_preference: components["schemas"]["PaymentRail"][]; + /** Format: double */ + require_approval_above_usd?: number | null; + status: components["schemas"]["PaymentStatus"]; + subject_id: string; + subject_type: string; + /** Format: date-time */ + updated_at: string; + }; + /** + * @description Payment rail used to settle a machine payment. + * @enum {string} + */ + PaymentRail: "mpp_tempo" | "x402_base"; + /** @enum {string} */ + PaymentStatus: + | "active" + | "disabled" + | "pending" + | "succeeded" + | "failed" + | "released"; /** @description Request to preview the final agent shape with capabilities applied */ PreviewAgentRequest: { /** @@ -5436,9 +6157,9 @@ export interface components { }; /** @description Data for reason.started event */ ReasonStartedData: { - agent_id?: null | components["schemas"]["TypedId"]; + agent_id?: null | components["schemas"]["agentId"]; /** @description Harness ID being used */ - harness_id: components["schemas"]["TypedId"]; + harness_id: components["schemas"]["harnessId"]; metadata?: null | components["schemas"]["ModelMetadata"]; }; /** @@ -5565,6 +6286,10 @@ export interface components { * @enum {string} */ RiskLevel: "low" | "medium" | "high"; + RollbackAgentVersionRequest: { + save_version?: boolean; + summary?: string | null; + }; /** @description Schedule execution response */ ScheduleExecutionResponse: { /** Format: date-time */ @@ -5688,6 +6413,11 @@ export interface components { * @example identity_01933b5a00007000800000000000001 */ agent_identity_id?: string | null; + /** + * @description Immutable agent version captured when the session was created or rebound. + * @example agentver_01933b5a00007000800000000000001 + */ + agent_version_id?: string | null; /** @description Validated config passed by host at blueprint spawn time. */ blueprint_config?: unknown; /** @@ -5932,6 +6662,9 @@ export interface components { | "idle" | "waitingfortoolresults" | "paused"; + SetDefaultAgentVersionRequest: { + version_id: components["schemas"]["agentverId"]; + }; /** @description Skill entity (API response type) */ Skill: { allowed_tools?: string | null; @@ -6376,11 +7109,6 @@ export interface components { */ turn_id: string; }; - /** - * @description Prefixed identifier with 'agent' prefix - * @example agent_01933b5a00007000800000000000001 - */ - TypedId: string; /** @description Request to update an agent. Only provided fields will be updated. */ UpdateAgentRequest: { /** @@ -6443,6 +7171,15 @@ export interface components { */ tools?: components["schemas"]["ToolDefinition"][] | null; }; + UpdateDeclarativeCapabilityRequest: { + /** @description Replacement declarative definition. Changing `name` updates the canonical capability ref after uniqueness validation. */ + definition?: Record; + /** + * @description Optional lifecycle state update. Use `disabled` to hide from runtime selection without archiving. + * @example disabled + */ + status?: string | null; + }; /** @description Request to update a file */ UpdateFileRequest: { /** @description New file content */ @@ -6593,6 +7330,28 @@ export interface components { */ name?: string | null; }; + UpdatePaymentAccountRequest: { + label?: string | null; + metadata?: unknown; + private_key?: string | null; + public_address?: string | null; + status?: string | null; + }; + UpdatePaymentPolicyRequest: { + allowed_capabilities?: string[] | null; + allowed_hosts?: string[] | null; + /** Format: double */ + max_amount_usd_per_day?: number | null; + /** Format: double */ + max_amount_usd_per_request?: number | null; + /** Format: double */ + max_amount_usd_per_turn?: number | null; + metadata?: unknown; + rail_preference?: string[] | null; + /** Format: double */ + require_approval_above_usd?: number | null; + status?: string | null; + }; /** @description Update schedule request */ UpdateScheduleRequest: { /** @description Catch up missed triggers */ @@ -6670,6 +7429,100 @@ export interface components { /** @description SKILL.md content to validate */ skill_md: string; }; + VoiceAttachRequest: components["schemas"]["VoiceSessionOptions"] & { + provider_call_id: string; + }; + VoiceAttachResponse: { + /** Format: date-time */ + expires_at: string; + model: string; + provider: string; + provider_call_id: string; + reasoning_effort: string; + voice: string; + voice_connection_id: string; + }; + VoiceCallRequest: components["schemas"]["VoiceSessionOptions"] & { + sdp: string; + }; + VoiceCallResponse: { + answer_sdp: string; + /** Format: date-time */ + expires_at: string; + model: string; + provider: string; + provider_call_id?: string | null; + reasoning_effort: string; + voice: string; + voice_connection_id: string; + }; + VoiceClientSecretRequest: components["schemas"]["VoiceSessionOptions"]; + VoiceClientSecretResponse: { + client_secret: unknown; + /** Format: date-time */ + expires_at: string; + model: string; + provider: string; + reasoning_effort: string; + voice: string; + voice_connection_id: string; + }; + VoiceEndRequest: { + reason?: string | null; + }; + VoiceEndResponse: { + status: string; + voice_connection_id: string; + }; + /** @description Data for voice.session.ended. */ + VoiceSessionEndedData: { + /** Format: int64 */ + duration_ms?: number | null; + reason?: string | null; + voice_connection_id: string; + }; + /** @description Data for voice.session.failed. */ + VoiceSessionFailedData: { + error: string; + voice_connection_id: string; + }; + VoiceSessionOptions: { + instructions?: string | null; + model?: string | null; + reasoning_effort?: string | null; + voice?: string | null; + }; + VoiceSessionResponse_VoiceCallResponse: { + session: components["schemas"]["Session"]; + voice: { + answer_sdp: string; + /** Format: date-time */ + expires_at: string; + model: string; + provider: string; + provider_call_id?: string | null; + reasoning_effort: string; + voice: string; + voice_connection_id: string; + }; + }; + /** @description Data for voice.session.started. */ + VoiceSessionStartedData: { + model: string; + reasoning_effort: string; + transport: string; + voice: string; + voice_connection_id: string; + }; + /** @description Data for voice transcript delta/completed events. */ + VoiceTranscriptData: { + accumulated: string; + delta?: string; + item_id?: string | null; + phase?: string | null; + response_id?: string | null; + voice_connection_id: string; + }; VolumeResponse: { /** Format: date-time */ archived_at?: string | null; @@ -6718,6 +7571,11 @@ export interface components { * @example model_01933b5a00007000800000000000001 */ default_model_id?: string | null; + /** + * @description Default immutable version used by deployments that choose the default policy. + * @example agentver_01933b5a00007000800000000000001 + */ + default_version_id?: string | null; /** * Format: date-time * @description Timestamp when the agent was deleted. @@ -6730,6 +7588,16 @@ export interface components { * Falls back to `name` when absent. */ display_name?: string | null; + /** + * @description Source agent for a forked agent. + * @example agent_01933b5a00007000800000000000001 + */ + forked_from_agent_id?: string | null; + /** + * @description Source version for a forked agent. + * @example agentver_01933b5a00007000800000000000001 + */ + forked_from_version_id?: string | null; /** * @description External identifier (agent_<32-hex>). Shown as "id" in API. * Client-supplied or auto-generated. @@ -6745,6 +7613,11 @@ export interface components { /** @description Name, unique per org (e.g. "customer-support"). */ name: string; network_access?: null | components["schemas"]["NetworkAccessList"]; + /** + * @description Root agent lineage identifier for grouping fork families. + * @example agent_01933b5a00007000800000000000001 + */ + root_agent_id?: string | null; /** @description Current lifecycle status of the agent. */ status: components["schemas"]["AgentStatus"]; /** @@ -6836,6 +7709,61 @@ export interface components { /** @description Full UI URL for viewing this resource. */ view_url: string; }; + /** + * @description Wrapper that adds API and UI links to a serialized resource. + * + * Uses `self_url` (not `url`) for the API link to avoid collision with + * resources that already have a `url` field (e.g. McpServer). + */ + WithUrls_DeclarativeCapability: { + /** Format: date-time */ + archived_at?: string | null; + /** + * @description Runtime capability reference. Agents and harnesses may use this or the plain unique name. + * @example declarative:research_pack + */ + capability_id: string; + /** Format: date-time */ + created_at: string; + /** @description Declarative capability payload: system prompt, skills, starter files, MCP servers, and metadata. */ + definition: Record; + /** Format: date-time */ + deleted_at?: string | null; + /** + * @description Short summary shown in pickers, search results, and API listings. + * @example Adds research instructions, starter files, and MCP tools. + */ + description: string; + /** + * @description Human-facing label shown in the UI. Defaults to `name` when omitted. + * @example Research Pack + */ + display_name?: string | null; + /** + * @description Public resource ID for this persisted declarative capability. + * @example cap_01933b5a000070008000000000000001 + */ + id: string; + /** + * @description Stable unique name used in capability refs. Lowercase letters, numbers, and underscores. + * @example research_pack + */ + name: string; + /** + * @description Lifecycle state for the resource: active, disabled, archived, or deleted. + * @example active + */ + status: string; + /** Format: date-time */ + updated_at: string; + } & { + /** @description Full API endpoint URL for this resource. */ + self_url: string; + /** @description Alias for `view_url`, used by command and MCP outputs. */ + ui_link: string; + /** @description Full UI URL for viewing this resource. */ + view_url: string; + }; /** * @description Wrapper that adds API and UI links to a serialized resource. * @@ -7121,6 +8049,11 @@ export interface components { * @example model_01933b5a00007000800000000000001 */ default_model_id?: string | null; + /** + * @description Default immutable version used by deployments that choose the default policy. + * @example agentver_01933b5a00007000800000000000001 + */ + default_version_id?: string | null; /** * Format: date-time * @description Timestamp when the agent was deleted. @@ -7133,6 +8066,16 @@ export interface components { * Falls back to `name` when absent. */ display_name?: string | null; + /** + * @description Source agent for a forked agent. + * @example agent_01933b5a00007000800000000000001 + */ + forked_from_agent_id?: string | null; + /** + * @description Source version for a forked agent. + * @example agentver_01933b5a00007000800000000000001 + */ + forked_from_version_id?: string | null; /** * @description External identifier (agent_<32-hex>). Shown as "id" in API. * Client-supplied or auto-generated. @@ -7148,6 +8091,11 @@ export interface components { /** @description Name, unique per org (e.g. "customer-support"). */ name: string; network_access?: null | components["schemas"]["NetworkAccessList"]; + /** + * @description Root agent lineage identifier for grouping fork families. + * @example agent_01933b5a00007000800000000000001 + */ + root_agent_id?: string | null; /** @description Current lifecycle status of the agent. */ status: components["schemas"]["AgentStatus"]; /** @@ -7300,6 +8248,11 @@ export interface components { * @example identity_01933b5a00007000800000000000001 */ agent_identity_id?: string | null; + /** + * @description Immutable agent version captured when the session was created or rebound. + * @example agentver_01933b5a00007000800000000000001 + */ + agent_version_id?: string | null; /** @description Validated config passed by host at blueprint spawn time. */ blueprint_config?: unknown; /** @@ -7474,6 +8427,41 @@ export interface components { /** @description Full UI URL for viewing this resource. */ view_url: string; }; + /** + * @description Prefixed identifier with 'agent' prefix + * @example agent_01933b5a00007000800000000000001 + */ + agentId: string; + /** + * @description Prefixed identifier with 'agentver' prefix + * @example agentver_01933b5a00007000800000000000001 + */ + agentverId: string; + /** + * @description Prefixed identifier with 'event' prefix + * @example event_01933b5a00007000800000000000001 + */ + eventId: string; + /** + * @description Prefixed identifier with 'harness' prefix + * @example harness_01933b5a00007000800000000000001 + */ + harnessId: string; + /** + * @description Prefixed identifier with 'payacct' prefix + * @example payacct_01933b5a00007000800000000000001 + */ + payacctId: string; + /** + * @description Prefixed identifier with 'payatt' prefix + * @example payatt_01933b5a00007000800000000000001 + */ + payattId: string; + /** + * @description Prefixed identifier with 'paypol' prefix + * @example paypol_01933b5a00007000800000000000001 + */ + paypolId: string; }; responses: never; parameters: never; @@ -7998,50 +8986,28 @@ export interface operations { }; }; }; - invoke_a2a: { + list_agent_versions: { parameters: { query?: never; header?: never; path: { - /** @description App ID */ - app_id: string; - /** @description A2A channel ID */ - channel_id: string; + /** @description Agent ID (prefixed) or name */ + agent_id: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": unknown; - }; - }; + requestBody?: never; responses: { - /** @description JSON-RPC 2.0 response (success or A2A error envelope) */ + /** @description Saved agent versions */ 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Missing or invalid API key */ - 401: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description App is not published or channel disabled */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; + "application/json": components["schemas"]["AgentVersion"][]; }; }; - /** @description App or channel not found */ + /** @description Agent not found or agent_versions disabled */ 404: { headers: { [name: string]: unknown; @@ -8052,28 +9018,41 @@ export interface operations { }; }; }; - agent_card: { + create_agent_version: { parameters: { query?: never; header?: never; path: { - /** @description App ID */ - app_id: string; - /** @description A2A channel ID */ - channel_id: string; + /** @description Agent ID (prefixed) or name */ + agent_id: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["CreateAgentVersionRequest"]; + }; + }; responses: { - /** @description Agent Card JSON */ + /** @description Agent version created */ 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["AgentVersion"]; + }; }; - /** @description App or channel not found / unpublished / disabled */ + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Agent not found or agent_versions disabled */ 404: { headers: { [name: string]: unknown; @@ -8084,35 +9063,33 @@ export interface operations { }; }; }; - invoke_webhook: { + set_default_agent_version: { parameters: { query?: never; header?: never; path: { - /** @description App ID */ - app_id: string; - /** @description Webhook channel ID */ - channel_id: string; + /** @description Agent ID (prefixed) or name */ + agent_id: string; }; cookie?: never; }; requestBody: { content: { - "application/octet-stream": string; + "application/json": components["schemas"]["SetDefaultAgentVersionRequest"]; }; }; responses: { - /** @description Webhook accepted */ - 202: { + /** @description Default version updated */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WebhookInvocationResponse"]; + "application/json": components["schemas"]["WithUrls_Agent"]; }; }; - /** @description Invalid or missing webhook token */ - 401: { + /** @description Invalid request */ + 400: { headers: { [name: string]: unknown; }; @@ -8120,8 +9097,8 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description App is not published or channel disabled */ - 403: { + /** @description Agent or version not found, or agent_versions disabled */ + 404: { headers: { [name: string]: unknown; }; @@ -8129,17 +9106,35 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description App or channel not found */ - 404: { + }; + }; + diff_agent_versions: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Agent ID (prefixed) or name */ + agent_id: string; + /** @description Base agent version ID */ + from_version_id: components["schemas"]["agentverId"]; + /** @description Comparison agent version ID */ + to_version_id: components["schemas"]["agentverId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Agent version diff */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ErrorResponse"]; + "application/json": components["schemas"]["AgentVersionDiffResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Agent or version not found, or agent_versions disabled */ + 404: { headers: { [name: string]: unknown; }; @@ -8149,32 +9144,34 @@ export interface operations { }; }; }; - list_capabilities: { + fork_agent_version: { parameters: { - query?: { - /** @description Search by name/description */ - search?: string; - /** @description Pagination offset (default: 0) */ - offset?: number; - /** @description Page size (default: 20, max: 100) */ - limit?: number; - }; + query?: never; header?: never; - path?: never; + path: { + /** @description Source agent ID (prefixed) or name */ + agent_id: string; + /** @description Agent version ID */ + version_id: components["schemas"]["agentverId"]; + }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["ForkAgentVersionRequest"]; + }; + }; responses: { - /** @description Paginated list of capabilities */ + /** @description Agent fork created */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["PaginatedResponse_WithUrls_CapabilityInfo"]; + "application/json": components["schemas"]["WithUrls_Agent"]; }; }; - /** @description Invalid query parameters */ + /** @description Invalid request */ 400: { headers: { [name: string]: unknown; @@ -8183,8 +9180,8 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Agent or version not found, or agent_versions disabled */ + 404: { headers: { [name: string]: unknown; }; @@ -8194,29 +9191,35 @@ export interface operations { }; }; }; - get_capability: { + rollback_agent_version: { parameters: { query?: never; header?: never; path: { - /** @description Capability ID */ - capability_id: string; + /** @description Agent ID (prefixed) or name */ + agent_id: string; + /** @description Agent version ID */ + version_id: components["schemas"]["agentverId"]; }; cookie?: never; }; - requestBody?: never; - responses: { - /** @description Capability found */ + requestBody: { + content: { + "application/json": components["schemas"]["RollbackAgentVersionRequest"]; + }; + }; + responses: { + /** @description Agent rolled back */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WithUrls_CapabilityInfo"]; + "application/json": components["schemas"]["WithUrls_Agent"]; }; }; - /** @description Capability not found */ - 404: { + /** @description Invalid request */ + 400: { headers: { [name: string]: unknown; }; @@ -8224,8 +9227,8 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Agent or version not found, or agent_versions disabled */ + 404: { headers: { [name: string]: unknown; }; @@ -8235,55 +9238,74 @@ export interface operations { }; }; }; - durable_config: { + create_agent_voice_session: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["VoiceCallRequest"]; + }; + }; responses: { - /** @description Resource config for durable surfaces */ - 200: { + /** @description Agent session and realtime call created */ + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ResourceConfigResponse"]; + "application/json": components["schemas"]["VoiceSessionResponse_VoiceCallResponse"]; }; }; }; }; - get_execution: { + invoke_a2a: { parameters: { query?: never; header?: never; path: { - /** @description Execution ID */ - execution_id: string; + /** @description App ID */ + app_id: string; + /** @description A2A channel ID */ + channel_id: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": unknown; + }; + }; responses: { - /** @description Execution details */ + /** @description JSON-RPC 2.0 response. For message/send and tasks/* the body is a single JSON envelope; for message/stream the body is text/event-stream of JSON-RPC envelopes. tasks/get and tasks/cancel surface -32001 Task not found for unknown task ids. */ 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Missing or invalid API key */ + 401: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ScheduleExecutionResponse"]; + "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Authentication required */ - 401: { + /** @description App is not published or channel disabled */ + 403: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; - /** @description Execution not found */ + /** @description App or channel not found */ 404: { headers: { [name: string]: unknown; @@ -8292,8 +9314,8 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description SSE connection limit reached for the org/session */ + 429: { headers: { [name: string]: unknown; }; @@ -8303,42 +9325,29 @@ export interface operations { }; }; }; - list_schedules: { + agent_card: { parameters: { - query?: { - /** @description Filter by enabled status */ - enabled?: boolean; - /** @description Filter by target type */ - target_type?: string; - /** @description Pagination offset */ - offset?: number; - /** @description Pagination limit */ - limit?: number; - }; + query?: never; header?: never; - path?: never; + path: { + /** @description App ID */ + app_id: string; + /** @description A2A channel ID */ + channel_id: string; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description List of schedules */ + /** @description Agent Card JSON */ 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["SchedulesListResponse"]; - }; - }; - /** @description Authentication required */ - 401: { headers: { [name: string]: unknown; }; content?: never; }; - /** @description Internal server error */ - 500: { + /** @description App or channel not found / unpublished / disabled */ + 404: { headers: { [name: string]: unknown; }; @@ -8348,30 +9357,35 @@ export interface operations { }; }; }; - create_schedule: { + invoke_webhook: { parameters: { query?: never; header?: never; - path?: never; + path: { + /** @description App ID */ + app_id: string; + /** @description Webhook channel ID */ + channel_id: string; + }; cookie?: never; }; requestBody: { content: { - "application/json": components["schemas"]["CreateScheduleRequest"]; + "application/octet-stream": string; }; }; responses: { - /** @description Schedule created */ - 201: { + /** @description Webhook accepted */ + 202: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ScheduleResponse"]; + "application/json": components["schemas"]["WebhookInvocationResponse"]; }; }; - /** @description Invalid request */ - 400: { + /** @description Invalid or missing webhook token */ + 401: { headers: { [name: string]: unknown; }; @@ -8379,15 +9393,17 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Authentication required */ - 401: { + /** @description App is not published or channel disabled */ + 403: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; - /** @description Schedule name already exists */ - 409: { + /** @description App or channel not found */ + 404: { headers: { [name: string]: unknown; }; @@ -8406,36 +9422,33 @@ export interface operations { }; }; }; - get_schedule: { + list_capabilities: { parameters: { - query?: never; - header?: never; - path: { - /** @description Schedule ID */ - schedule_id: string; + query?: { + /** @description Search by name/description */ + search?: string; + /** @description Pagination offset (default: 0) */ + offset?: number; + /** @description Page size (default: 20, max: 100) */ + limit?: number; }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Schedule details */ + /** @description Paginated list of capabilities */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ScheduleResponse"]; - }; - }; - /** @description Authentication required */ - 401: { - headers: { - [name: string]: unknown; + "application/json": components["schemas"]["PaginatedResponse_WithUrls_CapabilityInfo"]; }; - content?: never; }; - /** @description Schedule not found */ - 404: { + /** @description Invalid query parameters */ + 400: { headers: { [name: string]: unknown; }; @@ -8454,34 +9467,30 @@ export interface operations { }; }; }; - delete_schedule: { + create_declarative_capability: { parameters: { query?: never; header?: never; - path: { - /** @description Schedule ID */ - schedule_id: string; - }; + path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["CreateDeclarativeCapabilityRequest"]; + }; + }; responses: { - /** @description Schedule deleted */ - 204: { + /** @description Declarative capability created. Response id uses cap_<32-hex>; capability_id uses declarative:. */ + 201: { headers: { [name: string]: unknown; }; - content?: never; - }; - /** @description Authentication required */ - 401: { - headers: { - [name: string]: unknown; + content: { + "application/json": components["schemas"]["WithUrls_DeclarativeCapability"]; }; - content?: never; }; - /** @description Schedule not found */ - 404: { + /** @description Invalid declarative capability definition, name, limits, file mount, skill, or MCP server configuration. */ + 400: { headers: { [name: string]: unknown; }; @@ -8489,8 +9498,8 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description A declarative capability with the same unique name already exists. */ + 409: { headers: { [name: string]: unknown; }; @@ -8500,58 +9509,74 @@ export interface operations { }; }; }; - update_schedule: { + list_declarative_capabilities: { parameters: { - query?: never; - header?: never; - path: { - /** @description Schedule ID */ - schedule_id: string; + query?: { + /** @description Search by unique name, display name, or description */ + search?: string; + /** @description Include archived declarative capabilities */ + include_archived?: boolean; }; + header?: never; + path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["UpdateScheduleRequest"]; - }; - }; + requestBody?: never; responses: { - /** @description Schedule updated */ + /** @description Persisted declarative capability resources */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ScheduleResponse"]; + "application/json": components["schemas"]["ListResponse_WithUrls_DeclarativeCapability"]; }; }; - /** @description Invalid request */ - 400: { + }; + }; + declarative_capabilities_config: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Resource config for declarative capabilities */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ErrorResponse"]; + "application/json": components["schemas"]["ResourceConfigResponse"]; }; }; - /** @description Authentication required */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; + }; + }; + get_declarative_capability: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Public declarative capability resource ID, e.g. cap_01933b5a000070008000000000000001 */ + capability_id: string; }; - /** @description Schedule not found */ - 404: { + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Declarative capability resource */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ErrorResponse"]; + "application/json": components["schemas"]["WithUrls_DeclarativeCapability"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Declarative capability not found */ + 404: { headers: { [name: string]: unknown; }; @@ -8561,42 +9586,26 @@ export interface operations { }; }; }; - list_schedule_executions: { + delete_declarative_capability: { parameters: { - query?: { - /** @description Filter by status */ - status?: string; - /** @description Pagination offset */ - offset?: number; - /** @description Pagination limit */ - limit?: number; - }; + query?: never; header?: never; path: { - /** @description Schedule ID */ - schedule_id: string; + /** @description Public declarative capability resource ID */ + capability_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description List of executions */ + /** @description Declarative capability archived */ 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ScheduleExecutionsListResponse"]; - }; - }; - /** @description Authentication required */ - 401: { headers: { [name: string]: unknown; }; content?: never; }; - /** @description Schedule not found */ + /** @description Declarative capability not found */ 404: { headers: { [name: string]: unknown; @@ -8605,47 +9614,35 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; }; }; - pause_schedule: { + update_declarative_capability: { parameters: { query?: never; header?: never; path: { - /** @description Schedule ID */ - schedule_id: string; + /** @description Public declarative capability resource ID */ + capability_id: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateDeclarativeCapabilityRequest"]; + }; + }; responses: { - /** @description Schedule paused */ + /** @description Declarative capability updated */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ScheduleResponse"]; + "application/json": components["schemas"]["WithUrls_DeclarativeCapability"]; }; }; - /** @description Authentication required */ - 401: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Schedule not found */ - 404: { + /** @description Invalid update payload or declarative capability definition */ + 400: { headers: { [name: string]: unknown; }; @@ -8653,8 +9650,8 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description A declarative capability with the same unique name already exists */ + 409: { headers: { [name: string]: unknown; }; @@ -8664,35 +9661,26 @@ export interface operations { }; }; }; - resume_schedule: { + destroy_declarative_capability: { parameters: { query?: never; header?: never; path: { - /** @description Schedule ID */ - schedule_id: string; + /** @description Public declarative capability resource ID */ + capability_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Schedule resumed */ + /** @description Archived declarative capability permanently deleted */ 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ScheduleResponse"]; - }; - }; - /** @description Authentication required */ - 401: { headers: { [name: string]: unknown; }; content?: never; }; - /** @description Schedule not found */ + /** @description Declarative capability not found or not archived */ 404: { headers: { [name: string]: unknown; @@ -8701,46 +9689,30 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; - }; }; }; - get_schedule_stats: { + get_capability: { parameters: { query?: never; header?: never; path: { - /** @description Schedule ID */ - schedule_id: string; + /** @description Capability ID */ + capability_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Schedule statistics */ + /** @description Capability found */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ScheduleStatsResponse"]; - }; - }; - /** @description Authentication required */ - 401: { - headers: { - [name: string]: unknown; + "application/json": components["schemas"]["WithUrls_CapabilityInfo"]; }; - content?: never; }; - /** @description Schedule not found */ + /** @description Capability not found */ 404: { headers: { [name: string]: unknown; @@ -8760,25 +9732,45 @@ export interface operations { }; }; }; - trigger_schedule: { + durable_config: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Resource config for durable surfaces */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceConfigResponse"]; + }; + }; + }; + }; + get_execution: { parameters: { query?: never; header?: never; path: { - /** @description Schedule ID */ - schedule_id: string; + /** @description Execution ID */ + execution_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Schedule triggered */ + /** @description Execution details */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["TriggerResponse"]; + "application/json": components["schemas"]["ScheduleExecutionResponse"]; }; }; /** @description Authentication required */ @@ -8788,7 +9780,7 @@ export interface operations { }; content?: never; }; - /** @description Schedule not found */ + /** @description Execution not found */ 404: { headers: { [name: string]: unknown; @@ -8808,33 +9800,17 @@ export interface operations { }; }; }; - list_examples: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description List of harness examples */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["HarnessExample"][]; - }; - }; - }; - }; - list_harnesses: { + list_schedules: { parameters: { query?: { - /** @description Search by name or description (case-insensitive substring match). */ - search?: string | null; - /** @description Include archived harnesses. Deleted harnesses never appear in lists. */ - include_archived?: boolean | null; + /** @description Filter by enabled status */ + enabled?: boolean; + /** @description Filter by target type */ + target_type?: string; + /** @description Pagination offset */ + offset?: number; + /** @description Pagination limit */ + limit?: number; }; header?: never; path?: never; @@ -8842,17 +9818,17 @@ export interface operations { }; requestBody?: never; responses: { - /** @description List of harnesses */ + /** @description List of schedules */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ListResponse_WithUrls_ResourceWithCounts_Harness"]; + "application/json": components["schemas"]["SchedulesListResponse"]; }; }; - /** @description Forbidden */ - 403: { + /** @description Authentication required */ + 401: { headers: { [name: string]: unknown; }; @@ -8863,11 +9839,13 @@ export interface operations { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; }; }; - create_harness: { + create_schedule: { parameters: { query?: never; header?: never; @@ -8876,20 +9854,20 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["CreateHarnessRequest"]; + "application/json": components["schemas"]["CreateScheduleRequest"]; }; }; responses: { - /** @description Harness created */ + /** @description Schedule created */ 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WithUrls_Harness"]; + "application/json": components["schemas"]["ScheduleResponse"]; }; }; - /** @description Invalid input */ + /** @description Invalid request */ 400: { headers: { [name: string]: unknown; @@ -8898,8 +9876,15 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Forbidden */ - 403: { + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Schedule name already exists */ + 409: { headers: { [name: string]: unknown; }; @@ -8918,60 +9903,81 @@ export interface operations { }; }; }; - harness_config: { + get_schedule: { parameters: { query?: never; header?: never; - path?: never; + path: { + /** @description Schedule ID */ + schedule_id: string; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description Resource config for harnesses */ + /** @description Schedule details */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ResourceConfigResponse"]; + "application/json": components["schemas"]["ScheduleResponse"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Schedule not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; }; }; }; - import_harness: { + delete_schedule: { parameters: { - query: { - /** - * @description Import from a built-in harness example by name (e.g. `data-analyst`). - * Required: the only currently supported import mode is from-example. - */ - "from-example": string; - }; + query?: never; header?: never; - path?: never; + path: { + /** @description Schedule ID */ + schedule_id: string; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description Harness adopted from example */ - 201: { + /** @description Schedule deleted */ + 204: { headers: { [name: string]: unknown; }; - content: { - "application/json": components["schemas"]["WithUrls_Harness"]; - }; + content?: never; }; - /** @description Invalid input or missing capabilities */ - 400: { + /** @description Authentication required */ + 401: { headers: { [name: string]: unknown; }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; + content?: never; }; - /** @description Example not found */ + /** @description Schedule not found */ 404: { headers: { [name: string]: unknown; @@ -8991,26 +9997,54 @@ export interface operations { }; }; }; - preview_harness: { + update_schedule: { parameters: { query?: never; header?: never; - path?: never; + path: { + /** @description Schedule ID */ + schedule_id: string; + }; cookie?: never; }; requestBody: { content: { - "application/json": components["schemas"]["PreviewHarnessRequest"]; + "application/json": components["schemas"]["UpdateScheduleRequest"]; }; }; responses: { - /** @description Harness preview generated */ + /** @description Schedule updated */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["HarnessPreviewResponse"]; + "application/json": components["schemas"]["ScheduleResponse"]; + }; + }; + /** @description Invalid request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Authentication required */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Schedule not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; }; /** @description Internal server error */ @@ -9024,143 +10058,138 @@ export interface operations { }; }; }; - get_harness: { + list_schedule_executions: { parameters: { - query?: never; + query?: { + /** @description Filter by status */ + status?: string; + /** @description Pagination offset */ + offset?: number; + /** @description Pagination limit */ + limit?: number; + }; header?: never; path: { - /** @description Harness ID (prefixed) or name */ - harness_id: string; + /** @description Schedule ID */ + schedule_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Harness found */ + /** @description List of executions */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WithUrls_ResourceWithCounts_Harness"]; + "application/json": components["schemas"]["ScheduleExecutionsListResponse"]; }; }; - /** @description Forbidden */ - 403: { + /** @description Authentication required */ + 401: { headers: { [name: string]: unknown; }; content?: never; }; - /** @description Harness not found */ + /** @description Schedule not found */ 404: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; /** @description Internal server error */ 500: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; }; }; - delete_harness: { + pause_schedule: { parameters: { query?: never; header?: never; path: { - /** @description Harness ID (prefixed) */ - harness_id: string; + /** @description Schedule ID */ + schedule_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Harness archived */ - 204: { + /** @description Schedule paused */ + 200: { headers: { [name: string]: unknown; }; - content?: never; - }; - /** @description Invalid harness ID */ - 400: { - headers: { - [name: string]: unknown; + content: { + "application/json": components["schemas"]["ScheduleResponse"]; }; - content?: never; }; - /** @description Forbidden */ - 403: { + /** @description Authentication required */ + 401: { headers: { [name: string]: unknown; }; content?: never; }; - /** @description Harness not found */ + /** @description Schedule not found */ 404: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; /** @description Internal server error */ 500: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; }; }; - update_harness: { + resume_schedule: { parameters: { query?: never; header?: never; path: { - /** @description Harness ID (prefixed) */ - harness_id: string; + /** @description Schedule ID */ + schedule_id: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["UpdateHarnessRequest"]; - }; - }; + requestBody?: never; responses: { - /** @description Harness updated */ + /** @description Schedule resumed */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WithUrls_Harness"]; - }; - }; - /** @description Invalid input */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; + "application/json": components["schemas"]["ScheduleResponse"]; }; }; - /** @description Forbidden */ - 403: { + /** @description Authentication required */ + 401: { headers: { [name: string]: unknown; }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; + content?: never; }; - /** @description Harness not found */ + /** @description Schedule not found */ 404: { headers: { [name: string]: unknown; @@ -9180,46 +10209,35 @@ export interface operations { }; }; }; - copy_harness: { + get_schedule_stats: { parameters: { query?: never; header?: never; path: { - /** @description Source harness ID to copy */ - harness_id: string; + /** @description Schedule ID */ + schedule_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Harness copied successfully */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["WithUrls_Harness"]; - }; - }; - /** @description Invalid harness ID */ - 400: { + /** @description Schedule statistics */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ErrorResponse"]; + "application/json": components["schemas"]["ScheduleStatsResponse"]; }; }; - /** @description Forbidden */ - 403: { + /** @description Authentication required */ + 401: { headers: { [name: string]: unknown; }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; + content?: never; }; - /** @description Source harness not found */ + /** @description Schedule not found */ 404: { headers: { [name: string]: unknown; @@ -9239,37 +10257,35 @@ export interface operations { }; }; }; - get_harness_stats: { + trigger_schedule: { parameters: { query?: never; header?: never; path: { - /** @description Harness ID (prefixed) or name */ - harness_id: string; + /** @description Schedule ID */ + schedule_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Harness aggregate stats */ + /** @description Schedule triggered */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ResourceStatsResponse"]; + "application/json": components["schemas"]["TriggerResponse"]; }; }; - /** @description Forbidden */ - 403: { + /** @description Authentication required */ + 401: { headers: { [name: string]: unknown; }; - content: { - "application/json": components["schemas"]["ErrorResponse"]; - }; + content?: never; }; - /** @description Harness not found */ + /** @description Schedule not found */ 404: { headers: { [name: string]: unknown; @@ -9289,66 +10305,51 @@ export interface operations { }; }; }; - list_images: { + list_examples: { parameters: { - query?: { - /** @description Max items to return (default 50) */ - limit?: number; - /** @description Items to skip */ - offset?: number; - }; + query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description List of images */ + /** @description List of harness examples */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ImageInfo"][]; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; + "application/json": components["schemas"]["HarnessExample"][]; }; - content?: never; }; }; }; - upload_image: { + list_harnesses: { parameters: { query?: { - /** @description Optional: session ID stored as metadata for tracking (not required for upload) */ - session_id?: string; + /** @description Search by name or description (case-insensitive substring match). */ + search?: string | null; + /** @description Include archived harnesses. Deleted harnesses never appear in lists. */ + include_archived?: boolean | null; }; header?: never; path?: never; cookie?: never; }; - /** @description Multipart form data with 'file' field */ - requestBody: { - content: { - "multipart/form-data": string; - }; - }; + requestBody?: never; responses: { - /** @description Image uploaded successfully */ - 201: { + /** @description List of harnesses */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ImageUploadResponse"]; + "application/json": components["schemas"]["ListResponse_WithUrls_ResourceWithCounts_Harness"]; }; }; - /** @description Invalid request (bad format, size exceeded, etc.) */ - 400: { + /** @description Forbidden */ + 403: { headers: { [name: string]: unknown; }; @@ -9363,28 +10364,524 @@ export interface operations { }; }; }; - get_image: { + create_harness: { parameters: { query?: never; header?: never; - path: { - /** @description Image ID (prefixed, e.g., img_...) */ - image_id: string; - }; + path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["CreateHarnessRequest"]; + }; + }; responses: { - /** @description Image binary data */ - 200: { + /** @description Harness created */ + 201: { headers: { [name: string]: unknown; }; content: { - "image/*": unknown; + "application/json": components["schemas"]["WithUrls_Harness"]; }; }; - /** @description Invalid image ID */ + /** @description Invalid input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + harness_config: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Resource config for harnesses */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceConfigResponse"]; + }; + }; + }; + }; + import_harness: { + parameters: { + query: { + /** + * @description Import from a built-in harness example by name (e.g. `data-analyst`). + * Required: the only currently supported import mode is from-example. + */ + "from-example": string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Harness adopted from example */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WithUrls_Harness"]; + }; + }; + /** @description Invalid input or missing capabilities */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Example not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + preview_harness: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PreviewHarnessRequest"]; + }; + }; + responses: { + /** @description Harness preview generated */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HarnessPreviewResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + get_harness: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Harness ID (prefixed) or name */ + harness_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Harness found */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WithUrls_ResourceWithCounts_Harness"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Harness not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + delete_harness: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Harness ID (prefixed) */ + harness_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Harness archived */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Invalid harness ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Harness not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + update_harness: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Harness ID (prefixed) */ + harness_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateHarnessRequest"]; + }; + }; + responses: { + /** @description Harness updated */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WithUrls_Harness"]; + }; + }; + /** @description Invalid input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Harness not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + copy_harness: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Source harness ID to copy */ + harness_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Harness copied successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WithUrls_Harness"]; + }; + }; + /** @description Invalid harness ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Source harness not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + get_harness_stats: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Harness ID (prefixed) or name */ + harness_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Harness aggregate stats */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ResourceStatsResponse"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Harness not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + list_images: { + parameters: { + query?: { + /** @description Max items to return (default 50) */ + limit?: number; + /** @description Items to skip */ + offset?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of images */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImageInfo"][]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + upload_image: { + parameters: { + query?: { + /** @description Optional: session ID stored as metadata for tracking (not required for upload) */ + session_id?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + /** @description Multipart form data with 'file' field */ + requestBody: { + content: { + "multipart/form-data": string; + }; + }; + responses: { + /** @description Image uploaded successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ImageUploadResponse"]; + }; + }; + /** @description Invalid request (bad format, size exceeded, etc.) */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + get_image: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Image ID (prefixed, e.g., img_...) */ + image_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Image binary data */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "image/*": unknown; + }; + }; + /** @description Invalid image ID */ 400: { headers: { [name: string]: unknown; @@ -10328,11 +11825,213 @@ export interface operations { headers: { [name: string]: unknown; }; - content?: never; + content?: never; + }; + }; + }; + create_mcp_server: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateMcpServerRequest"]; + }; + }; + responses: { + /** @description MCP server created successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WithUrls_McpServer"]; + }; + }; + /** @description Invalid input or duplicate name */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + get_mcp_server: { + parameters: { + query?: never; + header?: never; + path: { + /** @description MCP server ID (prefixed, e.g., mcp_...) */ + server_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description MCP server found */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WithUrls_McpServer"]; + }; + }; + /** @description Invalid server ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description MCP server not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + delete_mcp_server: { + parameters: { + query?: never; + header?: never; + path: { + /** @description MCP server ID (prefixed, e.g., mcp_...) */ + server_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description MCP server deleted successfully */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Invalid server ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description MCP server not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + update_mcp_server: { + parameters: { + query?: never; + header?: never; + path: { + /** @description MCP server ID (prefixed, e.g., mcp_...) */ + server_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateMcpServerRequest"]; + }; + }; + responses: { + /** @description MCP server updated successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WithUrls_McpServer"]; + }; + }; + /** @description Invalid server ID or input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description MCP server not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + list_memory_stores: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List org memory stores */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListResponse_MemoryStoreResponse"]; + }; }; }; }; - create_mcp_server: { + create_memory_store: { parameters: { query?: never; header?: never; @@ -10341,20 +12040,20 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["CreateMcpServerRequest"]; + "application/json": components["schemas"]["CreateMemoryStoreRequest"]; }; }; responses: { - /** @description MCP server created successfully */ + /** @description Memory store created */ 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WithUrls_McpServer"]; + "application/json": components["schemas"]["MemoryStoreResponse"]; }; }; - /** @description Invalid input or duplicate name */ + /** @description Invalid input */ 400: { headers: { [name: string]: unknown; @@ -10363,8 +12062,8 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Duplicate name or default conflict */ + 409: { headers: { [name: string]: unknown; }; @@ -10374,118 +12073,151 @@ export interface operations { }; }; }; - get_mcp_server: { + get_memory_store: { parameters: { query?: never; header?: never; path: { - /** @description MCP server ID (prefixed, e.g., mcp_...) */ - server_id: string; + /** @description Memory store ID */ + store_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description MCP server found */ + /** @description Memory store */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WithUrls_McpServer"]; + "application/json": components["schemas"]["MemoryStoreResponse"]; }; }; - /** @description Invalid server ID */ - 400: { + /** @description Not found */ + 404: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; - /** @description MCP server not found */ - 404: { + }; + }; + list_memories: { + parameters: { + query?: { + query?: string | null; + kind?: string | null; + tag?: string[] | null; + include_inactive?: boolean | null; + limit?: number | null; + }; + header?: never; + path: { + /** @description Memory store ID */ + store_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Memories */ + 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ListMemoriesResponse"]; + }; }; - /** @description Internal server error */ - 500: { + /** @description Store not found */ + 404: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; }; }; - delete_mcp_server: { + forget_memory: { parameters: { query?: never; header?: never; path: { - /** @description MCP server ID (prefixed, e.g., mcp_...) */ - server_id: string; + /** @description Memory store ID */ + store_id: string; + /** @description Memory ID */ + memory_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description MCP server deleted successfully */ + /** @description Memory deactivated */ 204: { headers: { [name: string]: unknown; }; content?: never; }; - /** @description Invalid server ID */ - 400: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description MCP server not found */ + /** @description Not found */ 404: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; }; - /** @description Internal server error */ - 500: { + }; + }; + list_organizations: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of organizations */ + 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["ListResponse_OrganizationResponse"]; + }; }; }; }; - update_mcp_server: { + create_organization: { parameters: { query?: never; header?: never; - path: { - /** @description MCP server ID (prefixed, e.g., mcp_...) */ - server_id: string; - }; + path?: never; cookie?: never; }; requestBody: { content: { - "application/json": components["schemas"]["UpdateMcpServerRequest"]; + "application/json": components["schemas"]["CreateOrganizationRequest"]; }; }; responses: { - /** @description MCP server updated successfully */ - 200: { + /** @description Organization created */ + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["WithUrls_McpServer"]; + "application/json": components["schemas"]["OrganizationResponse"]; }; }; - /** @description Invalid server ID or input */ + /** @description Invalid input */ 400: { headers: { [name: string]: unknown; @@ -10494,7 +12226,30 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description MCP server not found */ + }; + }; + get_organization: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Organization public ID */ + org: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Organization details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["OrganizationResponse"]; + }; + }; + /** @description Organization not found */ 404: { headers: { [name: string]: unknown; @@ -10503,8 +12258,35 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Internal server error */ - 500: { + }; + }; + update_organization: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Organization public ID */ + org: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateOrganizationRequest"]; + }; + }; + responses: { + /** @description Organization updated */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["OrganizationResponse"]; + }; + }; + /** @description Organization not found */ + 404: { headers: { [name: string]: unknown; }; @@ -10514,27 +12296,30 @@ export interface operations { }; }; }; - list_memory_stores: { + list_payment_accounts: { parameters: { - query?: never; + query?: { + owner_type?: string | null; + owner_id?: string | null; + }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description List org memory stores */ + /** @description List payment accounts */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ListResponse_MemoryStoreResponse"]; + "application/json": components["schemas"]["PaymentAccount"][]; }; }; }; }; - create_memory_store: { + create_payment_account: { parameters: { query?: never; header?: never; @@ -10543,17 +12328,17 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["CreateMemoryStoreRequest"]; + "application/json": components["schemas"]["CreatePaymentAccountRequest"]; }; }; responses: { - /** @description Memory store created */ + /** @description Payment account created */ 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["MemoryStoreResponse"]; + "application/json": components["schemas"]["PaymentAccount"]; }; }; /** @description Invalid input */ @@ -10565,8 +12350,31 @@ export interface operations { "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Duplicate name or default conflict */ - 409: { + }; + }; + get_payment_account: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Payment account ID */ + payment_account_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Payment account */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PaymentAccount"]; + }; + }; + /** @description Not found */ + 404: { headers: { [name: string]: unknown; }; @@ -10576,26 +12384,24 @@ export interface operations { }; }; }; - get_memory_store: { + disable_payment_account: { parameters: { query?: never; header?: never; path: { - /** @description Memory store ID */ - store_id: string; + /** @description Payment account ID */ + payment_account_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Memory store */ - 200: { + /** @description Payment account disabled */ + 204: { headers: { [name: string]: unknown; }; - content: { - "application/json": components["schemas"]["MemoryStoreResponse"]; - }; + content?: never; }; /** @description Not found */ 404: { @@ -10608,34 +12414,41 @@ export interface operations { }; }; }; - list_memories: { + update_payment_account: { parameters: { - query?: { - query?: string | null; - kind?: string | null; - tag?: string[] | null; - include_inactive?: boolean | null; - limit?: number | null; - }; + query?: never; header?: never; path: { - /** @description Memory store ID */ - store_id: string; + /** @description Payment account ID */ + payment_account_id: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePaymentAccountRequest"]; + }; + }; responses: { - /** @description Memories */ + /** @description Payment account updated */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ListMemoriesResponse"]; + "application/json": components["schemas"]["PaymentAccount"]; + }; + }; + /** @description Invalid input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; }; }; - /** @description Store not found */ + /** @description Not found */ 404: { headers: { [name: string]: unknown; @@ -10646,59 +12459,54 @@ export interface operations { }; }; }; - forget_memory: { + list_payment_attempts: { parameters: { - query?: never; - header?: never; - path: { - /** @description Memory store ID */ - store_id: string; - /** @description Memory ID */ - memory_id: string; + query?: { + session_id?: string | null; + limit?: number; }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Memory deactivated */ - 204: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Not found */ - 404: { + /** @description List payment attempts */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ErrorResponse"]; + "application/json": components["schemas"]["PaymentAttempt"][]; }; }; }; }; - list_organizations: { + list_payment_policies: { parameters: { - query?: never; + query?: { + payment_account_id?: string | null; + subject_type?: string | null; + subject_id?: string | null; + }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description List of organizations */ + /** @description List payment policies */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ListResponse_OrganizationResponse"]; + "application/json": components["schemas"]["PaymentPolicy"][]; }; }; }; }; - create_organization: { + create_payment_policy: { parameters: { query?: never; header?: never; @@ -10707,17 +12515,17 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["CreateOrganizationRequest"]; + "application/json": components["schemas"]["CreatePaymentPolicyRequest"]; }; }; responses: { - /** @description Organization created */ + /** @description Payment policy created */ 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["OrganizationResponse"]; + "application/json": components["schemas"]["PaymentPolicy"]; }; }; /** @description Invalid input */ @@ -10731,28 +12539,28 @@ export interface operations { }; }; }; - get_organization: { + get_payment_policy: { parameters: { query?: never; header?: never; path: { - /** @description Organization public ID */ - org: string; + /** @description Payment policy ID */ + payment_policy_id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Organization details */ + /** @description Payment policy */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["OrganizationResponse"]; + "application/json": components["schemas"]["PaymentPolicy"]; }; }; - /** @description Organization not found */ + /** @description Not found */ 404: { headers: { [name: string]: unknown; @@ -10763,32 +12571,71 @@ export interface operations { }; }; }; - update_organization: { + disable_payment_policy: { parameters: { query?: never; header?: never; path: { - /** @description Organization public ID */ - org: string; + /** @description Payment policy ID */ + payment_policy_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Payment policy disabled */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + update_payment_policy: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Payment policy ID */ + payment_policy_id: string; }; cookie?: never; }; requestBody: { content: { - "application/json": components["schemas"]["UpdateOrganizationRequest"]; + "application/json": components["schemas"]["UpdatePaymentPolicyRequest"]; }; }; responses: { - /** @description Organization updated */ + /** @description Payment policy updated */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["OrganizationResponse"]; + "application/json": components["schemas"]["PaymentPolicy"]; }; }; - /** @description Organization not found */ + /** @description Invalid input */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description Not found */ 404: { headers: { [name: string]: unknown; @@ -10916,6 +12763,30 @@ export interface operations { }; }; }; + create_chat_voice_session: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VoiceCallRequest"]; + }; + }; + responses: { + /** @description Platform chat session and realtime call created */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VoiceSessionResponse_VoiceCallResponse"]; + }; + }; + }; + }; get_session: { parameters: { query?: never; @@ -11314,27 +13185,45 @@ export interface operations { parameters: { query?: { /** @description Filter events with ID greater than this event ID (prefixed format: event_{32-hex}) */ - since_id?: null | components["schemas"]["TypedId"]; - /** - * @description Positive type filter: only return events matching these types (can be specified multiple times). - * When empty, all types are returned. Example: ?types=turn.started&types=turn.completed - */ + since_id?: null | components["schemas"]["eventId"]; + /** @description Positive type filter (repeat key). Empty = all types. */ types?: string[]; - /** - * @description Event types to exclude from the response (can be specified multiple times). - * Applied after `types` filter. Common delta events to exclude: output.message.delta, reason.thinking.delta - */ + /** @description Event types to exclude (repeat key); applied after `types`. */ exclude?: string[]; /** * @description Max events to return (backward pagination). When set, returns the last N events * (or last N before `before_sequence`). Results are ordered oldest→newest. */ limit?: number | null; - /** - * @description Cursor for backward pagination: only return events with sequence < this value. - * Used with `limit` to paginate backward through event history. - */ + /** @description Cursor for backward pagination: only return events with sequence < this value. */ before_sequence?: number | null; + /** @description Forward cursor: only return events with sequence > this value. */ + after_sequence?: number | null; + /** + * @description Anchor event id: returns up to `window` events on each side (default 50, max 500). + * Mutually exclusive with `since_id`, `after_sequence`, and `before_sequence` — 400 if combined. + */ + around?: null | components["schemas"]["eventId"]; + /** @description Window size for `around` (events on each side). Defaults to 50, max 500. */ + window?: number | null; + /** @description Lower bound on `created_at` (RFC 3339, e.g. `2025-05-07T00:00:00Z`). */ + from_ts?: string | null; + /** @description Upper bound on `created_at`. */ + to_ts?: string | null; + /** @description Filter by `context.turn_id` (prefixed id, e.g. `turn_...`). */ + turn_id?: string | null; + /** @description Filter by `context.exec_id` (prefixed id, e.g. `exec_...`). */ + exec_id?: string | null; + /** @description Filter by `context.trace_id`. */ + trace_id?: string | null; + /** @description Tag any-match against `events.tags` (repeat key for multiple values). */ + tags?: string[]; + /** @description Filter by `data.tool_name` — useful for narrowing `tool.*` events. */ + tool_name?: string | null; + /** @description Full-text search (Postgres tsvector; substring fallback for in-memory mode). */ + q?: string | null; + /** @description When true, return newest first; default oldest first. */ + order_desc?: boolean; }; header?: never; path: { @@ -11379,6 +13268,50 @@ export interface operations { }; }; }; + events_summary: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Session ID (prefixed, e.g., sess_...) */ + session_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Per-type counts and time span for the session */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["EventsSummaryResult"]; + }; + }; + /** @description Invalid session ID */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Session not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; export_session_jsonl: { parameters: { query?: never; @@ -12406,7 +14339,7 @@ export interface operations { parameters: { query?: { /** @description Filter events with ID greater than this event ID (prefixed format: event_{32-hex}) */ - since_id?: null | components["schemas"]["TypedId"]; + since_id?: null | components["schemas"]["eventId"]; /** * @description Positive type filter: only return events matching these types (can be specified multiple times). * When empty, all types are returned. Example: ?types=turn.started&types=turn.completed @@ -12417,16 +14350,6 @@ export interface operations { * Applied after `types` filter. Common delta events to exclude: output.message.delta, reason.thinking.delta */ exclude?: string[]; - /** - * @description Max events to return (backward pagination). When set, returns the last N events - * (or last N before `before_sequence`). Results are ordered oldest→newest. - */ - limit?: number | null; - /** - * @description Cursor for backward pagination: only return events with sequence < this value. - * Used with `limit` to paginate backward through event history. - */ - before_sequence?: number | null; }; header?: never; path: { @@ -12598,6 +14521,112 @@ export interface operations { }; }; }; + create_call: { + parameters: { + query?: never; + header?: never; + path: { + session_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VoiceCallRequest"]; + }; + }; + responses: { + /** @description Realtime WebRTC call created */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VoiceCallResponse"]; + }; + }; + }; + }; + create_client_secret: { + parameters: { + query?: never; + header?: never; + path: { + session_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VoiceClientSecretRequest"]; + }; + }; + responses: { + /** @description Realtime client secret created */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VoiceClientSecretResponse"]; + }; + }; + }; + }; + attach_call: { + parameters: { + query?: never; + header?: never; + path: { + session_id: string; + voice_connection_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VoiceAttachRequest"]; + }; + }; + responses: { + /** @description Realtime sideband attached */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VoiceAttachResponse"]; + }; + }; + }; + }; + end_call: { + parameters: { + query?: never; + header?: never; + path: { + session_id: string; + voice_connection_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VoiceEndRequest"]; + }; + }; + responses: { + /** @description Realtime voice connection ended */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VoiceEndResponse"]; + }; + }; + }; + }; list_skills: { parameters: { query?: { diff --git a/typescript/src/models.ts b/typescript/src/models.ts index fb569fb..b908856 100644 --- a/typescript/src/models.ts +++ b/typescript/src/models.ts @@ -68,6 +68,61 @@ export interface Agent { updatedAt: string; } +export type AgentVersionChangeKind = + | "manual" + | "patch" + | "minor" + | "major" + | "import" + | "rollback" + | "fork"; + +export interface AgentVersion { + id: string; + agent_id: string; + version_number: number; + semver_major: number; + semver_minor: number; + semver_patch: number; + version: string; + change_kind: AgentVersionChangeKind; + config_hash: string; + authored_config: Record; + resolved_config: Record; + created_at: string; + created_by_principal_id?: string | null; + parent_version_id?: string | null; + source_version_id?: string | null; + summary?: string | null; +} + +export interface AgentVersionDiffResponse { + from_version_id: string; + to_version_id: string; + authored_diff: unknown; + resolved_diff: unknown; +} + +export interface CreateAgentVersionRequest { + changeKind?: AgentVersionChangeKind | null; + summary?: string | null; +} + +export interface SetDefaultAgentVersionRequest { + versionId: string; +} + +export interface ForkAgentVersionRequest { + name: string; + displayName?: string | null; + description?: string | null; +} + +export interface RollbackAgentVersionRequest { + saveVersion?: boolean; + summary?: string | null; +} + export interface CreateAgentRequest { /** Client-supplied agent ID (format: agent_{32-hex}). Auto-generated if omitted. */ id?: string; diff --git a/typescript/tests/client.test.ts b/typescript/tests/client.test.ts index 24abbd9..f88ceaf 100644 --- a/typescript/tests/client.test.ts +++ b/typescript/tests/client.test.ts @@ -10,6 +10,7 @@ import { extractToolCalls, toolResult, toolError, + type AgentVersion, type AgentCapabilityConfig, type Budget, type BudgetCheckResult, @@ -381,6 +382,149 @@ describe("Everruns", () => { ); }); + it("should call agent version endpoints", async () => { + const version: AgentVersion = { + id: "agentver_123", + agent_id: "agent_123", + version_number: 1, + semver_major: 1, + semver_minor: 0, + semver_patch: 0, + version: "1.0.0", + change_kind: "manual", + config_hash: "hash_123", + authored_config: { name: "assistant" }, + resolved_config: { name: "assistant" }, + created_at: "2026-05-08T00:00:00Z", + summary: "Initial version", + }; + const agent = { + id: "agent_456", + name: "forked-agent", + system_prompt: "Help.", + status: "active", + created_at: "2026-05-08T00:00:00Z", + updated_at: "2026-05-08T00:00:00Z", + }; + const fetchMock = vi + .fn() + .mockImplementation((url: string, init?: RequestInit) => ({ + ok: true, + status: 200, + json: async () => { + if (url.endsWith("/versions") && init?.method !== "POST") + return [version]; + if (url.includes("/diff/")) { + return { + from_version_id: "agentver_1", + to_version_id: "agentver_2", + authored_diff: [], + resolved_diff: [], + }; + } + if (url.endsWith("/versions/default") || url.endsWith("/fork")) { + return agent; + } + if (url.endsWith("/rollback")) return agent; + return version; + }, + })); + vi.stubGlobal("fetch", fetchMock); + + const client = new Everruns({ apiKey: "evr_test_key" }); + const versions = await client.agents.listVersions("agent_123"); + const created = await client.agents.createVersion("agent_123", { + changeKind: "manual", + summary: "Initial version", + }); + const defaultAgent = await client.agents.setDefaultVersion("agent_123", { + versionId: "agentver_1", + }); + const diff = await client.agents.diffVersions( + "agent_123", + "agentver_1", + "agentver_2", + ); + const forkedAgent = await client.agents.forkVersion( + "agent_123", + "agentver_1", + { + name: "forked-agent", + displayName: "Forked Agent", + description: "Forked", + }, + ); + const rolledBackAgent = await client.agents.rollbackVersion( + "agent_123", + "agentver_1", + { saveVersion: true, summary: "Revert" }, + ); + + expect(versions[0].id).toBe("agentver_123"); + expect(created.summary).toBe("Initial version"); + expect(defaultAgent.id).toBe("agent_456"); + expect(diff.to_version_id).toBe("agentver_2"); + expect(forkedAgent.name).toBe("forked-agent"); + expect(rolledBackAgent.name).toBe("forked-agent"); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + "https://custom.example.com/api/v1/agents/agent_123/versions", + expect.objectContaining({ headers: expect.any(Object) }), + ); + expect(fetchMock).toHaveBeenNthCalledWith( + 2, + "https://custom.example.com/api/v1/agents/agent_123/versions", + expect.objectContaining({ + method: "POST", + body: JSON.stringify({ + change_kind: "manual", + summary: "Initial version", + }), + }), + ); + expect(fetchMock).toHaveBeenNthCalledWith( + 3, + "https://custom.example.com/api/v1/agents/agent_123/versions/default", + expect.objectContaining({ + method: "POST", + body: JSON.stringify({ version_id: "agentver_1" }), + }), + ); + expect(fetchMock).toHaveBeenNthCalledWith( + 5, + "https://custom.example.com/api/v1/agents/agent_123/versions/agentver_1/fork", + expect.objectContaining({ + method: "POST", + body: JSON.stringify({ + name: "forked-agent", + display_name: "Forked Agent", + description: "Forked", + }), + }), + ); + expect(fetchMock).toHaveBeenNthCalledWith( + 6, + "https://custom.example.com/api/v1/agents/agent_123/versions/agentver_1/rollback", + expect.objectContaining({ + method: "POST", + body: JSON.stringify({ save_version: true, summary: "Revert" }), + }), + ); + }); + + it("should validate forked agent version names", async () => { + const fetchMock = vi.fn(); + vi.stubGlobal("fetch", fetchMock); + const client = new Everruns({ apiKey: "evr_test_key" }); + + await expect( + client.agents.forkVersion("agent_123", "agentver_1", { + name: "Invalid Name", + }), + ).rejects.toThrow("agent_name must match pattern"); + expect(fetchMock).not.toHaveBeenCalled(); + }); + it("should list capabilities with search and pagination", async () => { const fetchMock = vi.fn().mockResolvedValue({ ok: true,