Model routing for Pi

Pi-Bifrost picks a suitable model for each task.

Bifrost is an extension for the Pi coding agent. It chooses from models you configure before each prompt: fast or low-cost models for routine work, stronger models for hard code, without changing Pi's model by hand.

summarize this file use a faster model
debug this race condition use a stronger model

Routing that remembers failure.

Routing does more than choose a tier. It changes Pi's actual active model before generation, carries model health across restarts, and avoids repeating work that may already have side effects.

New request reaches Bifrost

The prompt enters the classification pipeline. Bifrost first checks its fuzzy Jaccard cache for a similar prompt, then optionally runs an LLM classifier. Regex rules serve as a fallback between the classifier and the default tier.

See route. Change route.

Automation stays in Pi, under your configuration and control.

Preview, pin, or force a tier

Run /bifrost preview before sending. Pin your active model, or prefix one prompt with frontier to override routing once without editing config.

Start from models that respond

/bifrost init probes supported models available through Pi and proposes tier lists from successful results. Review proposal before it writes config.

Choose policy, not hardcoded models

Use cost, context, order, or random selection per tier. Your own Pi registry and configuration determine candidates.

Record useful diagnostics locally

Optional local JSONL debug logs record routing reason, selected tier/model, and timing, not prompt bodies. They are local files, not a hosted observability service.

Avoid repeatedly failing models

After configured repeated failures, Bifrost temporarily skips a model and later allows one recovery trial. It does not replay a failed prompt automatically.

Install

Install package, then let Pi-Bifrost propose a config from models available in Pi. It writes only after your confirmation.

  1. 1
    pi install npm:pi-bifrost
  2. 2
    /bifrost init

Privacy and failure behavior

Classifier scope
The optional classifier receives the complete current prompt, tier names, and classifier instructions. It does not receive conversation history, prior messages, or tool output.
Local data
The cache may store normalized, sorted prompt words in .pi/bifrost-cache.jsonl. Debug logs contain routing metadata, timings, and prompt length, not the prompt body.
Classification failure
Pi-Bifrost tries the next classifier candidate, then regex rules, then the default tier. If nothing resolves, Pi keeps its current model.
Model failure
If no candidate matches or the selected model cannot be activated, Pi keeps its current model. Bifrost also records repeated failures and temporarily skips unreliable models — after a cooldown, it tries them again automatically. Your default tier always works as a fallback.
Credentials
Registry models use credentials managed by Pi. A custom classifier endpoint is treated as an unauthenticated OpenAI-compatible endpoint.

Frequently asked questions

Bifrost caches routing decisions locally, keeps provider caching in the provider layer, and never silently replays your work.

What does Pi-Bifrost's local cache store?

Pi-Bifrost maintains a local routing-classification cache. After a successful classifier result, it saves a normalized prompt and selected tier. Similar future prompts can skip the classifier call and route immediately. It does not store model answers.

The project-local file is .pi/bifrost-cache.jsonl. By default it keeps up to 500 entries, checks exact matches first, then uses token-set similarity, and evicts least-recently-used entries. Use /bifrost cache stats to inspect it or /bifrost cache clear to remove it.

Do I need multiple models?

No. One healthy configured model is enough to start. Multiple models and tiers let Pi-Bifrost choose different candidates for routine, general, and demanding work. /bifrost init shows its proposed configuration before it writes anything.

Does Pi-Bifrost cache assistant answers or replay failed prompts?

No. Your failed prompt is never silently replayed, so Bifrost does not repeat edits, commands, or external side effects. Files, tool output, branch, and user intent can change even when prompt text looks the same.

When a model fails, Pi-Bifrost records it and routes future prompts to healthy candidates instead of silently rerunning your work.

What about provider prompt caching?

Provider prompt or prefix caching belongs to Pi and the selected provider. Pi-Bifrost routes before the turn; it does not claim a universal provider-cache implementation or alter provider billing behavior.

What is stored locally, and can I disable it?

Classification-cache entries contain lowercased, punctuation-stripped, sorted prompt words, selected tier, last-use timestamp, and hit count. They can still contain sensitive terms. Disable caching for sensitive projects with "cache": { "enabled": false }, or choose a different location with cache.path.

Clear the cache after substantial tier or rule changes when you want every prompt classified fresh.

How does model reliability work?

Pi-Bifrost persists probe, model-activation, and settled stream failures in .pi/bifrost-reliability.json. Repeated failures open a circuit, so unhealthy candidates are skipped on later prompts. After cooldown, one half-open trial can prove a model recovered.

Configuration and commands

A tier is a key in models, such as frontier. A route rule uses the property model: its value can be a tier name or an exact provider/id. There is no tier property on a route rule.

Configuration example
.pi/bifrost.json
{
  "enabled": true,
  "default": "general",
  "strategy": "first",
  "categoryStrategies": {
    "quick": "cheapest",
    "general": "first",
    "frontier": "first"
  },
  "models": {
    "quick": [
      "ollama/qwen2.5-coder:latest"
    ],
    "general": [
      "lmstudio/openai/gpt-oss-20b"
    ],
    "frontier": [
      "openai-codex/gpt-5.4",
      "opencode-go/kimi-k3"
    ]
  },
  "rules": [
    {
      "pattern": "\\b(debug|fix|race condition)\\b",
      "model": "frontier"
    }
  ],
  "classifier": {
    "enabled": true,
    "model": "opencode/deepseek-v4-flash-free",
    "method": "auto"
  },
  "reliability": {
    "enabled": true,
    "failureThreshold": 3,
    "windowMinutes": 5,
    "cooldownMinutes": 60
  }
}
Selection strategies
Pi-Bifrost selection strategies
Name Behavior
cheapest Lowest combined input and output cost
cheapest_input Lowest input cost
cheapest_output Lowest output cost
largest_context Largest context window
random Random available candidate
first First available candidate in list order
fastest Alias for first; uses init's one-time probe-sorted list, not live latency measurement
Common commands
/bifrost preview <prompt>
Preview without sending
/bifrost pin / unpin
Pause or resume routing
/bifrost classifier off
Use regex without LLM classification
/bifrost probe
Run availability checks
/bifrost reload
Reload config
/bifrost debug
Print config state and route rules