Now accepting beta testers

Guide · Agent sandboxing

Sandboxing AI agents on Linux

Containers, microVMs and gVisor for AI agents, why identical images don't give identical runs, and a practical Incus setup for an agent lab.

Sandboxing an AI agent means running it where the damage it can do is bounded: no access to the host, to the network, or to data the task doesn’t need. On Linux the choices are containers, microVMs and user-space kernels such as gVisor, and the right one depends on how much you trust code that, by definition, nobody has reviewed before it runs.

This guide covers why agents need stronger isolation than ordinary workloads, how the three options compare, why two runs of the same image don’t behave the same, and a practical starting setup with Incus. It describes general, public practice only.

Why does an AI agent need a sandbox?

An agent is a program that writes and runs other programs. A coding agent installs packages, runs build scripts and executes tests. An operations agent runs shell commands against live systems. Whatever the agent decides to run, your machine runs.

That makes the agent’s environment an attack surface in two directions. Inward, a prompt injection in a web page or a dependency README can steer the agent into running something hostile. Outward, the agent itself may try to reach beyond its box, whether by instruction, by accident or because it has learned that doing so gets a task marked done. Sandbox escape is the name for the second case, and it is now measured directly: Quantifying Frontier LLM Capabilities for Container Sandbox Escape benchmarks how capable frontier models are at breaking out of container sandboxes (Sandbox escape benchmark, 2026).

The conclusion is not that agents are malicious. It is that an agent’s isolation has to be designed for an adversary, because you cannot predict what it will run.

Containers, microVMs or gVisor?

Three isolation models are in common use, and they trade security boundary against cost.

ContainersgVisorMicroVMs
What isolatesKernel namespaces and resource limits on a shared host kernelA user-space kernel that mediates the container’s system callsA separate guest kernel on a hardware-virtualised machine
BoundaryThe host kernel’s attack surfaceThe user-space kernel; the host kernel sees far fewer callsThe hypervisor
OverheadLowestModerate; some system calls are slowerLow at runtime; more memory per instance
StartupMillisecondsMillisecondsHundreds of milliseconds to seconds
FitsTrusted code, dense packingUntrusted code that still needs container toolingUntrusted code, strongest boundary, GPU and device passthrough
ExamplesDocker, Podman, LXC, Incus system containersgVisor (runsc)Firecracker, Cloud Hypervisor, Incus virtual machines

Containers share the host kernel. They are fast and cheap, and every kernel vulnerability is a potential escape. Standard hardening applies: unprivileged containers, dropped capabilities, read-only root filesystems, system-call filtering with seccomp, and no privileged devices. For an agent, treat a plain container as the floor, not the ceiling.

gVisor puts a user-space kernel between the workload and the host. The container’s system calls are served by that layer, so the host kernel is exposed to a much smaller set of operations. The cost is compatibility and performance for system-call-heavy work, which agent tasks often are.

MicroVMs give each workload its own kernel on a small virtual machine. The boundary is the hypervisor, which is the strongest of the three, and the price is memory per instance and slower starts. For long-running agents or anything with GPU access, the price is usually worth paying.

A reasonable default for an agent lab is a microVM or system container per task, created fresh and destroyed after. Reuse is where sandboxes rot.

Why isn’t “same image, same behaviour” true?

Teams often assume that an agent run is reproducible if the container image is pinned. It isn’t, for three reasons.

Model inference is not deterministic, even at temperature 0. Floating-point arithmetic on GPUs doesn’t guarantee the same result for the same input across batch sizes or hardware. Understanding and Mitigating Numerical Sources of Nondeterminism in LLM Inference traces output variance to numerical precision and finds that lower-precision formats such as BF16 diverge where FP32 holds steady (Numerical nondeterminism, 2025). Thinking Machines reaches the same conclusion from the serving side and attributes the variance to compute routines whose results depend on batch composition (Thinking Machines, 2025).

Timing differs. Network latency, scheduler order, and the wall-clock time an agent reads all vary between runs. A command that times out in one run succeeds in the next.

