#Sandbox
A Sandbox is an isolated execution environment where you can run code, manage files, and control network access. Each sandbox is created from a Template and has a writable root filesystem that is checkpointed across pause/resume for the same sandbox identity.
For shell access and file copy over standard SSH clients, see SSH.
Sandbox0 Cloud clients should use https://api.sandbox0.ai. Set SANDBOX0_BASE_URL only when you are connecting to a self-hosted or private deployment.
Sandbox Model#
Key Identifiers#
| Field | Description |
|---|---|
id | Unique sandbox identifier (e.g., sb_abc123) |
template_id | Template used to create this sandbox |
team_id | Team that owns this sandbox |
user_id | User who claimed this sandbox |
pod_name | Kubernetes pod name (internal) |
cluster_id | Cluster where sandbox runs in multi-cluster deployments. Present on claim and list responses, not on sandbox detail responses. |
Lifecycle States#
| Status | Description |
|---|---|
starting | Sandbox is being initialized |
running | Sandbox is active and ready to use |
paused | Sandbox has no runtime; identity and latest rootfs checkpoint are preserved |
terminating | Sandbox identity and durable state are being deleted |
failed | Sandbox encountered an error |
Pause and resume use internal lifecycle transactions, but pausing and resuming are not caller-visible statuses. Use the paused boolean as a convenience for status == "paused". Pause does not preserve running processes, memory, sockets, PID state, or live REPL sessions.
Persistent Root Filesystem#
Sandbox0 persists the sandbox writable root filesystem as part of checkpointed pause/resume:
- when
ttlexpires or pause is requested, Sandbox0 saves a rootfs checkpoint before releasing the runtime pod - when the sandbox resumes, Sandbox0 creates or reuses a runtime pod and restores the latest rootfs checkpoint before initializing sandbox processes
- files written outside mounted volumes survive pause/resume for the same sandbox identity after a checkpoint succeeds
- rootfs checkpoints for the sandbox identity are deleted when the sandbox is deleted or
hard_ttlexpires
Use the root filesystem for transparent same-sandbox continuity. Use Snapshot And Restore for named rootfs snapshots, restore, and fork operations. Use Volumes for storage that must be mounted by multiple sandboxes or accessed directly through Volume APIs.
Claim a Sandbox#
Claim a sandbox from a template. The sandbox is created from a pre-warmed pool for fast startup (<200ms cold start).
/api/v1/sandboxes
Request Body#
| Field | Type | Description |
|---|---|---|
template | string | Template ID to use |
snapshot_id | string | Optional rootfs snapshot ID used to initialize the writable root filesystem |
config | object | Optional sandbox configuration |
Sandbox Configuration#
| Field | Type | Description |
|---|---|---|
env_vars | object | Sandbox-level default environment variables for new procd-managed processes |
ttl | integer | Time to live in seconds (soft limit, triggers auto-pause; default: 0, disabled) |
hard_ttl | integer | Hard sandbox lifetime in seconds (deletes identity and durable state; default: 0, disabled) |
resources | object | Optional per-sandbox resource override. Only resources.memory is accepted; CPU is derived from the platform memory-per-CPU ratio. |
network | object | SandboxNetworkPolicy. Controls traffic rules, protocol controls, credential bindings, and destination-scoped egress auth |
webhook | object | Webhook configuration |
auto_resume | boolean | Auto-resume when accessed (default: true) |
services | array | Sandbox Services for public HTTP routes, including Sandbox Functions |
See Network and Protocol Controls for outbound control, Sandbox Services for public HTTP controls, Sandbox Functions for inline public handlers, and Credential for outbound auth and secret handling.
Sandbox env_vars override template/container environment variables for new contexts, command services, and function executions. Per-context, per-command, service runtime, and function env_vars override sandbox env_vars for that narrower scope. Warm processes start before the sandbox is claimed, so they do not receive claim-time sandbox env_vars.
Sandbox Resources#
Set config.resources.memory when one sandbox needs a different memory limit from its template. The minimum is 128Mi. The platform maximum defaults to 32Gi and can be changed by the operator with services.manager.config.sandboxMaxMemory.
Sandbox0 keeps CPU and memory in the platform-defined ratio. The request only accepts memory; manager derives CPU from services.manager.config.teamTemplateMemoryPerCpu and applies the result to the sandbox runtime container. Existing running sandboxes can update memory with the Update Sandbox API.
SDK helpers expose this as WithSandboxMemory / UpdateSandboxMemory in Go, memory / updateMemory in TypeScript, memory / update_memory in Python, and --memory in the s0 CLI.
TTL vs Hard TTL#
Sandbox0 uses two-tier TTL to balance resource efficiency and flexibility:
| Field | Behavior | Use Case |
|---|---|---|
ttl | Runtime soft pause: When expired, Sandbox0 checkpoints the writable root filesystem, deletes the runtime pod, and marks the sandbox paused. | Keep sandboxes alive during active use while freeing compute resources during idle periods. |
hard_ttl | Sandbox hard delete: When expired, Sandbox0 deletes the sandbox identity and durable state, including paused rootfs checkpoints. | Enforce a maximum lifetime for compute and storage resources. |
The relationship: ttl <= hard_ttl. When ttl expires first, sandbox pauses but can be resumed.
When hard_ttl expires, the sandbox is deleted and later access returns not found. Resume starts a new runtime generation from the latest rootfs checkpoint only while the sandbox is paused and still within its hard TTL.
Example timeline (sandbox created with ttl=300 and hard_ttl=3600):
t=0: Sandbox createdt=300: TTL expires → sandbox auto-pausest=310: User calls refresh → TTL reset to 300, Hard TTL reset to 3600 (new hard deadline att=3910)t=610: TTL expires again → sandbox auto-pausest=3910: Hard TTL expires → sandbox identity and durable state are deleted
goctx := context.Background() client, err := sandbox0.NewClient( sandbox0.WithToken(os.Getenv("SANDBOX0_TOKEN")), sandbox0.WithBaseURL(os.Getenv("SANDBOX0_BASE_URL")), ) if err != nil { log.Fatal(err) } // Claim a sandbox from the "default" template sandbox, err := client.ClaimSandbox(ctx, "default", sandbox0.WithSandboxHardTTL(300), sandbox0.WithSandboxMemory("512Mi"), sandbox0.WithSandboxEnvVars(map[string]string{ "APP_ENV": "development", }), ) if err != nil { log.Fatal(err) } fmt.Printf("Sandbox ID: %s\n", sandbox.ID) defer client.DeleteSandbox(ctx, sandbox.ID)
Get Sandbox Details#
Retrieve full details about a sandbox.
/api/v1/sandboxes/{id}
gosb, err := client.GetSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Printf("Status: %s\n", sb.Status) fmt.Printf("Template: %s\n", sb.TemplateID) fmt.Printf("Expires at: %s\n", sb.ExpiresAt)
Get Sandbox Status#
Get the current status of a sandbox (lighter weight than full details).
/api/v1/sandboxes/{id}/status
gostatus, err := client.StatusSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Printf("Status: %s\n", status.Status.Value)
Get Sandbox Logs#
Read sandbox process output. Procd service logs are filtered out of this API and remain available from Kubernetes pod logs. Snapshot and streaming requests return text/plain.
/api/v1/sandboxes/{id}/logs
Query Parameters#
| Parameter | Type | Description |
|---|---|---|
container | string | Pod container name (default: procd) |
tail_lines | integer | Number of Kubernetes log lines read from the end of the log before procd service log filtering (default: 200, max: 5000) |
limit_bytes | integer | Maximum Kubernetes log bytes read before procd service log filtering (default: 1048576 for snapshot responses, max: 8388608) |
follow | boolean | Stream logs as text/plain until the client disconnects |
previous | boolean | Return logs from the previously terminated container instance |
timestamps | boolean | Include Kubernetes log timestamps when available |
since_seconds | integer | Return logs newer than this many seconds |
gotailLines := int64(200) logs, err := sandbox.GetLogs(ctx, &sandbox0.SandboxLogsOptions{ TailLines: &tailLines, }) if err != nil { log.Fatal(err) } fmt.Print(logs.Logs)
For live streaming, use sandbox.StreamLogs(...), sandbox.stream_logs(...), sandbox.streamLogs(...), or s0 sandbox logs --follow.
List Sandboxes#
List all sandboxes with optional filters.
/api/v1/sandboxes
Query Parameters#
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status (starting, running, failed, completed, terminating) |
template_id | string | Filter by template ID |
paused | boolean | Filter by paused state independently of status |
limit | integer | Max results per page (default: 50, max: 200) |
offset | integer | Pagination offset (default: 0) |
golimit := 10 sandboxes, err := client.ListSandboxes(ctx, &sandbox0.ListSandboxesOptions{ Status: "running", TemplateID: "default", Limit: &limit, }) if err != nil { log.Fatal(err) } for _, sb := range sandboxes.Sandboxes { fmt.Printf("- %s (status: %s)\n", sb.ID, sb.Status) }
Update Sandbox#
Update sandbox configuration at runtime without restarting the sandbox.
/api/v1/sandboxes/{id}
Updatable Fields#
Only the following fields can be updated at runtime:
| Field | Type | Description |
|---|---|---|
ttl | integer | Time to live in seconds (soft limit) |
hard_ttl | integer | Hard sandbox lifetime in seconds |
resources | object | Runtime resource override. Only resources.memory is accepted. |
network | object | Network policy configuration |
auto_resume | boolean | Auto-resume when accessed |
services | array | Sandbox Services for public HTTP routes, including Sandbox Functions |
env_vars and webhook cannot be updated at runtime. These fields only take effect when the sandbox is created. To use different sandbox-level environment variables, create a new sandbox.
go_, err = client.UpdateSandboxMemory(ctx, sandbox.ID, "2Gi") if err != nil { log.Fatal(err) }
Pause And Resume#
Pause and resume is covered in a dedicated page because it affects TTL, auto_resume, service routes, SSH, and webhook behavior.
See Pause And Resume for explicit pause, state inspection, resume, and auto-resume behavior.
See Snapshot And Restore for named rootfs snapshots, restore, and fork operations that require a paused sandbox.
Refresh Sandbox TTL#
Extend the sandbox time-to-live. This resets both ttl and hard_ttl (if configured) from the current time while the sandbox has a runtime.
/api/v1/sandboxes/{id}/refresh
Request Body#
| Field | Type | Description |
|---|---|---|
duration | integer | Duration to extend TTL in seconds (optional, defaults to original TTL) |
If duration is not specified, both ttl and hard_ttl are reset to their original configured values. Use this to keep a sandbox alive as long as the user is actively using it.
go// Refresh with default duration (original TTL) resp, err := client.RefreshSandbox(ctx, sandbox.ID, nil) if err != nil { log.Fatal(err) } fmt.Printf("New expires at: %s\n", resp.ExpiresAt) // Refresh with custom duration (e.g., 1 minute) resp, err = client.RefreshSandbox(ctx, sandbox.ID, &apispec.SandboxRefreshRequest{ Duration: apispec.NewOptInt32(60), }) if err != nil { log.Fatal(err) } fmt.Printf("New expires at: %s\n", resp.ExpiresAt)
Delete Sandbox#
Terminate and delete a sandbox. This action is irreversible.
/api/v1/sandboxes/{id}
go_, err = client.DeleteSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Println("Sandbox deleted")
Next Steps#
Pause And Resume
Control checkpointed pause and resume behavior before wiring long-lived workflows.
Snapshot And Restore
Create named rootfs snapshots, restore paused sandboxes, and fork sandbox state.
Contexts
Run REPL and command contexts inside a sandbox and stream process output.