Skip to content

Backend registry reference

The agent-backend registry is warden’s persistent, machine-wide record of which coding-agent CLIs exist, how they’re billed, and which is the default. For the narrative and the mental model, see the Backend registry guide; this page is the flat reference.

One record per backend (keyed by its stable id) plus a reserved settings singleton, in an embedded ScrivaDB collection at ~/.warden/backends.

FieldTypeNotes
idstringStable id (claude, codex, aider, …, and the reserved local)
installedboolBinary found on PATH (or, for local, the endpoint reachable) — detection fact
binary_pathstringResolved LookPath (empty for local) — detection fact
detected_attimestampLast reconcile — detection fact
tierstringfree | subscription | pay_per_use | unclassified | localpreference
defaultboolAt most one row is truepreference
enabledboolWhether the backend may be used — preference
is_localboolThe reserved local-model row (never limited, never a default)
limited_untiltimestampRouter-stamped rate-limit expiry; always zero when is_local

Detection fields are reconciled by a rescan; preferences are preserved by a rescan.

FieldTypeNotes
internal_thinking_modestringlocal_only | free_plus_local (default)
allow_paid_autopilotboolThe paid-autopilot gate (migrated from autopilot.brain.allow_pay_per_use)
TierMeaningRouter calls it?
free$0 backend (free plan)✅ (the only CLI tier the router calls)
subscriptionFlat subscription
pay_per_useMetered / pay-as-you-go
unclassifiedNot yet tiered (a newly detected CLI); treated as not free
localReserved, system-set (the local row only)✅ (terminal candidate)
ModeCandidate walk
local_only[local]
free_plus_local (default)[eligible free CLIs (default-first, then stable id), …, local]

A free CLI backend is eligible only when installed && enabled && tier == "free" && limited_until is in the past. Paid (subscription / pay_per_use), unclassified, and disabled backends are never in the walk. When the walk is exhausted, the caller degrades gracefully — warden never escalates internal thinking to a paid backend.

  • local — a $0, never-limited, never-default class for the local model. Its tier is the system-set local; the terminal candidate of every internal-thinking walk.
CommandDoes
warden backend list (alias ls)Print the registry table (ID, installed, tier, default, enabled, limited) + the thinking mode
warden backend rescanRe-detect installed CLIs, reconcile detection, preserve preferences
warden backend tier <id> <tier>Assign a tier (free|subscription|pay_per_use|unclassified)
warden backend default <id>Set the single default (rejects unknown/uninstalled/disabled/local)
warden backend enable <id>Enable a backend
warden backend disable <id>Disable a backend
warden backend thinking-mode <mode>Set local_only | free_plus_local

The generated CLI reference has the full flag/help detail.

warden usage asks the daemon for provider-owned usage data from every persisted row whose tier is exactly subscription. Disabled and uninstalled rows remain in the result; the read never rescans the registry or changes routing, cooldowns, or the default backend. Use --json for the stable v1 document and --refresh to bypass the daemon’s 60-second fresh cache.

Each backend has a usage array containing zero or more distinct limits, sorted by stable id. Every limit includes id, applicability scope, a human label, nullable used_percent and resets_at, plus nullable model_families and models selectors. Multiple provider pools are never flattened: Codex primary/secondary windows remain separate, and an adapter that can safely identify Gemini and non-Gemini pools returns separate scoped entries. Unknown measurements, restore times, or model selectors remain JSON null; warden never guesses them.

Codex supplies structured percentage limits and reset times through its app-server protocol. Cursor supplies three never-flattened windows (included, auto, api) from POST https://api2.cursor.sh/aiserver.v1.DashboardService/GetCurrentPeriodUsage using the local cursor-agent login token — the same RPC as the feature-flagged CLI /usage pager. There is no cursor-agent usage subcommand; warden does not scrape the TUI or invent percents from spend cents. Antigravity supplies two never-flattened windows (gemini and non-gemini) from POST https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels using the local agy OAuth credentials. Claude supplies a single session (five_hour) window — used_percent and resets_at — from GET https://api.anthropic.com/api/oauth/usage (the endpoint the claude CLI’s /usage pager uses), authenticated with the local Claude Code OAuth access token and degrading gracefully to one null-percentage row when the endpoint is unreachable. Warden deliberately does not substitute its local synthetic quota estimates. Account labels, credentials, raw provider output, paths, and request IDs are excluded. An API-key-only Cursor login (no auth.json access token) still emits the three Cursor limit rows with used_percent: null.

