Tools that run LLM agents spawn subagents, and pi's example describes each one as having an "isolated context window". It’s easy to hear that as "isolated" in the security sense. But on Linux, a child process inherits its parent's environment, user ID, filesystem, and working directory unless something explicitly takes them away. So what does "isolated" actually remove here?
To find out, I read the example subagent extension that ships with Pi: an MIT-licensed open-source coding agent (Pi's core has no built-in subagents), and ran the same task twice:
- On the host. A subagent that is told to be read-only and is given only the “bash” tool reads “~/.ssh” and prints live API keys from its inherited environment. The tool list is enforced in code, but that is an application-level boundary. "Read-only" is just an instruction in the prompt, and “bash” goes straight through to the OS.
- In plain Docker, Pi's documented setup. “~/.ssh” is gone, but the key still prints, because it was passed in with “-e ANTHROPIC_API_KEY”. The mount namespace hid the files. It did nothing for the environment variable.
I close with the network-layer fix pi's docs describe for Docker Sandboxes: the sandbox only ever holds a placeholder token, and a proxy swaps in the real key for requests to the configured host. The pattern works without that particular product.
Pi is a good example precisely because its docs are upfront about what they isolate. The same check applies to anything that spawns workers: CI runners, plugin hosts, and agent frameworks.
Outline (12 min)
0-2: what a child process inherits on Linux
2-4: reading pi's spawn call
4-9: the host run and the Docker run, side by side
9-11: the placeholder-token and egress-proxy pattern
11-12: the checklist
Prerequisites: a Linux or macOS shell and one container run.