Long-lived workspace / desktop sessions
Every request needs a credential — see Authentication.
| Method | Path | Summary |
|---|
GET | /sandbox/sandboxes/v1 | List Sandboxes |
POST | /sandbox/sandboxes/v1 | Create Sandbox |
POST | /sandbox/sandboxes/v1/_reap | Reap Sandboxes |
DELETE | /sandbox/sandboxes/v1/{sandbox_id} | Destroy Sandbox |
GET | /sandbox/sandboxes/v1/{sandbox_id} | Get Sandbox |
PATCH | /sandbox/sandboxes/v1/{sandbox_id} | Update sandbox lifetime (TTL / expiry / autostop) |
GET | /sandbox/sandboxes/v1/{sandbox_id}/artifacts | List Sandbox Artifacts |
GET | /sandbox/sandboxes/v1/{sandbox_id}/artifacts/{capture_id} | Get Sandbox Artifact |
POST | /sandbox/sandboxes/v1/{sandbox_id}/capture | Capture Sandbox |
GET | /sandbox/sandboxes/v1/{sandbox_id}/events | SSE sandbox lifecycle events |
POST | /sandbox/sandboxes/v1/{sandbox_id}/exec | Exec Sandbox |
DELETE | /sandbox/sandboxes/v1/{sandbox_id}/files | Delete File |
GET | /sandbox/sandboxes/v1/{sandbox_id}/files | Get File |
PUT | /sandbox/sandboxes/v1/{sandbox_id}/files | Put File |
GET | /sandbox/sandboxes/v1/{sandbox_id}/ports | List TCP ports listening inside the sandbox (user apps) |
POST | /sandbox/sandboxes/v1/{sandbox_id}/screenshot | Screenshot an app running inside the sandbox (headless Chromium) |
POST | /sandbox/sandboxes/v1/{sandbox_id}/start | Start Sandbox |
POST | /sandbox/sandboxes/v1/{sandbox_id}/stop | Stop Sandbox |
POST | /sandbox/sandboxes/v1/{sandbox_id}/touch | Record activity (resets the idle auto-stop clock) |
POST | /sandbox/sandboxes/v1/{sandbox_id}/verify | Verify Sandbox |
GET | /sandbox/sandboxes/v1/{sandbox_id}/viewer | Mint viewer URL or proxy the desktop viewer UI |
POST | /sandbox/sandboxes/v1/{sandbox_id}/viewer/actions | Upload the viewer action log (clicks, scrolls, keys, searches) |
POST | /sandbox/sandboxes/v1/{sandbox_id}/viewer/annotations | Submit a task-ambiguity label for the session |
POST | /sandbox/sandboxes/v1/{sandbox_id}/viewer/recordings | Upload a viewer session screen recording |
POST | /sandbox/sandboxes/v1/{sandbox_id}/viewer/screenshots | Upload a screenshot captured from the viewer canvas |
POST | /sandbox/sandboxes/v1/{sandbox_id}/viewer/start | Start Viewer |
POST | /sandbox/sandboxes/v1/{sandbox_id}/viewer/stop | Stop Viewer |
POST | /sandbox/sandboxes/v1/{sandbox_id}/viewer/token | Remint a fresh signed viewer URL (token refresh) |
POST | /sandbox/sandboxes/v1/{sandbox_id}/workspace/sync | Sync tenant GCS workspace ↔ guest SandboxWorkspace |
POST | /sandbox/sandboxes/v1/environments/pairs | Create or reconnect to a paired desktop and private companion |
DELETE | /sandbox/sandboxes/v1/environments/pairs/{pair_id} | Asynchronously destroy both paired environment children |
GET | /sandbox/sandboxes/v1/environments/pairs/{pair_id} | Get durable paired environment status |
POST | /sandbox/sandboxes/v1/images/build | Build-or-resolve a content-addressed desktop image |
GET | /sandbox/sandboxes/v1/images/build/{build_id} | Poll desktop image build status |
GET | /sandbox/sandboxes/v1/images/build/{build_id}/events | SSE desktop image build events |
Accepted on every endpoint on this page.
| Name | In | Type | Required | Description |
|---|
x-correlation-id | header | string | no | End-to-end correlation id for this eval run. When set, the gateway and downstream services honor it verbatim in logs, Cloud Trace span attributes, async job payloads, and Langfuse trace.id. When omitted, the gateway generates a ULID and echoes it on the response. |
X-Sandbox-Project-Id | header | string | null | no | Project to bill and rate-limit this request against. Validated against the credential: a project-scoped token may only name its own project, and gets 403 otherwise. Defaults to the token's project when omitted. |
X-Sandbox-Tenant-Id | header | string | null | no | Tenant for this request. Must match the credential's tenant when the credential carries one. |
GET /sandbox/sandboxes/v1
| Name | In | Type | Required | Description |
|---|
task_id | query | string | null | no | |
reuse_fingerprint | query | string | null | no | Filter by create-intent fingerprint (sha256:…). |
status | query | string | null | no | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1
application/json, required — CreateSandboxRequest
| Field | Type | Required | Description |
|---|
profile | string | no | Default: "sandboxes-default". |
source | object | null | no | Workspace seed. {type: archive_url|gcs_prefix, uri}, {type: snapshot, seq}, or {type: workspace_latest} to restore the latest snapshot any earlier sandbox of the same task workspace (task_id / labels.task_id / labels.ctp_task_id, or workspace_key) wrote in this tenant/project. The create response's source names the snapshot it pinned (sandbox_id + snapshot_seq); with no snapshot yet the workspace starts empty. |
image_ref | string | null | no | Immutable pin from POST …/images/build: OCI repo@sha256:<digest> or gce:projects/{project}/global/images/{name}. Floating tags rejected. |
autostop_sec | number | null | no | Idle seconds before the sandbox is stopped (default 1800). Returned on create/GET so clients can show session policy. |
ttl_sec | number | null | no | Hard max lifetime in seconds before destroy (default 86400). expires_at on the record is created_at + effective ttl. Values above the profile max_ttl_sec (default 30 days) are clamped and reported in warnings. With reuse=true a larger ttl extends the reused sandbox. Extend later with PATCH /v1/{sandbox_id}. |
linked_job_id | string | null | no | |
task_id | string | null | no | Optional Gen Studio / CTP task id for labels and episode metadata; when omitted, sandbox_id is used. |
reuse | boolean | no | When true, return an existing non-destroyed sandbox whose create fingerprint matches (owner salt + tenant/project + profile + image_ref + workspace_key + purpose/template labels) instead of provisioning a new session. Default false so pass@k / episode reset stay create-always. Default: false. |
reuse_salt | string | null | no | Optional client nonce mixed into the fingerprint salt. Rotate to force a fresh VM while keeping the same task_id. Required for fingerprinting when the caller has no Keycloak owner principal. |
restore_latest | boolean | no | When true and no sandbox is reused, seed the new sandbox from the task workspace's latest snapshot (same as source.type=workspace_latest). Ignored when source is set or the task has no snapshot yet. Default false so creates stay fresh unless asked. Default: false. |
labels | object | no | Consumer tags for analytics (trainer, pass, program, …). |
| Status | Description | Body |
|---|
201 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/_reap
Operator hook: stop/destroy idle sandboxes for this scope.
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
DELETE /sandbox/sandboxes/v1/{sandbox_id}
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
discard_unsaved | query | boolean | no | Delete the workspace volume even when it holds work the last save did not capture (checkpoint_failed_at set, or the pod was lost). Without it such a volume is kept. |
| Status | Description | Body |
|---|
204 | Successful Response | — |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/{sandbox_id}
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
PATCH /sandbox/sandboxes/v1/{sandbox_id}
Extend or shorten a sandbox lifetime. Clamped values return warnings.
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
application/json, required — UpdateSandboxLifetimeRequest
| Field | Type | Required | Description |
|---|
ttl_sec | number | null | no | New lifetime counted from now: expires_at becomes now + ttl_sec (may shorten or extend). Clamped to the profile max_ttl_sec (default 30 days). |
expires_at | string | null | no | Absolute ISO 8601 expiry (naive values are UTC). Mutually exclusive with ttl_sec; must be in the future; clamped to now + max_ttl_sec. |
autostop_sec | number | null | no | Idle seconds before auto-stop. 0 disables idle stop (TTL still applies). |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/{sandbox_id}/artifacts
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
kind | query | string | null | no | |
limit | query | integer | no | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/{sandbox_id}/artifacts/{capture_id}
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
capture_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/capture
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/{sandbox_id}/events
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
Last-Event-ID | header | string | null | no | |
| Status | Description | Body |
|---|
200 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/exec
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
application/json, required — ExecRequest
| Field | Type | Required | Description |
|---|
command | string[] | yes | |
cwd | string | null | no | |
timeout_sec | number | null | no | |
env | object | null | no | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
504 | The command outlived timeout_sec (default 3600 s). Body: {"detail", "code": "exec_timeout", "timeout_sec", "correlation_id"}. Processes it started may still be running in the sandbox. | — |
DELETE /sandbox/sandboxes/v1/{sandbox_id}/files
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
path | query | string | yes | |
| Status | Description | Body |
|---|
204 | Successful Response | — |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/{sandbox_id}/files
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
path | query | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
PUT /sandbox/sandboxes/v1/{sandbox_id}/files
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
path | query | string | yes | |
application/json, required
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/{sandbox_id}/ports
Read-only probe of /proc/net/tcp{,6}; does not count as session activity.
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
include_internal | query | boolean | no | Also return platform listeners (OpenVSCode :8080, IDE helpers). |
| Status | Description | Body |
|---|
200 | Successful Response | object |
404 | Sandbox not found in the caller's tenant/project | — |
409 | Sandbox is not running | — |
422 | Validation Error | HTTPValidationError |
502 | The in-sandbox port probe failed | — |
POST /sandbox/sandboxes/v1/{sandbox_id}/screenshot
Load http://127.0.0.1:{port}{path} in the pod and store the PNG as an artifact.
Same artifact store as POST …/capture (GET …/artifacts lists it). Counts as
session activity. Omit port when exactly one app is listening.
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
inline | query | boolean | no | Include the PNG as base64. |
application/json, optional
| Status | Description | Body |
|---|
200 | Successful Response | object |
404 | Sandbox not found in the caller's tenant/project | — |
409 | Nothing is listening on the port, the sandbox is not running, or the image has no headless browser | — |
413 | PNG exceeds SANDBOX_VIEWER_SCREENSHOT_MAX_BYTES | — |
422 | Invalid target: external URL, redirect out of the sandbox, ambiguous auto-detection, or bad path/viewport | — |
502 | The app did not load (navigation error or timeout) | — |
POST /sandbox/sandboxes/v1/{sandbox_id}/start
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/stop
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/touch
Heartbeat between agent turns so idle auto-stop does not fire.
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | SandboxLifetime |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/verify
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
application/json, required — VerifyRequest
| Field | Type | Required | Description |
|---|
require_verifier_evidence | boolean | no | Default: false. |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/{sandbox_id}/viewer
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/viewer/actions
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
application/json, required — ActionLogRequest
| Field | Type | Required | Description |
|---|
events | ActionEvent[] | yes | |
recording_id | string | null | no | Recording this log is time-aligned with. |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/viewer/annotations
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
application/json, required — AmbiguityAnnotation
| Field | Type | Required | Description |
|---|
clarity | "clear" | "ambiguous" | yes | |
ambiguity_types | "intent" | "referential" | "parametric" | "cross_modal"[] | no | Required when clarity is 'ambiguous'. |
severity | "low" | "medium" | "high" | "blocking" | null | no | |
risk | "low" | "medium" | "high" | null | no | |
feasibility | "feasible" | "partially_feasible" | "infeasible" | "unknown" | null | no | |
alternate_answers | string[] | no | Other defensible answers a solver could have given. |
root_of_confusion | string | null | no | What in the task made it ambiguous. |
task_prompt | string | null | no | Instruction that was annotated. |
notes | string | null | no | |
annotator | string | null | no | |
recording_id | string | null | no | |
actions_id | string | null | no | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/viewer/recordings
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
duration_sec | query | number | null | no | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/viewer/screenshots
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/viewer/start
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | ViewerDescriptor |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/viewer/stop
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/viewer/token
Issue a new viewer descriptor when the previous signed token is near expiry.
Requires API key / Keycloak / team token — not an expired viewer cookie.
Gen Studio should call this and replace the iframe src with the new url.
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | ViewerDescriptor |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/{sandbox_id}/workspace/sync
| Name | In | Type | Required | Description |
|---|
sandbox_id | path | string | yes | |
application/json, required — WorkspaceSyncRequest
| Field | Type | Required | Description |
|---|
direction | "pull" | "push" | yes | pull = GCS→guest SandboxWorkspace; push = guest→GCS snapshot. |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/environments/pairs
application/json, required — CreatePairedEnvironmentRequest
| Field | Type | Required | Description |
|---|
attempt_key | string | yes | Required stable trial/attempt identity. Reusing it with the same immutable pins reconnects to the same pair; changing it creates a clean pair. |
task | PairTaskPinRequest | yes | |
desktop | PairDesktopPinRequest | yes | |
companion | PairCompanionPinRequest | yes | |
| Status | Description | Body |
|---|
202 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
DELETE /sandbox/sandboxes/v1/environments/pairs/{pair_id}
| Name | In | Type | Required | Description |
|---|
pair_id | path | string | yes | |
| Status | Description | Body |
|---|
202 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/environments/pairs/{pair_id}
| Name | In | Type | Required | Description |
|---|
pair_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
POST /sandbox/sandboxes/v1/images/build
Publish a curated desktop image via the platform BuildKit pool.
Default (async): 202 + build_id; poll GET …/images/build/{build_id}
or stream GET …/images/build/{build_id}/events. Pass sync=true for the
legacy hold-open behaviour (gateway long proxy timeout).
| Name | In | Type | Required | Description |
|---|
sync | query | boolean | no | When true, hold the connection until BuildKit finishes (legacy). |
Idempotency-Key | header | string | null | no | |
X-Sandbox-Job-Id | header | string | null | no | |
application/json, required — BuildDesktopImageRequest
| Field | Type | Required | Description |
|---|
profile | string | no | Default: "desktop-ubuntu". |
apps | string[] | null | no | Catalog desktop_app ids (e.g. chrome). Mutually exclusive with bundle. |
bundle | string | null | no | Catalog desktop_app_bundle id (e.g. osworld). Mutually exclusive with apps. |
datapoint_id | string | null | no | Optional builder tag prefix; defaults to sandboxes-{profile}. |
| Status | Description | Body |
|---|
200 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/images/build/{build_id}
| Name | In | Type | Required | Description |
|---|
build_id | path | string | yes | |
| Status | Description | Body |
|---|
200 | Successful Response | object |
422 | Validation Error | HTTPValidationError |
GET /sandbox/sandboxes/v1/images/build/{build_id}/events
| Name | In | Type | Required | Description |
|---|
build_id | path | string | yes | |
Last-Event-ID | header | string | null | no | |
| Status | Description | Body |
|---|
200 | Successful Response | any |
422 | Validation Error | HTTPValidationError |
The object shapes referenced above.
One operator interaction inside the viewer.
| Field | Type | Required | Description |
|---|
at | number | yes | Milliseconds since the recording started. |
type | string | yes | click, scroll, key, search, screenshot… |
x | integer | null | no | |
y | integer | null | no | |
delta_x | number | null | no | |
delta_y | number | null | no | |
key | string | null | no | |
text | string | null | no | |
detail | object | null | no | |
| Field | Type | Required | Description |
|---|
events | ActionEvent[] | yes | |
recording_id | string | null | no | Recording this log is time-aligned with. |
Task-ambiguity label for a session, with its evidence references.
| Field | Type | Required | Description |
|---|
clarity | "clear" | "ambiguous" | yes | |
ambiguity_types | "intent" | "referential" | "parametric" | "cross_modal"[] | no | Required when clarity is 'ambiguous'. |
severity | "low" | "medium" | "high" | "blocking" | null | no | |
risk | "low" | "medium" | "high" | null | no | |
feasibility | "feasible" | "partially_feasible" | "infeasible" | "unknown" | null | no | |
alternate_answers | string[] | no | Other defensible answers a solver could have given. |
root_of_confusion | string | null | no | What in the task made it ambiguous. |
task_prompt | string | null | no | Instruction that was annotated. |
notes | string | null | no | |
annotator | string | null | no | |
recording_id | string | null | no | |
actions_id | string | null | no | |
Screenshot the user's app from a headless browser inside the sandbox.
| Field | Type | Required | Description |
|---|
port | integer | null | no | App port inside the sandbox. Omit when exactly one app is listening. |
url | string | null | no | Full URL; host must be the sandbox itself (localhost, 127.0.0.1, ::1 or the pod IP). External URLs are rejected. |
path | string | null | no | Path on the app (with port), e.g. /dashboard?tab=1. Default /. |
viewport | Viewport | no | |
full_page | boolean | no | Default: false. |
wait_ms | integer | no | Extra settle time after the load event (HMR/SPAs render late). Default: 1500. |
Build-or-resolve a content-addressed desktop image from curated catalog apps.
| Field | Type | Required | Description |
|---|
profile | string | no | Default: "desktop-ubuntu". |
apps | string[] | null | no | Catalog desktop_app ids (e.g. chrome). Mutually exclusive with bundle. |
bundle | string | null | no | Catalog desktop_app_bundle id (e.g. osworld). Mutually exclusive with apps. |
datapoint_id | string | null | no | Optional builder tag prefix; defaults to sandboxes-{profile}. |
| Field | Type | Required | Description |
|---|
attempt_key | string | yes | Required stable trial/attempt identity. Reusing it with the same immutable pins reconnects to the same pair; changing it creates a clean pair. |
task | PairTaskPinRequest | yes | |
desktop | PairDesktopPinRequest | yes | |
companion | PairCompanionPinRequest | yes | |
| Field | Type | Required | Description |
|---|
profile | string | no | Default: "sandboxes-default". |
source | object | null | no | Workspace seed. {type: archive_url|gcs_prefix, uri}, {type: snapshot, seq}, or {type: workspace_latest} to restore the latest snapshot any earlier sandbox of the same task workspace (task_id / labels.task_id / labels.ctp_task_id, or workspace_key) wrote in this tenant/project. The create response's source names the snapshot it pinned (sandbox_id + snapshot_seq); with no snapshot yet the workspace starts empty. |
image_ref | string | null | no | Immutable pin from POST …/images/build: OCI repo@sha256:<digest> or gce:projects/{project}/global/images/{name}. Floating tags rejected. |
autostop_sec | number | null | no | Idle seconds before the sandbox is stopped (default 1800). Returned on create/GET so clients can show session policy. |
ttl_sec | number | null | no | Hard max lifetime in seconds before destroy (default 86400). expires_at on the record is created_at + effective ttl. Values above the profile max_ttl_sec (default 30 days) are clamped and reported in warnings. With reuse=true a larger ttl extends the reused sandbox. Extend later with PATCH /v1/{sandbox_id}. |
linked_job_id | string | null | no | |
task_id | string | null | no | Optional Gen Studio / CTP task id for labels and episode metadata; when omitted, sandbox_id is used. |
reuse | boolean | no | When true, return an existing non-destroyed sandbox whose create fingerprint matches (owner salt + tenant/project + profile + image_ref + workspace_key + purpose/template labels) instead of provisioning a new session. Default false so pass@k / episode reset stay create-always. Default: false. |
reuse_salt | string | null | no | Optional client nonce mixed into the fingerprint salt. Rotate to force a fresh VM while keeping the same task_id. Required for fingerprinting when the caller has no Keycloak owner principal. |
restore_latest | boolean | no | When true and no sandbox is reused, seed the new sandbox from the task workspace's latest snapshot (same as source.type=workspace_latest). Ignored when source is set or the task has no snapshot yet. Default false so creates stay fresh unless asked. Default: false. |
labels | object | no | Consumer tags for analytics (trainer, pass, program, …). |
| Field | Type | Required | Description |
|---|
command | string[] | yes | |
cwd | string | null | no | |
timeout_sec | number | null | no | |
env | object | null | no | |
| Field | Type | Required | Description |
|---|
detail | ValidationError[] | no | |
| Field | Type | Required | Description |
|---|
profile | string | yes | Catalog companion profile id (e.g. companion-drawio, companion-erpnext). |
application | string | yes | Catalog desktop_app id with companion pins (e.g. drawio, erpnext). |
state_model | "file" | "stateful" | yes | Must match the catalog desktop_app state_model for application. |
image_ref | string | yes | Immutable OCI repo@sha256:<digest> companion pin. |
application_version | string | yes | Catalog application version. The server verifies that this version and image_ref are the exact catalog-owned pair for application. |
evaluator_target | "desktop" | "companion" | no | Pinned evaluator target for this task revision. Default: "desktop". |
| Field | Type | Required | Description |
|---|
profile | string | no | Default: "desktop-ubuntu". |
image_ref | string | yes | Immutable gce:projects/{project}/global/images/{name} desktop pin. |
| Field | Type | Required | Description |
|---|
task_id | string | yes | |
revision | string | yes | Immutable full initial-state revision or digest covering the task payload and all seeded file state. The paired-environment API does not import a separate companion state snapshot. |
Lifetime fields of a sandbox record (touch / lifetime responses).
| Field | Type | Required | Description |
|---|
sandbox_id | string | yes | |
status | string | yes | |
last_activity | number | yes | Unix epoch seconds of the last activity. |
autostop_sec | number | null | no | Idle seconds before auto-stop; 0 or null = never. |
idle_stop_at | number | null | no | Epoch seconds when idle auto-stop fires if nothing else happens. |
ttl_sec | number | null | no | Total lifetime: expires_at - created_at. |
expires_at | number | null | no | Unix epoch seconds when the sandbox is destroyed. |
Change a sandbox's lifetime. Values above the profile cap are clamped.
| Field | Type | Required | Description |
|---|
ttl_sec | number | null | no | New lifetime counted from now: expires_at becomes now + ttl_sec (may shorten or extend). Clamped to the profile max_ttl_sec (default 30 days). |
expires_at | string | null | no | Absolute ISO 8601 expiry (naive values are UTC). Mutually exclusive with ttl_sec; must be in the future; clamped to now + max_ttl_sec. |
autostop_sec | number | null | no | Idle seconds before auto-stop. 0 disables idle stop (TTL still applies). |
| Field | Type | Required | Description |
|---|
loc | string | integer[] | yes | |
msg | string | yes | |
type | string | yes | |
input | any | no | |
ctx | object | no | |
| Field | Type | Required | Description |
|---|
require_verifier_evidence | boolean | no | Default: false. |
Signed desktop viewer entry returned on running desktop/ide sandboxes.
| Field | Type | Required | Description |
|---|
url | string | yes | Gateway URL to open the viewer (includes signed token). |
mode | "novnc" | "guacamole" | "provider" | "selkies-ws" | "openvscode" | yes | Integration mode for the external viewer_ui library. |
embed | string | no | Default: "iframe". |
input_enabled | boolean | yes | False while the sandbox is not in running status. |
resolution | integer[] | no | |
expires_at | integer | yes | Unix epoch seconds when the signed viewer token in url expires. Remint via POST /v1/{sandbox_id}/viewer/token before this time. |
guest_username | string | null | no | Guest OS login name when the provider exposes identity. |
guest_hostname | string | null | no | Guest OS hostname shown in the desktop shell. |
guest_home | string | null | no | Guest home directory. |
workspace_mount | string | null | no | Guest path for tenant workspace files (SandboxWorkspace). |
stream_url | string | null | no | Optional C1 gateway WebSocket path for pixels/input (/sandbox/stream/v1/{id}/websockify?ticket=…). |
guest_url | string | null | no | Optional ticket-authenticated guest health URL (/sandbox/stream/v1/{id}/guest/healthz?ticket=…). |
| Field | Type | Required | Description |
|---|
width | integer | no | Default: 1280. |
height | integer | no | Default: 800. |
| Field | Type | Required | Description |
|---|
direction | "pull" | "push" | yes | pull = GCS→guest SandboxWorkspace; push = guest→GCS snapshot. |
Machine-readable spec: OpenAPI YAML.