Bonya Python SDK
Run code in a fast, isolated sandbox — from Python.
python -m pip install bonya
from bonya import Bonya
with Bonya() as client: # reads BONYA_API_KEY
with client.create_sandbox() as sandbox: # deleted on the way out
result = sandbox.exec(["echo", "hello"], check=True)
print(result.stdout) # hello
That is a real VM: it boots in about a second, runs anything Linux runs, and is
gone when the with block ends.
The SDK is synchronous. It talks to the Bonya REST API over HTTPS
(httpx), and to the edge over a WebSocket (websockets) for streaming exec
and terminal sessions. Python 3.10 or newer; fully typed (py.typed).
Configuration
Every setting has an environment-variable fallback:
| Argument | Environment variable | Default |
|---|---|---|
api_key |
BONYA_API_KEY |
required |
endpoint |
BONYA_ENDPOINT |
https://api.bonya.ai |
edge_endpoint |
BONYA_EDGE_ENDPOINT |
the API endpoint |
organization_id |
BONYA_ORGANIZATION_ID |
your personal organization |
ca_bundle |
BONYA_CA_BUNDLE |
system trust store |
timeout |
— | 30 (seconds) |
max_retries |
— | 2 |
filesystem_read_limit |
— | 64 MiB |
An empty organization_id is an error rather than a silent fallback to your
personal organization.
What you can do
| I want to… | Call |
|---|---|
| Start a sandbox | client.create_sandbox(template=, image=, snapshot=, gpu=, network=, env=, secret_sets=) |
| Reconnect to one | client.get_sandbox(id) / .get_sandbox_by_name(name) |
| Find my sandboxes | client.list_sandboxes(states=, name=) |
| Run a command | sandbox.exec(cmd) |
| Stream output live | sandbox.exec_stream(cmd) |
| Keep a process running after I disconnect | sandbox.create_session(name, cmd) / .attach_session(name) |
| Move files in and out | sandbox.read_file / .write_file / .upload_file / .download_file / .list_files / .stat_file / .mkdir_file / .remove_file / .move_file |
| Expose a port to the web | sandbox.create_preview(port) |
| Capture disk state | sandbox.snapshot() / .list_snapshots() |
| Clone a running sandbox | sandbox.fork(count) |
| Pause or keep awake | sandbox.pause("warm" | "cold") / .keepalive(seconds) / .resume() |
| Restrict egress | sandbox.update_network(NetworkPolicy(mode="allowlist", allow=[NetworkRule(domain="pypi.org")])) |
| Run a managed or scheduled job | client.run_job(spec) / client.create_job_schedule(schedule, job) |
| See GPU capacity | client.list_gpu_options() |
| Save a launch configuration | client.create_template(name, config=TemplateConfig(...)) / .list_templates() / .update_template() / .delete_template() |
| Pull private images | client.create_registry_connection(...) / .validate_registry_connection(id, image) |
| Keep credentials out of code | client.create_secret(name, value) / .create_secret_set(name, values) (values are write-only) |
| Switch organization | client.list_organizations() / client.organization_id = id |
Everything is a flat method on Bonya or Sandbox.
Streaming exec
from bonya import Exit, Stderr, Stdout
with sandbox.exec_stream(["bash", "-lc", "echo out; echo err >&2"]) as session:
for event in session:
if isinstance(event, Stdout):
print("out:", event.data.decode(), end="")
elif isinstance(event, Stderr):
print("err:", event.data.decode(), end="")
elif isinstance(event, Exit):
print("exit:", event.exit_code)
Persistent sessions
sandbox.create_session("server", ["bash"])
with sandbox.attach_session("server") as stream:
stream.write("npm run dev\n")
for event in stream:
... # Stdout, Exit, SessionEnded, SessionOutputDropped
# leaving the block detaches; the process keeps running
Jobs
from bonya import JobSandboxSpec, JobSpec
run = client.run_job(JobSpec(new_sandbox=JobSandboxSpec(), cmd=["./run-tests.sh"]))
print(run.status, run.result.exit_code)
Snapshots and forks
snapshot = sandbox.snapshot(name="baseline")
restored = client.create_sandbox(snapshot=snapshot.id)
forks = sandbox.fork(2).sandboxes
Errors
Every error extends BonyaError (with sandbox_id, idempotency_key, code).
Catch the class you care about: AuthenticationError, SandboxNotFoundError,
SandboxCreationTimeoutError (carries the idempotency_key so create can be
retried), ExecFailedError, TimeoutError, NoCapacityError,
RateLimitedError, OutcomeUnknownError, RemoteFileNotFoundError, and so on.
API keys and capability tokens are redacted from error messages.
Create, exec, snapshot and other mutations accept an idempotency_key; the SDK
generates one and reuses it across its own retries, so a retried call joins the
original attempt instead of repeating it.
Examples
Runnable programs live in examples/: quickstart.py,
exec_streaming.py, files.py, sessions.py, previews.py, snapshots.py.
Development
python -m pip install -e '.[dev]'
make check # mypy + pytest
MIT licensed.
Metadata
Release files for bonya 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| bonya-1.0.0.tar.gz | 44.5 kB | Without provenance | Details for bonya-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| bonya-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for bonya-1.0.0-py3-none-any.whl |
Total release size: 84.8 kB
Release files / bonya-1.0.0.tar.gz
| Download URL | bonya-1.0.0.tar.gz |
|---|---|
| Size | 44.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fe03e10697c6d90f3127e8b97824303df836fe7361b135f401385d7158b284bb
|
|
BLAKE2b-256 checksum How to use checksums |
1e3032652865c92595d553a680898ad5469f35098be41b870641de1d8c92a68d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / bonya-1.0.0-py3-none-any.whl
| Download URL | bonya-1.0.0-py3-none-any.whl |
|---|---|
| Size | 40.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
65b3b5fcd9d2d28f161bcd38b22120bc9790e8efc5dd164c98e81031c1e88db0
|
|
BLAKE2b-256 checksum How to use checksums |
cb4180ec656b8be8d5450a7f8425e10372787351fdf1872f94c237e6d8c2630f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Security for bonya 1.0.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.