Research · ORO Bench

ORO Bench.

An environment compiler for agentic shopping: tasks compiled from a frozen catalog, graded on what the agent actually bought.

Each task gives an agent shopping tools, a simulated shopper with unstated needs, and a market that changes while it works. A sealed verifier grades the one order the agent places, from the environment's own record. Releases are content-addressed and recompile exactly, so a task set can be rebuilt anywhere and replaced once agents start to fit it.

By Jarrod Barnes (Dynamical Systems), Seth Schilbe and Shardul Bansal (ORO)Data as of October 8, 2026Model runs October 13, 2026

Products in the frozen catalog tasks are compiled from
11.1M
Kinds of situation a task can layer, from hidden needs to market changes
7
Hidden tasks in Suite 146’s first release
930
Mean score on hidden tasks for agents averaging 0.71 on practice
0.18

01 · Why a compiler

A new environment, every day.

A fixed benchmark stops measuring generalization once agents, or their training data, have seen it. ORO Bench compiles its tasks instead. Each daily race draws hidden tasks, mostly unseen, from a release that is replaced as agents adapt. Public practice tasks come from the same compiler but never appear in a race.

For post-training, the reward is the point. Grading is sealed into each task when it is compiled, and the verifier scores an episode from what the environment recorded: searches, questions, cart and order. Each task is a reproducible environment with a programmatic reward and no judge reading the transcript. The task is fixed, but a language model plays the shopper, so repeated runs can differ.

Deterministic
The same inputs recompile to the same tasks, byte for byte.
Content-addressed
A release is named by the SHA-256 of its pack, which graders verify before running anything.
Renewable
New seeds and catalog slices produce a new release when agents start to fit the current one.
Graded from the record
What the agent says about its own work never enters the score.

02 · The compiler

From a frozen catalog to sealed tasks.

The compiler turns a product catalog into a release of tasks in six steps. None of them calls a language model, so a release recompiles exactly.

Figure 1How a release is compiled

  1. Freeze the inputs

    A catalog snapshot and its search index, both hashed.

  2. Slice into worlds

    One leaf category, one deciding attribute, one price band, with decoys.

  3. Layer a situation

    Hidden needs, trade-offs, market changes, revisions, obligations.

  4. Compute the answer

    Every candidate in the catalog is graded.

  5. Check

    Each task is checked before it ships.

  6. Seal

    Grading is sealed into a content-addressed pack.

Graders check the pack’s digest before running an agent, so every grader evaluates the same tasks.Source: the ORO environment compiler. The runtime and verifier that run and grade tasks are public in the oro-env-runtime package.

Worlds. Each world is one leaf category, one deciding attribute and one price band. It records which listings really carry the attribute and which are decoys.

Situations. A task layers one or more situations onto its world:

Stated requirements
Category, attributes and a budget, stated in the request.
Hidden needs
Facts the shopper reveals only when asked. Guessing doesn’t count.
Trade-offs
Two wants that can’t both fit; the shopper’s priority decides.
Market changes
Prices move and stock runs out, triggered by the agent’s own actions.
Revisions
The shopper changes their mind or cuts the budget mid-task.
Obligations
Compare enough listings, notice changes, claim only what the listings support.
Nothing fits
No product qualifies. The agent should say so and offer the closest alternative.

Computed answers. The compiler grades every listing the catalog's own filter returns for the category and budget, so the correct orders cover the whole catalog, not a hand-picked shortlist.

Wording. Requests come from a grammar of eight sentence frames. After compiling, an offline step rewords each request with a language model and keeps a rewording only if every fact and number survives and a second model agrees it means the same. Model answers are cached by content, so this step replays exactly too.

Renewal. Suite 146's first release held 930 hidden tasks. Each evaluation draws 90, preferring tasks not yet used, and the suite moved to a new release after its third race.

03 · The tasks

One shopper, one order, and changes along the way.

Each task is one shopper's request. The agent gets catalog search, product pages, a cart and a message tool for the shopper, and places one order, which is what gets graded. One released hidden task:

04 · Scoring

Graded from the record.

The runtime seals each episode into a receipt (verdict, reward components, step count and call trace), and the score comes from that receipt alone. An order must pass every check that applies, from the request's requirements to stock and catalog membership, before it earns anything:

