Show HN: SandrPod – run the unmodified E2B SDK against your own infrastructure SandrPod, an open-source, self-hosted control plane for AI agent code execution, launched v0.5.10, enabling developers to run unmodified E2B SDK code on their own infrastructure across 8 clouds including Aliyun and Tencent, Docker, or bare machines. The project provides a one-command Docker setup, a CLI, and native REST/Python/TS APIs, with reverse-tunnel workers requiring no inbound ports. Self-hosted execution infrastructure for AI agents. Run agent code on any cloud, any machine — or none at all. Speak any SDK. Keep full control. Your clouds. Your machines. Your rules. One command brings up the control plane and a Docker worker from the published images — no Go toolchain, no build, no cloning the repo. curl -O https://raw.githubusercontent.com/sandrpod/sandrpod/main/docker/docker-compose.yml docker compose up -d That pulls ghcr.io/sandrpod/{server,poder,toolbox} and starts: the control plane on localhost:8080 and one Docker worker Poder that dials back over a reverse tunnel — no inbound ports on the worker. First run downloads ~170 MB here server + worker . The sandbox runtime toolbox , ~530 MB is pulled by the worker the first time you create a sandbox, so step 2 below is the slow one. After that, both steps take seconds. Check it: curl localhost:8080/health {"status":"ok",...} curl localhost:8080/api/v1/poders wait for one worker to show "state":"ONLINE" /health answers as soon as the control plane binds, which is before the worker has finished registering. The second command is the one that tells you the stack is actually ready. ⚠️ This dev stack runs withauthentication disabled anonymous admin — fine on localhost. Before exposing it, set SANDRPOD TOKEN see docs/AUTH AND KEYS.md . pipx install sandrpod-cli recommended — isolated, nothing to activate or: uv tool install sandrpod-cli or, inside a virtualenv: pip install sandrpod-cli sandrpod-cli --api-url http://localhost:8080 create demo --provider local sandrpod-cli --api-url http://localhost:8080 execute demo "echo hello from SandrPod; python3 -c 'print 6 7 '" Real output from a cold run no cached images against v0.5.10: Sandbox: demo Job ID: job-1788150453342465216-7j5di2LP Status: provisioning State: PENDING State: RUNNING Sandbox 'demo' is ready hello from SandrPod 42 SandrPod is the control plane for AI agent code execution — open source and self-hosted. It turns your own infrastructure into a fleet of on-demand sandboxes that agents create, run code in, and tear down, while you keep ownership of where that code runs, what it can touch, and where the data lives. Hosted sandbox services make you rent their runtime in their region. SandrPod inverts that: you bring the substrate — any cloud, plain Docker, or a bare machine — and SandrPod is the thin, portable layer that schedules, tunnels, and governs execution across it. It rests on three pillars: Run anywhere you own — 8 clouds incl. Aliyun & Tencent , Docker, or a machine with no Docker at all. Speak any SDK — a native REST/Python/TS API, LangChain/deepagents, and the unmodified E2B SDK as a drop-in. Stay in control — reverse-tunnel workers with zero inbound ports, an opt-in permission gate + decision audit, and self-hosted data that never leaves your infra. One binary schedules sandboxes across whatever infrastructure you have: AWS · GCP · Azure · Aliyun · Tencent · DigitalOcean · Hetzner · Oracle — plus plain Docker , or a bare machine with no Docker via sandrpod-agent . Aliyun and Tencent make China-region and data-residency deployments first-class — something hosted services don't offer. Each provider has a guide under docs/ /sandrpod/sandrpod/blob/main/docs AWS /sandrpod/sandrpod/blob/main/docs/AWS PROVISIONING.md , GCP /sandrpod/sandrpod/blob/main/docs/GCP PROVISIONING.md , Aliyun /sandrpod/sandrpod/blob/main/docs/ALIYUN PROVISIONING.md , Tencent /sandrpod/sandrpod/blob/main/docs/TENCENT PROVISIONING.md , … . Remote exec uses each cloud's managed run-command API where it exists AWS SSM, Aliyun CloudAssist, Azure Run Command, Tencent TAT, Oracle Instance Agent and an ephemeral-key SSH path elsewhere GCP, DigitalOcean, Hetzner . SandrPod isn't tied to one client. It exposes a native REST API and Python/TS SDKs, a first-class LangChain/deepagents backend, and the full E2B wire protocol — so the unmodified e2b / e2b-code-interpreter SDKs work against it with nothing but two env vars. Bring the ecosystem you already use; migrate nothing. Zero inbound ports. Workers dial out to the control plane over a WebSocket reverse tunnel — run them behind NAT, in a private subnet, or on a laptop. Governance, not just isolation. Opt-in employee-PC mode adds a per-machine permission gate path consent, command denylist, PTY consent and a decision audit pipeline NDJSON + central HTTP upload — turning "run agent code" into " govern what agents may touch on real machines." Your data stays yours. Self-hosted, Apache 2.0, no phone-home. | Hosted E2B, Modal, … | SandrPod | | |---|---|---| License | Closed | Apache 2.0, open source | Where it runs | Their infra / region | Your cloud, Docker, or bare metal | Clouds | Vendor-managed | AWS · GCP · Azure · Aliyun · Tencent · DO · Hetzner · Oracle | China regions | ✗ | ✓ Aliyun + Tencent | No-Docker mode | — | sandrpod-agent : any machine becomes a sandbox | SDKs | Their SDK | Native + LangChain + drop-in E2B | Inbound ports on workers | n/a | None reverse tunnel | Governance / audit | — | Opt-in permission gate + decision audit | Data residency | Their region | Your account, your region | Recorded live against a SandrPod deployment: the package is the one from PyPI, the only change is which host it points at. Source: assets/e2b-demo.py /sandrpod/sandrpod/blob/main/assets/e2b-demo.py . One example of "speak any SDK": already have code on the E2B SDK? Point it at your SandrPod and it just works — Sandbox.create , files. , commands. foreground/background/PTY , run code , watch dir , get metrics , pause / resume : python import os os.environ "E2B API KEY" = "e2b your key" issued by your SandrPod os.environ "E2B API URL" = "https://sandbox.you.com" control plane os.environ "E2B SANDBOX URL" = "https://sandbox.you.com" per-sandbox envd from e2b import Sandbox the real, unmodified e2b SDK sbx = Sandbox.create sbx.files.write "/tmp/hi.txt", "hello from my own cloud" print sbx.commands.run "cat /tmp/hi.txt" .stdout → hello from my own cloud from e2b code interpreter import Sandbox as CI ci = CI.create print ci.run code "import numpy as np; np.arange 6 .sum " .text → 15 For a zero-config drop-in no env vars, just a domain , run the gateway behind a wildcard domain — SANDRPOD E2B DOMAIN=sandbox.you.com + .sandbox.you.com DNS - TLS. Full surface, wire-protocol details, and the coverage matrix verified against the real, unmodified E2B SDK over a real container are in. docs/E2B COMPAT.md /sandrpod/sandrpod/blob/main/docs/E2B COMPAT.md E2B SDK ──┐ Native SDK ├─→ API Server Control Plane, :8080 LangChain ─┤ ↕ WebSocket + yamux reverse tunnel CLI ───────┘ Poder Worker ──→ Toolbox Sandbox container sandrpod-agent ──→ direct mode, any machine as a sandbox | Component | Description | |---|---| API Server | The control plane: native REST + E2B-compatible gateway, sandbox CRUD, scheduling, tunnel proxying | Poder | Worker node. Persistent WebSocket tunnel to the control plane; manages Docker container lifecycle | sandrpod-agent | Registers the local machine directly as a sandbox with an embedded Toolbox — no Docker required | sandrpod-tray | Optional user-session GUI for employee-PC mode: tray icon + consent prompts + local settings page | Toolbox | Execution service inside each sandbox. PTY, file ops, background processes, sessions | Employee-PC mode opt-in : when sandrpod-agent runs on a real employee laptop rather than a server, enable a per-PC permission gate path consent + command denylist + PTY consent and a decision-audit pipeline that ships every allow/deny/warn event to a central HTTP endpoint. Both are off by default --permission-mode=off — see. docs/PERMISSION AND AUDIT.md …or with plain curl no install curl -X POST localhost:8080/api/v1/sandboxes \ -d '{"name":"demo","provider type":"local"}' curl -X POST "localhost:8080/api/v1/sandboxes/execute?sandbox=demo" \ -d '{"code":"print 6 7 ","language":"python"}' python Native Python SDK from langchain sandrpod import SandrPodClient sb = SandrPodClient api url="http://localhost:8080" .get sandbox "demo" print sb.execute "echo hello from SandrPod" .output …or the unmodified E2B SDK set E2B API URL / E2B SANDBOX URL to your server from e2b import Sandbox print Sandbox.create .commands.run "echo hello from SandrPod" .stdout Other ways to run it Production, with TLS and a real domain — the reference deployment: PostgreSQL, a wildcard certificate, and the E2B surface on. docker compose -f docker/docker-compose.prod.yml up -d --wait , walked through end to end DNS, certificate, renewal, acceptance sweep in— or as a narrative, with the two failures it took to get there, in docs/PRODUCTION DEPLOYMENT.md /sandrpod/sandrpod/blob/main/docs/PRODUCTION DEPLOYMENT.md this writeup https://blog.sandrpod.com/e2b-compatible-sandbox-api/ . PostgreSQL only no TLS termination : docker compose -f docker/docker-compose.pg.yml up -d — see docs/MULTI INSTANCE DEPLOYMENT.md /sandrpod/sandrpod/blob/main/docs/MULTI INSTANCE DEPLOYMENT.md to scale out. Build from source contributors : docker compose -f docker/docker-compose.local.yml up -d --build From Go directly : go run ./cmd/server -port 8080 -db sqlite:./data/sandrpod.db , then add a worker with the docker run …/poder one-liner or go run ./cmd/poder -api-url=http://localhost:8080 . No Docker at all — turn any machine into a sandbox: go run ./cmd/agent -api-url=http://localhost:8080 -name=my-machine The default docker-compose.yml persists to SQLite a sandrpod-data volume , so sandboxes and tokens survive a restart. sandrpod-tray serve user-session tray + consent dialogs 🛡 go run ./cmd/agent -api-url=http://localhost:8080 -name=my-laptop \ -permission-mode=prompt \ -audit-upload-url=https://your-platform/api/audit/decisions/batch Permission modes: off default | prompt consent dialog outside work dir | strict silent deny outside work dir . Full architecture, permissions.json schema, tray CLI, and audit protocol: docs/PERMISSION AND AUDIT.md . pip install langchain-sandrpod python from langchain sandrpod import SandrPodClient from deepagents import create deep agent from langchain openai import ChatOpenAI model = ChatOpenAI model="gpt-4o", temperature=0 client = SandrPodClient api url="http://localhost:8080" sb = client.get sandbox "my-sandbox" agent = create deep agent model=model, backend=sb result = agent.invoke {"messages": {"role": "user", "content": "Write a quicksort and run it"} } Or auto-create + clean up with client.sandbox "temp-sb" as sb: agent = create deep agent model=model, backend=sb result = agent.invoke {"messages": ... } The backend also exposes richer per-sandbox capabilities directly: sb.run code "x = 40", context="ctx1" stateful Jupyter-style kernel sb.run code "x + 2", context="ctx1" "text" → "42" x persisted sb.metrics {cpu count, cpu used pct, mem , disk } with sb.watch dir "/workspace" as w: filesystem watch events = w.get new events See pkg/sdk/python/langchain sandrpod/examples/ /sandrpod/sandrpod/blob/main/pkg/sdk/python/langchain sandrpod/examples for full examples. pipx install sandrpod-cli or: uv tool install sandrpod-cli sandrpod-cli config set-url http://localhost:8080 --provider: local | aws | gcp | azure | aliyun | tencent | digitalocean | hetzner | oracle sandrpod-cli list sandrpod-cli create my-sandbox --provider local --image ghcr.io/sandrpod/toolbox:latest sandrpod-cli create gpu-box --provider gcp --region asia-east1-a --instance-type e2-medium sandrpod-cli execute my-sandbox "ls /workspace" one-shot stateless sandrpod-cli stream my-sandbox "make build" real-time streamed output sandrpod-cli run my-sandbox "z = 10" --context c1 stateful kernel — z persists in context c1 sandrpod-cli stats my-sandbox live CPU / memory / disk sandrpod-cli fs watch my-sandbox /workspace print filesystem events sandrpod-cli shell my-sandbox interactive PTY sandrpod-cli delete my-sandbox Poder management sandrpod-cli poder list sandrpod-cli poder delete