RuneBench with Jev

September 18, 2026 · View on GitHub

JevScape: let AI play RuneScape for $0.20 per hour

RuneBench with Jev

A RuneBench fork with a harness that lets TypeSafe's Jev play RuneScape.

What it is

This repository forks RuneBench, Max Bittker's RuneScape agent benchmark. The harness connects Jev to the game through a separate rs-sdk checkout. See the upstream README for RuneBench documentation.

Jev, TypeSafe's "System One," is a non-generative model. It answers typed questions (choice, noul, score) with calibrated probabilities. It writes no text or code and calls no tools. It cannot use RuneBench's OpenCode agent adapter.

The harness offers about 50 bounded actions built on rs-sdk. These include fishing, chopping, mining, cooking, fighting, buying, selling, dropping, walking, closing dialogs, and eating. Jev decides; code executes each action. Jev returns a probability for every offered option. The dashboard shows this distribution as its "thinking."

Demo

Jev walks to Draynor and fishes

A fresh character walks from Lumbridge to Draynor and starts net fishing. The recording uses real speed and real XP rates.

RecordingValue
Play time10 minutes
Playback speedAbout 15x

Watch the MP4.

How Jev plays

Burst mode and tick mode

Burst mode runs one action per burst. Jev then picks the next action. The skill sweep uses this mode. Tick mode asks Jev during live play. Set the base poll interval with --poll-every N.

TimingValue
Burst duration20 seconds; 60 seconds at 1x speed
Skill sweep task duration15 minutes
Game tick at real speed400 ms

Each tick-mode poll asks two questions:

QuestionOptions and effect
next_actionThe CURRENT action or another catalog action. Only a different goal stops the running action.
this_tickdo_nothing (normal), close_dialog, eat_food, or restart_current (re-click the target). These actions keep the goal.

Jev also answers poll_again_in_ticks with N, 2N, 5, or 10. This answer sets the next poll time. The answer timeout equals the poll interval. A late answer keeps the current action.

Facts and code responsibilities

No code rule decides for Jev. Each poll supplies these facts:

  • Player status: idle, moving, animating, skilling, under_attack, in_dialog, or dead.
  • Hitpoints and damage taken in the last 10 seconds.
  • Target name and seconds since the last XP drop.
  • Last server message.
  • Last eight events: action starts, XP drops, server messages, damage, deaths, restarts, and switches.

Code executes catalog actions and reports game state. Fishing scripts click the spot once and hold. Every re-click comes from Jev's restart_current decision. Code checks game state before retrying a click that the SDK reports as rejected. A blind retry previously ended the engine's fishing loop.

The live stack applies two small rs-sdk patches. walkTo cancellation stops walking when Jev switches actions. The level-curve patch uses the real RuneScape curve. Use --xprate 1 for real XP rates.

rs-sdk settingShipped valueLive value
Level curve2^(level/10)2^(level/7)
XP multiplier251 with --xprate 1

Quick start

Install bun. Keep an rs-sdk checkout at ../rs-sdk. Set TYPESAFE_API_KEY in your environment. No other secret is required. The local runner needs no Docker.

Start the live stack:

agents/jev/live-stack.sh up ../rs-sdk --skill Fishing --minutes 30 --policy jev --bot skyvern --speed 1 --xprate 1 --mode tick --poll-every 3

This command starts the engine, gateway, controller, and dashboard. Open the dashboard. Keep exactly one dashboard tab open. Keep that tab visible during login. Chrome pauses background tabs, so the game client only logs in while visible. A second dashboard tab takes over the game session.

The dashboard embeds the bot's own browser game client beside a sidebar. Simple view shows the task, skill level, XP to next level, ranked choices, and percentages. It also shows this-tick actions, recent actions, total cost, and time. Developer view adds the full state snapshot, probability bars, latency, tokens, and controller log.

Simple view · Developer view

Stop the stack:

agents/jev/live-stack.sh down

Benchmark commands

Run the local sweep with one isolated engine per task:

agents/jev/local-bench.sh

Aggregate Jev and random-policy results:

bun agents/jev/aggregate.ts --run jev=runs/jev-15m --run random=runs/random-15m

The Harbor adapter uses agents/jev_adapter.py and scripts/run-jev.sh. See the harness README for details, caveats, and the full design.

Results

RuneBench scores the best 15-second XP window as peak XP/min.

Sweep conditionsValue
Date2026-09-18
Task duration15 minutes
Skills16
RunnerLocal, no Docker
World speed20 ticks/s
Policy or modelMean peak XP/min
Random policy, same catalog235
Jev197
Claude Opus, best complete leaderboard model118

Jev gained more total XP through steady play. The peak metric rewards random's lucky bursts. Jev won on tasks that needed a multi-step chain.

Additional resultValue
Jev total XP / random total XP2.1x
Jev Fishing peak XP/min, fly fishing chain920
Jev Fletching peak XP/min213
Jev Crafting peak XP/min48
All leaderboard models on those three skills0
Whole Jev sweep decisions1,307
Whole Jev sweep input tokens4.14 M
Whole Jev sweep cost$0.17

The catalog carries the game knowledge. This comparison mostly measures the action space, not the model. Always present Jev beside the random baseline.

Live run evidence

These Fishing observations use real speed, real XP, and --poll-every 3 on 2026-09-18.

Observation windowValue
Duration / game ticks107 seconds / 266
Polls / timeouts28 / 0
Fishing level5 to 6
Time between catches7 to 20 seconds
this_tick: do_nothing / restart_current27 / 1
Quiet time before restart21 seconds

An earlier 30-minute run showed inventory handling and recovery. Jev dropped the catch when the inventory filled, then returned to fishing. It closed level-up dialogs without stopping fishing. It restarted the spot after it moved.

Cost profile

These figures cover live tick-mode Fishing runs at real speed on 2026-09-18. Luna and Astra costs apply their rates to the same token counts. Nobody ran Luna or Astra here.

ModelInput / M tokensCached input / M tokensOutput / M tokens
Jev$0.042Free
Luna (gpt-5.6-luna)$0.20$0.02$1.20
Astra (gpt-6-astra)$10$50
Measured usageValue
Input per poll, JSON state and option descriptionsAbout 3,950 tokens
Output per poll, answer JSONAbout 120 tokens
Median / p90 latency0.22 s / 0.31 s
All live polls13,402
All live input / output tokens52.9 M / 1.63 M
Total play time3.04 hours
Cost for all live runsCost
Jev$2.22
Luna, list price$12.55
Luna, 90% cached input$3.97
Astra$611
Poll schedule at real speedJev / hourLuna / hour, listAstra / hour
Every tick, 2.5 polls/sAbout $0.80–$1.00About $4.50–$5.30About $150–$300
Every 3 ticks, Jev stretches most polls to 10 ticks$0.55$3.14About $150

A generative model answers in seconds, not about 0.2 seconds. It could not answer every tick. This comparison covers cost only.

Repo layout

PathContents
agents/jev/Jev harness, live stack, local benchmark, and design documentation
agents/jev_adapter.pyHarbor adapter
scripts/run-jev.shHarbor run script
shared/pricing.tsPricing
results/jev-15m/Skill sweep results
results/jev-live/Live run results and dashboard screenshots
docs/Upstream README and media

Credits

RuneBench and rs-sdk are by Max Bittker. Jev is by TypeSafe.