Sandboxing and egress control
A file-system scope, a container and a network allow-list drawn as boundaries around a tool's process: which actions each layer stops, which it lets through, and the one no layer can see.
Loading the animation…
Concept
The policy of chapters 1 to 4 decides which calls an agent may make. A sandbox works one level down: it limits what a tool's process can do once it runs, whatever the call asked for. That matters most for tools that run code (a shell, a test runner, a package installer), because code can do anything its process is allowed to.
The animation puts one such process inside three layers, each drawn as a boundary. The file-system scope limits file access to the workspace. A container gives the process its own file system and process space with only the workspace mounted, so the user's home directory is invisible and a process it starts stays inside. A network allow-list at the host's edge lets connections reach only the package registry. The process tries 8 actions; the task (run the tests, install a package) needs 3 of them.
With no sandbox all 5 unneeded actions get through. Each layer closes some: the file scope stops reading the home directory and writing system files, the container also stops a process escaping to the host, and the allow-list stops connections to any other host. With all three on, 4 of the unneeded actions are stopped, the task still works, and 1 gets through: an upload to the allow-listed registry. The allow-list checks where a connection goes, not what it carries, so any destination that accepts writes is a way out. Claude Code's sandboxing documentation makes the same point: "Allowing broad domains such as github.com can create paths for data exfiltration", and "Effective sandboxing requires both filesystem and network isolation" (Claude Code docs, sandboxing, opened 2026-10-14). That residual is what the label policy of chapter 1 covers: it sees the data, not the connection. Turn layers off to see which actions each one alone would stop.
Maths
Each layer is a predicate on actions, and an action gets through a stack of layers only if no active layer stops it. So the set of actions that get through can only shrink as layers are added (the engine's tests check this on all subsets of the layers), and layers that stop the same action overlap: with the file scope on, the container adds only the process escape. A sandbox is worth judging by two counts: the unneeded actions still open, and the needed actions it breaks. Here the second is zero for every subset of layers, because each layer was configured from the task; a stricter allow-list without the registry would stop the package install and break the task. Chapter 9 weighs such costs against the published effect of each defence.
Code
The allow-list's rule, cut from the vendored engine (policy/sandbox.ts): it looks at the destination only.
if (lid === "egress") {
if (action.kind === "net" && !layer.allow.includes(action.dest)) return `${action.dest} is not on the allow-list`;
return null;
}