Document bitrouter.yaml and pivot to config-forward - #61
Merged
Conversation
The whole declarative surface was undocumented. `presets:` never appeared
as a YAML key on any page, `routing:` and `variants:` likewise, and
`policy_table:` — tiered per-request routing with a tool guardrail and
online adequacy learning — had zero coverage anywhere. Routing concepts
were documented API-first, so a reader who wanted routing in git had
nowhere to land.
Add `usage/configuration.mdx`: discovery order, the published JSON
Schema, `${VAR}` substitution, every top-level block, the policy table,
the adaptive loop, and `config validate` in CI.
The thesis is routing as code, and the differentiated half is that the
policy is not inert. `policy.writeback` defaults to `locked`, so the
router observes and proposes; `bitrouter policy evolve` prints a
dry-run and `--apply` publishes. You read the diff and commit it — the
same review path as any other change. That is the part LiteLLM's
config.yaml has no answer to, and it happens to be exactly what was
undocumented.
Pivot the positioning to match:
- migrate-from-tensorzero claimed "no schema to maintain" as an
advantage. That is no longer the line we want and was misleading
anyway — there is a schema, it is published, and it validates in CI.
Recast the difference as one of degree: BitRouter is also configured
as code, it just doesn't make you declare the shape of your
application before you can route a request.
- migrate-from-litellm mapped `model_list` onto "provider keys +
routing presets" with no config file in sight. Point both it and the
fallback paragraph at the actual file.
Also corrects virtual-model.mdx, which said `@name` is a Cloud
namespace feature and self-host gets `models:` instead. Verified
otherwise against the binary: `presets:` in bitrouter.yaml resolves
`@name` locally (`bitrouter route "@fast"` substitutes the preset's
model), and `models:` is a separate feature — a named alias over an
ordered endpoint chain, not invoked with `@`. The two were conflated.
Verified: every YAML example on the page validates as one combined
config against the real binary (valid, 2 presets, 1 variant); the
documented validate contract is empirical — exit 0 with counts, exit 1
with a line/column parse error, and unset `${VAR}` reported under
warnings WITHOUT failing, so CI can check shape without production
keys; the schema at the documented URL contains every key used; all 13
outbound links return 200 and all 5 anchors resolve.
Both PRs added a page to `usage/`, so the section list and CONTRIBUTING's inventory conflicted. Both resolutions are additive — neither side was replacing the other. Nav order is cli · tui · configuration · mcp · skills: the two surfaces you run, then the file they read, then the two agent-facing ones. Verified after merging: lint 49 docs / 6 sections, now including the GitHub-alert rule main gained in #60 — the configuration page uses <Callout> throughout and passes it; 83/83 tests; all five Usage pages plus the two edited pages return 200.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
usage/configuration.mdxand moves the positioning from "no config to maintain" to config-forward.Why
The declarative surface was undocumented. Coverage audit against
content/docs/:bitrouter.yamlblockpresets:(@name)variants:(:name)routing:(sort/only/ignore/require_tags)policy_table:policy:/policy-lock.yamlRouting was documented API-first and console-first, so a reader who wanted routing in git had nowhere to land.
The page
usage/configuration.mdx— discovery order, the published JSON Schema,${VAR}substitution, every top-level block, the policy table, the adaptive loop, andconfig validatein CI. Titled Configuration so it sits correctly beside CLI / MCP / Skills and doesn't overclaim (the file also holdsserver:,database:,mcp:), with Routing as code as the opening thesis and a named section anchor.The differentiated claim is that the policy isn't inert.
policy.writebackdefaults tolocked, so the router observes and proposes rather than writes;bitrouter policy evolveprints a dry-run and--applypublishes. You read the diff and commit it — the same review path as any other change. Adequacy escalation un-does downgrades that fail in production; exploration (off by default, and flagged as genuinely aggressive) finds safe downgrades instead of making you guess them. That's the part LiteLLM'sconfig.yamlhas no answer to, and it's exactly what had no docs.The page owns the file;
virtual-model.mdxandmodel-variants.mdxkeep owning the behavior, so semantics aren't duplicated.Positioning pivot
model_listonto "provider keys + routing presets" with no config file in sight. Both it and the fallback paragraph now point at the actual file.A correction this surfaced
virtual-model.mdxsaid@nameis a BitRouter Cloud namespace feature and that self-hosting getsmodels:instead. That's wrong. Verified against the binary:@fastresolved from the localpresets:block and substituted the preset's model — it only failed because the test provider doesn't serve that model.presets:works self-hosted; Cloud adds the managed lifecycle (namespaces, enable/disable, therouting-presetsendpoints), not the grammar. Separately,models:is a different feature — a named alias over an ordered endpoint chain, not invoked with@— and the page conflated the two. Both fixed.Verification
valid: true, 2 presets, 1 variant.validatecontract is empirical, not inferred — exit0with counts; exit1with a line/column parse error; an unset${VAR}reported underwarningsand not fatal, which is what lets CI check shape without production keys.policy_tableand theexplore_*block.pnpm lint:docsOK, 48 docs / 6 sections.#routing-as-code,#the-policy-table,#the-adaptive-loop,#validate-in-ci, andcli#policy) resolve.One thing for a follow-up, in the other repo
The schema ships at
dist/schema/bitrouter.config.schema.jsonand declares:bitrouter.devis NXDOMAIN — the domain doesn't resolve, andbitrouter.aiserves 404 there. This page therefore documents the raw GitHub URL, which is live and follows the patternDEFAULT_REGISTRY_URLalready uses for the registry. Worth either servingdist/schema/from bitrouter.ai or changing the$idinhelpers/dist-helper/src/schema.rs— a two-line fix that needs no infra.🤖 Generated with Claude Code