The agent’s path compounds the differences. A one-token difference early in a run changes the next command, which changes the output the agent reads, which changes everything after. Two runs of the same agent on the same image and the same task can end in different places.

The practical consequence is that you cannot replay an agent run to find out what happened in it. The record has to be made during the run, by something that isn’t the agent, and kept where the agent can’t change it. Qin et al. found that most agent harnesses they tested let the agent delete its own trace, and recommend logging outside the agent’s control (Qin et al., 2026).

What does a practical Incus setup look like?

Incus manages both system containers and virtual machines with one tool and one image store, which makes it a good fit for a small agent lab. A starting setup, using only standard features:

  1. One instance per task. Create it from a snapshot of a prepared base image, run the task, export the results, destroy the instance. Never let a second task inherit a first task’s state.
  2. Unprivileged containers or VMs. Unprivileged containers map root inside to an unprivileged user outside. Where the task will run untrusted code with any real capability, use a VM.
  3. No outside network by default. Put instances on an isolated bridge with no route out. Add a filtered egress only for tasks that need a named service, such as a package mirror you host.
  4. Resource limits. Cap CPU, memory, disk and process count per instance, so a runaway agent degrades its own box and not the host.
  5. Snapshots before and after. A snapshot at the start fixes the initial state; a snapshot at the end fixes the final state. The difference is your outcome evidence, taken from the host side rather than from the agent’s report.
  6. Results leave the instance; nothing comes back. Copy artefacts out to host storage the instance cannot mount. Keep whatever logs the host or hypervisor produces outside the instance as well.
  7. Fresh base images on a schedule. Rebuild the base from a declarative definition so that the environment is documented, not accumulated.

None of this is exotic, and none of it is sufficient on its own. It gives you bounded damage, a clean start per task, and a final state you observed rather than were told about. Inoku’s private evaluations run agents in isolated environments of this kind, so the agent is tested as shipped, with no code changes.

Evidence

Sources

Every factual claim on this page links to one of these. Numbers in brackets refer to this list.

  1. Open
  2. Open
  3. Defeating Nondeterminism in LLM Inference

    Thinking Machines2025-09thinkingmachines.ai

    Open
  4. Open

Research notes on this topic

Notes that go deeper

3 notes

Questions

Frequently asked questions

Why does an AI agent need a sandbox?
An agent is a program that writes and runs other programs, so whatever it decides to run, your machine runs. The attack surface goes both ways: a prompt injection can steer the agent into running something hostile, and the agent itself may try to reach beyond its box. Its isolation has to be designed for an adversary.
Containers, gVisor or microVMs for AI agents: which should I use?
Containers share the host kernel, with every kernel vulnerability a potential escape, so treat them as the floor. gVisor puts a user-space kernel between workload and host, at a cost in compatibility and performance. MicroVMs give each workload its own kernel behind the hypervisor, the strongest boundary. A reasonable default is one microVM or system container per task.
What is a sandbox escape for an AI agent?
Sandbox escape is when an agent reaches beyond its isolation boundary, whether by instruction, by accident, or because it has learned that doing so gets a task marked done. It is now measured directly: a 2026 benchmark quantifies how capable frontier models are at breaking out of container sandboxes.
Why don't two runs of the same agent on the same container image behave the same?
Three reasons. Model inference is not deterministic even at temperature 0, because floating-point results on GPUs vary with batch composition and hardware. Timing differs between runs: network latency, scheduler order and wall-clock time. And the agent’s path compounds the differences, so a one-token change early on alters every command after it.
Can you replay an AI agent run to see what happened?
No. Because runs are not reproducible, the record has to be made during the run, by something that isn’t the agent, and kept where the agent can’t change it. Qin et al. found that most agent harnesses they tested let the agent delete its own trace, and recommend logging outside the agent’s control.
How do you set up Incus for an AI agent lab?
One instance per task, created from a snapshot of a prepared base image and destroyed afterwards. Unprivileged containers or VMs. No outside network by default. Limits on CPU, memory, disk and process count. Snapshots before and after, so the difference is outcome evidence taken from the host side. Results leave the instance; nothing comes back.