FifeRouterRouter

One router · many models · decisions you can read

Route each request by the concept it belongs to.

Not by a guess at how hard the prompt looks. Concepts are written down, reviewed in a pull request, and readable by a person — and hard constraints gate before any preference ranks, so no score can outvote a requirement.

Try the playground Read the docs

$ curl -s api.fiferouter.com/v1/explain -d '{"text":"can this retry double-charge the customer?"}'

concept         moneypath.verify
confidence      1.0  (embedding)
objective       quality
eliminated      vendor-frontier — residency
chain           infra-large
chosen          infra-large

The request was classified into a concept, the concept pinned residency to in-infra, the pin eliminated the strongest model in the pool, and what was left is what ran. No provider was called — so a routing change can be reviewed against real phrasing before it ships.

The order is the whole safety story

Filter, then rank, then stick.

Ranking and stickiness are handed the survivor set, never the pool — so a preference has nothing to reach past. It is a property of the call graph, not a rule someone has to remember.

ClassifyExplicit tag → cache → embedding → default. Never refuses.
FilterResidency, capability, context, tier. Removes; never reorders.
RankQuality, cost or latency. Reorders survivors; never admits.
StickOne conversation keeps one model — while it still passes.
DispatchWith a fallback chain, and a log line per attempt.

Four artifacts, kept apart on purpose

Adding a model is a config edit.

It never touches a concept and never requires a retrain. That separation is the entire maintenance story.

Concept catalogue

What kinds of request exist. A description, at least three exemplars, required capabilities, hard constraints. Adding a route is an example sentence.

Pool

What can be reached, and on what terms — residency, tier, context window, capabilities, price. Adding a model is a row.

Policy table

Concept → ranked candidates plus one objective. The ranked list is also the fallback chain.

Decision log

One record per model attempt — fallbacks, refusals and errors included. Routing metadata only, never prompt or response content.

Explainable, or it doesn't ship

Every choice leaves a record.

It names what served you

The response's model field is the model that actually ran, not the one you asked for. A router that reports the request rather than the result is unauditable.

Refusals are typed

402 for a spend cap — never a quiet downgrade to something cheaper. 422 when hard filters leave nothing compliant. 502 when the chain is exhausted.

Your prompt stays out of it

The decision record is a closed set of typed fields with no free-form extra. Leaking content would take a deliberate schema change, in a diff a reviewer would see.

See it decide.

Type a request. Watch it get classified, watch the filters eliminate models, and see what it would route to — without spending a token.

Open the playground