We started BoxLite with one conviction: a sandbox for AI agents should be a library you import, not a service you call.
BoxLite's first commit, on December 8, 2025, said it in the opening line of the README:
BoxLite is an embeddable virtual machine runtime for secure, isolated execution environments.
It took SQLite as its model ("small, fast, reliable") and defined the property in one line:
Embeddable No daemon, no root, just a library in your application.
Ten months later, the design hasn't changed. Every box is a real virtual machine with its own Linux kernel, isolated in hardware: KVM on Linux, Hypervisor.framework on macOS. The VMM runs as a child of your process. There's nothing else to start.
On a Mac, that means BoxLite lives right on your Mac. There's no Linux VM to host the sandbox, no Docker Desktop and no background service. Your program starts a box, and when your program exits, the box is gone.
Postgres runs perfectly well on a single machine, and nobody calls it an embedded database. SQLite is embedded because it lives inside your program. There's no server to start, no port, and nothing to operate when your program isn't running.
We hold the embedded sandbox to the same bar:
Putting a sandbox platform on one machine makes it a smaller deployment, not an embedded one. The test is simple: when your program exits, is anything still running?
Agents don't run in one place. They run on a developer's laptop, inside a test suite, in a CLI someone installed with pip, and inside products that ship to customers who will never run your infrastructure. A sandbox that needs its own servers can follow the agent to only some of those places. A library can follow it everywhere.
Isolation shouldn't be the price of that. Agent-generated code is untrusted code, and a shared-kernel container is a different risk class from a VM. BoxLite gives every box its own kernel, so embedding never means weakening the boundary.
The term has spread this year. In September 2026, E2B launched E2B Embed, which in its own words "runs the whole E2B stack, every feature included, on a single machine." On that machine you run E2B's API, orchestrator, proxy, dashboard, Postgres, Redis, ClickHouse and a log pipeline. The machine has to be Linux with KVM, and on a Mac that means running it inside a Linux VM.
That's a useful product. It gives a customer a private copy of a hosted platform. By the test above, though, it's a single-node deployment rather than an embedded sandbox. The clearest way to show the difference is to measure it, so we installed both on the same MacBook Air (M4, 16 GB, macOS 26.1) and ran the same workload with 512 MiB sandboxes. Each was installed the way its own documentation describes for a Mac:
pip install boxlite. docker compose up -d --wait.
| BoxLite | E2B Embed | |
|---|---|---|
| What you install | a Python package | a Linux VM, Docker, and a 10-service stack |
| Install | 8 s, 93 MB | ~45 min ( compose up alone: 166 s) |
| Zero to first sandbox | ~15 s | ~45 min |
| Running with no sandboxes | 0 processes, 0 MB | 10 services, 1.1 GB RAM, plus 4 GiB reserved |
| Disk after install | 93 MB + images | ~7.5 GB |
| Command round trip (p50 / p95) | 1.0 / 1.3 ms | 6.0 / 8.7 ms |
| Resume a stopped sandbox (p50 / p95) | 175 / 178 ms | 292 / 1,255 ms |
| Create to first command (p50) | 1.1 s | 117 ms |
| 20 creates at once | 20 of 20 | 8 of 20; the rest return 500 |
The table follows from the two designs:
If you want your customer to run a copy of your cloud, E2B Embed does that. If you want the sandbox inside your product, that's what BoxLite was built for.
Each number is the median (p50) or 95th percentile (p95) of repeated runs: 30 creates, 100 commands and 20 resumes per tool. If you get different numbers, especially on bare-metal Linux, open an issue and we'll update this post.
BoxLite ships in two forms that share one SDK and one core API:
Moving between them is a change of endpoint, not a rewrite. When you need a server, we run it for you. You never have to start with one.
pip install boxlite
python
import asyncio
import boxlite
async def main():
async with boxlite.SimpleBox(image="python:slim") as box:
result = await box.exec("python", "-c", "print(2 + 2)")
print(result.stdout) # "4"
asyncio.run(main())