openapi: 3.1.0 info: title: agentkernel API description: | HTTP REST API for managing isolated sandboxes. All commands run in secure, isolated containers (Docker/Podman) or microVMs (Firecracker). ## Security Model - All code execution happens in isolated sandboxes - Sandboxes cannot access the host filesystem by default - Network access can be restricted per security profile - Three security profiles: permissive, moderate (default), restrictive ## Authentication Authentication is optional. When enabled, use Bearer token in the Authorization header. version: 0.15.0 license: name: MIT url: https://opensource.org/licenses/MIT contact: name: agentkernel url: https://github.com/thrashr888/agentkernel servers: - url: http://localhost:18888 description: Local development server security: - {} - BearerAuth: [] tags: - name: Health description: Health check endpoint - name: Run description: One-shot command execution - name: Tasks description: Durable agent task submission and lifecycle management - name: Sandboxes description: Persistent sandbox management - name: Files description: File operations inside sandboxes - name: Batch description: Parallel batch execution - name: Snapshots description: Snapshot and restore operations - name: Objects description: Durable object management (stateful sandbox actors) - name: Schedules description: Schedule management (timed triggers) - name: Stores description: Durable store management (sqlite, kv, queue) - name: Events description: Real-time sandbox lifecycle event stream - name: LLM Spend description: Authenticated, token-only LLM usage aggregates - name: SCIM description: Authenticated SCIM 2.0 user provisioning and group membership sync - name: Quotas description: Tenant-scoped enterprise resource quotas paths: /health: get: tags: [Health] summary: Health check description: Returns 200 if the server is healthy. operationId: healthCheck security: [] responses: '200': description: Server is healthy content: application/json: schema: $ref: '#/components/schemas/HealthResponse' /metrics: get: tags: [Health] summary: Prometheus metrics description: Returns Prometheus metrics in the text exposition format. operationId: getMetrics security: [] responses: '200': description: Prometheus metrics content: text/plain: schema: type: string /llm/spend: get: tags: [LLM Spend] summary: Query identity-aware LLM token usage description: | Returns daily aggregates from intercepted LLM traffic. This endpoint requires a validated JWT or configured API key even when the rest of the server allows anonymous local requests. Non-admin identities are hard-filtered to their authenticated organization and user. The response contains token counts only; prompts, responses, headers, secrets, and monetary estimates are never returned. operationId: getLlmSpend security: - BearerAuth: [] parameters: - name: agent in: query schema: {type: string} - name: user in: query schema: {type: string} - name: project in: query schema: {type: string} - name: from in: query description: Inclusive UTC date (YYYY-MM-DD) or RFC3339 timestamp schema: {type: string} - name: to in: query description: Inclusive UTC date (YYYY-MM-DD) or RFC3339 timestamp schema: {type: string} - name: limit in: query schema: {type: integer, minimum: 1, maximum: 200, default: 100} - name: offset in: query schema: {type: integer, minimum: 0, maximum: 100000, default: 0} responses: '200': description: Daily token aggregates content: application/json: schema: $ref: '#/components/schemas/LlmSpendResponse' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '503': $ref: '#/components/responses/ServiceUnavailable' /quotas: get: tags: [Quotas] summary: Get tenant-scoped resource quota usage description: | Returns the authenticated user's and organization's configured limits and current usage. When enterprise quotas are disabled, `enabled` is false and usage is still returned for the authenticated tenant. Quota accounting covers persistent HTTP create, list, get, start, stop, pause, resume, fork, resize, delete, logs, snapshot restore, and config import. Snapshot restore is created stopped and consumes total capacity; its running slot is charged when started. Firecracker CLI and MCP lifecycle operations delegate through these quota-enforced HTTP routes. Ephemeral `/run`, direct CLI/MCP manager calls, scheduler, and background object/task entrypoints are not quota-accounted. All sandbox-scoped HTTP routes are owner-filtered; only an explicit JWT `admin` role may cross owners. Unauthorized and legacy unowned sandboxes return `404` without revealing ownership. operationId: getQuotas responses: '200': description: Quota status content: application/json: schema: $ref: '#/components/schemas/QuotaStatusResponse' '401': description: Authentication required when API keys are configured '500': $ref: '#/components/responses/InternalError' /run: post: tags: [Run] summary: Run a command in a temporary sandbox description: | Executes a command in an isolated sandbox and returns the output. The sandbox is automatically cleaned up after execution. By default, uses a pre-warmed container pool for fast execution (~50ms). Set `fast: false` for custom images or advanced options (~500ms). operationId: runCommand requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RunRequest' examples: simple: summary: Simple echo command value: command: ["echo", "hello world"] python: summary: Run Python code value: command: ["python3", "-c", "print('Hello from Python!')"] custom_image: summary: Custom image (slow path) value: command: ["node", "--version"] image: "node:22-alpine" fast: false responses: '200': description: Command executed successfully content: application/json: schema: $ref: '#/components/schemas/RunResponse' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /tasks: post: tags: [Tasks] summary: Submit an agent task description: Queues a prompt for the selected sandbox. Execution is handled by the task worker. operationId: createTask requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateTaskRequest' example: prompt: "Inspect the failing test" sandbox: "sandbox-1" responses: '201': description: Task queued content: application/json: schema: $ref: '#/components/schemas/TaskResponse' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' get: tags: [Tasks] summary: List agent tasks description: Returns the newest 200 tasks first. operationId: listTasks responses: '200': description: Tasks returned content: application/json: schema: $ref: '#/components/schemas/TaskListResponse' '500': $ref: '#/components/responses/InternalError' /tasks/{task_id}: parameters: - name: task_id in: path required: true description: Task UUID schema: type: string format: uuid get: tags: [Tasks] summary: Inspect an agent task operationId: getTask responses: '200': description: Task found content: application/json: schema: $ref: '#/components/schemas/TaskResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' delete: tags: [Tasks] summary: Cancel an agent task description: Cancels queued or running work. Cancellation is idempotent for an already-cancelled task. operationId: cancelTask responses: '200': description: Task cancelled content: application/json: schema: $ref: '#/components/schemas/TaskResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '409': description: Task has already reached a terminal status content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': $ref: '#/components/responses/InternalError' /status: get: tags: [Health] summary: Server status description: Returns server version, backend, and whether API key auth is configured. operationId: getStatus security: [] responses: '200': description: Server status content: application/json: schema: $ref: '#/components/schemas/StatusResponse' /stats: get: tags: [Health] summary: Server statistics description: | Returns current sandbox count, resource usage (CPU, memory, disk), and server metadata. Designed for fleet load-balancing decisions. operationId: getStats security: [] responses: '200': description: Server statistics content: application/json: schema: $ref: '#/components/schemas/StatsResponse' examples: default: value: success: true data: sandbox_count: 12 sandbox_limit: 0 backend: "docker" uptime_seconds: 3600 version: "0.15.0" resource_usage: cpu_percent: 65.2 memory_used_mb: 8192 memory_total_mb: 16384 disk_used_mb: 4096 /events: get: tags: [Events] summary: Stream sandbox lifecycle events via SSE description: | Server-Sent Events (SSE) endpoint that streams sandbox lifecycle events in real-time. No authentication required. Returns events for up to 30 seconds or 100 events, whichever comes first. Events include: `sandbox.created`, `sandbox.exec.completed`, `sandbox.deleted`. Requires the server to be started with `--webhook-url` or `--otel-endpoint` to enable the event bus. operationId: streamEvents parameters: - name: sandbox in: query description: Filter events to a specific sandbox name required: false schema: type: string responses: '200': description: SSE event stream content: text/event-stream: schema: type: string examples: created: value: | event: sandbox.created data: {"event":"sandbox.created","timestamp":"2026-02-23T12:00:00Z","sandbox":"my-sandbox","labels":{},"metadata":{"image":"alpine:3.24","backend":"docker","vcpus":1,"memory_mb":512,"duration_ms":150}} '503': description: Event bus not enabled /gc: post: tags: [Sandboxes] summary: Garbage-collect expired sandboxes description: Removes sandboxes that have exceeded their time-to-live. Enterprise deployments require an administrator identity. operationId: garbageCollect responses: '200': description: GC result content: application/json: schema: $ref: '#/components/schemas/GcResponse' '403': description: Enterprise fleet garbage collection requires an administrator identity content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /lifecycle/reconcile: post: tags: [Sandboxes] summary: Reconcile sandbox lifecycle policies description: | Evaluates lifecycle policies for all sandboxes and applies any needed stop/archive/delete actions. Supports dry-run mode for previews. Enterprise deployments require an administrator identity. operationId: reconcileLifecycle requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/ReconcileLifecycleRequest' examples: apply: summary: Apply actions value: {} dry_run: summary: Preview actions only value: dry_run: true responses: '200': description: Lifecycle reconciliation result content: application/json: schema: $ref: '#/components/schemas/LifecycleReconcileResponse' '400': $ref: '#/components/responses/BadRequest' '403': description: Enterprise lifecycle reconciliation requires an administrator identity content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': $ref: '#/components/responses/InternalError' /sandboxes: get: tags: [Sandboxes] summary: List all sandboxes description: | Returns a list of all sandboxes and their current status. Supports filtering by labels using `?label=key:value` query parameters. Multiple label filters are ANDed together. operationId: listSandboxes parameters: - name: label in: query description: | Filter by label (format: `key:value`). Can be repeated for AND logic. Note: uses `:` separator in HTTP (not `=` like CLI) to avoid URL encoding issues. schema: type: string example: "env:prod" responses: '200': description: List of sandboxes content: application/json: schema: $ref: '#/components/schemas/SandboxListResponse' '500': $ref: '#/components/responses/InternalError' post: tags: [Sandboxes] summary: Create a new sandbox description: | Creates a new persistent sandbox. The sandbox starts automatically after creation. Use this for workflows that require multiple commands. operationId: createSandbox requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateSandboxRequest' examples: default: summary: Default Alpine sandbox value: name: "my-sandbox" with_labels: summary: Sandbox with labels value: name: "eval-sandbox" image: "python:3.12-alpine" labels: scenario: "drift_s3" model: "sonnet" eval_run: "pr-123" description: "Drift scenario evaluation" managed_network: summary: Docker/Podman managed bridge value: name: "dev-sandbox" backend: "docker" network: name: "agentkernel-dev" subnet: "172.30.0.0/24" gateway: "172.30.0.1" dns: ["1.1.1.1"] responses: '201': description: Sandbox created content: application/json: schema: $ref: '#/components/schemas/SandboxResponse' '400': $ref: '#/components/responses/BadRequest' '422': description: Requested backend is unavailable on this server content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '429': $ref: '#/components/responses/QuotaExceeded' '500': $ref: '#/components/responses/InternalError' /backends: get: tags: [Sandboxes] summary: Discover sandbox backends description: | Reports the backend selected by Automatic creation and every backend known to this server, including readiness and capability information. The endpoint does not require a sandbox manager to be initialized. operationId: listBackends responses: '200': description: Backend discovery result content: application/json: schema: $ref: '#/components/schemas/BackendDiscoveryResponse' /sandboxes/{name}: parameters: - $ref: '#/components/parameters/SandboxName' get: tags: [Sandboxes] summary: Get sandbox details description: Returns details about a specific sandbox. operationId: getSandbox responses: '200': description: Sandbox details content: application/json: schema: $ref: '#/components/schemas/SandboxResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' patch: tags: [Sandboxes] summary: Update sandbox metadata description: Update labels and/or description for a sandbox. operationId: updateSandbox requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchSandboxRequest' examples: labels: summary: Update labels value: labels: env: "staging" team: "ml" description: summary: Update description value: description: "Production evaluation sandbox" responses: '200': description: Sandbox updated content: application/json: schema: $ref: '#/components/schemas/SandboxResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' delete: tags: [Sandboxes] summary: Delete a sandbox description: Stops and removes a sandbox. operationId: deleteSandbox responses: '200': description: Sandbox deleted content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /sandboxes/{name}/start: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Start a stopped sandbox description: | Starts a stopped sandbox. Omit the optional request body to use the historical defaults (moderate permissions and no injected files). The local CLI may select a private persisted configuration when delegating a Firecracker VM to the long-running server. Capability values are derived by the server and cannot be supplied in this request. operationId: startSandbox requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/StartSandboxRequest' responses: '200': description: Sandbox started content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '429': $ref: '#/components/responses/QuotaExceeded' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /sandboxes/{name}/stop: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Stop a running sandbox description: | Stops the sandbox while retaining its persisted configuration. The long-running server owns the lifecycle task after accepting the request, so an HTTP waiter disconnect does not cancel the stop. Use full-state pause instead when Firecracker memory, processes, and the writable disk must survive. operationId: stopSandbox responses: '200': description: Sandbox stopped content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /sandboxes/{name}/pause: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Pause a running Firecracker sandbox description: | Captures a durable full-VM checkpoint, including guest memory and process state, then stops the Firecracker VM. This operation is only supported by the Firecracker backend on x86_64 Linux/KVM. Enterprise policy requires the Run action. operationId: pauseSandbox responses: '200': description: Sandbox paused content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': description: The sandbox backend does not support full-state pause content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /sandboxes/{name}/resume: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Resume a paused Firecracker sandbox description: Restores guest memory, processes, devices, and disk state from the sandbox's full-VM checkpoint. Enterprise policy requires the Run action. operationId: resumeSandbox responses: '200': description: Sandbox resumed content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': description: The sandbox backend does not support full-state resume content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '429': $ref: '#/components/responses/QuotaExceeded' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /sandboxes/{name}/fork: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Fork a paused Firecracker sandbox description: | Restores the paused source checkpoint into a new running sandbox. The source remains paused and may be resumed or forked again. Security warning: the fork copies guest memory and filesystem state. Credentials captured in the checkpoint are duplicated and should be rotated or revoked when appropriate. Enterprise policy requires Run on the source plus Create and Run for the child. operationId: forkSandbox requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ForkSandboxRequest' example: as_name: experiment-b responses: '201': description: Running sandbox forked from the paused source content: application/json: schema: $ref: '#/components/schemas/ForkSandboxResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '403': description: The requested fork would cross an owner or tenant boundary content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '409': $ref: '#/components/responses/Conflict' '422': description: The sandbox backend does not support full-state fork content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '429': $ref: '#/components/responses/QuotaExceeded' '500': $ref: '#/components/responses/InternalError' '503': $ref: '#/components/responses/ServiceUnavailable' /sandboxes/{name}/resize: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Resize a sandbox operationId: resizeSandbox requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ResizeSandboxRequest' responses: '200': description: Sandbox resized content: application/json: schema: $ref: '#/components/schemas/SandboxResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/QuotaExceeded' '500': $ref: '#/components/responses/InternalError' /sandboxes/by-uuid/{uuid}: parameters: - $ref: '#/components/parameters/SandboxUUID' get: tags: [Sandboxes] summary: Get sandbox details by UUID description: Returns details about a specific sandbox by UUIDv7. operationId: getSandboxByUuid responses: '200': description: Sandbox details content: application/json: schema: $ref: '#/components/schemas/SandboxResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /sandboxes/{name}/exec: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Execute command in sandbox description: Executes a command in an existing running sandbox. operationId: execInSandbox requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ExecRequest' examples: simple: summary: List files value: command: ["ls", "-la"] python: summary: Run Python value: command: ["python3", "-c", "import sys; print(sys.version)"] responses: '200': description: Command executed content: application/json: schema: $ref: '#/components/schemas/RunResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /sandboxes/{name}/git/status: parameters: - $ref: '#/components/parameters/SandboxName' - name: path in: query required: true description: Git repository path inside the sandbox schema: type: string example: /workspace/repo get: tags: [Sandboxes] summary: Get Git repository status operationId: getSandboxGitStatus responses: '200': description: Git status content: application/json: schema: $ref: '#/components/schemas/GitStatusResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' /sandboxes/{name}/git/branches: parameters: - $ref: '#/components/parameters/SandboxName' - name: path in: query required: true description: Git repository path inside the sandbox schema: type: string example: /workspace/repo get: tags: [Sandboxes] summary: List Git branches operationId: listSandboxGitBranches responses: '200': description: Git branches content: application/json: schema: $ref: '#/components/schemas/GitBranchesResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' /sandboxes/{name}/git/add: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Stage Git files operationId: addSandboxGitFiles requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GitAddRequest' responses: '200': description: Files staged content: application/json: schema: $ref: '#/components/schemas/GitOperationResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' /sandboxes/{name}/git/commit: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Commit staged Git changes operationId: commitSandboxGitChanges requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GitCommitRequest' responses: '200': description: Commit created content: application/json: schema: $ref: '#/components/schemas/GitCommitResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' /sandboxes/{name}/git/pull: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Pull Git changes operationId: pullSandboxGitChanges requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GitRepoRequest' responses: '200': description: Changes pulled content: application/json: schema: $ref: '#/components/schemas/GitOperationResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' /sandboxes/{name}/git/push: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Push Git changes operationId: pushSandboxGitChanges requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GitRepoRequest' responses: '200': description: Changes pushed content: application/json: schema: $ref: '#/components/schemas/GitOperationResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/UnprocessableEntity' /sandboxes/{name}/files/{path}: parameters: - $ref: '#/components/parameters/SandboxName' - name: path in: path required: true description: File path inside the sandbox (relative, e.g. tmp/hello.txt) schema: type: string get: tags: [Files] summary: Read a file from a sandbox operationId: readFile responses: '200': description: File content content: application/json: schema: $ref: '#/components/schemas/FileReadResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' put: tags: [Files] summary: Write a file to a sandbox operationId: writeFile requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FileWriteRequest' examples: text: summary: Write text file value: content: "hello world" base64: summary: Write binary file value: content: "aGVsbG8=" encoding: "base64" responses: '200': description: File written content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' delete: tags: [Files] summary: Delete a file from a sandbox operationId: deleteFile responses: '200': description: File deleted content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /sandboxes/{name}/logs: parameters: - $ref: '#/components/parameters/SandboxName' get: tags: [Sandboxes] summary: Get sandbox audit logs description: Returns audit log entries for this sandbox. operationId: getSandboxLogs responses: '200': description: Audit log entries content: application/json: schema: $ref: '#/components/schemas/SandboxLogsResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /sandboxes/{name}/extend: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Extend sandbox TTL description: | Extends the sandbox's time-to-live by the specified duration. If the sandbox has no current TTL, sets expiry from now. operationId: extendSandboxTtl requestBody: content: application/json: schema: $ref: '#/components/schemas/ExtendTtlRequest' examples: default: summary: Extend by 1 hour (default) value: {} custom: summary: Extend by 30 minutes value: by: "30m" responses: '200': description: TTL extended content: application/json: schema: $ref: '#/components/schemas/ExtendTtlResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /sandboxes/{name}/recover: parameters: - $ref: '#/components/parameters/SandboxName' post: tags: [Sandboxes] summary: Recover an archived sandbox description: | Clears archive metadata so an archived sandbox can be started again. operationId: recoverSandbox responses: '200': description: Sandbox recovered content: application/json: schema: $ref: '#/components/schemas/SandboxResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /snapshots: get: tags: [Snapshots] summary: List all snapshots description: Returns a list of all saved snapshots. operationId: listSnapshots responses: '200': description: List of snapshots content: application/json: schema: $ref: '#/components/schemas/SnapshotListResponse' '500': $ref: '#/components/responses/InternalError' post: tags: [Snapshots] summary: Take a snapshot description: | Creates a snapshot of a sandbox's current state. Uses Docker commit internally. operationId: takeSnapshot requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TakeSnapshotRequest' examples: simple: summary: Snapshot a sandbox value: sandbox: "my-sandbox" name: "checkpoint-1" responses: '200': description: Snapshot created content: application/json: schema: $ref: '#/components/schemas/SnapshotResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /snapshots/{name}: parameters: - name: name in: path required: true description: Name of the snapshot schema: type: string get: tags: [Snapshots] summary: Get snapshot info description: Returns information about a specific snapshot. operationId: getSnapshot responses: '200': description: Snapshot details content: application/json: schema: $ref: '#/components/schemas/SnapshotResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' delete: tags: [Snapshots] summary: Delete a snapshot description: Removes the snapshot and its Docker image. operationId: deleteSnapshot responses: '200': description: Snapshot deleted content: application/json: schema: $ref: '#/components/schemas/SuccessResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /snapshots/{name}/restore: parameters: - name: name in: path required: true description: Name of the snapshot to restore schema: type: string post: tags: [Snapshots] summary: Restore from snapshot description: | Creates a new sandbox from a snapshot. Defaults to naming the restored sandbox "{original}-restored". Snapshots are tenant-scoped; only the owning principal or an explicit JWT `admin` may restore them. Restore consumes total quota capacity and returns `429` when the authenticated tenant is at its limit. operationId: restoreSnapshot requestBody: content: application/json: schema: $ref: '#/components/schemas/RestoreSnapshotRequest' examples: default: summary: Restore with default name value: {} custom: summary: Restore with custom name value: as_name: "my-restored-sandbox" responses: '200': description: Sandbox restored content: application/json: schema: $ref: '#/components/schemas/RestoreSnapshotResponse' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/QuotaExceeded' '500': $ref: '#/components/responses/InternalError' /batch/run: post: tags: [Batch] summary: Run multiple commands in parallel description: | Executes multiple commands in parallel, each in its own temporary sandbox. Results are returned in the same order as the input commands. operationId: batchRun requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BatchRunRequest' examples: simple: summary: Two echo commands value: commands: - command: ["echo", "hello"] - command: ["echo", "world"] responses: '200': description: Batch results content: application/json: schema: $ref: '#/components/schemas/BatchRunResponse' '400': $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/InternalError' /objects: get: tags: [Objects] summary: List durable objects description: Returns all non-deleted durable objects. responses: '200': description: List of objects content: application/json: schema: type: object properties: success: type: boolean data: type: array items: $ref: '#/components/schemas/DurableObject' post: tags: [Objects] summary: Create a durable object requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateDurableObject' responses: '201': description: Object created content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/DurableObject' '400': $ref: '#/components/responses/BadRequest' /objects/{id}: parameters: - name: id in: path required: true schema: type: string get: tags: [Objects] summary: Get durable object by id responses: '200': description: Object found content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/DurableObject' '404': $ref: '#/components/responses/NotFound' patch: tags: [Objects] summary: Partially update a durable object description: Update storage and/or status of a durable object. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PatchDurableObject' responses: '200': description: Object updated content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/DurableObject' '404': $ref: '#/components/responses/NotFound' delete: tags: [Objects] summary: Delete a durable object responses: '200': description: Object deleted '404': $ref: '#/components/responses/NotFound' /objects/{class}/{object_id}/call/{method}: parameters: - name: class in: path required: true schema: type: string - name: object_id in: path required: true schema: type: string - name: method in: path required: true schema: type: string post: tags: [Objects] summary: Call a method on a durable object description: | Invokes a method on a durable object. Auto-creates the object if it does not exist and wakes it from hibernation if needed. requestBody: content: application/json: schema: type: object description: Method arguments (arbitrary JSON) responses: '200': description: Method result content: application/json: schema: type: object properties: success: type: boolean data: description: Method return value '500': $ref: '#/components/responses/InternalError' /stores: get: tags: [Stores] summary: List durable stores description: Returns all durable stores. responses: '200': description: List of stores content: application/json: schema: type: object properties: success: type: boolean data: type: array items: $ref: '#/components/schemas/DurableStore' post: tags: [Stores] summary: Create a durable store requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateDurableStore' responses: '201': description: Store created content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/DurableStore' '400': $ref: '#/components/responses/BadRequest' /stores/{id}: parameters: - name: id in: path required: true schema: type: string get: tags: [Stores] summary: Get durable store by id responses: '200': description: Store found content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/DurableStore' '404': $ref: '#/components/responses/NotFound' delete: tags: [Stores] summary: Delete a durable store responses: '200': description: Store deleted '404': $ref: '#/components/responses/NotFound' /stores/{id}/query: parameters: - name: id in: path required: true schema: type: string post: tags: [Stores] summary: Run a read query against a store description: Execute a read-only query (e.g. SQL SELECT for sqlite stores). requestBody: required: true content: application/json: schema: type: object properties: sql: type: string description: SQL query (for sqlite stores) params: type: array description: Query parameters responses: '200': description: Query results content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/StoreQueryResult' '404': $ref: '#/components/responses/NotFound' /stores/{id}/execute: parameters: - name: id in: path required: true schema: type: string post: tags: [Stores] summary: Run a write statement against a store description: Execute a write statement (e.g. SQL INSERT/UPDATE/DELETE for sqlite stores). requestBody: required: true content: application/json: schema: type: object properties: sql: type: string description: SQL statement (for sqlite stores) params: type: array description: Statement parameters responses: '200': description: Execution result content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/StoreExecuteResult' '404': $ref: '#/components/responses/NotFound' /schedules: get: tags: [Schedules] summary: List schedules description: Returns all schedules. responses: '200': description: List of schedules content: application/json: schema: type: object properties: success: type: boolean data: type: array items: $ref: '#/components/schemas/Schedule' post: tags: [Schedules] summary: Create a schedule requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateSchedule' responses: '201': description: Schedule created content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/Schedule' '400': $ref: '#/components/responses/BadRequest' /schedules/{id}: parameters: - name: id in: path required: true schema: type: string get: tags: [Schedules] summary: Get schedule by id responses: '200': description: Schedule found content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/Schedule' '404': $ref: '#/components/responses/NotFound' delete: tags: [Schedules] summary: Delete a schedule responses: '200': description: Schedule deleted '404': $ref: '#/components/responses/NotFound' /schedules/configured: get: tags: [Schedules] summary: List TOML-configured daemon jobs description: Returns status for the immutable jobs loaded from `[[schedule]]` entries. responses: '200': description: Configured schedule status list content: application/json: schema: type: object properties: success: type: boolean data: type: array items: $ref: '#/components/schemas/ConfiguredScheduleStatus' /schedules/configured/{id}: parameters: - name: id in: path required: true schema: type: string get: tags: [Schedules] summary: Get a TOML-configured daemon job responses: '200': description: Configured schedule status content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/ConfiguredScheduleStatus' '404': $ref: '#/components/responses/NotFound' /schedules/configured/{id}/status: parameters: - name: id in: path required: true schema: type: string get: tags: [Schedules] summary: Get execution status for a TOML-configured daemon job responses: '200': description: Configured schedule status content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/ConfiguredScheduleStatus' '404': $ref: '#/components/responses/NotFound' /schedules/configured/{id}/trigger: parameters: - name: id in: path required: true schema: type: string post: tags: [Schedules] summary: Trigger a TOML-configured daemon job immediately responses: '200': description: Job execution result content: application/json: schema: type: object properties: success: type: boolean data: $ref: '#/components/schemas/ConfiguredScheduleExecution' '404': $ref: '#/components/responses/NotFound' /scim/v2/ServiceProviderConfig: get: tags: [SCIM] security: [{BearerAuth: []}] summary: SCIM service provider capabilities operationId: getScimServiceProviderConfig responses: '200': description: SCIM capabilities content: application/scim+json: schema: type: object /scim/v2/ResourceTypes: get: tags: [SCIM] security: [{BearerAuth: []}] summary: List SCIM resource types operationId: listScimResourceTypes responses: '200': description: SCIM resource types content: application/scim+json: schema: $ref: '#/components/schemas/ScimListResponse' /scim/v2/ResourceTypes/{id}: get: tags: [SCIM] security: [{BearerAuth: []}] summary: Get a SCIM resource type operationId: getScimResourceType parameters: - $ref: '#/components/parameters/ScimResourceId' responses: '200': description: SCIM resource type content: application/scim+json: schema: type: object /scim/v2/Schemas: get: tags: [SCIM] security: [{BearerAuth: []}] summary: List SCIM schemas operationId: listScimSchemas responses: '200': description: SCIM schemas content: application/scim+json: schema: $ref: '#/components/schemas/ScimListResponse' /scim/v2/Schemas/{id}: get: tags: [SCIM] security: [{BearerAuth: []}] summary: Get a SCIM schema operationId: getScimSchema parameters: - $ref: '#/components/parameters/ScimResourceId' responses: '200': description: SCIM schema content: application/scim+json: schema: type: object /scim/v2/Users: get: tags: [SCIM] security: [{BearerAuth: []}] summary: List provisioned users operationId: listScimUsers parameters: - $ref: '#/components/parameters/ScimFilter' - $ref: '#/components/parameters/ScimStartIndex' - $ref: '#/components/parameters/ScimCount' responses: '200': description: SCIM user list content: application/scim+json: schema: $ref: '#/components/schemas/ScimListResponse' post: tags: [SCIM] security: [{BearerAuth: []}] summary: Provision a user operationId: createScimUser requestBody: required: true content: application/scim+json: schema: $ref: '#/components/schemas/ScimUserInput' responses: '201': description: User created content: application/scim+json: schema: $ref: '#/components/schemas/ScimUser' /scim/v2/Users/{id}: parameters: - $ref: '#/components/parameters/ScimResourceId' get: tags: [SCIM] security: [{BearerAuth: []}] summary: Get a provisioned user operationId: getScimUser responses: '200': description: SCIM user content: application/scim+json: schema: $ref: '#/components/schemas/ScimUser' put: tags: [SCIM] security: [{BearerAuth: []}] summary: Replace a provisioned user operationId: replaceScimUser requestBody: required: true content: application/scim+json: schema: $ref: '#/components/schemas/ScimUserInput' responses: '200': description: User replaced content: application/scim+json: schema: $ref: '#/components/schemas/ScimUser' patch: tags: [SCIM] security: [{BearerAuth: []}] summary: Patch or deactivate a user operationId: patchScimUser requestBody: required: true content: application/scim+json: schema: $ref: '#/components/schemas/ScimPatch' responses: '200': description: User patched content: application/scim+json: schema: $ref: '#/components/schemas/ScimUser' delete: tags: [SCIM] security: [{BearerAuth: []}] summary: Delete a provisioned user description: Tombstones the resource. Use PATCH active false for non-deleting deactivation. operationId: deleteScimUser responses: '204': description: User deleted /scim/v2/Groups: get: tags: [SCIM] security: [{BearerAuth: []}] summary: List provisioned groups operationId: listScimGroups parameters: - $ref: '#/components/parameters/ScimFilter' - $ref: '#/components/parameters/ScimStartIndex' - $ref: '#/components/parameters/ScimCount' responses: '200': description: SCIM group list content: application/scim+json: schema: $ref: '#/components/schemas/ScimListResponse' post: tags: [SCIM] security: [{BearerAuth: []}] summary: Provision a group operationId: createScimGroup requestBody: required: true content: application/scim+json: schema: $ref: '#/components/schemas/ScimGroupInput' responses: '201': description: Group created content: application/scim+json: schema: $ref: '#/components/schemas/ScimGroup' /scim/v2/Groups/{id}: parameters: - $ref: '#/components/parameters/ScimResourceId' get: tags: [SCIM] security: [{BearerAuth: []}] summary: Get a provisioned group operationId: getScimGroup responses: '200': description: SCIM group content: application/scim+json: schema: $ref: '#/components/schemas/ScimGroup' put: tags: [SCIM] security: [{BearerAuth: []}] summary: Replace a group and synchronize membership operationId: replaceScimGroup requestBody: required: true content: application/scim+json: schema: $ref: '#/components/schemas/ScimGroupInput' responses: '200': description: Group replaced content: application/scim+json: schema: $ref: '#/components/schemas/ScimGroup' patch: tags: [SCIM] security: [{BearerAuth: []}] summary: Patch group membership operationId: patchScimGroup requestBody: required: true content: application/scim+json: schema: $ref: '#/components/schemas/ScimPatch' responses: '200': description: Group patched content: application/scim+json: schema: $ref: '#/components/schemas/ScimGroup' delete: tags: [SCIM] security: [{BearerAuth: []}] summary: Delete a provisioned group description: Tombstones the group while preserving internal membership history. operationId: deleteScimGroup responses: '204': description: Group deleted components: parameters: ScimResourceId: name: id in: path required: true schema: type: string pattern: '^[A-Za-z0-9._:-]{1,128}$' ScimFilter: name: filter in: query schema: type: string description: Equality filter such as userName eq "alice@example.com". ScimStartIndex: name: startIndex in: query schema: type: integer minimum: 1 default: 1 ScimCount: name: count in: query schema: type: integer minimum: 0 maximum: 100 default: 100 schemas: ScimUserInput: type: object required: [schemas, userName] properties: schemas: type: array minItems: 1 maxItems: 1 items: type: string enum: [urn:ietf:params:scim:schemas:core:2.0:User] userName: type: string externalId: type: string active: type: boolean default: true displayName: type: string name: type: object properties: givenName: {type: string} familyName: {type: string} emails: type: array items: type: object required: [value] properties: value: {type: string, format: email} type: {type: string} primary: {type: boolean} locale: {type: string} timezone: {type: string} ScimUser: allOf: - $ref: '#/components/schemas/ScimUserInput' - type: object required: [schemas, id, meta] properties: schemas: type: array items: {type: string} id: {type: string} meta: {type: object} ScimGroupInput: type: object required: [schemas, displayName] properties: schemas: type: array minItems: 1 maxItems: 1 items: type: string enum: [urn:ietf:params:scim:schemas:core:2.0:Group] displayName: {type: string} externalId: {type: string} members: type: array items: type: object required: [value] properties: value: {type: string} display: {type: string} ScimGroup: allOf: - $ref: '#/components/schemas/ScimGroupInput' - type: object required: [schemas, id, meta] properties: schemas: type: array items: {type: string} id: {type: string} meta: {type: object} ScimPatch: type: object required: [schemas, Operations] properties: schemas: type: array items: {type: string} minItems: 1 Operations: type: array minItems: 1 maxItems: 32 items: type: object required: [op] properties: op: {type: string, enum: [add, replace, remove]} path: {type: string} value: {} ScimListResponse: type: object required: [schemas, totalResults, startIndex, itemsPerPage, Resources] properties: schemas: type: array items: {type: string} totalResults: {type: integer} startIndex: {type: integer} itemsPerPage: {type: integer} Resources: type: array items: {type: object} QuotaLimits: type: object properties: max_running_sandboxes: type: integer minimum: 0 description: Maximum concurrently running sandboxes; zero denies starts. max_total_sandboxes: type: integer minimum: 0 description: Maximum persisted sandboxes, including stopped sandboxes. max_total_vcpus: type: integer minimum: 0 max_total_memory_mb: type: integer minimum: 0 additionalProperties: false QuotaUsage: type: object required: [total_sandboxes, running_sandboxes, total_vcpus, total_memory_mb] properties: total_sandboxes: type: integer running_sandboxes: type: integer total_vcpus: type: integer total_memory_mb: type: integer QuotaScopeStatus: type: object required: [id, limits, usage] properties: id: type: string limits: $ref: '#/components/schemas/QuotaLimits' usage: $ref: '#/components/schemas/QuotaUsage' QuotaStatus: type: object required: [enabled, user, organization] properties: enabled: type: boolean user: $ref: '#/components/schemas/QuotaScopeStatus' organization: $ref: '#/components/schemas/QuotaScopeStatus' QuotaStatusResponse: type: object required: [success, data] properties: success: type: boolean data: $ref: '#/components/schemas/QuotaStatus' error: type: string RunRequest: type: object required: [command] properties: command: type: array items: type: string description: Command and arguments to execute example: ["echo", "hello"] image: type: string description: | Docker image to use (only when fast=false). If not specified, auto-detected from command. example: "python:3.12-alpine" profile: type: string enum: [permissive, moderate, restrictive] default: moderate description: | Security profile (only when fast=false). - permissive: network, mounts, env passthrough - moderate: network enabled, no mounts - restrictive: no network, read-only filesystem fast: type: boolean default: true description: | Use container pool for fast execution (~50ms). Set to false for custom images or profiles (~500ms). CreateTaskRequest: type: object additionalProperties: false required: [prompt, sandbox] properties: prompt: type: string minLength: 1 maxLength: 1048576 description: Prompt to dispatch to the agent worker sandbox: type: string pattern: '^[A-Za-z0-9](?:[A-Za-z0-9_-]*[A-Za-z0-9])?$' maxLength: 63 description: Target sandbox name (also accepted as target_sandbox) Task: type: object required: [id, prompt, sandbox, status, created_at, updated_at] properties: id: type: string format: uuid description: UUIDv7 task identifier prompt: type: string sandbox: type: string status: type: string enum: [queued, running, completed, failed, cancelled] isolation: nullable: true description: Per-task sandbox and Git worktree allocated by the worker allOf: - $ref: '#/components/schemas/TaskIsolation' result: type: string nullable: true description: Agent output or a reviewable Git diff when completed error: type: string nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time TaskIsolation: type: object required: [sandbox, branch] properties: sandbox: type: string description: Dedicated sandbox used by this task branch: type: string description: Dedicated Git branch created from the base ref worktree: type: string nullable: true description: Opaque identifier of the dedicated Git worktree base_ref: type: string nullable: true description: Commit from which the task branch was created TaskResponse: type: object required: [success, data] properties: success: type: boolean example: true data: $ref: '#/components/schemas/Task' TaskListResponse: type: object required: [success, data] properties: success: type: boolean example: true data: type: array items: $ref: '#/components/schemas/Task' CreateSandboxRequest: type: object required: [name] properties: name: type: string pattern: '^[a-zA-Z0-9][a-zA-Z0-9_-]*$' maxLength: 64 description: Unique name for the sandbox example: "my-sandbox" backend: type: string description: Backend identifier. Omit or use `automatic` for server selection. example: "docker" image: type: string default: "alpine:3.24" description: Docker image to use example: "python:3.12-alpine" vcpus: type: integer default: 1 description: Number of virtual CPUs memory_mb: type: integer default: 512 description: Memory in megabytes profile: type: string enum: [permissive, moderate, restrictive] description: Security profile volumes: type: array items: type: string description: Persistent volume mounts in `slug:/container/path` or `slug:/container/path:ro` format. Volumes must already exist. Named mounts are supported by Docker and Podman backends. example: ["my-data:/data", "cache:/cache:ro"] network: $ref: '#/components/schemas/ManagedNetworkConfig' labels: type: object additionalProperties: type: string description: User-defined labels for fleet management and filtering example: env: "prod" team: "ml" description: type: string description: User-defined description lifecycle: $ref: '#/components/schemas/LifecyclePolicy' ManagedNetworkConfig: type: object additionalProperties: false required: [name] description: | AgentKernel-managed bridge networking for Docker and Podman. The network is persisted with the sandbox and address leases are stored durably. Existing networks must carry AgentKernel ownership labels; externally owned networks are never adopted or removed. properties: name: type: string minLength: 1 maxLength: 63 pattern: '^[A-Za-z0-9][A-Za-z0-9_.-]*$' description: Runtime network name. subnet: type: string default: "172.30.0.0/24" description: IPv4 network CIDR; the address must be the network address. example: "172.30.0.0/24" gateway: type: string format: ipv4 description: IPv4 gateway inside the subnet. Defaults to the first host address. example: "172.30.0.1" dns: type: array items: type: string format: ipv4 description: IPv4 DNS servers passed to each managed container at runtime. example: ["1.1.1.1", "8.8.8.8"] static_ip: type: string format: ipv4 description: Optional fixed IPv4 address for this sandbox. It cannot be changed after allocation. example: "172.30.0.10" StartSandboxRequest: type: object additionalProperties: false properties: configuration: type: object additionalProperties: false required: [source, token] description: | Select the server-derived private start configuration previously persisted by the local CLI. Callers cannot provide permission or file-injection values in the HTTP request. The token is one-shot and bound to the sandbox UUID, owner, request identity, and a five-minute validity window. properties: source: type: string enum: [persisted] token: type: string pattern: '^[0-9a-f]{64}$' description: Opaque one-shot nonce generated by the local CLI. ResizeSandboxRequest: type: object properties: vcpus: type: integer minimum: 1 memory_mb: type: integer minimum: 1 minProperties: 1 PatchSandboxRequest: type: object properties: labels: type: object additionalProperties: type: string description: Replace all labels description: type: string description: Update description lifecycle: description: Set lifecycle policy, or `null` to clear policy oneOf: - $ref: '#/components/schemas/LifecyclePolicy' - type: "null" ExecRequest: type: object required: [command] properties: command: type: array items: type: string description: Command and arguments to execute example: ["ls", "-la"] GitRepoRequest: type: object required: [path] additionalProperties: false properties: path: type: string description: Git repository path inside the sandbox remote: type: string description: Optional validated Git remote name branch: type: string description: Optional validated branch/ref name set_upstream: type: boolean default: false username: type: string description: Reserved for SDK compatibility; configure credentials in the sandbox password: type: string format: password description: Reserved for SDK compatibility; configure credentials in the sandbox GitAddRequest: type: object required: [path, files] additionalProperties: false properties: path: type: string description: Git repository path inside the sandbox files: type: array minItems: 1 items: type: string description: Relative files to stage; use `.` for the whole repository GitCommitRequest: type: object required: [path, message] additionalProperties: false properties: path: type: string description: Git repository path inside the sandbox message: type: string minLength: 1 author: type: string description: Optional commit author name; must be paired with email email: type: string description: Optional commit author email; must be paired with author allow_empty: type: boolean default: false GitFileStatus: type: object required: [name, extra, staging, worktree] properties: name: type: string extra: type: string staging: type: string worktree: type: string GitStatusResponse: type: object properties: success: type: boolean example: true data: type: object required: [currentBranch, fileStatus, branchPublished, ahead, behind, detached] properties: currentBranch: type: string fileStatus: type: array items: $ref: '#/components/schemas/GitFileStatus' branchPublished: type: boolean ahead: type: integer minimum: 0 behind: type: integer minimum: 0 upstream: type: string detached: type: boolean GitBranchesResponse: type: object properties: success: type: boolean example: true data: type: object required: [branches, current] properties: branches: type: array items: type: string current: type: string GitCommitResponse: type: object properties: success: type: boolean example: true data: type: object required: [hash] properties: hash: type: string GitOperationResponse: type: object properties: success: type: boolean example: true data: type: object required: [output] properties: output: type: string HealthResponse: type: object properties: success: type: boolean example: true data: type: string example: "ok" RunResponse: type: object properties: success: type: boolean example: true data: type: object properties: output: type: string description: Combined stdout/stderr from command example: "hello world\n" StatusResponse: type: object properties: success: type: boolean example: true data: type: object properties: version: type: string example: "0.15.0" backend: type: string example: "docker" api_key_configured: type: boolean example: false BackendDiscoveryResponse: type: object properties: success: type: boolean example: true data: $ref: '#/components/schemas/BackendDiscovery' BackendDiscovery: type: object required: [backends] properties: default_backend: type: string nullable: true description: Backend used when creation requests Automatic selection backends: type: array items: $ref: '#/components/schemas/BackendDescriptor' BackendDescriptor: type: object required: [backend, configured, usable, readiness_reason, capabilities] properties: backend: type: string configured: type: boolean usable: type: boolean readiness_reason: type: string capabilities: $ref: '#/components/schemas/BackendCapabilities' BackendCapabilities: type: object required: [mount_cwd, mount_home, attach, host_volumes, ssh, proxy_secret_bindings, secret_files, snapshots, resume, full_state_pause_resume, full_state_fork, endpoints] properties: mount_cwd: {type: boolean} mount_home: {type: boolean} attach: {type: boolean} host_volumes: {type: boolean} ssh: {type: boolean} proxy_secret_bindings: {type: boolean} secret_files: {type: boolean} snapshots: {type: boolean} resume: {type: boolean} full_state_pause_resume: type: boolean description: Preserves guest memory, process, and device state; currently Firecracker only full_state_fork: type: boolean description: Restores independent running children from a paused full-state checkpoint; currently Firecracker only endpoints: {type: boolean} StatsResponse: type: object properties: success: type: boolean example: true data: type: object properties: sandbox_count: type: integer example: 12 sandbox_limit: type: integer example: 0 description: 0 means unlimited backend: type: string example: "docker" uptime_seconds: type: integer example: 3600 version: type: string example: "0.15.0" resource_usage: type: object properties: cpu_percent: type: number format: float example: 65.2 memory_used_mb: type: integer example: 8192 memory_total_mb: type: integer example: 16384 disk_used_mb: type: integer example: 4096 GcResponse: type: object properties: success: type: boolean example: true data: type: object properties: removed: type: array items: type: string description: Names of removed sandboxes example: ["old-sandbox-1", "expired-test"] LifecyclePolicy: type: object properties: auto_stop_after_seconds: type: integer format: int64 minimum: 0 description: Stop sandbox after this many seconds of inactivity auto_archive_after_seconds: type: integer format: int64 minimum: 0 description: Archive sandbox after this many seconds of inactivity auto_delete_after_seconds: type: integer format: int64 minimum: 0 description: Delete archived sandbox after this many seconds ReconcileLifecycleRequest: type: object properties: dry_run: type: boolean default: false description: Preview lifecycle actions without mutating sandboxes LifecycleAction: type: object required: [sandbox, action, reason] properties: sandbox: type: string description: Sandbox name action: type: string enum: [stop, archive, delete] reason: type: string LifecycleReconcileResult: type: object required: [dry_run, stopped, archived, removed, actions] properties: dry_run: type: boolean stopped: type: array items: type: string archived: type: array items: type: string removed: type: array items: type: string actions: type: array items: $ref: '#/components/schemas/LifecycleAction' LifecycleReconcileResponse: type: object properties: success: type: boolean example: true data: $ref: '#/components/schemas/LifecycleReconcileResult' SandboxInfo: type: object required: [name, uuid, status, backend] properties: name: type: string example: "my-sandbox" uuid: type: string format: uuid description: Globally unique sandbox identifier (UUIDv7) example: "019abc12-1234-7def-89ab-0123456789ab" status: type: string enum: [running, paused, stopped, dormant, archived] example: "running" backend: type: string example: "docker" image: type: string example: "python:3.12-alpine" vcpus: type: integer example: 1 memory_mb: type: integer example: 512 created_at: type: string example: "2026-01-30T12:00:00Z" labels: type: object additionalProperties: type: string description: User-defined labels description: type: string description: User-defined description last_activity_at: type: string description: Last observed sandbox activity timestamp (RFC3339) example: "2026-02-23T15:04:05Z" archived_at: type: string description: Archive timestamp (RFC3339), when sandbox is archived example: "2026-02-23T16:04:05Z" archived_reason: type: string description: Human-readable archive reason lifecycle: $ref: '#/components/schemas/LifecyclePolicy' SandboxResponse: type: object properties: success: type: boolean example: true data: $ref: '#/components/schemas/SandboxInfo' ForkSandboxRequest: type: object additionalProperties: false required: [as_name] properties: as_name: type: string description: Name for the new running sandbox example: "experiment-b" ForkSandboxResult: type: object required: [sandbox, security_warning] properties: sandbox: $ref: '#/components/schemas/SandboxInfo' security_warning: type: string description: Warning that guest memory and filesystem state, including captured credentials, were cloned. example: "Forking duplicates userspace memory. Rotate cached identifiers and cryptographic tokens in each child; prefer proxy-managed secrets that never enter the VM." ForkSandboxResponse: type: object properties: success: type: boolean example: true data: $ref: '#/components/schemas/ForkSandboxResult' SandboxListResponse: type: object properties: success: type: boolean example: true data: type: array items: $ref: '#/components/schemas/SandboxInfo' SuccessResponse: type: object properties: success: type: boolean example: true data: type: string example: "Sandbox removed" ErrorResponse: type: object properties: success: type: boolean example: false error: type: string example: "Sandbox not found" FileWriteRequest: type: object required: [content] properties: content: type: string description: File content (text or base64-encoded) encoding: type: string enum: [utf8, base64] default: utf8 description: Content encoding FileReadResponse: type: object properties: success: type: boolean example: true data: type: object properties: content: type: string description: File content encoding: type: string enum: [utf8, base64] size: type: integer description: File size in bytes BatchRunRequest: type: object required: [commands] properties: commands: type: array items: type: object required: [command] properties: command: type: array items: type: string description: Command and arguments BatchRunResponse: type: object properties: success: type: boolean example: true data: type: object properties: results: type: array items: type: object properties: output: type: string nullable: true error: type: string nullable: true SandboxLogsResponse: type: object properties: success: type: boolean example: true data: type: array items: type: object description: Audit log entry ExtendTtlRequest: type: object properties: by: type: string default: "1h" description: Duration to extend by (e.g., "1h", "30m", "2d") example: "1h" ExtendTtlResponse: type: object properties: success: type: boolean example: true data: type: object properties: expires_at: type: string nullable: true description: New expiry time in RFC3339 format example: "2026-02-05T15:00:00Z" SnapshotInfo: type: object properties: name: type: string example: "checkpoint-1" sandbox: type: string description: Original sandbox name example: "my-sandbox" image_tag: type: string description: Docker image tag for the snapshot example: "agentkernel-snap:checkpoint-1" backend: type: string example: "docker" base_image: type: string example: "python:3.12-alpine" vcpus: type: integer example: 2 memory_mb: type: integer example: 512 created_at: type: string example: "2026-02-05T12:00:00Z" SnapshotResponse: type: object properties: success: type: boolean example: true data: $ref: '#/components/schemas/SnapshotInfo' SnapshotListResponse: type: object properties: success: type: boolean example: true data: type: array items: $ref: '#/components/schemas/SnapshotInfo' TakeSnapshotRequest: type: object required: [sandbox, name] properties: sandbox: type: string description: Name of the sandbox to snapshot example: "my-sandbox" name: type: string description: Name for the snapshot example: "checkpoint-1" RestoreSnapshotRequest: type: object properties: as_name: type: string description: Name for the restored sandbox (defaults to original + "-restored") example: "my-restored-sandbox" RestoreSnapshotResponse: type: object properties: success: type: boolean example: true data: type: object properties: sandbox: type: string description: Name of the restored sandbox example: "my-sandbox-restored" from_snapshot: type: string description: Snapshot that was restored example: "checkpoint-1" parameters: SandboxName: name: name in: path required: true description: Name of the sandbox schema: type: string pattern: '^[a-zA-Z0-9][a-zA-Z0-9_-]*$' SandboxUUID: name: uuid in: path required: true description: Sandbox UUID (UUIDv7) schema: type: string format: uuid DurableObject: type: object properties: id: type: string format: uuid class: type: string object_id: type: string status: type: string enum: [active, hibernating, deleted] sandbox: type: string nullable: true storage: type: object idle_timeout_seconds: type: integer created_at: type: string format: date-time updated_at: type: string format: date-time CreateDurableObject: type: object required: [class, object_id] properties: class: type: string object_id: type: string sandbox: type: string storage: type: object idle_timeout_seconds: type: integer default: 300 Schedule: type: object properties: id: type: string format: uuid name: type: string cron: type: string nullable: true fire_at: type: string format: date-time nullable: true method: type: string args: type: object target_class: type: string nullable: true target_object_id: type: string nullable: true target_orchestration: type: string nullable: true status: type: string enum: [active, paused, completed] last_fired_at: type: string format: date-time nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time ConfiguredScheduleStatus: type: object required: [id, enabled, cron, target, status] properties: id: type: string enabled: type: boolean cron: type: string description: Five-field cron expression evaluated in UTC target: type: string enum: [sandbox_command, orchestration, object_method] status: type: string enum: [idle, running, success, failed, disabled] last_run_at: type: string format: date-time nullable: true last_error: type: string nullable: true next_run_at: type: string format: date-time nullable: true ConfiguredScheduleExecution: type: object required: [id, status] properties: id: type: string status: type: string enum: [success, failed] output: type: string nullable: true error: type: string nullable: true PatchDurableObject: type: object properties: storage: type: object description: Replace the object's storage (arbitrary JSON) status: type: string enum: [active, hibernating] description: Set the object status DurableStore: type: object properties: id: type: string format: uuid name: type: string kind: type: string enum: [sqlite, kv, queue] sandbox: type: string nullable: true config: type: object created_at: type: string format: date-time updated_at: type: string format: date-time CreateDurableStore: type: object required: [name, kind] properties: name: type: string kind: type: string enum: [sqlite, kv, queue] sandbox: type: string config: type: object StoreQueryResult: type: object properties: columns: type: array items: type: string rows: type: array items: type: array row_count: type: integer StoreExecuteResult: type: object properties: rows_affected: type: integer LlmSpendMetric: type: object required: - bucket - tenant - agent - user - project - provider - model - request_count - streaming_count - input_tokens - output_tokens - total_tokens - last_request properties: bucket: {type: string, format: date} tenant: {type: string} agent: {type: string} user: {type: string} project: {type: string} provider: {type: string} model: {type: string} request_count: {type: integer, format: int64} streaming_count: {type: integer, format: int64} input_tokens: {type: integer, format: int64} output_tokens: {type: integer, format: int64} total_tokens: {type: integer, format: int64} last_request: {type: string, format: date-time} MonetaryCostStatus: type: object required: [available, reason] properties: available: {type: boolean} currency: {type: string, nullable: true} reason: {type: string} LlmSpendResponse: type: object required: [success, data] properties: success: {type: boolean} data: type: object required: [metrics, retention_days, monetary_cost] properties: metrics: type: array items: {$ref: '#/components/schemas/LlmSpendMetric'} next_offset: {type: integer, nullable: true} retention_days: {type: integer} monetary_cost: $ref: '#/components/schemas/MonetaryCostStatus' error: {type: string, nullable: true} CreateSchedule: type: object required: [name, method] properties: name: type: string cron: type: string description: Cron expression (mutually exclusive with fire_at) fire_at: type: string format: date-time description: One-shot fire time (mutually exclusive with cron) method: type: string args: type: object target_class: type: string target_object_id: type: string target_orchestration: type: string responses: BadRequest: description: Invalid request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: success: false error: "command is required" NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: success: false error: "Sandbox not found" Conflict: description: Sandbox is not running or operation conflicts with its state content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: success: false error: "Sandbox is not running" UnprocessableEntity: description: Git command failed inside the sandbox content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: success: false error: "git commit failed" QuotaExceeded: description: Tenant resource quota denied the lifecycle request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: success: false error: "Resource quota denied: organization quota exceeded for max_total_sandboxes: current 12, requested 1, limit 12" InternalError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: success: false error: "Failed to start container" Unauthorized: description: Authentication required or invalid credentials content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Forbidden: description: Authenticated identity lacks the required access or policy permission content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' ServiceUnavailable: description: A required service, policy engine, or durable store is unavailable content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' securitySchemes: BearerAuth: type: http scheme: bearer description: | Optional API key authentication. When enabled, include the API key in the Authorization header as a Bearer token.