Sandboxes

Custom templates

A custom template bakes your dependencies into the sandbox image once, so every sandbox you create from it boots in about 300 ms with everything already installed - no pip install tax on each run. Build a template from one of the built-in base images plus a recipe of shell steps, then pass its id wherever you'd pass a built-in template name.

The short version
Build once with a base image + a recipe (via the console, REST API, or MCP), wait for it to go ready, then Sandbox.create(template="tmpl_..."). The image is captured on the host, so size never affects boot time.

Why templates

Installing packages at the start of every sandbox is slow and repetitive - a heavy pip install or apt-get can dwarf the actual work an agent does in the box. A template moves that cost to build time: the install runs once, the resulting filesystem is captured as a reusable image, and sandboxes boot straight into it. Because the image is hardlinked rather than copied, a 1 GB template boots just as fast as a bare base.

How a build works

When you create a template, orkestr boots a short-lived build VM from your base image with a writable root filesystem, runs each recipe step in order, and captures the result as a new image:

  • Each step runs as root with HOME=/root, so installs persist into the captured image.
  • If any step exits non-zero, the build stops and the template is marked failed with the failing step's output.
  • On success the image is scrubbed (package caches, logs, machine-id) and the template goes ready.
  • The recipe is the source of truth; the image is a derived artifact - templates are immutable, so to change one you build a new template.

Build a template

Templates are built via the Sandboxes console, the REST API, or the MCP server. The SDKs consume templates (you boot sandboxes from them) but don't build them - building is a control-plane operation. From the console, open the Templates section, click New template, and fill in a name, base image, and one build step per line.

Or over the REST API:

terminal
curl -X POST https://api.orkestr.eu/v1/templates \
  -H "Authorization: Bearer $ORKESTR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "data-stack",
    "base_template": "python-3.12",
    "recipe": [
      "pip install pandas numpy pyarrow",
      "echo \"ready\" > /root/.template-built"
    ],
    "network": "restricted"
  }'

# => { "id": "tmpl_01J...", "status": "building", ... }

Over MCP, call the create_template tool with the same fields (name, base_template, recipe, optional network); poll with list_templates. See the MCP reference.

Build settings
Recipe steps usually need network access to fetch packages, so the build defaults to restricted egress (package registries, GitHub, and major APIs through an allowlisting proxy) - use open if a step reaches something else. Installs land in the system and /root; /workspace and /tmp are tmpfs and are not captured. Custom templates are a paid-plan feature.

Check build status

A build is asynchronous. The create call returns immediately with status: "building"; poll until it's ready (or failed, which carries an error_message). The console does this for you and flips the status badge live.

terminal
# Poll until status is "ready" (or "failed", with error_message).
curl https://api.orkestr.eu/v1/templates/tmpl_01J... \
  -H "Authorization: Bearer $ORKESTR_API_KEY"

# List all of your templates:
curl https://api.orkestr.eu/v1/templates \
  -H "Authorization: Bearer $ORKESTR_API_KEY"

Boot a sandbox from a template

Once a template is ready, use its id as the template exactly like a built-in. In the console, it appears under "Your templates" in the New sandbox picker.

agent
from orkestr import Sandbox

# Pass the template id wherever you'd pass a built-in name.
with Sandbox.create(template="tmpl_01J...") as sbx:
    result = sbx.exec("python -c 'import pandas; print(pandas.__version__)'")
    print(result.stdout)  # already installed - no pip at boot

Or directly over the API:

terminal
curl -X POST https://api.orkestr.eu/v1/sandboxes \
  -H "Authorization: Bearer $ORKESTR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "template": "tmpl_01J...", "size": "small" }'

Lifecycle & limits

  • Statuses: buildingready | failed. Only ready templates can be booted.
  • Plan caps: the number of templates you can keep is plan-limited (Pro: 5, Team: 15). Failed builds don't count - delete and retry freely.
  • Deleting: removing a template frees the slot and its image. Sandboxes already running from it keep working.
terminal
curl -X DELETE https://api.orkestr.eu/v1/templates/tmpl_01J... \
  -H "Authorization: Bearer $ORKESTR_API_KEY"
Keep recipes deterministic
Pin versions where it matters (pip install pandas==2.2.0) so a rebuild reproduces the same image. A template is captured at build time and never changes afterwards; to pick up new package versions, build a new template.

Next steps