Autopilot — autonomous agent runs
import { Aside } from ‘@astrojs/starlight/components’;
Autopilot lets warden run a goal-directed, long-lived agent loop over your codebase. You describe what you want in a plan file, enable autopilot, and warden takes care of the rest: spawning a manager agent that breaks the goal into tasks, delegates each task to worker agents in isolated worktrees, gates their branches through CI, and lands them into an integration branch — healing itself when stuck, and escalating to cheaper backends when rate-limited.
The fleet
Section titled “The fleet”A run is a small fleet with separated jobs:
- Manager (role
autopilot) — the long-lived agent that drives the whole run. - Worker (role
worker) — one per task by default, owning it end-to-end (implement → self-review → PR → CI green → merge) and reporting back to the manager. A large task may instead get a pipeline ofimplementer/reviewer/auto-mergeragents. - Resolver (role
brain) — spawned on demand to unblock a stuck worker or make an ad-hoc design call, without human interaction.
A daemon-internal overwatch backstop keeps the fleet moving: it nudges the manager to tend workers that fall idle or wait on input. It is fully automatic — no user action needed — and its cadences are generous (a backstop, not a pacer).
For the underlying design — manager/worker/resolver topology, overwatch, ledger, guardian, cost-tier ladder — see Autopilot concepts.
Prerequisites
Section titled “Prerequisites”Before enabling autopilot, make sure:
warden daemonis running and healthy (warden doctor)- At least one agent backend is authenticated (
claude --versionfor the default Claude backend; or configure an alternative in~/.warden/config.yaml) - Your repository has a
mainbranch and GitHub Actions CI (or a local CI configured in.warden/check.yml) — thegatedstep verifies the gate before landing ghis authenticated (gh auth status) — autopilot opens PRs and checks CI status via the GitHub CLI
Step 1 — scaffold with warden autopilot init
Section titled “Step 1 — scaffold with warden autopilot init”Run init inside the repo you want autopilot to drive:
cd /path/to/my-repowarden autopilot init --name notificationsThis creates (without overwriting if they already exist):
plans/notifications.yaml — edit this to describe your goal:
version: 1goal: "Describe your goal here"constraints: - "keep all changes behind a feature flag"tasks: [] # leave empty to let the manager decompose the goal automatically~/.warden/config.yaml — updated with an autopilot block:
autopilot: enabled: false merge: target_branch: autopilot/integration # legacy default; new runs derive autopilot/<plan> gate: auto # auto | ci | local (auto picks ci when a workflow covers the branch)warden autopilot init also prints a CI hint when no workflow covers the
resolved integration branch — add autopilot/** to on.pull_request.branches
in one of your .github/workflows/*.yml files so gate: auto covers every
per-plan branch:
on: pull_request: branches: - autopilot/**Commit plans/<name>.yaml to your repo so the manager can read it from its
worktree.
Step 2 — edit your plan file
Section titled “Step 2 — edit your plan file”Open plans/notifications.yaml and fill in the goal. The manager decomposes the goal
into tasks automatically if you leave the tasks: list empty. Or provide coarse
tasks yourself to guide decomposition:
version: 1goal: "Ship the notifications feature end-to-end"constraints: - "all changes behind a feature flag named NOTIFICATIONS_ENABLED" - "every PR must pass lint and tests"tasks: - id: api prompt: "Implement the notifications REST API per docs/specs/notify.md" - id: ui prompt: "Implement the notification bell and dropdown UI" after: [api] - id: e2e prompt: "Write E2E tests covering the notifications happy path" after: [ui]The plan file is owner-editable mid-flight — the manager re-reads it on each planning tick. You can add tasks or change constraints while a run is active.
Step 3 — configure the cost tier (optional)
Section titled “Step 3 — configure the cost tier (optional)”By default, the manager picks the cheapest available backend. The cost-tier ladder
is now derived from the backend registry — a
backend’s tier is whatever you set with warden backend tier, and only installed,
enabled, non-local backends are eligible. So you steer autopilot’s spending by
tiering backends:
warden backend tier antigravity free # free tier — first choicewarden backend tier claude subscription # your existing planwarden backend tier codex subscriptionwarden backend list # verify the ladder| Tier | Typical backends | Notes |
|---|---|---|
free | antigravity | Google-hosted free tier; no billing |
subscription | claude, codex | Your existing plan |
pay_per_use | API-billed backends | Requires explicit opt-in (the paid-autopilot gate) |
To test autopilot at zero additional cost, tier only free backends and leave the
paid-autopilot gate off (the default) so the manager never reaches a pay_per_use
backend.
Step 4 — start the run
Section titled “Step 4 — start the run”warden autopilot run start notificationsOr use the legacy enable flow for a single plan:
warden autopilot enableThis enables only the current repository (other repos are unaffected) and
runs a preflight check before enabling. Add --repo <root> to target a
different repository. The preflight surfaces every problem that would stall an
unattended run — now, while you’re present — and prints actionable errors if
anything is missing:
✗ plan file not found: plans/notifications.yaml✗ integration branch does not exist: autopilot/notifications✗ no authenticated backend availablehint: run `warden autopilot init --name notifications` to scaffold a plan file and config blockFix any reported issues and re-run warden autopilot enable. When the preflight
passes, the manager is spawned and the run enters active state, and the repo is
persisted as enabled — so it comes back up automatically if the daemon
restarts. Enable more repos the same way; each is tracked independently.
Monitoring a run
Section titled “Monitoring a run”warden autopilot status # enabled repos + run state, manager id, task countswarden ls # shows the manager + all worker agentswarden status <manager-id> # full manager detail + eventswarden agent tail <manager-id> # recent manager outputwarden inspect audit # full append-only audit trail of every actionThe TUI cockpit (warden tui) shows each run as a plan-scoped tree — manager
(<scope>-autopilot), guardian (<scope>-guardian), plan checklist, and workers
grouped by ledger state. The web dashboard shows an Autopilot panel when a run
is active. The TUI header has a status badge (press ctrl+a to toggle autopilot
on/off without leaving the cockpit).
Landing a worker branch manually
Section titled “Landing a worker branch manually”The manager calls warden autopilot land automatically when a worker finishes and its PR
is gate-green. You can also call it manually to land a specific worker (e.g.
to bypass a stuck gate, or to pre-land a branch you’ve already reviewed):
warden autopilot land <agent-id> # land by agent idwarden autopilot land <branch-name> # land by branch nameThe land operation is idempotent — landing the same branch twice is a no-op. It fails with an error if:
- The branch is not autopilot-owned (ownership guard)
- The configured gate is not green (
--gate-mode=localbypasses CI and uses the local.warden/check.ymlchecks instead)
Over MCP: land { ticket: "<agent-or-branch>" }.
Reviewing the integration branch
Section titled “Reviewing the integration branch”When the manager has verified the plan’s done_when criteria, it marks the run
complete: the daemon writes an in-place status: complete marker (plus a
completed_at timestamp) into your plan file — preserving your other keys,
ordering, and comments — tears down the manager (in-flight workers keep running),
and retains the ledger. A plan carrying status: complete is skipped by
preflight, so a finished run is never re-run by mistake on a future enable or
daemon restart. To re-run it, remove the status: complete line (or point the
config at a fresh plan file).
The integration branch for a run (default autopilot/<plan-name>; shown in
warden autopilot status as integration_branch) holds all the merged worker
branches — one merge commit per landed task. Runs already on the legacy
autopilot/integration branch keep it across upgrade.
Review the branch, then fast-forward main when you’re satisfied:
git log autopilot/notifications --oneline # example per-plan branchgit diff main..autopilot/notifications
# fast-forward main (after your review)git checkout maingit merge --ff-only autopilot/notificationsgit pushThe integration branch is never merged to main automatically. That step
always belongs to the operator.
Kill switch
Section titled “Kill switch”warden autopilot disable # disable the current repowarden autopilot disable --repo <root> # disable a specific repoDisables the current repository (or --repo <root>); other enabled repos
keep running. Effective immediately, at any state:
- The Controller stops spawning new workers and landing new branches
- In-flight workers keep running to completion (they are not terminated)
- The manager is terminated gracefully
- The ledger is retained —
warden autopilot enablecontinues from where the run left off
Use the kill switch any time you want to pause the run, inspect what workers are doing, or abort a run that is heading in the wrong direction.
CLI reference
Section titled “CLI reference”| Command | What it does |
|---|---|
warden autopilot init [--name <name>] | Scaffold plans/<name>.yaml + config block |
warden autopilot run start <name> | Start a named run |
warden autopilot enable [--repo <root>] | Enable autopilot for this repo (runs preflight first) |
warden autopilot disable [--repo <root>] | Disable autopilot for this repo — the kill switch |
warden autopilot status | Show enabled repos + each run’s state, manager slot id, integration branch, task summary |
warden autopilot land <agent-or-branch> | Land a worker branch into the integration branch |
MCP tools
Section titled “MCP tools”| Tool | What it does |
|---|---|
set_autopilot { enabled: true|false, repo? } | Enable or disable autopilot for a repo (the kill switch); repo defaults to the daemon’s working directory |
autopilot_status | Return enabled repos + each run’s state, manager id, task counts |
autopilot_complete | Manager-only: declare the caller’s run complete once done_when is met (writes the in-place status: complete marker, tears down the manager) |
land { ticket: "<agent-or-branch>" } | Land a worker branch |
Config hot-reload
Section titled “Config hot-reload”The autopilot config block hot-reloads with no daemon restart — edit
~/.warden/config.yaml and the plan/manager/merge template, backend cost ladder,
and guardian heal thresholds re-apply on the next tick, with the per-repo enabled
set left untouched. Adding a plans[] entry starts it; removing one tears down
its run. Only the guardian tick interval still needs a restart. A syntactically
bad edit keeps the last-good config and alerts you. This applies to warden’s
whole config file — see Configuration.
Known limitations
Section titled “Known limitations”- Rate-limit resume and auto-restart are global config toggles (
rate_limit.auto_resume,auto_restart), not per-run overrides via autopilot — configure them in~/.warden/config.yamlfor the backends your manager uses. - Rotate (guardian stage 3) requires more than one free-tier backend to
exercise meaningfully. With only
antigravityin the free tier, the guardian falls back directly to backoff after a restart fails. - The manager picks worker backends itself based on the plan;
Controller.SelectWorkerBackendis exposed but the manager is not required to use it.