RoboEval Challenge · CoRL 2026

Off-policy RL with online inference tuning.

My entry for the RoboEval Challenge at CoRL 2026: one vision-language-action policy that does all eight bimanual tasks. It learns with RL on the exact challenge score, plus scripted demos for the moves the human demos never show.

Read the tech report ↗ Code ↗ Checkpoint ↗ Demo video ↗ Challenge ↗

The submitted policy on held-out seeds, real time. Every cell keeps running new episodes.

Final results
Nov 12 2026
Held-out RDS
0.990 / 1.0
Held-out success
99.6%
Share
01 /

The challenge

RoboEval is a set of eight tasks for two Franka arms in the MuJoCo simulator. Every episode starts with the objects in new random positions and orientations. The main point of the benchmark is not only whether the robot gets the job done, but how it behaves on the way: is it safe, is it efficient, do the two arms work well together. I trained one policy for all eight tasks.

Start and end states of the eight RoboEval tasks
The eight tasks, start and end. Click any figure to zoom.
The five camera views at the start of a LiftPot episode
What the policy sees: up to five cameras at 256×256, plus the joint angles of the arms. It moves the hands in small steps, 20 times a second.

Success is only part of the score

Each episode first gets an outcome: 70% of it is for succeeding and 30% for how many stages of the task you got through. Then the challenge looks at how you moved: safety (collisions and jerky motion), efficiency (time and path length) and how well the two arms worked together. All of these are compared with the human demonstrations, and moving like a typical human already gives full marks.

The behavior part is multiplied by the outcome, so a failure hurts twice: you lose the outcome points, and the behavior points shrink with them. Once a policy moves about as well as a human, the only way to gain more is to fail less and to hit every stage.

02 /

My approach in a nutshell

03 /

The eight tasks

One policy handles all eight. It is only told which task it is on, with no text instruction. Pick a task to watch a real episode and to see how it scores next to the human demos.

The submitted policy on a held-out seed, in real time. Human demos: every demo replayed and scored like a policy (0.875 on average). My policy: 500 held-out episodes per task.

04 /

One model that acts and judges itself

I started from the public π0.5 weights: a vision-language model with a flow-matching action expert. It is the same base I used for LeHome and for our BEHAVIOR 2025 solution. The orange parts are what I added.

The policy: pi0.5 with a value query, a Q head and advantage conditioning

Who sees what

All of this is one transformer, so the attention mask matters. The value query only sees the images and the task, so it never sees the advantage it is used to compute. The advantage token is the switch that guidance flips.

Attention mask between the token groups
Rows read columns. Orange: only when the advantage is on. Light grey: FAST tokens, used only in training.
05 /

The training loop

This is the heart of the project. Training, data collection and inference tuning all run at the same time. The trainer never stops, and the collector always runs the newest policy.

The training loop: a trainer and a collector sharing code, data and models through one bucket
Two machines, one code version, and one Hugging Face bucket for data and models. I ran everything with Claude Code.
1CollectThe newest policy plays 2,000 episodes in 20 MuJoCo workers. Each episode tries slightly different inference settings, and the policy's own value predictions are saved along the way.
2Add harder dataFailed episodes get a second try from the middle, and a fresh batch of scripted demos joins in.
3Score every stepThe trainer picks up the new data without stopping and scores every step against the exact challenge metric.
4TrainGood frames are sampled more often and tagged with an advantage token. Older data slowly gets less weight, so fresh rollouts dominate.
5ExportA new policy every 250 steps. The collector picks it up, and around we go.

Collection scales to more machines out of the box. I tried two collectors but mostly used one.

06 /

Training on the exact score

The reward is the challenge score itself. Every step gets credit for how much it moves each part of the score, weighted the same way the score weights it, plus a small bonus for making progress.

The baseline is the policy's own value estimate, used only as much as it can be trusted. The nice part is that this reward knows what an improvement is worth right now: making a path shorter than the human one earns nothing, while on StackTwoBlocks every centimetre saved still counts.

The advantage is then used twice: through the sampler, so good frames show up more often in training (AWR), and as an input token inspired by RECAP, so that guidance can push the actions towards “good” at test time.

07 /

Inference, and tuning it while training

A policy call here is much more than one sample. I used a lot of test-time logic:

One policy call: N candidates with CFG, Q-head ranking, execution and carry-over between chunks
One policy call (top) and how two chunks connect (bottom).

Tuning it with Thompson sampling

That is about 20 settings per task, and I didn't set any of them by hand. Every collected episode runs with its own settings, and Thompson sampling keeps moving each task towards the settings that score best. The same episodes are also the RL training data, so the policy and its settings improve together.

Speed is my favourite example. A policy trained on demos moves more slowly than the demos themselves, so early on the tuner played chunks 1.5–3.9× faster. RL then taught the policy the right pace, and the speed-up went back to about 1×. Here's where each task ended up, all found automatically:

Taskbest ofrank byflow stepstemp.CFGreplankeepspeedgripperhidden inputs
Lift pot5success190.109.4851.000.90front, external
Lift tray3success110.104.52461.050.89front, external
Stack two blocks6score150.214.7901.050.60external, velocity
Book to shelf6success50.154.7760.860.57front, velocity
Cube handover5success170.354.7700.910.69–
Pack box5score70.366.32550.950.66external
Pick book2success50.185.01850.910.65front, external, velocity
Rotate valve4score50.402.51701.000.60front, external

Final inference parameters. Best of the first k of 6 candidates, ranked by predicted change of success or of the whole score.

08 /

The original demos aren't optimal

The human demos show strategies that are far from the best ones for this score. My loop can tune speed and smoothness, but it can't invent a completely new strategy: RL can only reward a stage that some rollout actually reaches. Here are the three clearest cases.