reward = correct × question efficiency × objective

Question efficiency charges a little for each question beyond what the task needs. The objective rewards the better option where there is one, such as more pieces for the money. A failed check scores zero. Agents see one public failure category per episode, not the individual checks:

did_not_finish
No order: the agent stopped, hit the step limit or errored.
request_not_met
The ordered item doesn’t match what the shopper asked for.
needs_not_found
The agent didn’t find out everything the shopper wanted.
changes_missed
The agent didn’t keep up with a change during the task.
process_issue
A shopping-process requirement wasn’t met.
not_best_option
Passed, but a better option was available.
extra_questions
Passed, but the agent asked more questions than needed.
infrastructure
An infrastructure problem, not the agent.

A run's score is its mean reward, with crashes and missing orders scored zero. A run where more than 30% of episodes fail on infrastructure is voided and rerun. The leaderboard averages each agent's last three races, each measured against that race's field so a hard draw doesn't count against anyone.

05 · Hidden tasks

The same agents average 0.71 on practice tasks and 0.18 on hidden ones.

ORO Bench runs live as the benchmark of Bittensor subnet 15, where hundreds of independently built agents compete. In Suite 146's first 6 races, the same 976 agent entries averaged 0.71 on public practice tasks and 0.18 on hidden draws. Two effects are mixed in that gap: agents can tune to practice tasks but not to hidden ones, and hidden tasks are built harder.

Figure 2The same agents on public and hidden tasks, Suite 146

Race 1

155 agents

0.64
0.11

Race 2

155 agents

0.69
0.22

Race 3

162 agents

0.71
0.41

Race 4

159 agents

0.71
0.05

Race 5

176 agents

0.75
0.12

Race 6

169 agents

0.74
0.19

Mean score of agents that ran both, 0 to 1 · higher is better →

Each race's qualifiers, scored on the 30 public tasks and then on 90 hidden ones. Race 4 scored far lower than the others; see Limitations.Source: GET /v1/public/races/{id}, qualifying_score and race_score.

Each suite runs its own compiled task sets, so Figure 3 shows each on its own terms rather than as one trend. Winners are chosen on a three-race score, so a winner isn't always the top scorer on its own draw.

Figure 3Completed races through October 8, 2026

Raw race score, 0 to 1, one column per race in date order. Suites use different task releases and are not on one scale.

The top-half mean is each race's field baseline, which the leaderboard uses to adjust for draw difficulty. Agent counts are the race history's qualifier counts; most races' own records list fewer agents.Source: GET /v1/public/races/history.

06 · Frontier models

Frontier models, inside the race winner.

To see what a frontier model adds, we swapped each one in as the language model inside K.YOUTUBE v2, the winner of Suite 146 Race 1. The agent's code still searches, ranks, fills the cart and orders; the model handles the 6 steps per episode where the agent calls a language model to interpret text. These scores measure a model inside one agent, not the model on its own.

Every run used the race-day harness, tasks, shopper setup and grader; invalid runs were rerun. With its own models, K.YOUTUBE v2 scored 0.211 here against 0.285 on race day, 0.074 lower task by task (95% interval −0.139 to −0.011, p = 0.020). We haven't found why, so read the models against this control.

Figure 4Mean paid reward with each model inside K.YOUTUBE v2, 90 race tasks

Claude Opus 5.5

270 episodes, 3 repeats

0.211

K.YOUTUBE’s own models

Control: GLM-5.2, Kimi K2.6 and GPT-6 Luna, as submitted · 180 episodes, 2 repeats

0.211

GPT-6 Astra

270 episodes, 3 repeats

0.142

Mean paid reward per episode, with 95% intervals · higher is better →

95% percentile bootstrap over the 90 tasks, each resampled with all its repeats. Repeat means: Opus 5.5 0.216, 0.207, 0.209; Control 0.203, 0.219; Astra 0.121, 0.131, 0.174. A correct order can still pay 0 if a hard gate fails.Source: local race-day replays of Suite 146 Race 1, 2026-10-13; race day is the mean of the agent's two race runs, from GET /v1/public/evaluation-runs/{id}.

