#Template
A Template is the blueprint for creating Sandboxes. It defines the container image, resource limits, warm pool size, and default network policy. Every Sandbox is created from a Template.
Creating, updating, and deleting team-owned templates requires team admin permissions. developer and builder roles can read templates, and builder is typically used for registry push workflows rather than template management.
Template Types#
Sandbox0 has two categories of templates:
| Type | Description | Visibility |
|---|---|---|
| Builtin | System-provided templates managed by the platform operator | Public — visible to all teams |
| Custom | Templates created and owned by your team | Private — visible to your team only (configurable) |
Builtin templates use curated public images and are ready to use immediately. Custom templates let you bring your own image, fine-tune resources, mount volumes, configure environment variables, and define default network policy.
Custom Template Or Rootfs Snapshot#
You do not need a custom template for every initialized environment. If the base image, resources, network policy, and mount declarations already fit, you can claim a sandbox from a builtin template, install dependencies or clone repositories inside the writable root filesystem, pause it, create a rootfs snapshot, then claim future sandboxes with that snapshot_id.
This is useful for dependency-heavy agent workspaces:
- claim a sandbox from a platform-owned builtin template such as
defaultordins - install packages, populate caches, clone repositories, or write tool configuration
- pause the sandbox and wait for
statusto becomepaused - create a named rootfs snapshot for the initialized state
- claim each task sandbox with the same template and
snapshot_id
For platform-owned builtin templates, the operator manages the warm pool. That lets teams reuse warm builtin capacity and store only the initialized rootfs state for their own dependency set instead of maintaining a separate custom template pool for each variation.
| Need | Prefer |
|---|---|
| Different base image, resource envelope, default environment, mount paths, network defaults, or privileged runtime fields | Custom template |
| User-space dependencies, repository checkout, package cache, generated files, or per-project tool configuration on an existing base image | Builtin template plus rootfs snapshot and claim with snapshot_id |
| Data that must outlive sandbox identity, be mounted by multiple sandboxes, or be accessed through direct storage APIs | Sandbox Volume |
Rootfs snapshots do not create template IDs and do not appear in s0 template list. Claiming with snapshot_id creates a new running sandbox from the selected rootfs snapshot while the requested template still controls image, resources, mounts, services, and network defaults. Restore remains useful for rolling back an existing paused sandbox, and fork remains useful when you specifically need a paused child sandbox. See Snapshot And Restore for the paused-state requirements and API workflow, or read Initialize Once, Claim Many for the custom-rootfs pattern.
Create Template#
Create a custom template for your team. The template spec is defined in a YAML file.
CLI examples assume you already ran s0 auth login and selected the correct current team.
/api/v1/templates
Request Body#
| Field | Type | Description |
|---|---|---|
template_id | string | Unique identifier for the template (e.g., my-python-env) |
spec | object | Full template specification |
Template IDs must be unique within your team. Once created, the ID cannot be changed — create a new template if you need a different ID.
Example spec file (template.yaml):
yamlspec: mainContainer: image: python:3.12-slim resources: cpu: "1" memory: 4Gi ephemeralStorage: 8Gi pool: minIdle: 2 maxIdle: 10
gotpl, err := client.CreateTemplate(ctx, apispec.TemplateCreateRequest{ TemplateID: "my-python-env", Spec: apispec.SandboxTemplateSpec{ MainContainer: apispec.NewOptContainerSpec(apispec.ContainerSpec{ Image: "python:3.12-slim", Resources: apispec.ResourceQuota{ CPU: apispec.NewOptString("1"), Memory: apispec.NewOptString("4Gi"), EphemeralStorage: apispec.NewOptString("8Gi"), }, }), Pool: apispec.NewOptPoolStrategy(apispec.PoolStrategy{ MinIdle: 2, MaxIdle: 10, }), }, }) if err != nil { log.Fatal(err) } fmt.Printf("Template created: %s\n", tpl.TemplateID)
Get Template#
Retrieve a specific template by ID. Your team can access both its own templates and builtin templates.
/api/v1/templates/{id}
gotpl, err = client.GetTemplate(ctx, "my-python-env") if err != nil { log.Fatal(err) } fmt.Printf("Template: %s (scope: %s)\n", tpl.TemplateID, tpl.Scope)
List Templates#
List all templates visible to your team — including your team's custom templates and all public builtin templates.
/api/v1/templates
gotemplates, err := client.ListTemplate(ctx) if err != nil { log.Fatal(err) } for _, tpl := range templates { display, _ := tpl.Spec.DisplayName.Get() fmt.Printf("- %s (%s) scope=%s\n", tpl.TemplateID, display, tpl.Scope) }
Update Template#
Update the spec of an existing custom template. The update triggers a reconciliation across all clusters — running sandboxes are not affected.
/api/v1/templates/{id}
Updating a template does not affect already-running Sandboxes. New Sandboxes claimed after the update will use the new spec. Idle pods in the pre-warm pool are recycled and replaced with pods matching the new spec.
gotpl, err = client.UpdateTemplate(ctx, "my-python-env", apispec.TemplateUpdateRequest{ Spec: apispec.SandboxTemplateSpec{ MainContainer: apispec.NewOptContainerSpec(apispec.ContainerSpec{ Image: "python:3.12-slim", Resources: apispec.ResourceQuota{ CPU: apispec.NewOptString("2"), Memory: apispec.NewOptString("8Gi"), EphemeralStorage: apispec.NewOptString("8Gi"), }, }), Pool: apispec.NewOptPoolStrategy(apispec.PoolStrategy{ MinIdle: 3, MaxIdle: 10, }), }, }) if err != nil { log.Fatal(err) } fmt.Printf("Template updated: %s\n", tpl.TemplateID)
Delete Template#
Delete a custom template. All cluster allocations for the template are cleaned up via reconciliation.
/api/v1/templates/{id}
Deleting a template does not terminate running Sandboxes created from it, but no new Sandboxes can be created from the deleted template.
go_, err = client.DeleteTemplate(ctx, "my-python-env") if err != nil { log.Fatal(err) } fmt.Println("Template deleted")
Next Steps#
Custom Images
Build and reference custom container images for sandbox templates.
Warm Pool
Use warm pools to reduce startup latency for common templates.
Snapshot And Restore
Reuse initialized rootfs state without creating another template.
Initialize Once, Claim Many
Customize a builtin template with rootfs snapshots and claim-time snapshot IDs.