The command exits 0 when every row is ok or truthfully unsupported, 2 after rendering a partial result with an operational provider failure, and 1 when no consolidated document can be produced.

{
"id": "cursor",
"status": "rate_limited",
"usage": [
{"id": "cursor:api", "scope": "api", "label": "API", "model_families": ["claude", "gemini", "glm", "gpt", "kimi"], "models": null, "used_percent": 100, "resets_at": "2026-10-01T18:31:27Z"},
{"id": "cursor:auto", "scope": "auto", "label": "Auto", "model_families": null, "models": ["auto"], "used_percent": 4.09, "resets_at": "2026-10-01T18:31:27Z"},
{"id": "cursor:included", "scope": "included", "label": "Included", "model_families": ["composer", "cursor-grok"], "models": null, "used_percent": 8.87, "resets_at": "2026-10-01T18:31:27Z"}
]
}

status is ok when every bar is below 100, or rate_limited when any window is at the cap (recovery still ranks Composer/Grok/auto on their own headroom). Omitted percents stay JSON null — they are never defaulted to 0.

{
"id": "antigravity",
"status": "ok",
"usage": [
{"id": "antigravity:gemini", "scope": "gemini", "label": "Gemini models", "model_families": ["gemini"], "models": null, "used_percent": 50, "resets_at": "2026-09-01T12:00:00Z"},
{"id": "antigravity:non-gemini", "scope": "non-gemini", "label": "Non-Gemini models", "model_families": null, "models": null, "used_percent": 0, "resets_at": "2026-09-01T16:00:00Z"}
]
}

The Antigravity adapter maps live quota fractions from the provider models API into antigravity:gemini and antigravity:non-gemini windows with exact reset times.

ToolArgsReturns
list_backends{backends[], settings} (read-only)
rescan_backendsThe refreshed {backends[], settings}
set_backend_tier{id, tier}The updated backend
set_default_backend{id}The refreshed {backends[], settings}
set_thinking_mode{mode}The updated settings

Enable/disable is not an MCP tool — use the CLI, web, TUI, or REST PATCH /api/v1/backends/{id}.

Method + pathPurpose
GET /api/v1/backendsThe registry + settings (read-only)
GET /api/v1/usage?refresh=trueProvider usage for exact subscription-tier rows (read-only)
POST /api/v1/backends/rescanRe-detect and reconcile; returns the registry + settings
PUT /api/v1/backends/default{id} → set the default; returns the registry + settings
PUT /api/v1/backends/thinking-mode{mode} → set the thinking mode; returns settings
PATCH /api/v1/backends/{id}{tier?, enabled?} → update one backend (both fields optional)

See the OpenAPI reference (/api/docs) for the full schemas.

KeyDefaultDescription
backends.limit_retry15mGo duration — how long the internal-thinking router skips a free CLI backend after a rate-limit / spend signal, before retrying it

Tiers, the default, enabled flags, and the thinking mode live in the store, not the config file — edit them via the surfaces above.

Autopilot’s cost-tier ladder and paid-autopilot gate derive from the registry: only installed, enabled, non-local rows are eligible, bucketed by tier. The deprecated autopilot.brain.backends.{free,subscription,pay_per_use} ladder and autopilot.brain.allow_pay_per_use gate are imported once on the first boot after upgrade (sentinel-guarded, idempotent) and then ignored — the store is authoritative, and the daemon logs a deprecation warning if the config still carries them. See the Autopilot concepts page.