Skip to main content

boax

Python SDK for Boax, the self-hosted sandbox and microVM platform. Python 3.9 or newer, standard library only.

Your code asks for a profile, capabilities and a placement policy. Boax picks the pool; the SDK never needs to know which backend runs the sandbox.

Install

pip install boax

Until the package is published, install from a checkout: pip install ./sdk/python.

Quickstart

from boax import Boax

# Defaults: BOAX_API_KEY and BOAX_URL (or http://localhost:8080).
client = Boax()

# Waits until the sandbox is running; pass wait=False to return at once.
sandbox = client.sandboxes.create(
    profile="small",
    placement={"strategy": "private-first", "external": "never"},
)

result = sandbox.exec("uname -sm")  # a string runs via /bin/sh -c
print(result.exit_code, result.stdout)
sandbox.exec(["ls", "-la", "/work"], cwd="/work", timeout_seconds=30)  # a list runs directly

sandbox.files.write("/work/a.txt", "hi")
text = sandbox.files.read_text("/work/a.txt")

sandbox.delete()

A sandbox is also a context manager that deletes itself on exit:

with client.sandboxes.create(profile="small") as sandbox:
    print(sandbox.exec("uname -a").stdout)

Streaming output

import sys

for ev in sandbox.exec_stream("make test"):
    if ev.type == "stdout":
        sys.stdout.write(ev.data)
    elif ev.type == "stderr":
        sys.stderr.write(ev.data)
    elif ev.type == "exit":
        print("exit code", ev.exit_code)
    else:
        print("backend error:", ev.error)

The command starts when exec_stream is called. The iterator ends after exit or error. If the connection drops before either arrives, it raises a connection_error.

Errors

Every failure is a BoaxError with code, status, details and request_id. Branch on code, not on the message.

from boax import BoaxError

try:
    client.sandboxes.create(profile="gpu-large")
except BoaxError as err:
    if err.code != "quota_exceeded":
        raise
    print("over quota on", err.details.get("dimension"), "request", err.request_id)

Server codes include invalid_request, unauthenticated, permission_denied, not_found, conflict, quota_exceeded, no_eligible_pool, unsupported_capability, unsupported_operation, provider_unavailable, invalid_state, rate_limited, suspended and internal. The SDK adds timeout and connection_error (with status 0). Waiting raises invalid_state if the sandbox fails or terminates first.

Retries. GET, PUT and DELETE requests, and sandbox creation, are retried up to max_retries times (default 3). Retries happen on 503, on 429 rate_limited (never quota_exceeded) and on connection errors, with exponential backoff that respects Retry-After. Each create call sends its own Idempotency-Key, so a retried create never makes a second sandbox. Pass idempotency_key to keep the key stable across process restarts. Exec and other POSTs are never retried.

What's covered

Namespace Methods
sandboxes create, get, list, iterate, update, delete, wait
Sandbox handle exec, exec_stream, files.list/read/read_text/write, stop, start, pause, resume, snapshot, fork, expose_port, explain_placement, refresh, update, wait, delete
snapshots list, get, delete
projects list, create, get, delete
api_keys list, create, revoke
quotas, usage get
audit_events list, iterate
policies list, put, delete
capabilities, profiles, templates, classifications list
admin organizations.{list,create,get,update,suspend,resume}, projects.set_quota, pools.{list,get,create,update,drain,undrain,delete}, agents.list, trust_report, verify_audit, terminate_sandbox, reconcile
client me, version

Keyword arguments are snake_case. Records come back as plain dicts keyed exactly like the API's JSON (camelCase), typed with TypedDict in boax.types. ExecResult, ExecEvent and Page are dataclasses.

list returns one Page (items, next_cursor); iterate walks every page:

for sb in client.sandboxes.iterate(status="running", labels={"team": "ml"}):
    print(sb.id)

Options

Boax(
    api_key="dly_...",       # default: BOAX_API_KEY
    base_url="https://...",  # default: BOAX_URL, then http://localhost:8080
    timeout=120.0,           # socket timeout in seconds; waits and streams set their own
    max_retries=3,
    headers={},              # extra headers on every request
)

Plain exec uses the client timeout unless you pass timeout_seconds. For long commands, pass timeout_seconds or use exec_stream, which has no socket timeout.

Development

python3 -m unittest discover -s tests   # runs against an in-process http.server

Metadata

Release files for boax-py 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for boax-py 0.1.0
File Size Uploaded Provenance Actions
boax_py-0.1.0.tar.gz 23.6 kB Without provenance Details for boax_py-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for boax-py 0.1.0
File Interpreter ABI Platform Actions
boax_py-0.1.0-py3-none-any.whl Python 3 none any Details for boax_py-0.1.0-py3-none-any.whl

Total release size: 45.1 kB

Release files / boax_py-0.1.0.tar.gz

Download URL boax_py-0.1.0.tar.gz
Size 23.6 kB
Tags Source
SHA-256 checksum
How to use checksums
aa05a545f457e12dd6df586981d18b273ba3376e8d59e70d41cb757bf853a736
BLAKE2b-256 checksum
How to use checksums
e6cccb2db83c803b67590881b83f88541becf8686f9c128e866420392696cb1f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / boax_py-0.1.0-py3-none-any.whl

Download URL boax_py-0.1.0-py3-none-any.whl
Size 21.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
15cdc242fe1a7b26128e9d93431525f0ffc015d17f6271d6593778ba12677775
BLAKE2b-256 checksum
How to use checksums
ca2d551a1341bd0d54951b2ba924b1a50c2e0fe6150f5f95d1a59ee71ce7cbd2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for boax-py 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page