Set Up Looping
Turn on the self-improving loop — bind a policy to a preset, let the adequacy signal learn from live traffic, and fold what it proves back into the policy spec.
This is the page that closes the act → observe → evaluate → learn cycle. The router acts on a policy spec, telemetry observes every hop, the adequacy signal evaluates each route — and here you wire the learn step, so proven improvements get written back into the spec. It assumes you've set up routing and have a preset in mind.
The artifact at the center is policy-lock.yaml — the current effective policy, living next to bitrouter.yaml. Git owns its history; the local database owns the evidence.
1. Create the policy
One command scaffolds everything:
bitrouter policy init coding --preset coding \
--economy moonshotai/kimi-k2.7-codeThis writes policy-lock.yaml with a two-tier table (strong = your preset's model, economy = the cheap model), clamps tool-carrying requests to the strong tier so a downgrade never strands a tool call, pre-seeds adequacy learning, and edits bitrouter.yaml to bind the policy to the preset with writeback: locked:
# bitrouter.yaml (edited by policy init)
presets:
coding:
model: anthropic/claude-opus-4.8
policy: coding
policy:
writeback: locked2. Route traffic through it
Select the preset as the model — that's the entire opt-in boundary. Bare model requests are untouched by policies:
curl http://127.0.0.1:4356/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "@coding", "messages": [{"role": "user", "content": "..."}]}'Each request is fingerprinted by loop step (opening, after_<tool>, midstream) and routed per the table. Right now every fingerprint routes strong — the table starts conservative.
3. Learning runs automatically
With adequacy enabled, the daemon learns online from the eval signal — no LLM, no randomness, a deterministic trial cadence:
- Escalation (the safety half) — a downgraded fingerprint that hard-fails
escalation_thresholdconsecutive times is pinned up to the strong tier. Pins decay after a cooldown. - Exploration (the aggressive half) — with
explore_enabled, roughly 1-in-explore_intervalcandidate requests is trialed on the economy tier;explore_thresholdconsecutive adequate trials qualify the fingerprint for the cheap tier. A failed trial escalates and stops.
# policy-lock.yaml
adequacy:
enabled: true
escalation_tier: strong
explore_enabled: true
explore_tier: economy
explore_threshold: 34. Fold learning back into the spec
Qualified downgrades live in the database until you publish them. The publish cycle is explicit and digest-checked:
bitrouter policy status # path, digest, writeback mode, bindings
bitrouter policy evolve # dry-run: which routes would materialize
bitrouter policy unlock # permit programmatic writeback
bitrouter policy evolve --apply # atomically republish policy-lock.yaml
bitrouter policy reload # daemon picks it up — no restart
bitrouter policy lock # forbid programmatic writes againevolve --apply only adds qualified routes — it never overwrites or removes anything you or Git wrote, and a detected intervening edit aborts the publish instead of clobbering it. Commit the result and the improved table is in Git, where a policy belongs. Run the cycle on whatever cadence suits you — by hand, from cron, or from an agent you trust with unlock.
Next steps
How is this guide?