Agent Sandbox Image
flowbot-agent-sandbox is a Docker base image for Cloud Agent ephemeral containers. The orchestrator mounts a workspace, injects commands, and tears the container down when the agent run finishes. The image pre-installs git and common language toolchains so agents start ready to clone, build, and test code.
This image is not the Flowbot server container. See Deployment for the main flowbot service image built from deployments/Dockerfile.
How this differs from other sandboxes
| Mechanism | Scope | Purpose |
|---|---|---|
| Agent sandbox image (this document) | Ephemeral Docker container | Cloud Agent runtime environment |
Flowbot server image (deployments/Dockerfile) |
Long-running service | Run the Flowbot hub on port 6060 |
Chat agent workspace (chat_agent.workspace) |
Host directory path | File-system sandbox for DM chat agent tools |
The agent sandbox image follows the same principle as Cursor Cloud Agent Dockerfiles: do not COPY the project into the image. The orchestrator checks out or mounts sources at runtime under /workspace.
Image variants
The Dockerfile defines a single runtime stage base. Interactive browsing is not bundled in this image; use chat agent browser_* tools with Compose CDP services (Browser tools).
| Stage | GHCR tag examples | Use when |
|---|---|---|
base |
1.0.0, latest |
Coding agents: git, Go, Node, Python, shell tools |
Registry: ghcr.io/flowline-io/flowbot-agent-sandbox
For interactive browsing use Browser tools with Compose CDP services (lightpanda, optional playwright-cdp profile in deployments/docker-compose.yaml). This image does not ship a Playwright or Chromium browser toolchain.
Pre-installed toolchain
Versions are pinned in deployments/agent-sandbox/Dockerfile build args and upgraded by releasing a new sandbox-v* tag.
| Tool | Version / source | Notes |
|---|---|---|
| Base OS | Ubuntu 24.04 | Cloud Agent / coding toolchain base |
| git | distro package | Required for Cloud Agent clone workflows |
| sudo | NOPASSWD for agent |
Privileged setup steps when orchestrator needs them |
| Go | 1.27.1 (official tarball) | Matches go.mod. GOROOT=/usr/local/go, GOTOOLCHAIN=local (no auto toolchain download). Used by Cloud Agents and by named FaaS (go run main.go, stdlib-only, Network=none) |
| Node.js | 22.x LTS (NodeSource) | Matches CI node-version: lts/* |
| oxfmt / oxlint | npm global | Matches Flowbot JS lint/format tooling |
| Python | 3.x (distro) | python symlinked to python3; pip and venv included |
| Shell / CLI | bash, jq, ripgrep, curl, wget, openssh-client, build-essential | Aligned with Flowbot server runtime packages |
dcg |
GitHub release (DCG_VERSION, default v0.6.7) |
Installed as /usr/local/bin/dcg (linux musl amd64) with SHA256 verify; config at /etc/dcg/config.toml (same as pkg/agent/dcg/config.toml). Parity only — Flowbot's Always-on DCG gate for run_terminal / run_code runs on the host before sandbox exec; the image does not re-check. |
The image does not bake the flowbot CLI. Chat agent sandbox injects flowbot-cli_linux_amd64 from beside the Flowbot server binary into /opt/flowbot-cli (on PATH). See Chat agent CLI injection below.
Credential files materialized by the chat agent sandbox runner are chowned to uid/gid 1000 (the image agent user) when possible; otherwise they are mode 0644 so the container can still read them when the host process cannot chown.
Destructive Command Guard (dcg)
Flowbot chat agent Always-on protection for run_terminal / run_code uses dcg on the host (dcg --robot test via pkg/agent/dcg), before permission ask and before sandbox exec:
- Install
dcgon the Flowbot serverPATH(required; missing binary → startup warning, first shell/code tool call fails closed). - Policy is embedded from
pkg/agent/dcg/config.toml(default cores + windows default packs +remote/database/containers/system/platform). DCG_BYPASSis stripped from the dcg child process only; agents have no bypass path.- The sandbox image ships
dcg+ the same toml for operational parity only — Flowbot does not run a second check inside the container.
Runtime contract
Ephemeral containers using this image should follow these conventions:
- Workspace — Mount the agent working copy at
/workspace(defaultWORKDIR). - User — Run as
agent(uid/gid 1000) unless root is explicitly required. - Command — The image has no ENTRYPOINT and no CMD. The orchestrator supplies the process (e.g. shell, test runner, agent wrapper).
- No baked-in repo — Do not rely on files copied at build time; clone or bind-mount at runtime.
- Lifecycle — Use
--rm(or equivalent) so containers are destroyed after each agent run. - Flowbot CLI — Not baked into the image. Chat agent sandbox injects the binary and credentials from
chat_agent.sandbox(see below). Do not bake tokens into the image. Do not mount a human operator's host~/.config/flowbotin production.
Example:
docker run --rm \
-u agent \
-v "$(pwd):/workspace" \
-w /workspace \
ghcr.io/flowline-io/flowbot-agent-sandbox:1.0.0 \
bash -lc 'go test ./...'
Manual CLI against a host server (debug only; mount a linux/amd64 CLI binary):
docker run --rm \
-u agent \
-e FLOWBOT_SERVER_URL=http://host.docker.internal:6060 \
-e FLOWBOT_TOKEN=your-access-token \
--add-host=host.docker.internal:host-gateway \
-v "$(pwd):/workspace" \
-v /path/to/cli-dir:/opt/flowbot-cli:ro \
-w /workspace \
ghcr.io/flowline-io/flowbot-agent-sandbox:1.0.0 \
bash -lc 'PATH=/opt/flowbot-cli:$PATH flowbot bookmark list'
/path/to/cli-dir is a directory that contains an executable named flowbot.
Older published CLI builds ignore FLOWBOT_TOKEN and only read ~/.config/flowbot/token. Prefer mounting a materialized config directory (what Flowbot's sandbox runner does).
Registry and tags
| Git tag | Image tags |
|---|---|
sandbox-v1.0.0 |
1.0.0, 1.0, sandbox-v1.0.0, latest |
workflow_dispatch + suffix dev-abc |
dev-abc |
workflow_dispatch (no suffix) |
dev-<sha> |
Versioning
Sandbox releases use sandbox-v* git tags, independent of Flowbot server releases (v*).
Release steps:
- Merge Dockerfile or workflow changes to
main. - Tag:
git tag sandbox-v1.0.0 && git push origin sandbox-v1.0.0 - GitHub Actions workflow
docker-agent-sandbox.ymlbuilds and pushes thebasetarget to GHCR.
Manual builds (development):
- Open Actions → Docker Agent Sandbox → Run workflow.
- Optionally set tag suffix (e.g.
dev-abc1234).
Build locally
# Context is repo root for dcg config COPY
docker build -f deployments/agent-sandbox/Dockerfile --target base \
-t flowbot-agent-sandbox:local .
# Smoke test (no baked flowbot CLI)
docker run --rm flowbot-agent-sandbox:local bash -lc \
'git --version && go version && node --version && python3 --version && dcg --version && test -f /etc/dcg/config.toml'
# FaaS offline Go contract (matches Network=none + GOPROXY=off)
docker run --rm --network=none -w /tmp \
flowbot-agent-sandbox:local bash -lc \
'printf "%s\n" "module flowbotfn" "" "go 1.27" > go.mod && printf "%s\n" "package main" "" "import \"fmt\"" "" "func main() { fmt.Println(\"{}\") }" > main.go && GOPROXY=off GOSUMDB=off CGO_ENABLED=0 go run main.go'
CI/CD
| Workflow | Trigger | Output |
|---|---|---|
docker-agent-sandbox.yml |
Push tag sandbox-v*; manual workflow_dispatch |
Pushes base to GHCR |
Each build runs a post-build smoke test (git, go, node, python3, dcg; offline go run main.go under --network=none) and prints docker image inspect Size (packaging).
Orchestrator integration
Cloud Agent orchestrators should reference a pinned semver tag in production, for example:
- Coding tasks:
ghcr.io/flowline-io/flowbot-agent-sandbox:1.0.0 - Browser tasks: chat agent Browser tools + Compose CDP services (not this image)
Named FaaS (go run main.go)
Functions invoke the sandbox with Network=none and no Flowbot CLI credentials. On Docker, the ephemeral host workspace is copied into /workspace (WorkspaceInject); see .agents/notes/implemented/bug-fix/2026-09-04-function-sandbox-workspace-inject.md. Go entrypoints write a minimal go.mod (module flowbotfn / go 1.27) and run go run main.go with GOPROXY=off, GOSUMDB=off, GOTOOLCHAIN=local, and CGO_ENABLED=0 (stdlib only; no module download). The image pins GOTOOLCHAIN=local so the bundled Go 1.27.1 compiler cannot attempt a toolchain fetch when the proxy is off.
Chat agent CLI injection (chat_agent.sandbox)
When Flowbot runs shell/code tools in Docker sandbox mode, configure:
chat_agent:
sandbox:
enabled: true
image: ghcr.io/flowline-io/flowbot-agent-sandbox:latest
server_url: "http://host.docker.internal:6060"
access_token: "<hub-access-token>"
Behavior:
- The runner resolves
flowbot-cli_linux_amd64next to the Flowbot server executable (the server image ships this sibling under/opt/app/). - Docker: after container create, each Exec copies the CLI (as
flowbot) into/opt/flowbot-clivia the Docker Engine API (CopyToContainer), and prepends that dir toPATH. Credentials (token+server_urlfiles) are copied the same way to/home/agent/.config/flowbot, andFLOWBOT_TOKEN/FLOWBOT_SERVER_URLare set. No host bind is used for CLI or credentials (avoids Docker-in-Docker path visibility issues). See .agents/notes/implemented/simplification/2026-09-16-sandbox-cli-api-inject.md. - If the sibling CLI is missing or copy fails, a failing stub named
flowbotis injected instead (non-zero exit + clear stderr). Other shell/code tools still run. - kern: same sibling/stub semantics; CLI and config use bind mounts (host paths are visible to kern).
- If
server_urlhost ishost.docker.internal, the Docker runner addsExtraHosts: host.docker.internal:host-gateway. - Empty
access_tokenskips credential injection (CLI calls fail with not logged in).
server_url must reach the same port as listen (example 6060 above matches the reference config). Changing listen without updating server_url yields connection refused inside the sandbox (note).
Local development with go run (temp binary under /tmp/go-build... with no sibling CLI): build a linux CLI with go tool task build:cli:linux and place flowbot-cli_linux_amd64 beside a packaged server binary, or run the packaged bin/flowbot that sits next to the linux CLI artifact.
Kern runtime (chat_agent.sandbox.runtime)
Set runtime: kern to use the kern CLI instead of Docker (Linux only; kern on PATH, kern doctor passing). Configure security_profile: untrusted for the hardened bundle. Use server_url: http://127.0.0.1:6060 with network: host — host.docker.internal is not available under kern (Flowbot logs a warning). Workflow steps use the separate kern:<image> action; see .agents/notes/implemented/architecture/2026-09-01-kern-executor-runtime.md.
Network options for server_url:
| Approach | When |
|---|---|
http://host.docker.internal:6060 + host-gateway |
Default; Docker Desktop and Linux with host-gateway |
network: host + http://127.0.0.1:6060 |
Linux same-host |
| Shared Docker network + service DNS | Flowbot and sandbox on the same user-defined network |
Release note: FLOWBOT_TOKEN requires a CLI build that supports it. Mounted config files keep older CLIs working.
Future Flowbot configuration for Cloud Agent runtime image selection will point at these GHCR coordinates.
Extending the image
Fork or extend deployments/agent-sandbox/Dockerfile when you need extra system packages or compiler versions. Prefer optional later stages so slim agents are not forced to pay for heavy toolchains. For interactive browsing, use Browser tools instead of baking browsers into this image.
Limitations
The sandbox image intentionally does not include:
- Docker-in-Docker (large, requires privileged mode; Flowbot workflow Docker executor is separate)
- PostgreSQL or Redis (provide via orchestrator sidecars or host services)
- The Flowbot server binary or a baked
flowbotCLI (chatagent injectsflowbot-cli_linux_amd64at runtime) - Pre-baked login tokens (inject at runtime via
chat_agent.sandbox.access_tokenor manual Env/mount; never bake into the image)
Related documentation
- Agent Engine —
pkg/agent/runtime - Deployment — Flowbot server and CI/CD overview
- Architecture diagram — CI → GHCR → ephemeral run flow