Configure bridges, workflows, and gates
The fleet reads .autodev/fleet.toml from the repository root. The parser rejects unknown fields, unknown bridge kinds, unresolved role names, an empty command bridge, and a worker setup with no validation command.
All current bridges launch locally installed coding-agent CLIs. Start with Connect coding-agent CLIs for installation, authentication, native Codex and Claude Code adapters, and generic Pi or OpenCode examples. Direct provider API access is planned but not implemented.
Configure named bridges and roles
Named bridges make the harness choice for each role explicit:
[bridges.worker]
kind = "codex"
model = "worker-model"
[bridges.reviewer]
kind = "codex"
model = "review-model"
[roles]
worker = "worker"
judge = "reviewer"
Supported bridge kinds are:
| Kind | Configuration | Notes |
|---|---|---|
codex | optional model, extra_args, confinement | Runs the installed Codex CLI, parses JSONL results and usage, and uses Codex's sandbox or fleet confinement. |
claude-code | optional model, extra_args, confinement | Runs the installed Claude Code CLI and parses stream-json results and usage. Use fleet confinement for a worker role. |
command | required non-empty argv; optional name, confinement | Runs a headless coding-agent CLI or wrapper after substituting {prompt}. Harness-specific usage stays unknown. |
Do not pass sandbox-bypass or profile-selection flags through a Codex bridge's extra_args.
Current validation does not recognize every flag that can weaken or redirect the adapter's declared
sandbox; see Current limitations.
roles.worker selects the implementation harness. roles.judge selects the independent review turn. roles.analyst is optional; when absent or when prediction fails, scheduling falls back to story-declared areas.
autodev also accepts legacy singular [bridge] and [judge] tables, but named bridges keep role selection and model pins easier to audit.
Set confinement = "fleet" on a bridge to wrap its process in the fleet's Bubblewrap boundary. The
driver refuses a role on a bridge that declares no sandbox. The escape hatch is the driver
environment variable AUTODEV_ALLOW_UNSANDBOXED_ROLE=1. This is an explicit risk acceptance, not a
recommended default, and it intentionally cannot be placed in repository-controlled TOML.
Configure proof commands
Every worker configuration needs a validation command:
[validation]
argv = ["cargo", "test", "--workspace"]
gate = ["cargo", "test", "--workspace"]
argv proves worker evidence. gate is run against the integrated candidate; when gate is omitted or empty, it falls back to argv. Both are argument arrays, not shell strings.
The compatibility key test_pattern is still accepted but no longer decides which changed files count as tests. Prefer leaving it unset.
On Linux, validation is confined with Bubblewrap and network access is denied. If bwrap is missing or cannot start, validation is refused. AUTODEV_ALLOW_UNCONFINED_VALIDATION=1 lets the driver's environment accept an environment-only run, but that gives candidate-authored code the driver's filesystem and network reach. Use it only as a conscious temporary exception.
Size the fleet
[fleet]
worktree_root = "../project-fleet-worktrees"
max_wave_size = 3
max_open_waves = 2
max_concurrent_turns = 3
max_concurrent_judges = 3
attempt_limit = 2
turn_deadline_seconds = 3600
disk_floor_gb = 20
transcript_budget_bytes = 2097152
| Key | Meaning |
|---|---|
worktree_root | Where isolated worker and temporary verification worktrees are created. Relative paths resolve from the repository root. |
max_wave_size | Maximum stories grouped into one integration wave. |
max_open_waves | Maximum active waves counted for new dispatch. Parked or stranded holds are not counted even though they still hold stories. Zero withholds all dispatch. |
max_concurrent_turns | Machine-wide worker-turn concurrency. If absent, the effective limit falls back to max_wave_size. A configured zero is clamped to one. |
max_concurrent_judges | Judge-turn concurrency across every wave under review. If absent, the effective limit falls back to max_concurrent_turns, then max_open_waves. A configured zero is clamped to one. The shared agent pool still bounds worker and judge harnesses together. |
attempt_limit | Maximum retries after the initial worker turn. For example, 2 permits up to three total attempts. |
turn_deadline_seconds | Maximum age of a live worker turn before failure and retry. |
disk_floor_gb | Free-space floor below which new dispatch is withheld. No floor is enforced when absent. |
transcript_budget_bytes | Maximum stored transcript size; overruns are marked as truncated rather than silently discarded. |
Worktrees and build caches can be much larger than source checkouts. Measure with autodev fleet disk, leave room for all resident open waves, and keep the worktree root on the filesystem whose free space you intend to protect.
Control the worker environment
Harness processes start with a cleared environment. PATH and HOME pass through by default; add only what the work needs:
[env]
pass_through = ["RUSTUP_HOME", "CARGO_HOME"]
[env.set]
CARGO_TARGET_DIR = "target"
CI = "true"
Do not pass broad credential-bearing variables casually. Transcript capture makes turn output auditable, which also means a secret printed by a tool may become durable runtime data.
Every absolute environment value that points to an existing directory is bind-mounted read-only during confined validation: letting a tool find its registry or configuration must not also let candidate-authored code modify it. Write access is a separate, explicit grant. Prefer relative build caches inside each worktree anyway; they are narrower and simpler to reclaim. The mount plan is printed before launch, so you can check what a run was actually given.
Route complexity to models
Stories may declare complexity: low|medium|high. Map those demands separately from the selected bridge:
[models]
default = "general-model"
low = "fast-model"
medium = "general-model"
high = "frontier-model"
An unmapped complexity level uses default; if that is absent, the worker bridge's own model is the fallback. Missing routing never withholds a story.
Override workflows
Built-in workflows are used when .autodev/workflows.toml is absent. A repository can add or shadow a workflow whose name matches a story kind:
[workflow.feature]
level = 3
states = ["backlog", "ready", "in-progress", "review", "done"]
initial = "backlog"
terminal = ["done"]
[workflow.feature.gates]
"criteria-present" = "check"
"evidence.failing-first" = "evidence"
"evidence.write-set" = "evidence"
"gate.repo" = "evidence"
"verdict.independent-review" = "judge"
[[workflow.feature.edge]]
from = "backlog"
to = "ready"
gates = ["criteria-present"]
[[workflow.feature.edge]]
from = "ready"
to = "in-progress"
[[workflow.feature.edge]]
from = "in-progress"
to = "review"
gates = ["evidence.failing-first", "evidence.write-set", "gate.repo"]
[[workflow.feature.edge]]
from = "review"
to = "done"
gates = ["verdict.independent-review"]
Gate kinds are check, evidence, judge, and human. The loader validates IDs, states, edges, and gate references. Custom workflows can change ceremony, so keep repository proof, evidence, and independent review on every delivery path; do not treat syntactic validation as a security review of the workflow.
After any configuration change, run:
autodev board check
autodev fleet disk
autodev fleet doctor
autodev fleet tick
Use a single tick to confirm the resolved configuration before starting a long drive.