What Is an AI Agent Sandbox?
An AI agent sandbox is an isolated, disposable compute environment where an AI agent can run the code, shell commands, and tools it decides to use — without that code being able to touch your host, your data, or any other user. That's the whole definition. Everything else in this post is unpacking why an agent needs one, what separates a good sandbox from a leaky one, and how strong the isolation boundary actually has to be. If you build agents, this is the single most load-bearing piece of infrastructure you'll pick, so it's worth getting the mental model right.
I run PandaStack, an open-source Firecracker microVM platform, so I have opinions about the boundary — I'll flag where they're opinions. But the definition above is vendor-neutral, and most of this post is too. A sandbox is a place, not a product.
Why an agent needs a sandbox at all
A language model doesn't just produce text. Give it tools and it produces actions: a shell command to install a package, a Python script to transform a CSV, a tool call to hit an API. Those actions are untrusted by construction — not because the model is malicious, but because no human read them before they ran. The whole point of an agent is that it acts faster than you could review. That speed is the feature and the risk in the same breath.
So you have to assume the action can be wrong or hostile. Wrong: the model hallucinates a command that deletes the wrong directory, or writes an infinite loop, or fills the disk. Hostile: the model's context was steered by something it read — a prompt-injected web page, a poisoned file, a malicious tool result — into exfiltrating secrets or attacking your infrastructure. You cannot tell these apart from the outside, and you cannot prompt your way out of them reliably. The defense isn't a better prompt; it's running the action somewhere it can do no harm. That somewhere is the sandbox.
The anatomy of a good agent sandbox
"Isolated and disposable" is the headline, but a sandbox an agent can actually work in has a few distinct parts. If any of them is missing or leaky, the sandbox either can't do useful work or can't safely contain it.
- The isolation boundary — the wall between the agent's code and everything else. This is the part that matters most, and its strength is a spectrum (see below). A sandbox is only as trustworthy as this boundary; everything else is comfort.
- A filesystem — a writable root the agent can install packages into, write files to, and read them back from, that is thrown away with the sandbox. The agent should be able to trash it completely without you caring.
- Network egress control — whether and where the sandboxed code can reach the network. Agents often need to pip install or fetch data, but unrestricted egress is also how exfiltration and abuse happen, so you want a knob here, not an all-or-nothing.
- Exec and PTY — a way to run commands and capture stdout, stderr, and the exit code, plus an interactive terminal (PTY) for tools that expect one. This is the agent's hands inside the box.
- A lifecycle — create → run → destroy, made cheap enough that a fresh environment per task is normal rather than a thing you batch to avoid. A backstop TTL that reaps the environment even if your process crashes is part of this.
- Snapshot and state — the ability to freeze the environment and restore or fork it, so you can branch an agent's work, retry from a checkpoint, or park an idle session without losing it.
Notice that most of these are about ergonomics — filesystem, exec, lifecycle. They're what make the sandbox usable. The isolation boundary is the one that makes it safe, and it's the one people most often get wrong, because a container feels sandbox-shaped even when it isn't a strong enough wall for someone else's code.
The isolation-strength spectrum
Not all "isolation" is the same wall. From weakest to strongest, there are four broad tiers, and the difference between them is entirely about what an escape reaches:
- Process / exec (chroot, ulimits, a bare subprocess) — the agent's code runs as a process on your host, sharing your kernel, filesystem, and often your environment variables. Escape blast radius: your whole host. Startup: instant. Best fit for agent code: only code you wrote and trust — never model-written code.
- Container (Docker, Podman) — namespaces, cgroups, and seccomp give the process a private view, but every syscall still hits the one shared host kernel. Escape blast radius: the host and its neighbors, via a kernel bug or misconfiguration. Startup: fast. Best fit: trusted first-party workloads; a hardened container is mitigation, not isolation, for untrusted code.
- microVM (Firecracker) — a real guest kernel per sandbox behind hardware virtualization, with only a tiny device model facing the host. Escape blast radius: one VM — a kernel bug stays inside that guest. Startup: sub-second with snapshot-restore. Best fit: untrusted, multi-tenant, or model-generated code — this is the sweet spot for agents.
- Full VM (traditional hypervisor) — the same hardware boundary as a microVM, but with a full device model and a heavier VMM. Escape blast radius: one VM. Startup: tens of seconds to boot. Best fit: strong isolation where boot latency doesn't matter and per-task freshness isn't the goal.
The jump that matters for agents is from container to microVM: it's the jump from a shared kernel to a private one. I've written the long version of this ladder — where each tier's boundary actually sits and why — in the code isolation hierarchy, and the specific case for why a container isn't a sandbox for untrusted code in why Docker is not a sandbox. If you take one thing from this section: the boundary strength you need is a function of who wrote the code, and an agent's code was written by a model.
What a sandbox looks like in code
Concretely, using a sandbox is three moves: create an isolated environment, run the untrusted thing inside it, read the result. Here's the canonical shape with the PandaStack Python SDK — the API is deliberately boring, because the interesting part happens below the line where the boundary lives:
from pandastack import Sandbox
# Create one isolated, disposable environment. ttl_seconds is a backstop:
# even if your process crashes, the sandbox self-destructs after it.
with Sandbox.create(template="base", ttl_seconds=300) as sbx:
# The model asked to run this. We didn't review it. So it runs HERE,
# not on our host. This command's syscalls hit the GUEST kernel inside
# the microVM — never the host kernel, filesystem, or secrets.
result = sbx.exec("python3 -c 'print(sum(range(101)))'")
print(result.stdout) # -> 5050
print(result.exit_code) # -> 0
# Leaving the `with` block destroys the whole microVM. Nothing the agent
# installed, wrote, or broke survives into the next task.The API surface would look nearly identical against any decent sandbox provider — create, exec, read, destroy. What differs between providers is entirely the boundary underneath that exec call. In PandaStack's case it's a Firecracker microVM with its own guest kernel, so the untrusted command hits the guest kernel, not yours. In a container-backed sandbox, that same call runs against the shared host kernel. Same code, very different blast radius when something goes wrong.
Ephemeral vs persistent sandboxes
A second axis, orthogonal to isolation strength, is how long the sandbox lives. Ephemeral sandboxes are created for a task and destroyed when it's done — clean slate every time, maximum isolation, nothing bleeds from one task into the next. Persistent sandboxes stick around across turns or sessions so state accumulates: installed packages, files written in step one and read in step two, a dev server started and curled later, a database that has to survive.
Neither is more correct — it depends on the agent. A "compute this expression" tool wants ephemeral: no reason to carry state, and a fresh box is the safest default. A coding agent working through a repo wants persistence: it needs its earlier work to still be there. Many real systems do both, sometimes via snapshotting an ephemeral box into a reusable checkpoint. I go deep on that trade-off — and how snapshot/fork lets you have cheap freshness and durable state — in stateful vs ephemeral AI agent sandboxes, and on keeping a session alive across a long task in long-running sandboxes for AI agents.
This is where snapshot and fork stop being a nice-to-have and become the thing that makes the whole model economical. Because a microVM's entire state is a snapshot, you can freeze a configured environment and restore it, or fork it into parallel branches copy-on-write. On PandaStack a same-host fork lands in roughly 400–750ms and a cross-host fork in about 1.2–3.5s, so "branch this agent's state ten ways and explore in parallel" is a cheap operation rather than a research project.
Hosted vs self-hosted
The last decision is who runs the machines. Self-hosting a sandbox layer means you own the hard parts: safe multi-tenant isolation, a network egress policy that can't be trivially bypassed, fast create latency (which almost always means snapshotting a booted VM rather than cold-booting per task), reaping leaked sandboxes, and capacity. It's very doable — Firecracker is open source and so is PandaStack — but it's real systems work, and the failure modes are the kind you find in production at 3am.
A hosted sandbox gives you an API and makes those problems someone else's on-call rotation. The trade is the usual one: less control and a per-use cost, against not building and operating a security-critical distributed system yourself. My honest take: self-host if sandboxing is core to your product and you want to own the boundary, or if compliance demands it; use a hosted service if the sandbox is a means to an end and you'd rather spend your engineering on the agent. Either way, the isolation-strength question above doesn't change — a hosted container sandbox is still a shared kernel, and a self-hosted microVM is still a private one.
Where this lands, concretely
PandaStack is one answer to the definition: every sandbox is its own Firecracker microVM with its own guest kernel, created via snapshot-restore so the VM boundary costs almost nothing at create time. A create restores a baked snapshot in around 49ms (≈179ms p50, ≈203ms p99 end-to-end), and only the very first cold boot of a template is around 3s. Each agent pre-allocates 16,384 /30 subnets so per-sandbox networking is set up in single-digit milliseconds, which is part of why a fresh microVM per task is cheap enough to be the default rather than a thing you avoid. The ergonomics stay container-grade — create, exec, destroy — while the boundary stays VM-grade.
That's the whole pitch of a good agent sandbox in one line: give the agent a real place to work, and make that place cheap enough to throw away and strong enough that throwing it away is all cleanup ever means. If you want to actually wire one into an agent loop, the how-to is in give your AI agent a sandbox; if you want the isolation theory, start with what is a microVM.
Frequently asked questions
What is an AI agent sandbox?
An AI agent sandbox is an isolated, disposable compute environment where an AI agent runs the code, shell commands, and tools it decides to use — without that code being able to touch your host, your data, or other users. Agents need one because a language model emits actions that no human reviewed before they ran, so those actions are untrusted by construction. The sandbox is the place those untrusted actions run safely: a mistake or an attack is contained to a throwaway environment instead of reaching your infrastructure.
Why can't I just run agent code in a Docker container?
You can, and for trusted first-party code it's fine — but a container shares the host's single Linux kernel, so a kernel bug, a container-escape exploit, or a misconfiguration can reach the host and any neighbor containers. For code a language model wrote and no human reviewed, that's mitigation, not isolation. A microVM (Firecracker) boots its own guest kernel behind hardware virtualization, so an escape is contained to one VM. The rule of thumb: containers isolate your code from your code; microVMs isolate your code from someone else's.
What's the difference between an ephemeral and a persistent agent sandbox?
An ephemeral sandbox is created for a task and destroyed when it finishes — a clean slate every time, maximum isolation, no state bleeding between tasks. A persistent sandbox stays alive across turns or sessions so state accumulates: installed packages, files, a running server, a database. Ephemeral suits independent computations and untrusted one-shot work; persistent suits coding agents and long-running sessions that need their earlier work to still be there. Snapshot-and-fork lets you get cheap freshness and durable state at once.
What should a good agent sandbox provide besides isolation?
Beyond a strong isolation boundary, a usable agent sandbox needs a writable, disposable filesystem; network egress control (so the agent can fetch packages but you can restrict exfiltration); an exec/PTY interface to run commands and capture stdout, stderr, and exit codes; a cheap create → run → destroy lifecycle with a backstop TTL that reaps leaked sandboxes; and snapshot/state so you can freeze, restore, or fork an environment. Isolation makes it safe; the rest makes it actually usable.
Should I self-host an agent sandbox or use a hosted one?
Self-host if sandboxing is core to your product, you want to own the isolation boundary, or compliance requires it — Firecracker and platforms like PandaStack are open source, but you take on multi-tenant isolation, egress policy, fast create latency, and reaping leaked sandboxes as real systems work. Use a hosted service when the sandbox is a means to an end and you'd rather spend engineering on the agent itself. The isolation-strength question is the same either way: a container sandbox is a shared kernel whether hosted or not, and a microVM is a private one.
49ms p50 cold start. Fork, snapshot, and scale to zero.