Decisioner (Jev pre-router)
What the decisioner does
On a chat-shaped key (openai / openrouter / anthropic / google), you can pick one decisioner: a TypeSafe, OpenRouter, Requesty, Vercel, or Ramp Router provider key. Before the key's routing rule runs, FreeRouter asks Jev which of the attached targets should serve this request. Optionally, Allow Decisioner to pick a model lets Jev choose a listed model on those hosts and override the inbound model; the inbound model through the static rule is the fallback if Jev cannot pick. The client still sends a chat completion and still receives one — Jev is a side-channel, not the served model.
How it picks
- By default the Choice options are the backends already on the rule, for the inbound model. Jev does not invent a model id. Turn on Allow Decisioner to pick a model and use Select models to curate up to 12 model ids. Jev may pick only those ids, on every attached chat gateway that lists them. An empty list does not override. Keys saved before this control still use an automatic catalog shortlist until you save a selection. The inbound model is the fallback.
- When Decisioner is on, pick Optimize for:
cost(cheapest listed $ / million tokens — default),capability(listed model, context window, stronger remap when the prompt is hard), orefficiency(cheap path for simple prompts, capable path for hard ones). - Catalog prices and context windows come from the crawled
fr_gateway_modelstable (cached). A missing price is unknown, never $0. If every target is unpriced on a cost key, Jev is skipped (no_facts) and the static rule runs. - When cost is unique and listed, FreeRouter picks that target in code and does not call Jev. Jev is for ties, missing prices, and request-shaped questions (how hard is this prompt?).
- A confident pick is tried first. When a model was picked, that pair is the first hop (remaps do not steal it). If the pick errors retryably, the remaining targets fail over through the inbound model and remaps as usual.
- A pinned Responses chain skips the decisioner: a follow-up turn has to go back to the gateway that holds the state.
Which provider keys can decide
- A TypeSafe, OpenRouter, Requesty, Vercel, or Ramp Router provider key can be the decisioner (Cloudflare and OpenAI cannot — the decisioner runs Jev). See which host carries which model.
- TypeSafe provider keys are Decisions-only and never appear as chat targets. Until you have a TypeSafe invite, an OpenRouter provider key is a complete decisioner.
- A
systemonekey is already a Decisions key — it does not take a chat decisioner. Call Jev directly withPOST /v1/systemone.
Seeing what Jev did
Logs show Jev → gateway when it picked a backend, or Jev → gateway / model when it overrode the inbound model, or Jev skipped · … when it could not. The same verdict rides every response as the X-FreeRouter-Decisioner header — pick:<gateway>;model:…;choice:…;conf:…;p:…;obj:cost on a pick, skipped:<reason>;obj:… on a skip (single_target, no_facts, low_confidence, jev_error, over_budget, …); see the response headers. The routing diagram on the Routing Rules tab draws the decisioner as the first step of a key's rule.
Configuring it
Configure it on the key card, on PUT /api/v1/keys/:id/routing as decisioner: { provider_key_id, objective?, allow_model_override?, max_usd_m?, notes?, models? }, or with the MCP set_routing tool. Omit it (or send empty) to turn it off — a routing write replaces the whole rule.
| Field | Meaning |
|---|---|
provider_key_id | The UUID of a TypeSafe, OpenRouter, Requesty, Vercel, or Ramp Router provider key. |
objective | cost, capability, or efficiency; default cost. |
allow_model_override | Let Jev override the inbound model. With models, an explicit list of model ids (max 12); omit models to keep the auto shortlist, send [] to not override. |
max_usd_m | A listed prompt+completion ceiling in $ per million tokens; a number above 0. When no target lists a price under it, Jev is skipped (over_budget) and the static rule runs. |
notes | Jev-only preferences, max 500 characters. |
Operator flag
Operators gate this with FR_DECISIONER_ENABLED=1 on both the api and app processes (unset or 0 leaves chat routing as it was; saved decisioner config is kept but not used). systemone keys and POST /v1/systemone are not gated.