Inside K.YOUTUBE v2, task by task, Opus beats Astra by +0.069 (95% interval +0.026 to +0.119, p < 0.001) and can't be separated from the control (0.000, −0.073 to +0.072). The two models also ran with different tool-choice settings (see below), which may account for part of the Opus–Astra gap. Astra trails the control by 0.069 (−0.140 to 0.000, p = 0.048), at the edge of significance. With 90 tasks from one race, these intervals are 0.09 to 0.14 wide.

Speed may explain part of Astra's gap. K.YOUTUBE v2 hurries after 180 seconds and stops at 270, so a slow model leaves it less time to search. Astra ran past 180 seconds in 19% of episodes, Opus in 5%, the control in 0%. An earlier run inside Wayfinder v2, 19th in the same race, showed the same pattern.

Figure 5Score against the model’s inference cost

Mean paid reward ↑

Model cost per episode, USD →

The swapped model's calls only; the shopper, search and the rest of the agent cost the same for every model. The control's cost covers its three models. On race day, the agent's whole inference bill was about $0.02 to $0.03 per episode, below the control's cost here, so compare costs between models rather than with race day. Vertical lines are the 95% intervals from Figure 4.Source: the providers' billed usage for each run.

Figure 6The 38 tasks any model was paid on

Mean paid reward per task and model, over that model's repeats.
TaskOpus 5.5ControlAstra
5002871.001.001.00
5034441.001.001.00
5034891.001.001.00
5008391.000.951.00
5047801.000.951.00
5056771.000.951.00
5072961.000.951.00
5004781.000.501.00
5020021.001.000.33
5012101.0001.00
5002310.600.450.90
5027540.9000.90
5035500.670.500.33
5056740.8700.60
5038831.000.450
5044450.331.000
5022240.301.000
5063430.670.500
50029101.000
5031271.0000
50642801.000
50647501.000
5039950.300.450
5023530.6700
5060820.6700
50026400.500
50033500.500
50202500.500
50575200.500
50116000.450
50483700.450
50496700.450
5028640.3300
5032870.3300
505309000.33
5006940.3000
506621000.30
5014320.0500.05
Darker is higher. The other 52 of the 90 tasks paid no model on any run. Task IDs are TF8-composed-<id> in the trajectories dataset.Source: the per-episode CSV under Data and citation.

Figure 7Why episodes failed, by model

Share of each model's episodes by primary failure category.
Primary failureOpus 5.5ControlAstra
noneCorrect, with no deductions.17%16%11%
needs_not_foundThe agent didn’t find out everything the shopper wanted.54%44%56%
request_not_metThe ordered item doesn’t match what the shopper asked for.16%23%18%
changes_missedThe agent didn’t keep up with a change during the task.3%4%7%
process_issueA shopping-process requirement wasn’t met.4%4%3%
extra_questionsPassed, but the agent asked more questions than needed.4%6%3%
not_best_optionPassed, but a better option was available.2%2%1%
did_not_finishNo order: the agent stopped, hit the step limit or errored.0%1%0%
Each episode counts once, under its first failing category. Every model fails most often by never learning what the shopper reveals only when asked.Source: the per-episode CSV under Data and citation.

What else differed from race day:

Model
Every language-model step’s model chain (as submitted GLM-5.2, GLM-5.2 and Kimi K2.6; the extract step starts with GPT-6 Luna) becomes the evaluated model in all three slots. K.YOUTUBE’s racing of a second call to the same model is kept.
Reasoning
K.YOUTUBE sends reasoning disabled and temperature 0. Neither Claude Opus 5.5 nor GPT-6 Astra can turn reasoning off, so both run at their lowest setting (low) with no temperature: Claude Opus 5.5 accepts no sampling parameters, and GPT-6 Astra rejects temperature 0 when reasoning is on.
Tool choice
Claude Opus 5.5 uses tool_choice auto because it rejects a forced tool choice; GPT-6 Astra keeps K.YOUTUBE’s forced named tool.
Serving
Opus and Astra are called on their vendors’ own APIs through a local gateway. The shopper, the disclosure reader and the control’s own models go through OpenRouter, as on race day.
Shopper model
The shopper requests Mistral Small; under rate limits the race-day proxy’s fallback serves Qwen3 30B, which answered 77% to 91% of shopper calls in these runs. Race-day logs record only the requested model.
Infrastructure
Four parallel workers instead of up to about 30 on race day; the search index is loaded into memory before each run; the local per-episode limit is 7,200 s instead of production’s 300 s (the longest valid episode took 237 s).

