Skip to content
MrJev

pi-jev-router

Ranks the OpenRouter catalogue per task, takes the Pareto frontier over quality, cost and latency, and routes pi to the knee point.

View on GitHub →

Hands-on review

Five typed questions about a task, then a Pareto frontier over the OpenRouter catalogue picks the model. Shadow mode is the default.

Good for

  • Choosing a model per task without hand-tuning a weight file
  • Recommend-only by default, with routing as an explicit opt-in
  • A classifier failure that degrades to a fallback table rather than stopping

Watch out for

  • The whole task envelope goes in the state, including the context you attach
  • It will read the OpenRouter key out of `~/.pi/agent/auth.json` if the env var is unset
  • No CI, and the benchmark numbers are one author's run on one day

Tested Sep 21, 2026 at b9650e680795 · node:24 in Docker; its own test suite, and the shipped classifier driven against a local stand-in with one patched constant, reverted and diffed

How we reviewed this: we ran the test suite in node:24, then drove the shipped classifier against a local stand-in of ours by patching the one base-URL constant — reverted and diffed afterwards — and forced the two failure paths. We made no Jev calls.

What it does

A pi extension that picks which OpenRouter model should do each task. One batched request asks Jev five questions about the work item — category (a seven-way choice), complexity and risk (four-level scores), brief (sufficient / inspect / clarify) and decompose (a noul) — and the answers become inputs to a selection policy, not the decision itself.

The selection is the interesting half. It ranks the whole OpenRouter catalogue, filters to models that fit the task, computes a Pareto frontier over quality, cost and latency, and takes the knee — the frontier member farthest from the chord joining the cheapest and dearest. As the README puts it, that needs no weights, so the pick follows the catalogue and the recorded evidence rather than a tuning file someone has to maintain. When the frontier is too small or too flat for a knee, a weighted value function takes over.

AGENTS.md states the rules the code actually follows, and the first one is the right one:

  1. Jev output is evidence, not truth. Never treat a Jev answer as a guarantee of task success.
  2. Never route mid-tool-call. Route only at task, subtask, and retry boundaries.
  3. Never trust a worker’s self-report. Run the verifier. Read the exit code.

Default mode is shadow — it recommends and logs, and you opt into auto for it to actually switch models.

What we ran

npm test passes: six files of pure-function tests covering the frontier maths, selector behaviour, catalogue normalisation and role routing. The assertions are the ones you would want — three-point frontier picks the knee, empty catalog falls back, relaxes proven gate when nothing qualifies, classifier down still selects, writing is the most cost averse.

Driving the real classifier against our stand-in, one request carried all five questions:

{"model": "typesafe/jev-1.13",
 "state": {"taskId": "t-1", "role": "implementer", "objective": "…",
           "acceptanceCriteria": ["…"], "relevantContext": "…", "facts": {…}},
 "questions": {"category": …, "complexity": …, "risk": …, "brief": …, "decompose": …}}

Answers are validated on the way back rather than trusted: a non-finite score or an invalid probability map drops that answer instead of poisoning the selection, and ok is false when nothing survives.

Both failure paths behave:

what we did result
stand-in returns HTTP 503 ok: false, classifierUnavailable: true, error recorded, 51 ms
no key anywhere ok: false, classifierUnavailable: true, “OPENROUTER_API_KEY not set”, 0 ms

In both cases the selector still returns a model from its fallback table — which is what the classifier down still selects test asserts, and what you want from a router: a slow or missing classifier should cost you a better pick, not the task.

What leaves your machine

The state is the whole task envelope: objective, acceptance criteria, relevantContext, and a facts block with repository, branch and file list. We planted a canary string in relevantContext and it went out, as it must — that field is the context you chose to attach. The thing to know is that there is no separate summarisation step before the request: what you put in the envelope is what the classifier sees. (summarizeEnvelope exists, but it is for display and logging — role plus objective, one line — and the comment says so: “never full history”.)

The key comes from OPENROUTER_API_KEY, or, failing that, out of ~/.pi/agent/auth.json. Reading pi’s own credential file is the convention for a pi extension and saves a duplicate key, but it is worth knowing that installing this extension gives it your pi OpenRouter token.

The classifier is pinned to typesafe/jev-1.13 and runs through OpenRouter, so it is billed on the same account as the models it routes to, with one overall deadline and maxRetries: 0 — no hidden retry cascade behind a timeout.

Maintenance

MIT, one author, active on 20 September, with AGENTS.md scoping the project tightly (“Do not add a server, a dashboard, or an MCP layer”). There is no .github directory, so the tests do not run anywhere but your machine.

eval/ holds a benchmark harness and one recorded run from 20 September with its report. Those are the author’s numbers on the author’s account, and the quality inputs are third-party indices — Artificial Analysis for general models, EQ-Bench Creative Writing Elo for prose, which is a more careful distinction than most routers make. We did not reproduce them.

Verdict

The most principled model router we have looked at: the model answers questions about the task, a documented policy turns those answers into a pick, and the two are separate files with the boundary written down. Shadow-by-default and a fallback table that survives a dead classifier are the details that make it safe to try.

Read AGENTS.md before you install it — it is the clearest statement of intent in this batch — and decide whether you want an extension holding your pi OpenRouter token.

For routing between Claude models instead, see jev-router; for routing between capabilities rather than models, JevRouter.

See how it compares with other tools in Best Jev tools, tested hands-on.

Review updated Sep 21, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.

More in Model Routing

jev-router

★ 650▲ 24

gargpratyush/jev-router

Per-turn model routing for Claude Code and Codex. Simple work goes to the fast tier and difficult work to the strong tier.

JavaScriptReviewed

JevRouter

★ 466

BillionsBobby/JevRouter

Routes each agent step to a model, subagent, Skill, MCP tool, or CLI with one Jev Choice, requiring confirmation for risky capabilities and keeping decision receipts.

TypeScriptReviewed

HiRoute

★ 371▲ 20

higress-group/HiRoute

Local-first routing and coordination engine for long-running agent work, with a jev-decider extension that routes on typed decisions.

Rust

Get new Jev projects every week

New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.

Powered by Buttondown. See our privacy policy.