PLATINUM DOCS

Declarative builder

Define a template image as a chain of steps in code. Platinum caches builds by content.

Template defines an image as a chain of steps in code. Build the chain as a named template, or pass it inline when you create a sandbox. Platinum content-hashes each spec, so a repeat spec is a cache hit, not a rebuild.

Build a template

The step chain is SDK-only. The CLI and REST accept the compiled spec, not the chain.

A failed build does not throw. It returns state: "failed" with the tail of build_logs. Always check state.

Chain steps from a base image, then call build().

import { Platinum, Template } from "@platinum-dev/sdk";

const client = new Platinum({ url: process.env.PT_API_URL!, token: process.env.PT_TOKEN! });

const tpl = await Template
  .fromPythonImage("3.13-slim")
  .pipInstall(["pandas", "fastapi", "uvicorn"])
  .aptInstall(["curl", "ripgrep"])
  .env("LOG_LEVEL", "info")
  .workdir("/app")
  .copy("app.py", "/app/app.py")
  .entrypoint("uvicorn app:app --host 0.0.0.0 --port 8000")
  .build(client, { name: "my-agent", default_ram_mb: 1024 });

if (tpl.state === "failed") throw new Error(tpl.build_logs);
import os
from platinum import Platinum, Template

client = Platinum(token=os.environ["PT_TOKEN"], api_url=os.environ["PT_API_URL"])

tpl = (Template.from_python_image("3.13-slim")
       .pip_install(["pandas", "fastapi", "uvicorn"])
       .apt_install(["curl", "ripgrep"])
       .env("LOG_LEVEL", "info")
       .workdir("/app")
       .copy("app.py", "/app/app.py")
       .entrypoint("uvicorn app:app --host 0.0.0.0 --port 8000")
       .build(client, "my-agent", default_ram_mb=1024))

if tpl["state"] == "failed":
    raise RuntimeError(tpl["build_logs"])
# No dedicated CLI command for from-spec builds. Use the API passthrough.
pt api POST /v1/templates/from-spec -d @spec.json
curl -X POST $PT_API_URL/v1/templates/from-spec \
  -H "Authorization: Bearer $PT_TOKEN" \
  -d '{
    "name": "my-agent",
    "base_image": "python:3.13-slim",
    "steps": [
      { "op": "pip",     "packages": ["pandas", "fastapi", "uvicorn"] },
      { "op": "apt",     "packages": ["curl", "ripgrep"] },
      { "op": "env",     "key": "LOG_LEVEL", "value": "info" },
      { "op": "workdir", "path": "/app" }
    ],
    "entrypoint": "uvicorn app:app --host 0.0.0.0 --port 8000",
    "default_ram_mb": 1024
  }'

When the template is ready, create sandboxes with template: "my-agent". See Sandboxes.

Choose a base image

The build rejects floating tags: latest, lts, stable, main, master, edge, rolling. Pin a version (python:3.13-slim) or a @sha256: digest.

Factory (TS / Python)Base image
Template.fromImage(ref) / from_imageany Docker image ref
fromPythonImage(v) / from_python_imagepython:<v>
fromNodeImage(v) / from_node_imagenode:<v>
fromBunImage(v) / from_bun_imageoven/bun:<v>
fromUbuntuImage(v) / from_ubuntu_imageubuntu:<v>
fromDebianImage(v) / from_debian_imagedebian:<v>
fromAlpineImage(v) / from_alpine_imagealpine:<v>

Add steps

Every step returns the builder, so calls chain. TS is camelCase, Python is snake_case.

copy inlines a local file into the spec, up to 256 KiB. For larger files, write them after create with the filesystem API, or use a build context (see Templates).

Use containerRuntime() or container_runtime() only when the sandbox must run dockerd or Podman. It adds the complete module tree for the Platinum guest kernel. The default runtime profile includes only the transport modules required by Platinum and keeps the template smaller.

The equivalent REST step is:

{ "op": "kernel_modules", "profile": "container" }

readyCmd does not gate boot. A sandbox turns running when it boots, not when your app is ready. To wait for your app, poll its health endpoint via exec.

Configure build()

TS takes an options object: build(client, { name, ... }). Python takes name/version as arguments and the rest as keywords: build(client, "name", default_cpu=2, ...).

OptionDefaultNotes
namerequired^[a-z0-9][a-z0-9._-]*$, max 64 chars; unique per org. A rebuild of an existing name reuses its row.
version"1.0.0"floating values rejected
default_cpu11–16 — sandbox default when create does not override
default_ram_mb512128–32768
default_disk_gb21–100
size_mb1024initial rootfs size in MB; per-org cap 20,480
wait_ms300000how long to poll for ready/failed. 0 returns at once as building. A non-zero wait that expires throws PlatinumTimeoutError. The build keeps running — poll templates.get(id) to pick it up.

The SDK polls every 3 s until the template leaves building.

Build inline at sandbox create

Inline builds must finish within 300 s. A slower build fails the create. For large images, build() a named template first, then create from it by name.

Pass the builder as image. Platinum builds and boots in one call.

const image = Template.fromImage("alpine:3.20").runCmd("apk add --no-cache curl jq");
const sbx = await client.sandboxes.create(
  { image, env: { GREETING: "hi" } },
  { waitForRunning: true, waitTimeoutMs: 600_000 },
);
image = Template.from_image("alpine:3.20").run_cmd("apk add --no-cache curl jq")
sbx = client.sandboxes.create(image=image, env={"GREETING": "hi"},
                              wait_for_running=True, wait_timeout_ms=600_000)
# No CLI flag for an inline image spec. Use the API passthrough.
pt api POST /v1/sandboxes --query "wait_for_state=running" -d @body.json
curl -X POST "$PT_API_URL/v1/sandboxes?wait_for_state=running&wait_timeout_ms=60000" \
  -H "Authorization: Bearer $PT_TOKEN" \
  -d '{
    "image": {
      "base_image": "alpine:3.20",
      "steps": [{ "op": "run", "cmd": "apk add --no-cache curl jq" }],
      "size_mb": 256
    }
  }'
RuleBehavior
image + templateMutually exclusive — sending both is a 400. Omit both to use the default pt-base template.
CachingAn identical spec reuses the cached build; a new spec builds; a previously failed one rebuilds.
Hash coverageOnly base_image, steps, entrypoint, and ready_cmd count. A change to size_mb or a default_* still hits the old cached build.
Cache scopePer-org — two orgs with identical specs each pay their own first build.
size_mbCaps at 20,480.

See also

  • Templates — other build routes, listing, updates, deletion, quotas
  • Sandboxes — create options, wait semantics, lifecycle
  • API reference — exact /v1/templates/from-spec request/response schemas