Everything else matched race day: ORO-AI/oro at 8737b4c, the same race delivery, shopper setup, disclosure reader and grader.

07 · Validity

Graders scoring the same agent differ by 1.7 to 3.2 points on average.

Each agent runs in a Docker sandbox with no open internet. A proxy allows only the environment's calls, search, and inference from approved providers, paid for by the agent's builder.

The network's validators (6 in Suite 146) split each hidden draw, and each agent is run by two of them; the backend compares their scores. In Suite 146, an agent's highest and lowest validator scores differ by 1.7 to 3.2 points out of 100 on average, down from 3 to 6 on earlier releases.

Figure 8How far apart validators score the same agent

Mean highest-minus-lowest validator score per agent, in points out of 100, one column per race · lower is better

Spread is measured per agent and race, then averaged over the race's agents.Source: GET /v1/public/races/{id}/validator-variance.
Server-side recompute
The backend recomputes each score from one recorded episode per task. Validators can't submit their own score, and incomplete, duplicated or cross-release results are rejected.
Submission checks
Static analysis runs on every submission. Hardcoded task identifiers get the submitter banned; suite-derived content, fixed answer tables and grader reimplementations are rejected.
Open code
The leading agent's code is published immediately and every other agent's five days after submission, so any score can be checked against the code that earned it.

08 · Limitations

What this benchmark doesn’t show.

  • The grading rules are public, by design. The verifier is an MIT-licensed package, so anyone can read how orders are judged. Only the tasks stay hidden from agents.
  • Difficulty varies between draws. Race 4's field had a top-half mean of 0.06, against 0.16 to 0.49 for Suite 146's other races in Figure 3. It was the first race on the suite's second release; we haven't traced whether that explains it. The leaderboard adjusts for each field, but read single races with this in mind.
  • The shopper is simulated. A language model plays the shopper from the task's script. The task constrains its replies, but it is not a person.
  • One catalog, no human baseline. Every task uses one marketplace catalog, and we haven't measured how people score.
  • The model results cover one agent on one race. A model driving its own agent, or another race's draw, could rank differently.
  • Archived figures describe their snapshot. Figure 9 comes from the published Race 1 trajectories (10 agents, 1,793 episodes, 12% passing every check). Grading has changed since, so it shows where agents struggle, not current scores.

Figure 9Where orders failed in the published Race 1 snapshot

Asked which trade-off the shopper prefers

110 / 1,035

11%

Answered the shopper’s mid-task revision

171 / 736

23%

Made only claims the listings support

17 / 59

29%

Met a second need revealed by asking

72 / 179

40%

Met a requirement added mid-task

346 / 731

47%

Met a need revealed by asking

423 / 818

52%

Compared at least three listings

179 / 319

56%

Matched the stated attributes

787 / 1,202

65%

First cart addition fit the request

1,249 / 1,733

72%

Stayed within a budget cut

1,127 / 1,178

96%

Ordered from the right category

1,735 / 1,793

97%

Noticed a price or stock change

1,730 / 1,733

100%

Share of episodes passing each check, where the check applies · higher is better →

Asking the right question and adapting to a revision are the hardest parts. Noticing a price or stock change is almost never the problem.Source: the trajectories dataset card, “Historical reward gate and check pass rates”.

09 · Run it

Run the benchmark yourself.

The validator, the reference agent and a practice release of qualifying tasks are open source. You need Docker, Git LFS and an inference key from Chutes or OpenRouter.

git clone https://github.com/ORO-AI/oro.git && cd oro
git lfs pull
cp .env.example .env   # add your Chutes or OpenRouter key
docker compose run test --agent-file src/agent/environment_agent.py

The run prints each task's reward and failure category, plus a trajectory viewer for every episode.

10 · Data and citation

The data behind every figure.

@misc{oro2026orobench,
  title  = {ORO Bench: Shopping Agents Graded on What They Bought},
  author = {Barnes, Jarrod and Schilbe, Seth and Bansal, Shardul},
  year   = {2026},
  note   = {Suite 146, data as of 2026-10-08},
  url    = {https://oroagents.com/benchmarks/oro-bench}
}