Self-hostable sandbox for agent code execution — SandboxManager, control-plane, 4 SDKs, MCP server, running inside real Kubernetes pod isolation
Overview
Website · Quickstart · Docs · Self-hosting · Security · Roadmap · Examples · Discord Most "agent sandbox" projects give you raw isolation — a pod, a VM, a container — and leave you to build the tool surface an LLM agent actually needs on top of it. boxxkite is the other half: a complete bash/python/file/search/process tool surface running inside real Kubernetes pod isolation, self-hostable end to end. Point your agent framework at it and you have a real sandbox in minutes, on infrastructure you control.
README
boxxkite
Website · Quickstart · Docs · Self-hosting · Security · Roadmap · Examples · Discord
▶ Watch the demo
The missing batteries-included, self-hostable sandbox for agent code execution.
Most “agent sandbox” projects give you raw isolation — a pod, a VM, a container —
and leave you to build the tool surface an LLM agent actually needs on top of it.
boxxkite is the other half: a complete bash/python/file/search/process tool
surface running inside real Kubernetes pod isolation, self-hostable end to end.
Point your agent framework at it and you have a real sandbox in minutes, on
infrastructure you control.
- 15 framework-agnostic tools (plus an opt-in 8-tool git set) — LangChain, LangGraph, LlamaIndex, CrewAI, AutoGen, the OpenAI Agents SDK, or plain function calling, with no required dependency on any of them
- One Kubernetes pod per session — non-root, all capabilities dropped, read-only root filesystem, network egress denied by default
- A hosted-API control-plane you run yourself — accounts, API keys, fair-use limits, and client SDKs in four languages, if you want a real multi-tenant API in front of the sandbox instead of embedding it directly
- CLI, MCP server, Helm chart, and a one-click Render deploy for the control-plane — see Self-hosting
- Nothing held back. Every piece here — runtime, control-plane, all four SDKs, the MCP server — is Apache-2.0-licensed and self-hostable; there’s no separate closed hosted-only tier
Who this is for: teams building their own agent products that need
isolated, multi-tenant code execution at scale. It’s not a single-user
local dev-session sandbox like the built-in bash tool in an IDE or CLI
coding agent — if you just want your own assistant to run shell commands on
your machine, boxxkite is the wrong layer.
Start Here
If you are new to the repo, use this decision tree:
-
I just want to try the sandbox locally
Useboxxkite upfrom the Quickstart below. This is the fastest path and does not require Kubernetes. -
I want the real Kubernetes deployment on my laptop
Usedeploy/local-kind/README.md. It explains the kind-based flow, the Apple Silicon limitation, and thekubectl proxystep. -
I want the hosted API / multi-tenant control-plane
Use the control-plane section below, then theexamples/basic/hosted_control_plane/guide. -
I want the repository documentation map Start with
docs/, which groups getting started, guides, reference, architecture, and community material.
For contributors, the important mental model is: the root package gives you
the sandbox runtime, while control-plane/, the SDKs, and mcp-server/ are
separate packages with their own installs and tests.
Quickstart
Clone the repo, create a virtualenv, install the root package, then start the local stack:
git clone https://github.com/EvAlssment/boxxkite.git boxxkite && cd boxxkite
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
boxxkite up # builds + starts sandbox, sidecar, and local MinIO
boxxkite exec "python3 -c 'print(1 + 1)'"
Running the test suite needs two extra things the quickstart above doesn’t:
pip install -r sidecar/requirements.txt(several tests importsidecar/main.pydirectly, and its dependencies are tracked separately frompyproject.toml) andtmuxon your PATH (it backs the sidecar’s PTY takeover session; tmux-dependent tests skip cleanly without it). See CONTRIBUTING.md.
The PyPI name is
boxxkite-sandbox, notboxxkite(already taken). Install it withpip install -e ".[dev]"from the repo root; the import path (import boxxkite) and theboxxkiteCLI command are unaffected.
If boxxkite up succeeds, the quickest smoke test is:
boxxkite exec "python3 -c 'print(1 + 1)'"
boxxkite files ls /
That confirms the sandbox, the sidecar, and the CLI are talking to each other correctly.
Start a project with boxxkite new
To create a small Python project wired to the hosted control-plane client:
boxxkite new my-agent
cd my-agent
cp .env.example .env
# Edit .env with your control-plane URL and API key.
set -a && source .env && set +a
python app.py
The generated project creates one sandbox, runs print(1 + 1), and cleans up
the sandbox when it exits. The command never writes a live .env file and
refuses to overwrite an existing destination. Its initial template is
available as --language python --framework plain --use-case code-interpreter;
the other integration choices can be added without changing the generated
project contract.
from uuid import uuid4
from boxxkite import SandboxManager
from boxxkite.tools import create_sandbox_tool_specs
manager = SandboxManager()
session_id = str(uuid4())
await manager.create_session(organization_id=uuid4(), session_id=session_id)
specs = create_sandbox_tool_specs(sandbox_manager=manager, session_id=session_id)
bash_tool = next(s for s in specs if s.name == "bash_tool")
result = await bash_tool.handler(command="echo hello from boxxkite")
Framework adapters (boxxkite.tools.adapters) convert the same tool specs for
LangChain, LlamaIndex, the OpenAI Agents SDK, Google ADK, or plain OpenAI/
Anthropic/Gemini/Mistral function-calling schemas — see the
full integration guide
and examples/ for a runnable version of every framework.
Self-hosting
Everything in this repo — including the control-plane/ hosted multi-tenant
API — is something you deploy yourself:
- Real Kubernetes — two steps. First lay down the cluster prerequisites
(RBAC, NetworkPolicy, pod-security admission policy, ServiceAccount,
Config/Secret scaffolding) by applying
deploy/rbac.yaml/network-policy.yaml/pod-security-policy.yaml, orhelm install boxxkite deploy/helm/boxxkite. This chart does not deploy the control-plane itself (it has no Deployment/Service) — the per-session sandbox pods are created programmatically by the control-plane at runtime. Then deploy thecontrol-plane/API separately (see the Render button below or the developer docs). For Argo CD, Flux, or another Kustomize-based GitOps flow, use the generated Helm projection and environment overlays indeploy/kustomize/README.md. A localkindcluster works too:./deploy/local-kind/setup.sh. - Per-cluster warm-pool sizing — use the optional declarative file in
docs/FLEET-CAPACITY.mdwhen each process needs a reviewed cluster-specific capacity target. - Serving more than one internal team? See
docs/guides/self-hosted-multi-tenancy.md for
what separates one tenant from another (and what doesn’t), plus reference
ResourceQuota/LimitRange/NetworkPolicymanifests in deploy/multi-tenancy/. - One-click Render deploy for the control-plane API —
(still needs a real Kubernetes cluster for actual sandbox execution).
- docker-compose, for local iteration without a cluster — see the Quickstart above.
docker-compose mode shares a PID namespace with the sandbox container and execs into it via
nsenter, the same mechanism the Kubernetes runtime uses — it no longer needs (or mounts) the host’s Docker socket. See SECURITY.md for the current list of disclosed limitations.
Full walkthroughs for every path above (Kubernetes, Helm, Render, the
boxxkite CLI’s hosted mode, secrets, webhooks, MCP, and every SDK) are
organized in the repository documentation map and the
developer docs site.
Run the control-plane locally
The control-plane/ multi-tenant API is a separate service from the
boxxkite up SDK path — it is not part of deploy/docker-compose.yml, and you
run it on its own. To bring it up against a throwaway SQLite database (no
Postgres required) for API exploration:
cd control-plane
uv venv # create .venv
uv pip install -e '../[dev]' # install the boxxkite runtime (sibling pkg)
uv pip install -e '.[dev]' # install the control-plane itself
ENVIRONMENT=development DATABASE_URL=sqlite+aiosqlite:///./cp.db \
uv run uvicorn control_plane.main:app --port 8099
Then check it’s up:
http://localhost:8099/health— liveness (process is up)http://localhost:8099/health/ready— readiness (round-trips a DB query)http://localhost:8099/docs— interactive OpenAPI docs
This gets you the API surface (accounts, API keys, session bookkeeping), but
actually executing sandbox pods still needs a real Kubernetes cluster — the
control-plane creates per-session pods programmatically at runtime (a local
kind cluster via deploy/local-kind/setup.sh works). Against SQLite with no
cluster you can exercise the HTTP/auth surface, not real code execution.
Run the local MemoryBase embedding server
MemoryBase’s default embeddings and optional reranking can run in a separate local process using Hugging Face Transformers, without Ollama or PyTorch in the control-plane:
cd memory-model-server
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
BOXKITE_EAGER_LOAD=true .venv/bin/uvicorn app:app --host 127.0.0.1 --port 8000
The first start downloads the configured local embedding and reranker models.
On Apple Silicon, device auto-detection selects MPS. Set the control-plane’s
BOXXKITE_MEMORY_EMBEDDINGS_ENABLED and
BOXXKITE_MEMORY_RERANKING_ENABLED to true to use the local endpoints.
For a managed embedding comparison, set
BOXXKITE_MEMORY_EMBEDDING_PROVIDER=gemini,
BOXXKITE_MEMORY_EMBEDDING_MODEL=gemini-embedding-2,
BOXXKITE_MEMORY_EMBEDDING_DIMENSIONS=1024, and provide
BOXXKITE_MEMORY_EMBEDDING_API_KEY. Gemini Embedding 2 uses a separate vector
space, so switching providers requires re-embedding existing memories; the
model ID and dimensions are part of the vector-store key for that reason.
What’s in this repo
One repo, several independently-versioned pieces, kept together deliberately (see CONTRIBUTING.md):
| Piece | What it is |
|---|---|
src/boxxkite/ (boxxkite-sandbox on PyPI) |
The core: SandboxManager, WarmPoolManager, and the 15+ tool boxxkite.tools surface. Embed this directly against your own cluster. |
sidecar/ |
The FastAPI service that runs in every sandbox pod — filesystem I/O, command exec via nsenter, storage sync. |
control-plane/ |
Optional hosted-API layer in front of SandboxManager — accounts, API keys, fair-use limits. |
sdk-python/, sdk-js/, sdk-go/, sdk-rust/ |
Thin HTTP clients for your own running control-plane. |
mcp-server/ (boxxkite-mcp) |
Wraps the Python SDK as an MCP tool source for Claude Code, Claude Desktop, Codex, or Cursor. |
src/boxxkite/handoff/ (boxxkite handoff , part of the main CLI) |
Moves an in-progress local Claude Code/Codex CLI/opencode/Cursor session into a fresh sandbox, full conversation history included — see the handoff guide. |
bastion/ |
Standalone SSH server bridging into a session’s human-takeover WebSocket. |
deploy/ |
Kubernetes manifests, Helm chart, Dockerfiles, docker-compose, Render Blueprint. |
examples/ |
Runnable cookbook — LangGraph, LangChain, raw HTTP, OpenAI/Gemini/Mistral function calling, and more. |
Security
boxxkite executes arbitrary, agent-generated code — its security posture is
layered defense in depth: a per-pod shared-secret sidecar auth token, a
fresh empty network namespace on every exec call, non-root execution with
every Linux capability dropped, and a read-only root filesystem. No single
one of these is meant to stand alone.
See SECURITY.md for the full model, known limitations, and how to report a vulnerability privately — this project runs arbitrary code, so a sandbox-escape report deserves a fast, private path, not a public issue. The repository’s isolation model covers the runtime boundary and its trade-offs.
Published packages and images
| Package | Registry |
|---|---|
boxxkite-sandbox |
PyPI |
boxxkite-client (Python) |
PyPI |
boxxkite-client (JS/TS) |
npm |
boxxkite-mcp |
PyPI |
boxxkite-client (Go) |
pkg.go.dev |
boxxkite-client (Rust) |
crates.io |
Container images are published to GHCR (ghcr.io/evalssment/…):
| Image | Architectures |
|---|---|
boxxkite-sandbox |
linux/amd64 only |
boxxkite-sandbox-minimal |
linux/amd64, linux/arm64 |
boxxkite-sidecar |
linux/amd64, linux/arm64 |
boxxkite-control-plane |
linux/amd64, linux/arm64 |
boxxkite-sandboxis amd64-only. Its Dockerfile deliberately hard-fails on arm64 because the pinned Chrome-for-Testing release has nolinux/arm64build (deploy/sandbox.Dockerfile). arm64 / Apple-Silicon users should useboxxkite-sandbox-minimal(multi-arch, no Chrome/LibreOffice/pandoc stack), or build/run the full image underlinux/amd64emulation —docker-compose.ymlalready forcesplatform: linux/amd64for exactly this reason. The other three images are multi-arch.
Community
Join the Discord — get help from other users and maintainers, report a bug, or discuss implementation ideas. The community guide links contribution, governance, conduct, security, roadmap, and release information.
License
Apache 2.0 — permissive, with an explicit patent grant. Use, modify, self-host, or build a competing hosted service on top of boxxkite; there’s no restriction.
Contributing
See CONTRIBUTING.md — we use the Developer Certificate of
Origin (git commit -s), not a CLA. Questions before opening a PR? Ask in the
Discord first.
Install
This server does not publish a one-line install command.
Open the repository installation guide New to MCP? Start with the mcpskill.org guide →