Sandboxes

Quickstart

This guide takes you from zero to a sandbox running real code in about five minutes. By the end you'll have run Python in a stateful interpreter session (variables persist between calls, like a notebook), run shell commands, worked with files, streamed output from a long-running process, and paused / resumed a session.

Get started
Sandboxes are free to start. Enable them in one click from the Sandboxes console, then mint a token with a sandbox scope to use the SDK.

1. Install the SDK

Pick the language your agent runs in. The Python and JS SDKs ship the same surface; field names are snake_case in Python and camelCase in JS.

terminal
pip install orkestr

2. Mint an API token

Sign in to the orkestr console, open Settings, and create a new API token scoped to sandboxes:read and sandboxes:write. Sandbox-scoped tokens cannot reach the rest of the platform - use them in agent runtimes where credentials may end up in stack traces or LLM contexts.

Export the token:

terminal
export ORKESTR_API_KEY="ork_..."

3. Run your first sandbox

The code-interpreter template gives you a persistent Python session: every run_code call executes in the same interpreter, so variables, imports and dataframes carry over between calls - and results come back rich (text, HTML tables, PNG charts and parsed chart data), with exceptions as structured data instead of stderr text. pandas, NumPy and matplotlib are preinstalled. The with / withTemp pattern auto-terminates the sandbox on exit, which keeps your bill bounded if the agent loop crashes before it gets to call terminate explicitly.

agent
from orkestr import Sandbox

with Sandbox.create(template="code-interpreter") as sbx:
    sbx.run_code("import pandas as pd; df = pd.DataFrame({'eur': [120, 80, 45]})")

    # A separate call, same interpreter: df is still there.
    execution = sbx.run_code("df.sum()")
    print(execution.text)   # eur    245

That two-calls-one-session shape is the whole trick: an agent can load data once and keep analyzing it across turns. Charts, isolated contexts, and error semantics are covered in the full Code interpreter guide.

4. Run shell commands

Alongside the interpreter, every sandbox runs shell commands with exec - builds, scripts, servers, package installs. Both work in the same sandbox, and exec is available on every template.

agent
sbx.files.write("/workspace/main.py", "print(sum(range(1_000_000)))")
result = sbx.exec("python /workspace/main.py")
print(result.stdout)        # 499999500000
print(result.duration_ms)   # ~120

5. Stream long-running output

For commands that take longer than a few seconds, use streaming so the SDK doesn't hold all the bytes in memory and you can react to output as it arrives.

for chunk in sbx.exec_stream("python long_task.py"):
    if chunk.stream == "stdout":
        print(chunk.data, end="", flush=True)
    if chunk.is_final:
        print(f"exit={chunk.exit_code} in {chunk.duration_ms}ms")

6. Work with files

Every sandbox has a writable /workspace directory. Reads and writes go through the SDK as base64 over HTTPS; the SDK handles encoding so you can pass plain strings or bytes.

# Write
sbx.files.write("/workspace/data.json", '{"x": 1}')
sbx.files.write_bytes("/workspace/blob.bin", b"\x00\x01\x02")

# Read
content = sbx.files.read("/workspace/out.txt")
raw = sbx.files.read_bytes("/workspace/blob.bin")

# List
for entry in sbx.files.list("/workspace"):
    print(entry.name, entry.is_dir, entry.size)

7. Pause and resume across requests

Long-lived agent sessions can pause a sandbox between turns to stop the compute meter and resume from the same state minutes or hours later. pause() returns the sandbox id; persist it wherever your agent keeps state and pass it back to Sandbox.resume(). This includes interpreter sessions: a paused code-interpreter sandbox resumes with its kernel and every variable exactly where you left them.

sbx = Sandbox.create(template="node-22", network="restricted")
sandbox_id = sbx.pause()
# Persist sandbox_id somewhere (Redis, DB, agent state).

# Later, anywhere:
sbx = Sandbox.resume(sandbox_id)
result = sbx.exec("node server.js --status")
Snapshot retention
Snapshot retention is tier-capped (free: 1, payg: 10, enterprise: 50). Calling pause() over the cap raises SnapshotCapReached; terminate or resume an older snapshot first. A paused sandbox is also not kept forever: it expires after 7 days on the free tier and 30 days with a card on file (never on enterprise). The exact deadline is returned as paused_expires_at on the sandbox, and every resume restarts the clock.

Next steps

Reading with an agent? This page is also plain markdown at /docs/sandboxes/quickstart.md, and the full docs index lives at /docs/llms.txt.