v0.2 · MCP server + CLI · MIT
Two AI agents are given the same task at the same moment, played back at 4× speed. jev-ra is the one your coding agent calls: it finishes, and goes again, while the other is still working.
Played at 4× speed; the clocks show the measured seconds (2026-09-18, one machine, one Chrome, both through OpenRouter). jev-ra's total is the median of 5 verified runs; browser-use's is its single recorded run, which was faster than its own 5-run median. browser-use's steps are drawn evenly across its measured total. Raw rows in BENCHMARKS.md.
The browser draws this from the log of one Google Flights run made on 2026-09-18. Each click, typed value and timing comes from that log. It is not a video.
Source: demo.js (a dependency-free SVG replayer) fed by demo-run-flights.json. Raw screen recordings of the benchmark tasks are in assets/demo/.
Each step is five operations. The only network call is one request to Jev with typed questions. jev-ra builds no prompt and generates no text, and model output is never used as a selector or as script.
Wall time divided by steps on the Wikipedia task, 2026-09-18, both through OpenRouter: browser-use's recorded run, 23.1 s / 4, against jev-ra's 5-run median, 2.7 s / 2. A jev-ra step is a Jev decision (253-380 ms in the Flights run recorded that day) plus the page's own load and settle time.
Jev is a decision model. jev-ra sends the page as state with five typed questions and gets back a chosen option with probabilities and two yes/no answers with confidence. A decision cost $0.00023 on average through OpenRouter on 2026-09-18 ($0.0068 for the 30 decisions of the five recorded tasks), and there is no prose to parse.
request · state + questionsPOST /decisions
answers · 312 mstypesafe/jev-1.13
Question ids and instruction texts are the ones in jev_ra/decide/questions.py; the answers shown are an example. Values your agent passes are chosen by name; jev-ra does not invent strings to type.
Your agent talks to jev-ra over MCP (stdio). jev-ra drives Chrome over the DevTools Protocol and calls Jev over HTTPS once per step.
stale instead of a wrong click.A run that cannot finish returns one of ten reasons, the top candidates and the page text, so the agent can act without observing again.
needs_valuea field needs a string you did not supply. Add it to values, call again.stuck_loopthree steps, no page change. Read the text, click one candidate, continue.unverified_doneJev says done, no visible proof. Check with browser_extract.stalethe page kept changing under it. browser_wait(), retry once.budgetsteps or time ran out. Narrow or split the goal.too_many_controlsover 250 controls in view. Scroll or open the section first.blockedlogin, captcha, empty results. Tell the user; do not retry blindly.invalid_decisionan answer not on the page, twice. Re-observe and drive one step yourself.blocked_by_sitethe site served a wall or an error page, not a page. An error page was already reloaded once; a wall blocks automation and a retry from the same network will not help.provider_errorthe decision provider would not answer. Check the key and route with jev-ra doctor; do not retry the goal.Measured 2026-09-18 on one machine and one Chrome, both tools through OpenRouter. jev-ra bench --live re-measures the jev-ra column and --baseline re-runs the browser-use script.
| Task | browser-use flash_mode | browser-use default | jev-ra | ratio |
|---|---|---|---|---|
| Wikipedia: open the Gödel incompleteness article | 23.1 s · 4 steps | 46.5 s · 5 steps | 2.7 s · 2 steps | 8.5x |
| Google Flights ZRH→LON one-way, 7 checks verified | 66.4 s · 11 steps | 63.6 s · 11 steps | 8.9 s · 11 steps | 7.5x |
| Olive Young category: sort by newest | 15.1 s · 3 steps | 17.5 s · 3 steps | 3.8 s · 2 steps | 4.0x |
jev-ra columns are medians of 5 runs (5/5 success each); browser-use columns are the single baseline runs, and its own 5-run medians are slower (24.6 s / 73.8 s / 27.6 s). On 0.2.5 through the TypeSafe direct route (2026-09-23) jev-ra took 4.7 s / 11.6 s / 5.7 s; browser-use was not re-run that day, so those are not ratios. BENCHMARKS.md carries p90, cost per task and the per-step time breakdown.
| Corpus | tool | passed | rate | median |
|---|---|---|---|---|
| 83 tasks, 10 families, 3 runs each (0.2.4, 2026-09-23, TypeSafe direct) | jev-ra | 213 / 249 | 85.5 % | - |
| The same 40 tasks, 3 runs each (0.1, 2026-09-18) | jev-ra | 102 / 120 | 85 % | 3.1 s |
| The same 40 tasks, 1 run each (2026-09-22) | browser-use flash_mode | 29 / 40 | 72 % | 19.4 s |
Every task has a spec that checks the page the run left behind; a run that stops without doing the task is a failure. Medians are over the runs that passed. The two rows for the 40 tasks were measured on different days with different run counts, so they are not a like-for-like comparison. One three-run pass moves by about five tasks on site weather alone. On the two held-back tasks browser-use filled in a name and uploaded a file it was never given.
An OpenRouter key is enough; no TypeSafe account is needed. jev-ra doctor checks the key, Chrome and one live decision.
export OPENROUTER_API_KEY=sk-or-... uvx jev-ra install claude uvx jev-ra doctor # then in Claude Code: "search the web for X and summarise"
export OPENROUTER_API_KEY=sk-or-... uvx jev-ra install codex uvx jev-ra doctor # Codex asks you to trust the new MCP server once
export OPENROUTER_API_KEY=sk-or-... npx -y jev-ra install claude # or: install codex
{
"mcpServers": {
"jev-ra": { "command": "uvx", "args": ["jev-ra", "mcp"], "env": { "OPENROUTER_API_KEY": "sk-or-..." } }
}
}uvx jev-ra run https://en.wikipedia.org/wiki/Main_Page \ "Find and open the article about Gödel's incompleteness theorems" --json uvx jev-ra search "python 3.12 release date" "the exact release date, with source" uvx jev-ra doctor
If an agent installs this for you, point it at AGENTS.md: install steps, the tool table, what to do on each escalation, and cost.
These return an escalation with a reason.