EU-hosted sandbox VMs for AI agents - official Python SDK
Project description
orkestr Python SDK
EU-hosted sandbox VMs for AI agents. Type-safe Python client for the
api.orkestr.eu/v1/sandboxes REST API.
Status: private beta pre-release (
0.1.0a1). The client surface is stable and tested, but theapi.orkestr.eu/v1/sandboxesbackend is not live yet - every endpoint returns501 Not Implementeduntil the public beta. This release exists so you can pin the package and review the API. Seedocs/sandbox-mvp-plan.mdin the orkestr repo for the timeline.
Install
pip install --pre orkestr
Requires Python 3.10+. The --pre flag is needed while the SDK is a
pre-release; it is dropped once 0.1.0 ships with the public beta.
Authenticate
Mint an API token in the orkestr console with the sandboxes:write scope.
export ORKESTR_API_KEY="sp_live_..."
The SDK picks the key up from ORKESTR_API_KEY or you pass it explicitly.
Quick start
One-shot execution inside a fresh sandbox. The with block auto-terminates
the sandbox on exit, preventing runaway costs if the caller crashes.
from orkestr import Sandbox
with Sandbox.create(template="python-3.12") as sbx:
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
API
Create a sandbox
sbx = Sandbox.create(
template="python-3.12", # one of the templates listed below
cpu=1.0, # vCPU (default 1, plan-capped)
memory_mb=2048, # RAM (default 2048, plan-capped)
network="off", # "off" | "restricted" | "open"
timeout_seconds=600, # auto-terminate after this many seconds
env={"OPENAI_API_KEY": "sk-..."},
metadata={"agent_run": "r_123"},
region="fsn1", # "fsn1" (DE) | "hel1" (FI) | None for auto
api_key=None, # falls back to ORKESTR_API_KEY
)
print(sbx.id) # "sbx_01HXYZ..."
print(sbx.status) # "running"
Templates
| Template | Description |
|---|---|
python-3.12 |
CPython 3.12 with pip and common libs |
python-3.12-bare |
CPython 3.12 only, faster start |
node-22 |
Node 22 with npm |
ubuntu-24.04 |
Minimal Ubuntu shell environment |
Run a command
result = sbx.exec("python /workspace/main.py", timeout_seconds=60)
result.stdout # str
result.stderr # str
result.exit_code # int
result.duration_ms # int
Stream a long command
for chunk in sbx.exec_stream("python long_task.py"):
if chunk.stream == "stdout":
print(chunk.data, end="", flush=True)
else:
print(chunk.data, end="", flush=True, file=sys.stderr)
Files
sbx.files.write("/workspace/data.json", '{"x": 1}')
sbx.files.write_bytes("/workspace/blob.bin", b"\x00\x01\x02")
content = sbx.files.read("/workspace/out.txt") # returns str
raw = sbx.files.read_bytes("/workspace/blob.bin") # returns bytes
for entry in sbx.files.list("/workspace"):
print(entry.name, entry.is_dir, entry.size)
sbx.files.delete("/workspace/out.txt")
Pause + resume
Pausing snapshots the sandbox memory + disk and stops the compute meter.
Resume restores it on the same or a different host. pause() returns
the sandbox id; persist it across processes and pass to Sandbox.resume.
sbx = Sandbox.create(template="node-22", network="restricted")
sandbox_id = sbx.pause()
# ... minutes or hours later, from any worker:
sbx = Sandbox.resume(sandbox_id)
Snapshot retention is plan-capped (free: 1, pro: 3, team: 10). Calling
pause() over the cap raises SnapshotCapReached.
Terminate
Context-manager exit calls terminate(). Outside with:
sbx.terminate()
After terminate() the sandbox row stays in your account history but
the VM and any in-memory state are gone.
List your sandboxes
for sbx in Sandbox.list(status="running"):
print(sbx.id, sbx.template, sbx.created_at)
Errors
All SDK errors inherit from orkestr.OrkestrError.
| Exception | When |
|---|---|
AuthError |
Missing / invalid / expired API key, or scope mismatch |
RateLimitError |
Plan rate limit hit |
PlanLimitError |
Sandbox limit, concurrent limit, snapshot cap |
SandboxNotFound |
sandbox_id doesn't exist or isn't yours |
SandboxNotReady |
Operation called on a paused / terminated sandbox |
ExecTimeout |
exec() exceeded timeout_seconds |
NetworkPolicyError |
Command tried to reach a host the policy blocks |
OrkestrError |
Any other API-level error |
Async support
The MVP SDK is sync only. Async (AsyncSandbox) lands in v0.2.0 if a
design partner blocks on it; the wire format is identical.
Versioning
Follows Semantic Versioning. The SDK targets the
/v1/sandboxes API; bumps to v1 of the API are non-breaking for SDK
callers. v2 of the API will require an SDK major.
Links
- Sandbox waitlist
- Public API docs
- Questions and bug reports during the private beta: hello@orkestr.eu
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file orkestr-0.1.0a1.tar.gz.
File metadata
- Download URL: orkestr-0.1.0a1.tar.gz
- Upload date:
- Size: 21.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97b49caed1892980bb9de33d702c9dd27ab36ad763c9224cd1548c2e3a06646c
|
|
| MD5 |
7cc00f778545ea682ecfd5497ec6a13e
|
|
| BLAKE2b-256 |
202a3062be6287e663ae2d7124e2829c25d18af3a28936f81dfed79ba1c4a1d7
|
File details
Details for the file orkestr-0.1.0a1-py3-none-any.whl.
File metadata
- Download URL: orkestr-0.1.0a1-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1bc69b81cdabd12c96158db84452dcee8b6b19f02d7cb684b6f815eb0c792fd
|
|
| MD5 |
d90323cfc8017a5178d3501239b35b2a
|
|
| BLAKE2b-256 |
e75dafb01619f42a003c87db2d94301646974efe853d4152e44b0938d710d7bb
|