Sandbox API

Architecture

Gateway, executors, queue, and substrates — pods, VMs, and external desktops.

How the platform is put together, and how a request moves through it. Use the component picture to see what exists; use the flow diagrams for order and hand-offs.

High-level components

BandWhat it is
ClientsYour apps and CLIs — HTTP only
EdgePublic gateway: auth, routing, /docs, OpenAPI
ExecutorsHarbor, Agent, CodeEdit, Sandboxes (long-lived + desktop)
ElasticityPub/Sub job queue + KEDA-scaled Harbor worker fleet
Control planeCatalog (agents, languages, profiles), per-project concurrency quota
SubstratesWhere isolation runs: pods, VMs, external Mac, optional Daytona

Substrates (pods and VMs)

Callers never pick a machine type in the HTTP path. The catalog profile carries a driver_hint; Sandboxes routes with ProfileRoutingBackend.

driver_hintSubstrateUsed by
k8sGKE / Kubernetes pod (often gVisor for trials; desktop Linux uses a standard runtime)Harbor default, Agent default, sandboxes-default, desktop-ubuntu
dockerLocal/docker-style execCodeEdit default profile
ec2-vm / gce-vm / vmCloud VM (Windows desktop today: EC2 + Guacamole)desktop-windows
externalVendor Mac cloud (not a GKE pod)desktop-macos → provider aws-ec2-mac
daytona (request override)Daytona environment via Harbor CLIOptional Harbor sandbox field

Desktop viewer modes follow the substrate:

ProfileSubstrateviewer.mode
desktop-ubuntuK8s podnovnc
desktop-windowsEC2 VMguacamole
desktop-macosExternal Macprovider

Deep dive: Desktop architecture.

How Harbor and Agent traffic flows

Harbor and Agent are asynchronous: 202 + job_id immediately; work runs on the shared worker fleet (typically into a pod substrate).

Step by step:

  1. Gateway authenticates and routes to Harbor or Agent.
  2. Catalog check (Agent is always strict; Harbor depends on enforcement mode).
  3. Executor enqueues the job → 202 + job_id.
  4. KEDA scales workers from queue depth.
  5. Worker admits a per-project slot, obtains LLM Gateway credentials if needed (ADR 0020), runs the trial.
  6. You poll or follow SSE until terminal; artifacts land in object storage.

Over the concurrent cap: async jobs stay queued; sync calls get 429. See Errors and limits.

How CodeEdit differs

Synchronous — one HTTP call waits for stdout/stderr. Claims a warm pool pod or creates one. Does not use the Harbor/Agent job queue.

How Sandboxes differ

Long-lived sessions (exec/files/checkpoint) and desktop GUIs share POST /sandbox/sandboxes/v1. The profile decides the substrate:

  • Default workspace profile sandboxes-default → K8s pod + PVC.
  • Desktop profiles return a signed viewer.url when status=running.
  • Browser never sees your API key — only the signed viewer URL.

Guides: Long-lived sandboxes, Desktop sandboxes.

How the developer docs differ

SurfacePurpose
/docsThis documentation
/openapi/sandbox-platform.yamlPublished OpenAPI
/sandbox/*Product APIs
/internal/swaggerEngineer Swagger (when enabled)

Packages (platform engineers)

Import direction: HTTP shells → executor libraries → control plane → sandbox core → drivers.

AreaRole
HTTP edgeThin FastAPI services behind the gateway
Executor librariesharbor_service, agent_service, sandboxes_service, …
PortsJob queue, object store, credential plane, sandbox driver
Drivers / backendsK8s, ECS, VM desktop, external Mac providers

L4 products use SandboxClient only.

In-repo: docs/layers/, docs/sandbox/HLD.md, docs/sandbox/desktop/.

Deployment topology

EnvironmentTypical substrate mixRole
Production / stagingGKE pods + (optional) AWS desktop VPC for Windows/MacLive API
LocalDocker Compose (make up)Developer loop

Local development.