Skip to content

Backend registry

Picking a backend per spawn with --aicli is the foreground choice. The backend registry is the durable background picture behind it: warden detects the coding-agent CLIs installed on this machine and remembers, per backend, how it’s billed, whether it’s enabled, and which one is the default.

That store is warden’s single source of truth for backends. It feeds Autopilot’s cost-tier ladder — cheapest-first backend selection for the manager and guardian.

warden’s own internal thinking (task classification, summaries, agent naming, commit messages, digest narration, memory curation, REPL planning) is not driven by the registry: it runs on Fast-Brain, a latency-bounded, fail-open gateway over a headless backend CLI. There is no thinking-mode setting and no reserved local row any more (a legacy PUT /api/v1/backends/thinking-mode is a 200 no-op).

The mental model: detection is a fact, tiering is a preference

Section titled “The mental model: detection is a fact, tiering is a preference”

The registry keeps two kinds of data per backend, and a rescan treats them differently:

KindFieldsOn rescan
Detection (fact)installed, binary_path, detected_atReconciled — newly installed CLIs are added; vanished ones are marked uninstalled
Preference (yours)tier, default, enabledPreserved — a rescan never overwrites your choices

So you can warden backend rescan freely: it refreshes what’s on disk without ever resetting how you tiered things.

The store lives in an embedded ScrivaDB collection at ~/.warden/backends and is managed by the daemon — every surface below is a thin caller of the same /api/v1/backends* endpoints.

How the registry participates in model routing

Section titled “How the registry participates in model routing”

The role and task inputs select a target model tier; the resolver then reads this registry to find a candidate. It requires a model enabled for automatic assignment, an installed and enabled backend, account availability, and a model that is not in a rate-limit cooldown. It ranks eligible candidates by quota headroom, with special preference for safe capacity that resets soon.

For ordinary agent routing, installed and enabled subscription backends are eligible by default; pay_per_use requires explicit allowance. Autopilot’s cost ladder is a separate consumer: it reads installed, enabled registry rows and orders its choices by billing tier. Review the current model assignments with warden models list --by-tier; refresh account-scoped catalog evidence via the model-catalog rollout.

Every detected backend carries a billing tier:

TierMeaning
freeA $0 backend (you run it on a free plan). The cheapest rung of autopilot’s cost ladder.
subscriptionCovered by a flat subscription.
pay_per_useMetered / pay-as-you-go.
unclassifiedNot yet tiered. A newly detected CLI starts here, treated as not free.

A newly detected CLI is unclassified until you tier it, so warden never assumes a backend is free without you saying so.

Terminal window
warden backend list # full table of detected backends (alias: ls)
# ID INSTALLED TIER DEFAULT ENABLED LIMITED
# aider ✓ unclassified - ✓ -
# claude ✓ subscription ✓ ✓ -
# codex ✓ free - ✓ -
warden backend rescan # re-detect installed CLIs (preferences preserved)
warden backend tier codex free # free | subscription | pay_per_use | unclassified
warden backend default claude # set the single default
warden backend enable codex # / warden backend disable aider

warden backend default <id> is rejected for an unknown, uninstalled, or disabled target — the same rules the daemon enforces.

Open the 🧩 backends button in the web AttentionBar (Esc closes it). It’s a table with a Tier dropdown, a Default radio, an Enabled checkbox, and a live Limited countdown per row, plus a header ⟳ Rescan button.

Press b in the TUI cockpit to open the Backends page:

KeyAction
tCycle the focused backend’s tier
d / enterMake it the default
e / spaceToggle enabled
rRescan
esc / bBack

For an orchestrating agent:

ToolDoes
list_backendsThe whole registry + settings (read-only)
rescan_backendsRe-detect and reconcile, return the refreshed registry
set_backend_tierAssign a billing tier
set_default_backendSet the single default

Enabling/disabling a backend is intentionally not an MCP tool — it is available on the CLI, web, and TUI, and over REST as PATCH /api/v1/backends/{id}.

Autopilot’s cost-tier backend ladder and its paid-autopilot gate are derived from this registry: only installed, enabled backends are eligible, bucketed by tier, cheapest first. So the way you steer autopilot’s spending is simply how you tier backends here.

Integrity, single-daemon rule, and offline repair

Section titled “Integrity, single-daemon rule, and offline repair”

The backend registry is opened by exactly one warden process at a time. The daemon takes an exclusive data-directory ownership lock (<data_dir>/.warden-owner.lock) at startup.

Direct CLI operations (wd models, wd role) route transparently through the daemon’s API when the daemon is running, avoiding split-brain writes. When the daemon is stopped, CLI commands take a temporary lock.

If the registry suffers revision regressions or damage:

  • The daemon refuses to start on unresolvable/ambiguous damage with an actionable error pointing to warden repair backends.
  • warden doctor inspects backend registry integrity in read-only mode. Beside a running daemon the persisted index legitimately trails its latest writes (it is persisted lazily), so doctor reports that as clean; only findings that remain with the daemon stopped (warden repair backends --dry-run) call for a repair.
  • warden update preflights registry integrity before swapping binaries.

Offline repair is backup-first, audited, and strictly offline:

Terminal window
# 1. Stop the daemon
systemctl --user stop warden
# 2. Inspect findings without modifying anything (read-only)
warden repair backends --dry-run
# 3. Repair with backup and confirmation (or pass --yes)
warden repair backends
# 4. Restart the daemon
systemctl --user start warden

Each repair takes a verified backup first, removes only provably stale revisions, and writes an audit report. Ambiguous findings are never guessed.

Perishable quota: reset-aware model selection

Section titled “Perishable quota: reset-aware model selection”

When warden picks a backend and model within a tier (initial routing and reactive rate-limit recovery alike), it prefers capacity that is about to reset so subscription quota isn’t wasted. Candidates fall into two classes:

  • Class A — impending resets: quota resets within 1 hour and has at least 10% headroom. Ordered by earliest reset first, then most headroom.
  • Class B — standard: resets further out, already past, unknown, or with under 10% headroom. Ordered by most headroom, with round-robin among ties.

Class A is tried before Class B. The 10% safety floor means a nearly exhausted pool is never prioritized just because it resets soon — that would only cause an immediate rate-limit stall.

Everything warden thinks internally (classification, naming, commit messages, narration) runs on Fast-Brain and is observable without exposing content.

Terminal window
warden inspect fastbrain status # attempts/outcomes per kind and tier, queue, cache, circuits, runners
warden inspect fastbrain decisions # last 200 decisions, newest first
warden inspect fastbrain pause summarize_activity --for 30m
warden inspect fastbrain resume summarize_activity

The cockpit’s F page shows the summary, circuits, per-kind controls (p pause/resume) and recent decisions. The Metrics tab of the web GUI shows the same data: separate Fast-brain and Thinking-brain views with outcome bars and latency percentiles, circuit badges, per-kind pause buttons and a recent-decisions table.

  • Privacy: labels are limited to decision kind, tier, outcome, provider, AI CLI and model. Prompts, terminal content, paths and agent/session IDs never appear in metrics, the decision trace, audit entries or cache keys.
  • Controls fail open: a paused kind returns its deterministic fallback with reason paused and never invokes a runner. Pauses default to 1 hour and are capped at 24 hours; a daemon restart clears them. Each pause/resume and each provider circuit transition is written to the audit log.
  • Persistent disable: list kinds under fast_brain.disabled_kinds in the config file; these never expire. Activity summaries remain disabled by default.
  • Recovery: resume the kind, remove it from disabled_kinds, or restart the daemon.