Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

sandboxio

One secure Python API for running AI-agent code in any sandbox. Swap Docker ↔ E2B with one line; no network by default; test your agent tools offline with the built-in fake.

CI Python 3.11+ License: MIT OpenSSF Scorecard Coverage

Why this exists

Every sandbox provider ships its own SDK with its own shape, so agent code that runs on one is rewritten for the next. The framework layers each solve it captively — LangChain's backends only help inside LangChain. sandboxio is the framework-agnostic substrate underneath, with the security posture that agent execution actually needs.

  • Security is the headline, not an add-on. Deny-by-default egress, mandatory timeouts, isolation-tier reporting and audit hooks are all in v0.1 — not a later hardening pass.
  • No lowest common denominator. One-backend features stay reachable through Capability flags and .native instead of being sanded off.
  • Tiny, auditable core. anyio and typing-extensions only; every backend SDK sits behind an extra and is imported lazily.
  • Offline-testable. FakeBackend and a pytest fixture, so your agent's tools have tests that need no Docker, no network and no provider account.
  • Usable without writing Python. The same sandbox and the same defaults are served over MCP, so a client like Claude Desktop or Cursor gets code execution it cannot reconfigure at runtime.
  • Provider churn is absorbed publicly. Upstream breaking changes are tracked, absorbed and written down.

Quickstart

Every Python block below is executed by CI exactly as written (tests/test_readme_examples.py); a copied example that does not run is a P0 bug. The Docker-backed lines run against the built-in fake in CI, so they are the same code you would run — only the backend differs.

The commands below are what v0.1 will install. Today the name on PyPI holds a 0.0.0 placeholder that carries no code, so uv add sandboxio does not yet get you a library. uvx sandboxio demo is the documented entry point — never the sbx alias, which resolves to an unrelated PyPI package (ADR-0014).

uv add "sandboxio[docker]"     # from v0.1
uvx sandboxio demo             # create, run, stream, prove egress is denied, tear down
sandboxio doctor               # what is installed, reachable and missing — no secrets printed

Run code in a sandbox. create() with no arguments is local Docker; nothing leaves the sandbox unless you say so.

import sandboxio

async with await sandboxio.create() as sb:              # zero-config, local Docker
    res = await sb.run_code("print('hello')")
    print(res.stdout)                                    # hello
    res = await sb.run(["python", "--version"], timeout=30)
    print(res.exit_code, res.stdout.strip())

Swap the backend with one line. The code that uses the sandbox does not change.

import sandboxio

async def summarise(sb: sandboxio.protocols.AsyncSandbox) -> str:
    await sb.files.write("/work/input.txt", "3 4\n")
    res = await sb.run_code("a, b = open('/work/input.txt').read().split(); print(int(a) * int(b))")
    res.raise_for_status()                               # ExecutionError on a non-zero exit
    return res.stdout.strip()

async with await sandboxio.create("docker://python:3.12-slim") as sb:
    print(await summarise(sb))
async with await sandboxio.create("e2b://code-interpreter-v1") as sb:   # needs E2B_API_KEY
    print(await summarise(sb))

Stream output while a long command runs, and rely on the timeout: a sandbox timeout is sandboxio.SandboxTimeout, never the builtin TimeoutError.

import sandboxio

async with await sandboxio.create() as sb:
    async with sb.stream(["sh", "-c", "echo start; sleep 1; echo done"], timeout=30) as proc:
        async for chunk in proc:
            print(chunk.stream, chunk.data.decode(), end="")
        res = await proc.wait()
    try:
        await sb.run(["sleep", "999"], timeout=1)
    except sandboxio.SandboxTimeout as exc:
        print(exc.code)                                  # SBX_E1302 — stable, documented

Sync code gets the same surface through create_sync(). One sandbox is one portal thread; use the async API for heavy concurrency.

import sandboxio

with sandboxio.create_sync("docker://python:3.12-slim", timeout=60) as sb:
    print(sb.run_code("print(6 * 7)").stdout)

Test your agent's tools offline. sbx_fake is a pytest fixture installed with the package; it executes nothing, records everything, and passes the same contract suite as the real backends.

