# Filesystem Volumes arrived. Multi-ensemble isolation in one runtime (v1.1.0)

> Source: <https://loomcycle.dev/blog/filesystem-volumes-arrive.html>
> Published: 2026-06-26 12:00:00+00:00

loomcycle v1.1.0 ships Filesystem Volumes (RFC AH, Phases 1 through 5). Per-agent ro/rw filesystem roots replace the global jail. Phase 1: a Volume is {name, path, mode: ro|rw}; an AgentDef binds to a named subset, file tools take an optional volume arg, ro/rw is enforced (Bash refuses ro). The load-bearing invariant is spawn confinement: a sub-agent's volume set is parent intersect child, with ro/rw resolving to the more restrictive. The TOCTOU-safe resolveInsideRoot is unchanged; only which root is passed in changes. Phase 2a adds the dynamic VolumeDef substrate, tenant-scoped, runtime-mutable, with a runtime-derived path that never accepts a caller-supplied directory. Names match a strict regex; no slashes, no dots, no path injection. The op set is create/delete/purge, not retire/promote/fork. Phase 2b adds ephemeral run-scoped volumes: create with ephemeral=true, the runtime provisions under _ephemeral//, auto-purges when the top-level run completes (terminally, in any state). Run-tree isolation: the ephemeral set is created fresh per top-level run, inherited by sub-agents, never crosses between runs. Behind four fences for the purge; a singleton sweeper backstops crashed runs; paused runs skipped so snapshot-and-resume keeps its working tree. Phase 3 BREAKING: the legacy jail env vars (LOOMCYCLE_READ_ROOT, WRITE_ROOT, BASH_CWD) are removed. Volumes are now the sole filesystem mechanism. An agent not bound to any volume has no filesystem access. A deploy still setting the retired env vars fails at config-load with a migration hint. Migration is one-line: replace the three env vars with a single default volume in the new volumes: yaml block. Phase 4 ships a Volumes tab in the Web UI; Phase 5 closes cross-transport parity (HTTP, gRPC, MCP, TypeScript adapter, Python adapter all carry the same surface). The killer demo: exp8 ships as a self-contained directory; a dispatcher agent creates an ephemeral volume, git-clones loomcycle into it, fans out 8 reviewer agents via Agent op=parallel_spawn (in-process barrier, no MCP round-trip), each writes findings to Memory, a consolidator merges them into a report on the default volume, the ephemeral volume auto-purges when the dispatcher exits. Contrasts with exp7 (external MCP fan-out, pre-cloned static ro volume, operator-driven barrier). Six PRs (#510 through #515). The Paca conversation that surfaced the multi-ensemble shared-jail problem produced its answer at the runtime level.
