Agent containers
Choose an explicit image and authentication volume before selecting container execution. A Docker installation alone does not make a provider ready to run inside that image.
Prepare an isolated agent
Agent isolation runs the actual vendor CLI in a prepared Docker image. It is separate from
the existing container option for setup and verification commands. Set loop.agentContainer
on a run, for example:
{
"agentContainer": {
"image": "my-codeflow-agents:local",
"authVolume": "codeflow-agent-login",
"network": true,
"memoryMb": 4096,
"cpus": 2
}
}
The image must already exist locally and contain the official claude, codex, or agy
binaries used by the run. Missing images fail rather than being pulled or falling back to
host execution. Images should also provide the language tools required by the repository.
The process runs as your host UID and GID (65532:65532 where those IDs are unavailable).
Prepare /home/codeflow so that this user can read and write it. HOME is /home/codeflow
and CODEX_HOME is /home/codeflow/.codex. For persistent authentication and conversations,
use a named Docker volume created and authenticated by you inside the image. For example,
on macOS or Linux:
docker run --rm -it \
--user "$(id -u):$(id -g)" \
--mount type=volume,source=codeflow-agent-login,target=/home/codeflow \
--env HOME=/home/codeflow --env CODEX_HOME=/home/codeflow/.codex \
--entrypoint codex my-codeflow-agents:local login
Use each vendor's own login flow in that container. The image or volume must have the correct ownership before login; Docker's default root-owned empty volumes may need initialization. Code-flow never mounts your host home, reads or copies your cached provider tokens, or forwards host API keys into the container. Credentials baked into an image are accessible to anyone who can access that image; a privately managed named volume is preferable. A volume persists agent conversations as well as login state. Without one, CLI changes inside the container are discarded, including newly written conversations needed to resume later.
Only the selected workspace is bound into the container, writable for write turns and
read-only for read turns. Its .git marker and the verified repository Git metadata are
mounted read-only. This allows inspection while preventing agents from rewriting repository
metadata; code-flow performs commits on the host after the turn. Git global and system
configuration are disabled inside the container. Extra files generated by code-flow, such
as a Codex output schema, are mounted individually read-only when needed.
The container uses Docker's isolated network by default because inference requires network
access. Setting network: false passes --network none; inference will then be unavailable
unless the configured image supports an offline provider. There is no host networking or
Docker socket mount. Linux capabilities are dropped, privilege escalation is disabled,
processes are limited to 256, and memory and CPU limits are enforced. The container's own
temporary filesystem layer remains writable for vendor CLI state and installed-tool needs;
it is discarded when the turn ends.
Live team-tool bridges are not supported inside containers. The UI and adapter status report this limitation, and team members use structured outcomes and replies on subsequent turns. Codex app-server still supports streaming, steering, and scoped one-shot approval over stdin. Additional filesystem/network permission requests and session-wide policy amendments remain declined. Selecting full CLI trust does not remove the outer Docker container boundary.
Cancellation, timeout, stall, and shutdown remove the daemon-owned container as well as the Docker client. Container names are recorded in the process recovery journal so startup can also remove containers left behind by a server crash before recovering worktrees.
Run npm run test:containers for native ordinary and filtered runtime checks.
The tests build and remove small fake-CLI fixture images and never
use provider credentials or model quota. The regular suite also tests launch arguments,
all adapter transports, daemon/client separation, cancellation, and timeout with a fake
Docker runtime.
Per-project read/write restrictions use the separate filtered task backend, with a fresh allowed-file Git namespace and explicit review-branch import. Ordinary agent containers mount their worktree's full Git common directory and cannot enforce those restricted reads.