Agent sandboxes compared, and a sneak peek at Zerops Box
An agent needs somewhere to run the code it just wrote. Give it a shell, a repository and a database, and the infrastructure questions arrive quite quickly: which kernel is it using, what can it reach, and what happens to the running processes when you leave it overnight?
We've built Box around a workspace in your own project, with Firecracker sandboxes inside it, next to your applications and databases. You size the workspace, set the rules and decide how much of that project the agent gets to see. I'm particularly happy with the part where you can fork a sandbox and keep its running processes.
Before we get to that, a tour of the choices other providers made. There is good engineering here, and the differences are more interesting than another list of startup times.
Start with what runs the code
Firecracker is the common choice for a Linux sandbox with its own kernel. E2B, Vercel, Render and CodeSandbox use it. So does Box. Firecracker runs a small VM through KVM; the guest kernel handles the agent's system calls, with a VM boundary between it and the host.
Cloudflare's naming needs a moment here. Workers run in V8 isolates, lightweight execution contexts within a shared runtime. That's an attractive model when the work fits the runtime's APIs: you can put a lot of isolated code into one runtime without booting a Linux guest for each function. An agent that needs a Linux shell and arbitrary binaries takes you to Cloudflare Containers, where each instance runs inside a Firecracker microVM.
gVisor sits at another point in the design space. It handles Linux system calls in userspace, in front of a shared host kernel. Modal lets you choose runtime="gvisor" or runtime="vm", and both Modal and Northflank use gVisor for GPU sandboxes. If the agent's work needs a local GPU, those are useful products to look at.
Then there are ordinary shared-kernel containers. Daytona's default Linux class uses them; its VM classes have their own kernels. Containers avoid a guest kernel per sandbox, which is a useful density and startup trade-off. For code an agent can freely change and execute, I prefer having that guest kernel and VM boundary.
Firecracker also has company among VM monitors. Koyeb runs Kata Containers on Cloud Hypervisor, and Northflank uses Cloud Hypervisor for CPU sandboxes. Koyeb described its move from Firecracker in terms of broader hardware and GPU support. The hardware you need to expose affects the choice.
The table I would keep open
These are the providers' documented designs, checked on November 6, 2026. The links lead to their own architecture or lifecycle documentation. Startup numbers are left out: a cold container start and a resume from a prepared memory image measure different work.
| Provider | Execution boundary | What survives a pause or saved state |
|---|---|---|
| E2B | Firecracker microVM | Files and memory on pause; forks supported |
| Daytona | Shared-kernel container by default; VM classes available | Memory-preserving pause and fork on VM classes |
| Modal | gVisor or VM | Memory snapshots in alpha, expire after 7 days and terminate the original |
| Vercel | Firecracker microVM | Filesystem snapshots |
| Cloudflare | Container inside a Firecracker microVM | Filesystem snapshots, in beta |
| Fly Sprites | Fly Machine with an inner container | Warm state keeps memory; checkpoints keep files |
| Render | Firecracker microVM | Runtime snapshots keep memory and processes |
| Koyeb | Kata Containers on Cloud Hypervisor | FULL snapshots include processes |
| Northflank | Cloud Hypervisor for CPU; gVisor for GPU | Pause ends processes; attached volumes remain |
| Railway | Linux VM | Checkpoints and forks copy disk |
| Zerops Box | Firecracker microVM inside a workspace VM | Park keeps memory by default; forks include running processes |
I care about that last column because a working environment includes what is running in it. You might have a dev server, a language server and a process waiting for input. Saving their files is useful, but restoring the running state lets you continue the session without rebuilding it from startup commands.
The details matter even within one product. A warm Sprite keeps memory; a Sprite checkpoint keeps the filesystem. Both are useful, and you would build a different recovery path around each.
Put the sandbox next to the application
The other choice I care about is where the sandbox lives. An agent running integration tests needs your database and queue. If those services are private, connecting a remote execution environment becomes part of the job.
Providers have put real work into this. Vercel has Secure Compute with AWS VPC peering. E2B has BYOC and private connectivity options. Railway's PRIVATE mode joins the environment network, Koyeb can opt into its private mesh, and Northflank has project private networking. Railway is particularly close to the model I want: the sandbox can reach the services already in the environment.
Box puts a workspace directly into a Zerops project. It is a managed service, alongside PostgreSQL, Valkey or your application runtimes. Zerops runs the workspace VM, its OS and the Box orchestrator. Inside it, each sandbox is a Firecracker microVM running as a separate unprivileged process with its own limits.
That gives agent code two VM boundaries before the Zerops host. It also gives you a resource pool you can see in the same project as the application using it.
Box is in open beta, so anyone on Zerops can create a workspace today. Workspace data has no automatic backup yet, so treat it as disposable for now.
Why we built Box this way
The project is the useful unit for this design. It already contains the services the agent needs, and the workspace sits on that project's private network. A sandbox in the default mode just connects to PostgreSQL at db.zerops:5432, and the database never sees the internet.
That was the requirement from day one. An agent writing code needs the real database, the real queue and the real services around it. A remote sandbox wired back through a tunnel is exactly the friction we wanted to remove.
The workspace is also where you control capacity. Every sandbox draws from its CPU, memory and disk. You can give a development team a pool and decide how densely to pack it, while the workspace policy sets ceilings for the sandboxes they create.
Why a workspace VM with Firecracker inside it? First, isolation: agent code gets its own guest kernel. Second, code quality: Firecracker is a small VMM with far fewer critical vulnerabilities than a full QEMU/KVM stack. Third, practicality: our bare metal already runs Incus, and running a second VM manager alongside it on the same hosts would be trouble. Inside a workspace VM, Firecracker has the whole machine to itself.
And it fits how we think about Zerops in general. We give you the primitives and a golden path, and you build whatever you want on top. A workspace with your own capacity, overcommit and policies gives you the widest set of options to do that.
Memory is part of the saved environment. Parking releases a sandbox's CPU and RAM while keeping a memory image on disk; waking resumes its processes. Forking carries the running state into independent copies. I want to be able to try two changes from the environment I already have running.
Both defaults are deliberate. Agents lose minutes rebuilding a dev server and warming caches after every restart, so we keep memory. And we bill the workspace like any other Zerops service.
A first workspace
The CLI can create a project and workspace:
curl -fsSL https://box.zerops.io/install.sh | sh
zbox login
zbox setup --ram 8 --disk 40
That example asks for 8 GiB of RAM and 40 GiB of disk, with shared CPU by default. Adding --cpu requests dedicated cores. In an existing project, you can add a Box Workspace service alongside the services already there.
The default base is Ubuntu 26.04 with Node.js 24, Python 3, gcc, git, the GitHub CLI, Claude Code and Codex. Most linux/amd64 images work as bases. You can pull from an OCI registry, import a docker save archive or have the workspace build a Dockerfile. Docker inside a sandbox is not supported yet.
A warm template lets you prepare an environment once and create sandboxes from its saved state:
zbox template create --base default --name dev --warm \
--cpus 2 --memory 1g --disk 10g \
--warmup 'claude --version && sync'
zbox new agent1 --template dev
zbox park agent1
zbox wake agent1
zbox fork agent1 --name try-a --name try-b
The two forks continue with running processes included. In our test, both inherited the same in-memory counter and process ID, then advanced their counters independently. Parking and waking the original kept its counter too; the CLI reported a 221 ms memory resume, with 344 ms for the whole command on that run. A snapshot restored the same running process into another sandbox.
The CLI, web console and MCP server all use the workspace's HTTP API. For Claude Code, attaching the MCP server looks like this:
claude mcp add zbox -- zbox mcp --template dev
It exposes run_code and kill_sandbox. If you're building your own client, each workspace serves its OpenAPI document.
Your pool, your limits
Workspace size determines how much you can run. Memory is never overcommitted. A running sandbox reserves the RAM you assign it. CPU overcommit is your setting, from 1 to 64, with a default of 8.
Our 2-core workspace with 4 GiB of RAM reported CPU overcommit 8 and 3.25 GiB of sandbox memory after its reserve, enough for six running sandboxes at 512 MiB each. The capacity docs round that example to 16 vCPU and 3.3 GiB. Parked sandboxes use disk for their filesystem and memory image, so disk capacity matters too.
For workloads that wait a lot, higher CPU overcommit lets you fit more running environments into the pool. If they all start compiling at once, they share the physical CPU capacity you bought. You can turn the factor down when predictable CPU time matters more than density.
The workspace policy puts a ceiling on CPU, RAM and disk per sandbox, caps TTLs and limits available network modes. Templates can set lower ceilings. This is useful when your application creates sandboxes on behalf of users: the resource and network rules live in the workspace as well as in the calling application.
Billing follows the workspace. You pay its CPU, RAM and disk at normal Zerops rates; creating another sandbox, fork or snapshot has no separate fee. Parking frees capacity inside the workspace and leaves its bill unchanged. Stopping the workspace stops CPU and RAM charges, with disk still billed.
Per-second sandbox billing at E2B or Daytona is attractive for occasional short jobs. I like the workspace model for environments that spend the day next to an application: choose the pool, use its capacity, see one service on the project bill.
Decide what the agent can reach
Each sandbox gets one network mode at creation: project_internet, internet, project or airgapped. The default has both project and internet access. Switch a sandbox to internet or airgapped and the same db.zerops:5432 connection goes nowhere. A sandbox testing your application can use the project network; one running code for an external user can be restricted to internet access or no network at all. Workspace policy decides which modes are available.
Egress rules narrow access by IPv4 CIDR and port, including a project keyword for the private network. For example, you can limit project access to PostgreSQL's port. Hostname allowlists and IPv6 are not supported in these sandbox rules; Vercel and E2B have hostname filtering if that's a requirement for your workload.
Traffic can go back into a sandbox too. Open an HTTP port in project mode and your other project services can reach it through the workspace, without a public URL. The application needs to listen on 0.0.0.0; HTTP and WebSocket ports are supported.
Credentials have a useful separation. You can deliver a secret as an environment variable, or keep it on the workspace and use an integration proxy to add it to outgoing requests. Connectors configure this for Claude Code, GitHub and Codex. Once a sandbox has received a plain secret, it is marked secret-bearing and cannot be forked, exported or snapshotted with memory. Use the proxy path when the sandbox only needs to make authenticated requests.
Try Box in a development project.
Try Zerops in < 5 minutes without installing or forking anything — deploy one of our curated recipes, which are examples covering the full development lifecycle from local dev through staging to production, with built-in seeding, migrations, backups and scaling.
Your favorite language / framework not covered by our recipes? Deploy the Showcase recipe, or join Zerops Discord and we'll help you out.
Production-ready image processing pipeline showcasing distributed architecture on Zerops — a Bun + React frontend with real-time WebSocket updates and live architecture visualization, a Python worker for async image processing via NATS, backed by PostgreSQL, Valkey, and S3-compatible object storage.