Skip to main content

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:

.autodev/fleet.toml
[bridges.worker]
kind = "codex"
model = "worker-model"

[bridges.reviewer]
kind = "codex"
model = "review-model"

[roles]
worker = "worker"
judge = "reviewer"

Supported bridge kinds are:

KindConfigurationNotes
codexoptional model, extra_args, confinementRuns the installed Codex CLI, parses JSONL results and usage, and uses Codex's sandbox or fleet confinement.
claude-codeoptional model, extra_args, confinementRuns the installed Claude Code CLI and parses stream-json results and usage. Use fleet confinement for a worker role.
commandrequired non-empty argv; optional name, confinementRuns 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
KeyMeaning
worktree_rootWhere isolated worker and temporary verification worktrees are created. Relative paths resolve from the repository root.
max_wave_sizeMaximum stories grouped into one integration wave.
max_open_wavesMaximum 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_turnsMachine-wide worker-turn concurrency. If absent, the effective limit falls back to max_wave_size. A configured zero is clamped to one.
max_concurrent_judgesJudge-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_limitMaximum retries after the initial worker turn. For example, 2 permits up to three total attempts.
turn_deadline_secondsMaximum age of a live worker turn before failure and retry.
disk_floor_gbFree-space floor below which new dispatch is withheld. No floor is enforced when absent.
transcript_budget_bytesMaximum 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:

.autodev/workflows.toml
[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.