import pytest
from sandboxio import ExecResult


@pytest.mark.anyio
async def test_my_tool_reads_the_pandas_version(sbx_fake):
    sbx_fake.on_run_code(match="import pandas", returns=ExecResult(0, "2.2.1\n", ""))
    res = await sbx_fake.sandbox.run_code("import pandas; print(pandas.__version__)")
    assert "2.2.1" in res.stdout
    assert sbx_fake.calls[0].network.egress == "deny"     # the default, recorded

Full surface, including capability discovery, require_isolation, audit sinks and spans: docs/quickstart.md and the normative docs/spec/03-public-api.md.

Backends

Backend Status Isolation tier
Docker adapter built, unreleased CONTAINER — containers share the host kernel
E2B adapter built, unreleased MICROVM — Firecracker microVM, its own kernel
FakeBackend built, unreleased n/a — in-process, for tests
Modal planned for v0.1.1 GVISOR — containerised and virtualised using gVisor

Every tier above is the mechanism the provider documents for itself, read on 2026-09-20. None of those three pages carries its own revision date, so that is the date it was read, not a date the provider published; re-verification is a quarterly item. What the tiers mean — and why GVISOR is defence in depth rather than VM equivalence — is in docs/explanation/isolation-tiers.md.

Third-party adapters are first-class: the adapter contract is specified and enforced by a shared contract suite.

Integrations

  • LangGraph / LangChain — sandboxio.integrations.langgraph.make_code_tool() returns a native BaseTool (sandboxio[langgraph]).
  • OpenAI Agents SDK — sandboxio.integrations.openai_agents.make_code_tool() returns a native FunctionTool (sandboxio[openai-agents]).
  • MCP — python -m sandboxio.mcp --backend docker://python:3.12-slim serves run_python, run_command, file tools and sandbox_info (sandboxio[mcp]), also as a container image.

Documentation

docs.sandboxio.dev — the Markdown under docs/ is its source and stays the source, so nothing below moves. Read it here or there:

Security

Isolation tiers are reported, not assumed: CONTAINER is not a security boundary against hostile code, and sandboxio says so rather than implying otherwise.

Report vulnerabilities privately — see SECURITY.md. A report that a declared control did not apply is the highest-severity class this project has.

The project's own supply-chain posture is scored weekly by OpenSSF Scorecard and published — the badge above links to the run that produced it.

Contributing

Read CONTRIBUTING.md. Contributions need a DCO Signed-off-by line; there is no CLA.

License

Code is MIT. Prose in docs/ is CC BY 4.0; code samples inside those documents are MIT (ADR-0026).

Metadata

Release files for sandboxio 0.1.0rc3

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

Source distribution (sdist)

Source distribution for sandboxio 0.1.0rc3
File Size Uploaded
sandboxio-0.1.0rc3.tar.gz 336.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sandboxio 0.1.0rc3
File Interpreter ABI Platform
sandboxio-0.1.0rc3-py3-none-any.whl Python 3 none any Details

Total release size: 403.1 kB

Release files / sandboxio-0.1.0rc3.tar.gz

Download URL sandboxio-0.1.0rc3.tar.gz
Size 336.0 kB
Tags Source
SHA-256 checksum
How to use checksums
f53cae0224088b818abb0e1e71d7771b9db279a4f4d6b35cf7a62125be1df794
BLAKE2b-256 checksum
How to use checksums
9988b214c2ebc85124ecbc38fddc2022e5586dd8f09b7d617a4ae6468bd16a38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / sandboxio-0.1.0rc3-py3-none-any.whl

Download URL sandboxio-0.1.0rc3-py3-none-any.whl
Size 67.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
55263d6318d5115c5189e445525e26116508dd90c5932bab36aac8ab458734c3
BLAKE2b-256 checksum
How to use checksums
af944568fe364d08ca7d8fb2fb5a7cd49278b35915e331db8a6b16b53876b3d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.0

2 release files

This release

0.1.0rc3 This release

2 release files

0.0.0

2 release files

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