The code your agent runs in production wasn't written by an engineer. A model produced it seconds earlier, shaped by whatever entered its context, and nothing reviewed it before it ran. That single fact breaks the assumption every container security model rests on, and it's why the isolation layer under agent code execution is now an architecture decision rather than an afterthought. Here is how the options actually differ, and how to choose.
Key takeaways
- Standard containers share the host kernel, so a kernel bug or bad mount can become a container escape. That risk is acceptable for reviewed code and unacceptable for code a model just generated.
- Firecracker microVMs give each workload its own guest kernel in a KVM virtual machine, boot in about 125ms, and add under 5 MiB of memory overhead per microVM, per AWS's figures.
- Production sandboxes avoid the boot cost by restoring from a snapshot in 5 to 30 milliseconds; E2B reports a provisioned sandbox ready in under 200ms using pre-warmed pools.
- gVisor's userspace kernel (the Sentry) never passes syscalls to the host, but implements roughly 70%-80% of Linux syscalls and adds 10%-30% overhead on I/O-heavy work.
- Isolation contains code execution; it does nothing about egress, standing credentials, or actions the agent is authorized to take. Those are where most agent breaches will actually happen.
Why Does Agent Code Need Stronger Isolation Than a Normal Container?
Because you can't review it before it runs. Traditional application security assumes a human wrote the code, a pipeline tested it, and a reviewer approved it. An agent that writes and executes code at runtime removes all three checks: the payload is generated on demand, shaped by whatever entered the model's context, and run immediately.
That inverts the threat model. You're no longer defending trusted code against hostile input; you're running code that may itself be hostile. A prompt injection buried in a fetched web page or an uploaded document can steer the agent into writing code that reads credentials, scans the internal network, or ships data out. I covered the injection vector itself in a separate piece.
Standard containers were never built for that. They're namespaces and cgroups over a shared host kernel, so a single kernel vulnerability or a misconfigured mount can turn into a container escape and host access. For code you've vetted, that exposure is a reasonable trade. For code a model invented a moment ago, it isn't.
What Are the Isolation Options, and How Do They Actually Differ?
Four approaches dominate in 2026, and they trade off along one axis: how much of the host they let the workload touch. Ordered by how strong the boundary is, they run standard containers, then gVisor, then the hardware-virtualized options, Kata Containers and Firecracker microVMs.
A standard container is a set of Linux namespaces and cgroups over a shared kernel. gVisor, built by Google, inserts a userspace application kernel called the Sentry that intercepts the workload's system calls and services them itself. As its documentation puts it, the Sentry "does not pass system calls through to the host kernel." Kata Containers and Firecracker go further, handing each workload its own guest kernel inside a KVM-backed virtual machine, so a guest escape has to break the CPU's virtualization boundary instead of a shared kernel.
| Approach | Isolation boundary | Startup | Runtime overhead | Best fit |
|---|---|---|---|---|
| Standard container | Shared host kernel (namespaces, cgroups) | Milliseconds | Near-zero | Trusted, reviewed code |
| gVisor | Userspace kernel (Sentry) over the host | Milliseconds | 10%-30% on I/O-heavy work | CPU-bound work, no nested virtualization |
| Kata Containers | Dedicated guest kernel in a KVM VM | ~150-300ms | Near-native | Kubernetes needing VM-level isolation |
| Firecracker microVM | Dedicated guest kernel in a KVM VM | ~125ms | Near-native | Custom multi-tenant sandbox platforms |
The practical read: gVisor narrows the attack surface without a VM but charges a per-syscall tax, while microVMs move the cost to startup and hand you a hardware-enforced boundary. For runtime-generated code, most teams want the hardware boundary.
How Do MicroVMs Boot Fast Enough to Sit in a Request Path?
Two techniques carry it: a stripped-down virtual machine monitor, and snapshotting. AWS wrote Firecracker in Rust to run Lambda and Fargate, and its design drops the emulated hardware a general-purpose hypervisor carries. What's left boots in about 125 milliseconds with under 5 MiB of memory overhead per microVM, and a single host can launch up to 150 of them per second, per AWS's figures and the NSDI '20 Firecracker paper.
Even 125ms is too slow to pay on every request, so production sandboxes don't boot cold. They snapshot a fully initialized VM, memory and filesystem included, then restore from that snapshot in 5 to 30 milliseconds and keep a pool pre-warmed. E2B, which builds a sandbox cloud on Firecracker, reports a provisioned sandbox ready in under 200 milliseconds using exactly this pattern.
The engineering consequence is that the isolation boundary stops being the bottleneck. A fresh microVM per task, destroyed when the task ends, costs little enough to be the default rather than a premium tier you ration.
When Is gVisor the Right Call Instead of a MicroVM?
When the workload is CPU-bound, syscall-light, and you can't run nested virtualization. gVisor gives you a real boundary without a guest kernel, which matters on hosts or managed clouds where KVM inside your own workload isn't available.
The cost is compatibility and syscall speed. The Sentry implements roughly 70%-80% of Linux system calls, so code that reaches for advanced ioctls or eBPF can hit unsupported-operation errors and fail in ways the same code wouldn't on a real kernel. And because every syscall detours through userspace, I/O-heavy workloads carry 10%-30% overhead by gVisor's own accounting. A build step that shells out constantly or an agent that hammers the filesystem will feel that; a tight numeric computation won't notice.
So the decision is workload-shaped. Syscall-light and virtualization-constrained points to gVisor. Untrusted code doing heavy or unpredictable I/O points back to a microVM, where the boundary is hardware and the syscalls run native.
Should You Build on Firecracker Directly or Buy a Sandbox Service?
Buy it, unless sandbox infrastructure is your product. Firecracker is a VMM, not a platform: you own snapshot management, the pre-warm pool, networking, filesystem provisioning, resource limits, and the orchestration that binds a sandbox to an agent session. That's real, continuous systems work, and several vendors have already absorbed it.
The managed options differ mostly in what they optimize for.
| Service | Isolation base | What it optimizes for |
|---|---|---|
| E2B | Firecracker microVMs | Ephemeral code sandboxes for AI apps, sub-200ms provisioning |
| Modal | Sandboxed execution with GPU support | Serverless compute where the code also needs accelerators |
| Northflank | Kata Containers and gVisor, chosen adaptively | Running sandboxes alongside general production workloads |
| Daytona | MicroVM-backed sandboxes | Agent development environments and longer-lived sessions |
Newer entrants compete on idle cost, keeping a sandbox in standby at no compute charge and resuming it in tens of milliseconds with memory intact, which suits agents that pause and resume across a long task. Whichever you choose, the property to insist on is a dedicated guest kernel per untrusted workload. A service that "sandboxes" with shared-kernel containers alone is selling you resource limits, not isolation from adversarial code.
What Does Isolation Not Solve?
The VM boundary contains code execution and does nothing about what the agent is allowed to do on purpose. Most agent breaches won't arrive through a guest escape. They'll arrive through an agent using its legitimate access badly: calling an API with a credential it holds, reaching a service it can already reach, moving data it can already read.
That makes the sandbox one control among several, and two others carry as much weight. The first is egress. A sandbox with open outbound network access can still exfiltrate anything it touches, so default-deny egress with a narrow allowlist matters more than the isolation tier you picked. The second is credentials. A long-lived key mounted into the sandbox is a long-lived key an adversarial payload can read and reuse, so scope and expire them; I went deeper on this in scoped agent identities.
The same logic extends to actions with real cost. An agent cleared to spend or transact needs guardrails on the action, not only on the process running it, which is a governance problem more than an infrastructure one. I worked through that separately in agents that spend.
What Should You Put in Place Before an Agent Runs Code?
Treat every sandbox as disposable, untrusted, and offline by default. A workable baseline:
- One microVM per task, destroyed after it. No reuse across sessions or tenants. State that outlives the task is state an attacker can plant for the next one.
- Default-deny egress. Allowlist the specific hosts the task needs, and log every other attempt.
- No standing credentials inside. Inject short-lived, task-scoped tokens, never a broad API key or cloud role.
- Hard resource ceilings. CPU, memory, disk, and wall-clock limits, so a runaway or malicious payload can't starve the host.
- Full audit of code and calls. Record what the agent generated and every outbound request, because incident response depends on having it.
None of this is exotic. It's the posture you'd take toward any untrusted tenant, applied to a tenant your own system spins up on the fly.
What to Watch as This Stack Matures
The isolation techniques are largely settled; the movement now is in cost and convenience, and that's where the risk hides. Snapshot-restore and standby pooling keep pushing per-sandbox cost toward zero, which is what makes microVM-per-task the easy default. The same pressure pushes vendors to blur the line and market shared-kernel containers with resource caps as "sandboxes." Read the isolation model, not the label.
The second thing to track is the gap isolation leaves open. As agents gain more real authority, the interesting failures migrate from the runtime to the permission set. Infrastructure isolation is necessary and close to solved. Bounding what an agent is allowed to do once it's running safely is the harder, less-settled problem, and it's where the next round of engineering attention belongs.
Sources
- Firecracker design documentation (boot time, memory overhead, KVM model)
- Firecracker: Lightweight Virtualization for Serverless Applications, Agache et al., NSDI '20 (USENIX)
- gVisor documentation (Sentry syscall interception, compatibility and performance trade-offs)
- Northflank: Kata Containers vs Firecracker vs gVisor (comparative startup and overhead figures)
- Northflank: How to sandbox AI agents (agent threat model, isolation strategies)
- Modal: Best code execution sandboxes for AI agents
- E2B documentation (Firecracker-based sandbox provisioning)