Stack two blocks

One stage needs both blocks in the air at once. Only 1 of 141 demos does that.

Pack box

The flaps should be held with the fingers. The demos push them shut, and only 2 of 99 reach every stage.

Lift tray

54 of 154 demos stop about 1 cm up, short of the 2.3 cm the task needs.

Top: human demo from the RoboEval dataset (Wang et al., 2025). Middle: my script. Bottom: the learned policy on a held-out seed.

Writing my own demos

So I wrote a scripted policy for each task. The scripts read object positions straight from the simulator, so they can't be submitted, but they make great training data: they get the full reward in more than 99.5% of episodes, and I generated around 200k of them.

Each script picks its own speeds, offsets and grasp points every episode and reacts to what happens, so the policy sees many slightly different ways of doing the task. Every cycle adds a fresh batch, with some of the robot state hidden so the policy has to rely on the cameras.

09 /

Learning from its own failures

The policy played more than 240k episodes of its own. The failed ones are the most useful, because they show exactly where it goes wrong.

So every failed or partly failed episode is replayed up to a branch point (the failure, 2 s before it, or the last moment it looked good) and continued from there, first by the policy itself and then by a script. Only continuations that reach the full reward are kept, about 100 per collect.

Two recoveries from training, in real time: the policy's failed rollout, then the continuation from a branch point. Left: Lift pot. Right: Stack two blocks.

10 /

How the competition went

I worked on this for about nine days. Here's the whole run in one curve: first the generic loop, then a switch to lots of scripted data.

RDS of every collect over training steps: 2,000 held-out episodes each, every one with its own inference settings, so the curve runs below the tuned score. Mean per 2k steps. At step 42k training moved from one H200 to eight B300s with a bigger batch. Hover or tap for values.

1The generic loopMy LeHome recipe as it was: the organisers' demos plus the policy's own rollouts, no scripted data. It reached at least 0.85 in about two days on one GPU and was still climbing.
2The demos run outSome tasks couldn't get close to 1.0 with these demos, so I wrote scripted policies. The score dipped while the policy relearned its style, then took off.
3The plateauAround step 50k it levelled off at about 0.97 in the collects and about 0.98 with the best settings. Training on to 60k didn't help, so I stopped.
4The final modelTwo days of trying weight averages and inference settings, always on new seeds: from 0.981 to 0.990.
11 /

Squeezing out the last 0.01

Once the curve levelled off, I stopped training and spent the last two days on a big search over weight averages and inference settings, starting from a few checkpoints around step 50k.

Best single checkpoint, tuned
0.981
Weight average + per-task tuning
0.990

500 held-out episodes per task, on different seeds for each. The bars run from 0 to 1.

Extra evaluation runs are cheap, so every option was tested on new random seeds. That mattered: with dozens of candidates and differences around 0.005, the winner on one set of seeds is often just the luckiest one. An option only went in if it won again on seeds that played no part in choosing it. All that for about +0.01. It matters on a leaderboard, but in a real deployment it probably wouldn't be worth the effort.

12 /

Results

The submitted policy scores 0.990 with 99.6% success over 4,000 held-out episodes.

TaskSuccessFull rewardOutcomeSafetyEfficiencyCoord.Score
Lift pot1.0000.9860.9991.0001.0001.0000.999
Lift tray0.9980.9980.9981.0001.0001.0000.998
Stack two blocks0.9960.9940.9970.9930.9201.0000.979
Book to shelf0.9980.9980.9980.9991.0001.0000.998
Cube handover1.0001.0001.0000.9931.0001.0000.998
Pack box1.0000.9900.9990.9181.0001.0000.974
Pick book0.9880.9880.9900.9950.9951.0000.988
Rotate valve0.9880.9800.9891.0001.0001.0000.989
Mean0.9960.9920.9960.9870.9891.0000.990

500 held-out episodes per task, each task at its final parameters. Full reward: success with every stage reached.

Coordination is 1.000 everywhere, and every task succeeds more than 98% of the time. What's left is mostly behavior: the StackTwoBlocks path is longer than its reference, which comes from one-arm demos, and on PackBox some contacts happen at reset, before the policy even moves.

Final results

The final results of the challenge will be published on November 12, 2026. Before that, the organisers re-run the top entries on unpublished seeds.

What still fails

Failures are very rare: 16 in 1,589 extra episodes on the five tasks where it fails most. Here are three of them.

Failures of the submitted policy on fresh held-out seeds. Episodes longer than 10 s play at 2×.

What it took

Time
~9 days
start to submission
Training
~600 GPU-h
1× H200, then 8× B300
Collection
1 GPU
RTX PRO 6000 + 24 CPU cores
Rollouts
240k+
the policy's own, on top of the scripted demos
13 /

Takeaways

∞ /

Report, code & citation

Read the tech report ↗ Code ↗ Checkpoint ↗ Demo video ↗ RoboEval Challenge ↗
@misc{larchenko2026roboeval, title = {{Off-Policy RL with Online Inference Tuning: My Solution to the CoRL 2026 RoboEval Challenge}}, author = {Larchenko, Ilia}, year = {2026}, eprint = {2611.11464}, archivePrefix = {arXiv}, primaryClass = {cs.RO}, url = {https://arxiv.org/abs/2611.11464} }

License. The code and the checkpoint are released under Apache-2.0. The checkpoint is a modified π0.5 (openpi).

Credits. The benchmark, the simulator and the human demonstrations are from RoboEval (Wang et al., 2025); the demonstration clips and frames on this page come from the helen9975/roboeval_ee_delta_20hz_scaled dataset on the Hugging Face Hub. Everything else is rendered with the challenge environment. I used Claude Code to run the experiments.

Share