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.
Data model
Section titled “Data model”One record per backend (keyed by its stable id) plus a reserved settings singleton,
in an embedded ScrivaDB collection at ~/.warden/backends.
Backend row
Section titled “Backend row”| Field | Type | Notes |
|---|---|---|
id | string | Stable id (claude, codex, aider, …) |
installed | bool | Binary found on PATH — detection fact |
binary_path | string | Resolved LookPath — detection fact |
detected_at | timestamp | Last reconcile — detection fact |
tier | string | free | subscription | pay_per_use | unclassified — preference |
default | bool | At most one row is true — preference |
enabled | bool | Whether the backend may be used — preference |
is_local | bool | Deprecated — the reserved local row is pruned; always false |
limited_until | timestamp | Rate-limit expiry stamped on a spend / limit signal |
Detection fields are reconciled by a rescan; preferences are preserved by a rescan.
Settings singleton
Section titled “Settings singleton”| Field | Type | Notes |
|---|---|---|
internal_thinking_mode | string | Deprecated, ignored — thinking-mode was retired with the local router; internal thinking runs on Fast-Brain |
allow_paid_autopilot | bool | The paid-autopilot gate (migrated from autopilot.brain.allow_pay_per_use) |
| Tier | Meaning |
|---|---|
free | $0 backend (free plan) |
subscription | Flat subscription |
pay_per_use | Metered / pay-as-you-go |
unclassified | Not yet tiered (a newly detected CLI); treated as not free |
Internal thinking
Section titled “Internal thinking”warden’s own micro-cognition (classify, summarize, naming, commit messages,
curation, digest/insights narration, REPL planning) runs on Fast-Brain
(internal/fastbrain) — latency-bounded and fail-open — not on a registry walk. The
former thinking-mode, the reserved local row, and the local-LLM/Ollama provider are
retired; local_llm.* YAML keys still parse but are ignored.
CLI — warden backend
Section titled “CLI — warden backend”| Command | Does |
|---|---|
warden backend list (alias ls) | Print the registry table (ID, installed, tier, default, enabled, limited) |
warden backend rescan | Re-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) |
warden backend enable <id> | Enable a backend |
warden backend disable <id> | Disable a backend |
The generated CLI reference has the full flag/help detail.
Subscription usage — warden usage
Section titled “Subscription usage — warden usage”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
pool buckets (antigravity:gemini and antigravity:non-gemini) from
POST https://daily-cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary
using the local agy OAuth credentials — the same RPC as the agy /usage TUI.
Each bucket reports its 5-hour session limit while its weekly limit still has
headroom, and flips to the exhausted weekly limit (100% used, reached, weekly
duration and reset) once that pool’s weekly bucket is drained.
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": "rate_limited", "usage": [ {"id": "antigravity:gemini", "scope": "gemini", "label": "Gemini", "model_families": ["gemini"], "models": null, "used_percent": 100, "duration_minutes": 300, "resets_at": "2026-09-05T21:40:45Z", "limit_state": "reached"}, {"id": "antigravity:non-gemini", "scope": "non-gemini", "label": "Non-Gemini", "model_families": null, "models": null, "used_percent": 0, "duration_minutes": 300, "resets_at": "2026-09-06T01:04:38Z"} ]}The Antigravity adapter maps retrieveUserQuotaSummary buckets into two pool
buckets (antigravity:gemini and antigravity:non-gemini). Each bucket reports
its 5-hour session limit (usage % + reset) while its weekly limit still has
headroom; once the pool’s weekly limit is exhausted the bucket reports the weekly
limit fully consumed (100% used, reached, duration_minutes: 10080, weekly
reset) — matching how agy /usage gates the 5-hour window under the weekly cap.
MCP tools
Section titled “MCP tools”| Tool | Args | Returns |
|---|---|---|
list_backends | — | {backends[], settings} (read-only) |
rescan_backends | — | The refreshed {backends[], settings} |
set_backend_tier | {id, tier} | The updated backend |
set_default_backend | {id} | The refreshed {backends[], settings} |
set_thinking_mode | {mode} | Deprecated no-op — returns the current settings |
Enable/disable is not an MCP tool — use the CLI, web, TUI, or REST
PATCH /api/v1/backends/{id}.
REST endpoints
Section titled “REST endpoints”| Method + path | Purpose |
|---|---|
GET /api/v1/backends | The registry + settings (read-only) |
GET /api/v1/usage?refresh=true | Provider usage for exact subscription-tier rows (read-only) |
POST /api/v1/backends/rescan | Re-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} → deprecated 200 no-op; 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.
Config
Section titled “Config”| Key | Default | Description |
|---|---|---|
backends.limit_retry | 15m | Go duration — how long a free CLI backend is skipped after a rate-limit / spend signal, before retrying it |
Tiers, the default, and enabled flags live in the store, not the config file — edit them via the surfaces above.
Autopilot ladder & deprecated config
Section titled “Autopilot ladder & deprecated config”Autopilot’s cost-tier ladder and paid-autopilot gate derive from the registry: only
installed, enabled 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.