Runners & isolation
Where agent code executes: the mandatory sandbox, remote runners with labels, and the warm workspace cache.
The control plane orchestrates runs; runners execute them. Wherever a phase runs, one rule holds: agent code never executes on the host directly, and there is no way to turn isolation off.
The sandbox
Every phase runs in a fresh, one-shot container: non-root, all capabilities dropped, no privilege escalation, CPU/memory/process caps, torn down when the phase ends. Multi-tenant deployments (including Peractor Cloud) run the same container under gVisor for a kernel-level boundary. The sandbox sees only what the run needs: the workspace, the secrets the workflow declares, the agent credential, and a repo-scoped git token — never the host environment.
Because Peractor owns the boundary, agents inside it run with their own permission prompts disabled — the human control point is the gate, not a terminal prompt nobody is watching.
Registered runners: your machines
Need phases to run close to your infrastructure — a GPU box, a macOS builder, a machine inside your VPN? Run the runner agent there. It dials the control plane outbound-only over one WebSocket, so it needs no inbound ports:
PERACTOR_RUNNER_URL=wss://peractor.com/runners \
PERACTOR_RUNNER_TOKEN=<shared secret> \
PERACTOR_RUNNER_LABELS=docker,gpu \
peractor-runner
A runner announces its capabilities as labels. A phase is
dispatched to a connected runner whose labels cover what it needs; with
no runner connected, the phase runs in the host's own sandbox. A
registered runner machine needs the agent CLIs (claude,
codex) on its PATH — and since it's your machine, the
machine itself is the isolation boundary there.
The warm workspace cache
By default each phase clones fresh. For install-heavy repos, a workflow can opt into a per-run cached workspace:
defaults:
cacheWorkspace: true
Phases then reuse one volume — but every phase still hard-resets
it to the remote branch on entry, so git stays the only source of
truth; only git-ignored files like node_modules survive
between phases. The volume is dropped when the run ends, and anything
that can't use it (a repo-less run, a remote runner) silently falls back
to a fresh clone.
If a machine disappears
A runner that drops its connection fails the phase it was holding — and the phase parks at its gate, where Approve retries it. A host restart re-dispatches whatever was in flight from the branch state. Losing hardware never loses work: the branch has everything that completed.