Decisioner (Jev pre-router)

An optional pre-router on a chat-shaped key: Jev picks which of the attached targets should serve the request — and optionally which model — before the static routing rule runs. The static rule is the fail-open fallback.

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.

Fail-open by design If Jev times out, 5xxs, returns low confidence, or cannot pick — or if the key has only one target — FreeRouter serves the request as if the decisioner were off. The inbound model through the existing rule is the fail-open path.

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), or efficiency (cheap path for simple prompts, capable path for hard ones).
  • Catalog prices and context windows come from the crawled fr_gateway_models table (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 systemone key is already a Decisions key — it does not take a chat decisioner. Call Jev directly with POST /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.

FieldMeaning
provider_key_idThe UUID of a TypeSafe, OpenRouter, Requesty, Vercel, or Ramp Router provider key.
objectivecost, capability, or efficiency; default cost.
allow_model_overrideLet 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_mA 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.
notesJev-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.

Next System One shape