Skip to main content

Templates and images

A template is the stable name your agents ask for. A revision is an immutable snapshot of everything a sandbox runs with. Templates are managed in the dashboard (Sandboxes → Templates), with the API, or with the MCP tools save-sandbox-template and create-sandbox-template-revision.

Template fields​

FieldDescription
nameHuman-readable name; a URL-safe slug is derived from it.
descriptionOptional.
appIdOptional app the template belongs to (set at creation only).
enabledWhen false, new sandboxes cannot be created from it. Running sandboxes are not affected.

Save the same templateId again to rename it, change the description, or disable it. Runtime settings are never edited on the template itself.

Revisions​

Each call to POST /sandbox-template/revision appends revision n + 1. New sandboxes always use the latest revision; sandboxes already created keep the exact revision they started with for their whole life (templateRevisionId on the sandbox). There is no in-place edit and no delete: to roll back, append a revision with the old values.

FieldDefaultDescription
imageDigestrequiredImage pinned by digest: registry/repo@sha256:<64 hex>. Tags alone are refused, so every sandbox runs the exact image you approved.
imageRefReadable reference such as python:3.12-slim, for display only.
commandimage entrypointEntrypoint argv. It must keep running; ["sleep", "infinity"] is the usual choice when you only run commands through the API.
workingDirimage defaultWorking directory of the container.
zClouds1Size. 1 zCloud = 0.5 vCPU + 512 MB of memory, reserved and capped (request = limit).
persistenceModeEPHEMERALDefault mode for new sandboxes; each create call may override it. See Persistence and volumes.
volumeSizeMbVolume modes: size of the volume created for a sandbox when it does not reuse one. Nominal on object storage.
mountPath/workspace/persistDIRECTORY and BOTH: where the persistent directory is mounted.
snapshotExcludeSNAPSHOT and BOTH: gitignore-like patterns left out of the pause snapshot, such as node_modules or *.log.
snapshotMaxMb2048SNAPSHOT and BOTH: cap on the uncompressed snapshot size.
idleTimeoutSecondsTerminate the sandbox after this long without activity.
hardLifetimeSecondsTerminate the sandbox this long after it was created, whatever it is doing.
networkControlopen egressEgress restrictions; see below.

Always set both timeouts: they are what guarantees an abandoned sandbox stops costing money. Typical values are 10–30 minutes idle and 1–8 hours lifetime for interactive work, and a short lifetime for one-shot code execution.

Choosing an image​

Any Linux OCI image works. The sandbox runs it under gVisor as uid/gid 1001, without root, and Quave ONE adds a small runtime agent next to your process to run commands, so your image needs nothing special. To get the most out of it:

  • Preinstall your tools. Package installs at runtime cost time on every new sandbox. Bake languages, CLIs, and dependencies into the image.
  • Include a shell (sh) if you want to run shell pipelines with ["sh", "-c", "..."]. Distroless images can still run direct argv commands.
  • Make paths writable by uid 1001. Commands run as uid/gid 1001. /workspace and the persistent mount are writable; create any other directory you need with that owner in the Dockerfile.
  • Keep it small. Smaller images start faster on a fresh node.
  • Use a registry the region can pull from. Public images work, and so do images in the Quave ONE registry. Credentials for your own private registry are not applied to sandbox images yet; publish the image publicly or ask Quave ONE support.

A coding-agent image, for example:

FROM node:22-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
git curl ca-certificates ripgrep jq python3 \
&& rm -rf /var/lib/apt/lists/* \
&& npm install -g @anthropic-ai/claude-code
# Non-root user matching the sandbox uid, with a writable home and workspace
RUN useradd -m -u 1001 agent && mkdir -p /workspace && chown agent /workspace
USER agent
WORKDIR /workspace
CMD ["sleep", "infinity"]

Build and push it, then read the digest from the push output (or docker buildx imagetools inspect <image>), and create a revision with imageDigest set to <image>@sha256:.... Pass API keys the agent needs through envVars on each command, never in the image or the template.

Egress control​

Without networkControl, a sandbox can reach the public internet. Private and infrastructure ranges (cluster networks, cloud metadata) are always blocked. To narrow it:

  • Only some IPs/CIDRs: {"enabled": true, "addressAllowlist": ["203.0.113.0/24"]}.
  • Only some domains: {"enabled": false, "domainAllowlist": ["github.com", "pypi.org"]}. Traffic goes through an egress proxy that allows only those domains.
  • Both: enabled: true with both lists. Domains go through the proxy, and the listed addresses are allowed directly.

Blank-only lists are refused. See the revision API for the full rules.

Warm pools​

A revision can keep warm capacity (warmPool with desired, min, max, set in the dashboard template form) so sandboxes start without waiting for a container to boot. Warm-pool templates must use EPHEMERAL: volume modes, pidLimit, and ephemeralDiskMb are refused on them.

Updating a template safely​

  1. Build and push the new image; note its digest.
  2. Append a revision with the new digest and the same settings.
  3. Create one sandbox from it and run a smoke command.
  4. New sandboxes now use it. Sandboxes already running keep the previous revision until they end.

To stop new sandboxes from a template, save it with enabled: false.