Skip to main content
Most applications should use createRouter. Import @mupt-ai/dari-router/policy-engine only when your host must inspect routing evidence, call a selector itself, persist routing state, or coordinate selection with other work. The policy engine is the advanced deterministic core beneath createDariRoutingPolicy. It works with a different vocabulary than the framework: candidates are model/reasoning-level pairs keyed by model (not id), and inputs use wire-style names like thinking_level, prefix_hits, and tool_choice_fp.

Prepare, select, finalize

prepareRoute() performs deterministic candidate resolution and builds the selector request. Your host calls the selector. finalizeRoute() validates the selector output against the prepared candidates.
The input is deliberately explicit. The policy engine does not read credentials, environment variables, databases, or a clock. Supply model metadata, pricing, conversation state, and timestamps from your host. route(input, selector) composes the two phases when you do not need an interleaving point. Most fields have straightforward meanings. chainsByModel and prefixHits describe the conversation’s prompt-cache history: which provider-cache blocks are already warm, so cost estimates can price a cached read instead of a full write. toolChoiceFp and responseFormatFp are fingerprints of the last tool-choice and response-format settings; a change there invalidates prompt-cache continuity, so the engine prices the tail differently.

Evidence and state

The prepared result exposes resolved model/reasoning pairs, cache-aware cost estimates, pruning decisions, recovered decisions, warnings, and the exact selector request. Unknown pricing remains unknown rather than becoming zero. Hosts can persist and later provide chainsByModel, prefixHits, and previous decisions. Those values describe provider-cache continuity (whether a provider can read previously seen prompt blocks from cache instead of paying for them again); they are not a replacement for application conversation storage. Prompt Caching explains how this routing evidence differs from provider usage and selection leases.

Selector output and fallback

The selector returns JSON containing selected_model, reasoning_effort, and reason. finalizeRoute() requires the selected pair to be among prepared candidates. The prepared fallback configuration can produce a validated fallback decision; executing it and reporting usage remain host responsibilities.

Anonymous selection

The policy engine also supports training/evaluation flows where the selector input hides which real model each option is: candidates are replaced by shuffled action labels (for example A, B, C) so the selector scores the option, not the brand:
Use a seeded random source for reproducible datasets. Anonymous selection is for selector training and evaluation, not a requirement for ordinary routing. The complete no-network example is dari-router/examples/basic_route.ts.