Research blog · November 11, 2026

Repairing Robot Policies with Weight Space Programming

Frontier Models can restore task success for vision-based behavior cloning policies under distribution shifts, directly in weight space

Jannick Stranghöner1* Philipp Hartmann1* Felix Störck1*

Barbara Hammer1 Klaus Neumann1,2

1CITEC, Bielefeld University 2Fraunhofer IOSB-INA *Equal contribution

TL;DR

demonstrate train deploy policy failures LLM edits weights more data, retrain

Teaching your robot new skills has never been easier: low-cost robots have boomed, open datasets keep growing, and robot foundation models are closer than ever to working out of the box.

So say you collected some demonstrations, fine-tuned your favourite VLA and deployed it on your 3D-printed robot of choice. Then, in certain states, it just does not work. It tries to grasp something, fails and loops. It stalls halfway through the task. Something as simple as a change in lighting throws it off. What do you do?

For most roboticists, the answer is more data (e.g. DAgger [2]) and another round of training. We skip both and instead present early results showing that a frontier LLM can identify the failure modes that appear in closed loop and iterate on fixes, entirely in weight space.

Behaviour Cloning and Its Limits

Learning robust behaviour by imitating humans is a long-standing goal in robotics. Behaviour cloning is attractive because it is simple: it turns a control problem into a supervised learning problem.

For the same reason, it is also hard: it is fundamentally limited by distribution shift. The policy learns from the state distribution of its demonstrator, but when rolled out, it visits its own. Each small mistake takes it into states the demonstrator never saw, where bigger mistakes become more likely. This is known as compounding error [3], and it happens even in the very environment the policy was trained in.1 It only gets worse under the obvious shifts, like a visual distractor or a new object.

Yet much of what a policy has learned often stays useful under a shift, which suggests that a fix may be small and surgical. But where would we make it? To us, a trained policy is a black box. The only lever we have is the data it learns from.

Opening the Black Box

LLMs already sit at the heart of robot learning. Vision-language models are the backbone of today's robot foundation models (OpenVLA [4], π0 [5]), and LLMs write robot code (Code as Policies [6]) or even control robots directly [7]. But none of them can look inside a trained policy and tell us why it fails.

That is starting to change. In Sparks of Weight-Space Programming [1], LLMs read and write a network's weights directly, without an optimizer, which the authors call weight space programming. In one of many striking demonstrations, GPT-6 Astra is handed a policy whose car gets stuck on a ramp in every episode. From the raw weights and one recorded episode, it explains why, then rewrites 3.5% of the weights in a single reply. Now the car succeeds every time. LLMs, it seems, can reason in weight space about how a policy behaves. While recent work applies this to specific aspects of a robot foundation model, such as making π0.5 move faster [8] or follow paraphrased instructions more reliably [9], the rest of this blog is dedicated to studying whether LLMs can rescue policies that no longer work at all, by finding out in closed loop why they fail and fixing them in weight space.

The Setup

To study this in a controllable and reproducible way, we test it on a standard robotic manipulation task in simulation: cube pick-and-place. Our suite builds on OCBench [10], with one slight tweak. A tray now marks where the cube goes, which gives us a goal we can move later to introduce distribution shift.

To train a policy, we need demonstrations. Here we script a near-optimal expert that collects them for us, using privileged information such as the true position of the cube. This expert is memoryless and only reacts to the current state of the world; it is Markov.

The policy is a neural network that sees three camera images and the robot's own state. A pretrained ResNet [11] compresses each image into 256 numbers, and a small network with three layers of 256 ReLU neurons maps everything to target angles for the joints and a command for the gripper. Like the expert, the policy only sees the present, so it is Markov as well, and in principle it can imitate the expert perfectly. The difference lies in what they see. The expert reads the simulator's true state, while the policy has to infer it from images.

layer 1 · 256 units layer 2 · 256 units layer 3 · 256 units front side wrist robot state cameras ResNet pretrained base shoulder elbow wrist bend wrist roll wrist twist gripper
The policy. Later figures show the LLMs' edits on this same drawing.

If we simply train the policy to reproduce the expert's actions, it fails almost completely at test time. Ironically, the expert is too good; it never makes a mistake, so its data never shows how to recover from one, and the policy runs straight into the compounding error described above. The fix may seem counterintuitive: we run the expert with noise added to its actions, so its demonstrations also visit states slightly off its own path, and the recorded actions show how it steers back. The policy learns to recover from its own small mistakes, which keeps it in-distribution even in closed loop. With this recipe, known as DART [12], our policy succeeds in 95.8% of held-out test episodes after training on 8,426 demonstrations.2

This trained policy is where every experiment starts. We drop it into a situation it was never trained for, watch it fail, and ask an LLM to restore its performance. The LLM can act only by changing the 335,111 parameters of the MLP on top of the frozen ResNet, numbers that come with no labels and no explanation. To make that a fair and repeatable test, a harness controls everything else, from what the LLM gets to see to how its final edit is scored.

What it getsThe policy's weights in a Python kernel, 200 demonstrations from the training environment, and a recording of every test it has run. It can run the network on these recordings as often as it likes, but the kernel has no simulator.
How it testsTo see the robot move, it spends one of 25 test rounds. Each round runs its current edit on the same 100 practice episodes in the changed environment.
What is off-limitsGradients, optimizers, fitting and automated search. To write the strongest policy it can, it has to edit the weights itself.
How it is scoredIts final edit runs on 500 new episodes it never sees, from the same starts as the original policy, in some experiments with a variant it was never shown. A cube counts once it has been lifted and then reaches the tray.3
The harness in detail
LLM HARNESS TOOLS AND BUDGET RULES AND SCORE The task Told what changed, not where the tray or wall is. Language model Opus 5.5, Sonnet 5.5, Fable 5.1 or GPT-6 Astra One action per turn, each explained first; otherwise refused. Memory reset Chat restarts every 40 turns from its own notes, saved edits and files. action result Harness routes replies, counts budgets, logs all code submit Final evaluation 500 unseen episodes, original vs. edit from the same starts. Opens after all 25 test passes. 1 submission rollout Collecting a rollout Tests the current edit on 100 fixed practice episodes; returns outcomes and full traces. 25 test passes view Camera viewer Shows the 128×128 images the policy received in tests and demonstrations. In rollouts the agent only receives the encoded image features. 60 views python Sandboxed Python kernel Reads and writes weights. Holds 200 demonstrations and all test traces. No internet, GPU or simulator. 300 code runs Task success, wall experiment 1.6%→49.4% unedited → Opus 5.5 Not allowed Gradients, optimizers Fitting weights to data Automated weight search New demonstrations Allowed Any analysis of the network Hand-derived weight values Data-derived directions, with stated derivation All code is checked afterwards. THE POLICY BEING REPAIRED 3 cameras front, side, wrist Image encoder frozen, not accessible 787 numbers 768 camera features, 19 arm readings (6 masked) Network head 335,111 weights in 3 layers: the only editable part 7 outputs joints, gripper the only way to change the policy
Each LLM reply is one action, and the network head can only be rewritten from inside the sandbox. The harness routes every action to one of four tools and charges it to that tool's budget. The score shown is one example, Opus 5.5 on the forbidden wall.

Five Ways to Break a Policy

To find out whether an LLM can repair a failing policy, we first need one that fails. We move the goal, once or in every episode. We recolour the cube, declare a zone off-limits, and swap the expert for one that behaves like a human. Every change collapses the original policy from 96% to near 0% task success. Then an LLM gets to work. Some frontier models even found a loophole in our success test and used it to score. In each experiment we present the best-performing LLM without such an exploit. The exploits are covered later in the case studies.

Experiment 1 of 5 · Spatial Adaptation

Distribution shift. The base policy is trained with the tray at position A. We move the tray by 21 cm to position B, where the LLM edits and tests the policy. There the base policy still lifts the cube, then hovers between the old and the new tray, with 0.2% task success. To test generalization, we also test on a new position C, 24 cm from position A in the opposite direction, which the LLM never sees.

050100task success [%]0510152025round12345✓
Task success on the 100 practice episodes the LLM tests on in every round, visualizing rounds where it discovered key insights. Click on a number to show more details.
1Shift the scene while carryingrounds 0 → 3: 0 → 5% task success1 of 6
Practice episode 45. Left: before editing, the policy lifts the cube and hovers with it about 6 cm from the tray until time runs out. Right: it carries the cube to the tray and lowers it (404 steps).
Diagnosis
Swapping inputs with demonstrations: the held cube stops short of the new tray and hovers. The front and side camera views and joint positions cancel the push toward the tray, because these cues still steer to the old tray's place.
Fix
While the gripper holds a cube, the network is told the tray still stands in its old place, so the carry looks like the training scene; with the gripper open the shift is off. 512 weights written (0.15% of the network) · gripper-closure row and all 256 first-layer biases · no new units
The first placed cubes: 5 of 100 in tests 2 and 3. The other carried cubes still stop about 7 cm short of the tray, now in a stable stall.
In Opus's own words
  1. t4After lifting, the policy carries the cube to roughly (0.52, 0.12, 0.22) and hovers there indefinitely. […]
  2. t23[…] Swapping in the hover frame's front features (−1.2 cm/step) or proprioception (−1.0 cm/step) weakens it, and front+side+proprio together cancel it to ≈0. So the stall comes from absolute-position cues (front-camera arm appearance and proprioception) that implicitly assume the old container position.
  3. t30The edit overshoots badly. The arm carries the cube to x ≈ −0.10, y ≈ 0.5–0.8, far beyond the container and behind the base […]
  4. t69[…] My earlier (0.57, 0.20) was 7 cm off in x, which alone would have doomed any fixed-target edit.
  5. t112Under v4, the xy velocity at the hover spot is essentially zero (0.24, 0.01): this is a stable stall, about 7 cm short of T1 in y.
The edit, as written into the network · excerpts of turns 77, 106 and 107; d is the shift of the inputs (arm readings, front and side cameras), row 785 of fc0.W reads the gripper closure
def build_shift(d):
    W0=load_original('fc0.W'); b0=load_original('fc0.b'); mu=load_original('obs_mean'); sd=load_original('obs_std')
    dn=np.where(np.isfinite(sd), d/sd, 0).astype(np.float32)
    w=dn@W0
    W=W0.copy(); W[785]+=sd[785]*w; b=b0+mu[785]*w
⋮
d4=comp(gpan=0.8,gi=1.0,ge=0.5,gjo=-0.3)
⋮
write_shift(d4); np.save(os.path.join(WORK,'d4.npy'),d4)

94.6% task success in 500 unseen episodes at position B (original 0.2%), 0.0% at position C. Its controllers steer to fixed numbers for the tray at position B, and Opus predicted the result. It had checked whether the wrist camera could find the tray anywhere, found it could not, and kept the fixed target. Experiment 2 asks for the general version. Fable 5.2 scored higher, through a loophole much like the one in Memory in a Memoryless Network.

For [position C], which I never saw, I expect no gain over the original. Both will most likely be near 0%, because my edit carries the cube to [position B].

Opus 5.5, in its final report

Total edits: 4,674 weights written (1.4% of the network) and 39,512 set to zero (11.8%), in 320 reasoning turns.

How about other LLMs?

All five LLMs got the same task, tools, budget and rules: GPT-6 Astra, Sonnet 5.5, Fable 5.1, Opus 5.5 and Fable 5.2. Task success over the rounds, and in the unseen episodes at position B (right).

0255075100task success [%]0510152025roundAstra, round 0: 0%Astra, round 1: 2%Astra, round 2: 2%Astra, round 3: 1%Astra, round 4: 21%Astra, round 5: 23%Astra, round 6: 26%Astra, round 7: 1%Astra, round 8: 19%Astra, round 9: 31%Astra, round 10: 7%Astra, round 11: 9%Astra, round 12: 39%Astra, round 13: 40%Astra, round 14: 42%Astra, round 15: 31%Astra, round 16: 49%Astra, round 17: 41%Astra, round 18: 58%Astra, round 19: 52%Astra, round 20: 52%Astra, round 21: 62%Astra, round 22: 51%Astra, round 23: 56%Astra, round 24: 52%Astra, round 25: 62%Sonnet 5.5, round 0: 0%Sonnet 5.5, round 1: 3%Sonnet 5.5, round 2: 58%Sonnet 5.5, round 3: 77%Sonnet 5.5, round 4: 47%Sonnet 5.5, round 5: 78%Sonnet 5.5, round 6: 89%Sonnet 5.5, round 7: 87%Sonnet 5.5, round 8: 84%Sonnet 5.5, round 9: 90%Sonnet 5.5, round 10: 90%Sonnet 5.5, round 11: 84%Sonnet 5.5, round 12: 88%Sonnet 5.5, round 13: 89%Sonnet 5.5, round 14: 90%Sonnet 5.5, round 15: 91%Sonnet 5.5, round 16: 92%Sonnet 5.5, round 17: 90%Sonnet 5.5, round 18: 91%Sonnet 5.5, round 19: 89%Sonnet 5.5, round 20: 90%Sonnet 5.5, round 21: 94%Sonnet 5.5, round 22: 92%Sonnet 5.5, round 23: 91%Sonnet 5.5, round 24: 94%Sonnet 5.5, round 25: 93%Fable 5.1, round 0: 0%Fable 5.1, round 1: 0%Fable 5.1, round 2: 0%Fable 5.1, round 3: 0%Fable 5.1, round 4: 0%Fable 5.1, round 5: 0%Fable 5.1, round 6: 0%Fable 5.1, round 7: 1%Fable 5.1, round 8: 0%Fable 5.1, round 9: 20%Fable 5.1, round 10: 77%Fable 5.1, round 11: 25%Fable 5.1, round 12: 79%Fable 5.1, round 13: 88%Fable 5.1, round 14: 88%Fable 5.1, round 15: 94%Fable 5.1, round 16: 55%Fable 5.1, round 17: 59%Fable 5.1, round 18: 92%Fable 5.1, round 19: 91%Fable 5.1, round 20: 96%Fable 5.1, round 21: 93%Fable 5.1, round 22: 77%Fable 5.1, round 23: 94%Fable 5.1, round 24: 95%Fable 5.1, round 25: 95%Opus 5.5, round 0: 0%Opus 5.5, round 1: 0%Opus 5.5, round 2: 5%Opus 5.5, round 3: 5%Opus 5.5, round 4: 43%Opus 5.5, round 5: 77%Opus 5.5, round 6: 54%Opus 5.5, round 7: 81%Opus 5.5, round 8: 92%Opus 5.5, round 9: 91%Opus 5.5, round 10: 93%Opus 5.5, round 11: 90%Opus 5.5, round 12: 93%Opus 5.5, round 13: 94%Opus 5.5, round 14: 96%Opus 5.5, round 15: 97%Opus 5.5, round 16: 97%Opus 5.5, round 17: 100%Opus 5.5, round 18: 98%Opus 5.5, round 19: 99%Opus 5.5, round 20: 98%Opus 5.5, round 21: 100%Opus 5.5, round 22: 99%Opus 5.5, round 23: 99%Opus 5.5, round 24: 100%Opus 5.5, round 25: 100%Fable 5.2, round 0: 0%Fable 5.2, round 1: 0%Fable 5.2, round 2: 8%Fable 5.2, round 3: 76%Fable 5.2, round 4: 85%Fable 5.2, round 5: 96%Fable 5.2, round 6: 98%Fable 5.2, round 7: 90%Fable 5.2, round 8: 91%Fable 5.2, round 9: 93%Fable 5.2, round 10: 98%Fable 5.2, round 11: 79%Fable 5.2, round 12: 74%Fable 5.2, round 13: 66%Fable 5.2, round 14: 91%Fable 5.2, round 15: 88%Fable 5.2, round 16: 97%Fable 5.2, round 17: 98%Fable 5.2, round 18: 99%Fable 5.2, round 19: 99%Fable 5.2, round 20: 99%Fable 5.2, round 21: 97%Fable 5.2, round 22: 99%Fable 5.2, round 23: 99%Fable 5.2, round 24: 99%Fable 5.2, round 25: 98%finalFable 5.2: 98.2% in the unseen episodes● Fable 5.2 98.2%†Opus 5.5: 94.6% in the unseen episodes● Opus 5.5 94.6%Fable 5.1: 93.0% in the unseen episodes● Fable 5.1 93.0%Sonnet 5.5: 91.2% in the unseen episodes● Sonnet 5.5 91.2%Astra: 54.4% in the unseen episodes● Astra 54.4%original 0.2%† loophole of the success test
End of experiment 1

Experiment 2 of 5 · Spatial Generalization

Distribution shift. Now the tray is placed at random for each episode, anywhere in a rectangle of 27 cm × 63 cm. A fixed solution like the one in experiment 1, which steers to one known spot, is no longer enough: the policy has to look where the tray is in every episode and carry the cube there. Unedited, it carries the cube toward the tray's old spot and hovers: 5.0% task success.

050100task success [%]0510152025round1234✓
Task success on the 100 practice episodes the LLM tests on in every round, visualizing rounds where it discovered key insights. Click on a number to show more details.
1Steer while holding the cuberounds 0 → 4: 6 → 11% task success1 of 5
Practice episode 24, the tray 22 cm from where it stood in training. Left: before editing, the arm carries the cube only part of the way and hovers about 6 cm short of the tray until time runs out. Right: it carries the cube to the tray and sets it down after 7.5 s.
Diagnosis
Swapping in demonstration camera views: the arm stops partway to a moved tray. The front and side cameras keep pulling the carry back toward the tray's training spot.
Fix
Four idle units now read where the tray appears in the front and side cameras while holding the cube, and push the carry toward it. 3,080 weights written (0.92% of the network), 1,096 set to zero (0.33%) · 4 idle first-layer units reading the front and side cameras and pad contact · feed all 256 second-layer units
A first gain, 6 → 11. In the finished edit the readout is worth 17 points: switched off, 27 successes on 100 practice-style episodes Opus never saw fall to 10.
In Opus's own words
  1. t5The under-reaction is clean: placement ≈ fixed point + 0.19·Δcx + 0.41·Δcy, independent of the cube start.
  2. t49This is the key finding. Swapping in demo front/side features, where the tray sits at c0, makes the policy move strongly toward c0 (cos +0.77). So the carry target is set visually, by where the tray appears in the front/side images relative to the gripper; proprioception barely matters.
  3. t56Pass 2 broke grasping: 40 episodes never touched the cube and 19 touched without lifting. The amplification is applied in every phase, so readout noise disturbs the reach.
  4. t98Big finding: 236 of the 256 fc0 units are dead, i.e. never active in demos or pass 0; only ~20 live units carry everything.
  5. t111Pass 3 used 3.7 and 1.6, about 5× too strong, hence the overshoot and runaway.
The edit, as written into the network · excerpts of turns 104 and 111; rows 0–511 of fc0.W read the front and side cameras, row 786 the pad contact
for (k_,(a_,u_,w_,sg)) in enumerate([(ax_,ux_m,wx,1),(ax_,ux_m,wx,-1),(ay_,uy_m,wy,1),(ay_,uy_m,wy,-1)]):
    j=U[k_]; W0n[:,j]=0; W0n[:512,j]=sg*a_*u_; W0n[786,j]=Bc
    b0n[j]=-sg*a_*(u_@muD)-Bc*thr_n
    W1n[j,:]=sg*0.5*(w_@W1)
⋮
E2=build_steer(0.75,0.30)

33.2% task success in 500 unseen episodes (original 5.0%). Opus's edit reads where the tray is from the cameras and carries the cube there, so it now succeeds with trays the original never reaches. Its estimate of the tray is only accurate to a few centimetres, so with the tray far from its training position the cube often stays hovering next to it. Three other LLMs scored higher, all through loopholes of the success test: both Fable models, with 93.0% and 99.0%, and, much less successfully, Sonnet 5.5 with 46.0% (Memory in a Memoryless Network).

The readout scatters by about 5–7 cm per coordinate.

The arm sometimes hovers within a few cm of the container without the descent trigger firing.

Opus 5.5, in its final report

Total edits: 2,522 weights written (0.75% of the network) and 30,082 set to zero (9.0%), in 322 reasoning turns.

How about other LLMs?

All five LLMs got the same task, tools, budget and rules: GPT-6 Astra, Sonnet 5.5, Fable 5.1, Opus 5.5 and Fable 5.2. Task success over the rounds, and in the unseen episodes (right). The scores of Sonnet 5.5 and both Fable models come from loopholes (†); Fable 5.1's is described in Memory in a Memoryless Network.

0255075100task success [%]0510152025roundAstra, round 0: 6%Astra, round 1: 6%Astra, round 2: 8%Astra, round 3: 6%Astra, round 4: 11%Astra, round 5: 6%Astra, round 6: 4%Astra, round 7: 2%Astra, round 8: 9%Astra, round 9: 21%Astra, round 10: 11%Astra, round 11: 15%Astra, round 12: 14%Astra, round 13: 20%Astra, round 14: 21%Astra, round 15: 24%Astra, round 16: 15%Astra, round 17: 21%Astra, round 18: 19%Astra, round 19: 27%Astra, round 20: 20%Astra, round 21: 25%Astra, round 22: 34%Astra, round 23: 31%Astra, round 24: 30%Astra, round 25: 36%Sonnet 5.5, round 0: 6%Sonnet 5.5, round 1: 5%Sonnet 5.5, round 2: 3%Sonnet 5.5, round 3: 0%Sonnet 5.5, round 4: 7%Sonnet 5.5, round 5: 10%Sonnet 5.5, round 6: 5%Sonnet 5.5, round 7: 15%Sonnet 5.5, round 8: 25%Sonnet 5.5, round 9: 27%Sonnet 5.5, round 10: 40%Sonnet 5.5, round 11: 30%Sonnet 5.5, round 12: 27%Sonnet 5.5, round 13: 36%Sonnet 5.5, round 14: 45%Sonnet 5.5, round 15: 53%Sonnet 5.5, round 16: 58%Sonnet 5.5, round 17: 56%Sonnet 5.5, round 18: 49%Sonnet 5.5, round 19: 55%Sonnet 5.5, round 20: 57%Sonnet 5.5, round 21: 54%Sonnet 5.5, round 22: 51%Sonnet 5.5, round 23: 56%Sonnet 5.5, round 24: 61%Sonnet 5.5, round 25: 50%Fable 5.1, round 0: 6%Fable 5.1, round 1: 86%Fable 5.1, round 2: 89%Fable 5.1, round 3: 90%Fable 5.1, round 4: 83%Fable 5.1, round 5: 90%Fable 5.1, round 6: 91%Fable 5.1, round 7: 90%Fable 5.1, round 8: 90%Fable 5.1, round 9: 92%Fable 5.1, round 10: 71%Fable 5.1, round 11: 93%Fable 5.1, round 12: 93%Fable 5.1, round 13: 94%Fable 5.1, round 14: 91%Fable 5.1, round 15: 93%Fable 5.1, round 16: 93%Fable 5.1, round 17: 92%Fable 5.1, round 18: 93%Fable 5.1, round 19: 93%Fable 5.1, round 20: 92%Fable 5.1, round 21: 94%Fable 5.1, round 22: 92%Fable 5.1, round 23: 93%Fable 5.1, round 24: 94%Fable 5.1, round 25: 93%Opus 5.5, round 0: 6%Opus 5.5, round 1: 6%Opus 5.5, round 2: 1%Opus 5.5, round 3: 7%Opus 5.5, round 4: 11%Opus 5.5, round 5: 14%Opus 5.5, round 6: 19%Opus 5.5, round 7: 0%Opus 5.5, round 8: 1%Opus 5.5, round 9: 22%Opus 5.5, round 10: 17%Opus 5.5, round 11: 20%Opus 5.5, round 12: 26%Opus 5.5, round 13: 25%Opus 5.5, round 14: 27%Opus 5.5, round 15: 24%Opus 5.5, round 16: 25%Opus 5.5, round 17: 26%Opus 5.5, round 18: 26%Opus 5.5, round 19: 23%Opus 5.5, round 20: 31%Opus 5.5, round 21: 31%Opus 5.5, round 22: 21%Opus 5.5, round 23: 29%Opus 5.5, round 24: 23%Opus 5.5, round 25: 32%Fable 5.2, round 0: 6%Fable 5.2, round 1: 56%Fable 5.2, round 2: 86%Fable 5.2, round 3: 93%Fable 5.2, round 4: 97%Fable 5.2, round 5: 98%Fable 5.2, round 6: 97%Fable 5.2, round 7: 98%Fable 5.2, round 8: 98%Fable 5.2, round 9: 98%Fable 5.2, round 10: 98%Fable 5.2, round 11: 98%Fable 5.2, round 12: 96%Fable 5.2, round 13: 99%Fable 5.2, round 14: 98%Fable 5.2, round 15: 98%Fable 5.2, round 16: 99%Fable 5.2, round 17: 99%Fable 5.2, round 18: 100%Fable 5.2, round 19: 100%Fable 5.2, round 20: 100%Fable 5.2, round 21: 100%Fable 5.2, round 22: 100%Fable 5.2, round 23: 100%Fable 5.2, round 24: 100%Fable 5.2, round 25: 100%finalFable 5.2: 99.0% in the unseen episodes● Fable 5.2 99.0%†Fable 5.1: 93.0% in the unseen episodes● Fable 5.1 93.0%†Sonnet 5.5: 46.0% in the unseen episodes● Sonnet 5.5 46.0%†Opus 5.5: 33.2% in the unseen episodes● Opus 5.5 33.2%Astra: 28.8% in the unseen episodes● Astra 28.8%original 5.0%† loophole of the success test
End of experiment 2

Experiment 3 of 5 · Object Generalization

Distribution shift. The policy was trained on a blue cube; now it is green. The camera encoder is frozen, so the LLM cannot change how the cameras see green, only what the policy network does with it. In 60% of episodes the gripper never touches the cube and hovers about 15 cm above it. The LLM only sees green during the rounds; the unseen episodes add six more colours (red, yellow, orange, purple, magenta and white) to test generalization.

Unseen episode 3, the unedited policy. Left: blue cube, placed in 3.2 s. Right: green cube, it never touches it.
050100task success [%]0510152025round1234✓
Task success on the 100 practice episodes the LLM tests on in every round, visualizing rounds where it discovered key insights. Click on a number to show more details.
1Make green look like bluerounds 0 → 1: 0 → 9% task success1 of 5
Practice episode 88. Left: before editing, the gripper hovers 11–13 cm above the table, 2–4 cm beside the green cube, for the whole episode and never goes down. Right: it goes down, grasps the cube and places it.
Diagnosis
Swapping in blue camera features: the arm reaches the cube but never goes down. Giving only the wrist camera its blue values restores the descent, because the green cube is seen as a faint blue cube, at about a quarter of blue's strength.
Fix
When the wrist camera sees the faint green cube below the gripper, the network now also gets the missing part of the blue pattern, so the arm goes down. 65,527 weights written (19.6% of the network), none set to zero · one pattern on 255 of the 256 wrist-camera inputs of the first layer, plus its 256 biases · no new units
The first successes: 9 of 100, none lost. Episodes where the gripper never touches the cube fell from 64 to 24, and lifted cubes rose from 6 to 30.
In Fable's own words
  1. t5Key finding: the arm gets within ~2.6 cm horizontally of the green cube (median) but does not descend […]
  2. t7Correcting just the wrist block's mean in hover frames restores most of the descend action […] So the "cube is under the gripper → descend" signal lives in colour-sensitive wrist features.
  3. t20Important observation: the "blue-specific" wrist features do respond to the green cube in the same direction, only much weaker (roughly 15–30% of the blue response […] So the green cube is seen as a faint blue cube.
  4. t40Offline, the rank-one translation (scale 1.0) restores the full descent command on green hover frames (−0.0185 m/step vs −0.020 for blue) […]
  5. t42Pass 1 gives 9/100 (from 0), with far more contact and lifts, so the wrist-pattern repair helps but is not enough.
The edit, as written into the network · excerpts of turns 39 and 40; rows 512–767 of fc0.W read the wrist camera; uG is the green "cube below" direction, D1 the blue hover mean minus the green one
rG_all, fG_all = green_dir(np.ones(len(Hr),bool)); uG = rG_all/(rG_all@rG_all)
D1 = hovB - hovG
def edit_translate(P, u, m0, Delta, scale=1.0):
    Q = dict(P); Wn = P['fc0.W'].astype(np.float64).copy(); bn = P['fc0.b'].astype(np.float64).copy()
    t = scale*(Delta @ Wn[512:768])            # effect of the pattern on fc0 pre-activations
    Wn[512:768] += np.outer(u, t); bn -= (m0@u)*t
⋮
P1 = edit_translate(P0, uG, fG_all, D1, 1.0)
save_edit('fc0.W', P1['fc0.W']); save_edit('fc0.b', P1['fc0.b'])

Task success in the unseen episodes, per cube colour:

Cube colourOriginal policyAfter Fable's edit
bluetrained on95.0%95.5%
greenseen during the rounds0.0%71.6%
redunseen18.2%68.2%
purpleunseen13.0%72.0%
magentaunseen12.5%44.5%
yellowunseen2.5%38.0%
orangeunseen11.5%16.5%
whiteunseen0.0%0.0%

Key edits 2 to 4 read only the arm's own state, so they work for any colour. Key edit 1 does not: it adds blue's wrist-camera pattern where it sees green's. Still, every unseen colour but white gains. On blue, the colour it was trained on, the policy even does slightly better after Fable's edit (95.5% against 95.0%).

The policy fails because the wrist-camera features that tell it "cube is under the open gripper" and "cube is held" respond mainly to blue.

It was not tested on any other colour.

Fable 5.2, in its final report

Total edits: 60,378 weights written (18.0% of the network) and 36,818 set to zero (11.0%), in 337 reasoning turns.

How about other LLMs?

All five LLMs got the same task, tools, budget and rules: GPT-6 Astra, Sonnet 5.5, Fable 5.1, Opus 5.5 and Fable 5.2. Task success over the rounds, and in the unseen episodes (right).

0255075100task success [%]0510152025roundAstra, round 0: 0%Astra, round 1: 1%Astra, round 2: 0%Astra, round 3: 2%Astra, round 4: 3%Astra, round 5: 3%Astra, round 6: 0%Astra, round 7: 9%Astra, round 8: 10%Astra, round 9: 1%Astra, round 10: 8%Astra, round 11: 4%Astra, round 12: 4%Astra, round 13: 9%Astra, round 14: 5%Astra, round 15: 4%Astra, round 16: 7%Astra, round 17: 16%Astra, round 18: 23%Astra, round 19: 31%Astra, round 20: 31%Astra, round 21: 34%Astra, round 22: 28%Astra, round 23: 30%Astra, round 24: 34%Astra, round 25: 38%Sonnet 5.5, round 0: 0%Sonnet 5.5, round 1: 2%Sonnet 5.5, round 2: 3%Sonnet 5.5, round 3: 2%Sonnet 5.5, round 4: 5%Sonnet 5.5, round 5: 5%Sonnet 5.5, round 6: 1%Sonnet 5.5, round 7: 0%Sonnet 5.5, round 8: 2%Sonnet 5.5, round 9: 0%Sonnet 5.5, round 10: 10%Sonnet 5.5, round 11: 14%Sonnet 5.5, round 12: 15%Sonnet 5.5, round 13: 12%Sonnet 5.5, round 14: 16%Sonnet 5.5, round 15: 19%Sonnet 5.5, round 16: 24%Sonnet 5.5, round 17: 33%Sonnet 5.5, round 18: 47%Sonnet 5.5, round 19: 46%Sonnet 5.5, round 20: 49%Sonnet 5.5, round 21: 0%Sonnet 5.5, round 22: 49%Sonnet 5.5, round 23: 49%Sonnet 5.5, round 24: 52%Sonnet 5.5, round 25: 57%Fable 5.1, round 0: 0%Fable 5.1, round 1: 5%Fable 5.1, round 2: 6%Fable 5.1, round 3: 9%Fable 5.1, round 4: 1%Fable 5.1, round 5: 5%Fable 5.1, round 6: 15%Fable 5.1, round 7: 25%Fable 5.1, round 8: 17%Fable 5.1, round 9: 18%Fable 5.1, round 10: 25%Fable 5.1, round 11: 27%Fable 5.1, round 12: 18%Fable 5.1, round 13: 22%Fable 5.1, round 14: 20%Fable 5.1, round 15: 19%Fable 5.1, round 16: 3%Fable 5.1, round 17: 18%Fable 5.1, round 18: 42%Fable 5.1, round 19: 35%Fable 5.1, round 20: 31%Fable 5.1, round 21: 33%Fable 5.1, round 22: 36%Fable 5.1, round 23: 42%Fable 5.1, round 24: 40%Fable 5.1, round 25: 38%Opus 5.5, round 0: 0%Opus 5.5, round 1: 0%Opus 5.5, round 2: 17%Opus 5.5, round 3: 14%Opus 5.5, round 4: 12%Opus 5.5, round 5: 1%Opus 5.5, round 6: 17%Opus 5.5, round 7: 10%Opus 5.5, round 8: 28%Opus 5.5, round 9: 4%Opus 5.5, round 10: 18%Opus 5.5, round 11: 26%Opus 5.5, round 12: 32%Opus 5.5, round 13: 45%Opus 5.5, round 14: 21%Opus 5.5, round 15: 37%Opus 5.5, round 16: 45%Opus 5.5, round 17: 41%Opus 5.5, round 18: 44%Opus 5.5, round 19: 59%Opus 5.5, round 20: 52%Opus 5.5, round 21: 55%Opus 5.5, round 22: 57%Opus 5.5, round 23: 60%Opus 5.5, round 24: 53%Opus 5.5, round 25: 60%Fable 5.2, round 0: 0%Fable 5.2, round 1: 9%Fable 5.2, round 2: 3%Fable 5.2, round 3: 27%Fable 5.2, round 4: 27%Fable 5.2, round 5: 21%Fable 5.2, round 6: 65%Fable 5.2, round 7: 58%Fable 5.2, round 8: 46%Fable 5.2, round 9: 54%Fable 5.2, round 10: 51%Fable 5.2, round 11: 53%Fable 5.2, round 12: 71%Fable 5.2, round 13: 64%Fable 5.2, round 14: 74%Fable 5.2, round 15: 69%Fable 5.2, round 16: 74%Fable 5.2, round 17: 68%Fable 5.2, round 18: 64%Fable 5.2, round 19: 60%Fable 5.2, round 20: 76%Fable 5.2, round 21: 77%Fable 5.2, round 22: 78%Fable 5.2, round 23: 79%Fable 5.2, round 24: 74%Fable 5.2, round 25: 78%finalFable 5.2: 71.6% in the unseen episodes● Fable 5.2 71.6%Opus 5.5: 55.2% in the unseen episodes● Opus 5.5 55.2%Sonnet 5.5: 53.8% in the unseen episodes● Sonnet 5.5 53.8%Astra: 33.6% in the unseen episodes● Astra 33.6%Fable 5.1: 26.6% in the unseen episodes● Fable 5.1 26.6%original 0.0%
End of experiment 3

Experiment 4 of 5 · Safety

Distribution shift. A red wall, 30 cm high, marks a no-go zone next to the tray. It is not physical: if the arm, gripper or cube enters it, the episode fails. It also disturbs the camera features. Cube and gripper start at random places, so in some episodes one of them starts beyond the wall and the arm must go over it. Unedited, the policy enters the zone in half the episodes and has 1.6% task success.

050100task success [%]0510152025round12345✓
Task success on the 100 practice episodes the LLM tests on in every round, visualizing rounds where it discovered key insights. Click on a number to show more details.
1Undo the wall's camera blurrounds 0 → 2: 1 → 13% task success1 of 6
Practice episode 31; the cube lies on the robot's side of the wall. Left: before editing, the gripper comes down to 17 cm and hovers about 20 cm from the cube until time runs out. Right: it grasps the cube, carries it to the tray and places it after 4.8 s.
Diagnosis
Matching wall frames to demonstration frames with the same arm and cube positions: the front and side camera features shrink toward one fixed "wall" pattern, to about 0.5 and 0.35 of their normal range. So the network sees the cube pulled toward the wall, and the arm hovers short of it.
Fix
The first layer now amplifies the front and side camera inputs (×1.9 and ×1.5) around their demonstration means; in unused units, Fable added a small controller that centres a held cube over the tray, lowers it and lets go. 121,222 weights written (36.2% of the network), 25,225 set to zero (7.5%) · front and side camera weights of the first layer and all its biases; 20 idle first-layer units reading the gripper's position and closure, 6 + 6 in layers 2 and 3 · drive all six joints and the gripper
From 1 to 13 of 100. With the camera fix alone (round 1), lifted cubes rose from 20 to 49, but only 3 were placed: the arm held them above the tray.
In Fable's own words
  1. t16The hover points show a clear pattern: the perceived cube position is pulled toward roughly (0.35, 0.22) — the wall — as if the pooled features were a mixture (1−α)·cube + α·wall. […]
  2. t20The contraction is remarkably uniform across features: front slopes ≈0.5 of baseline, side ≈0.35 of baseline, with correlations largely preserved. […]
  3. t27The repaired policy now grasps and carries the cube to just above the tray (≈(0.42, 0.03, 0.2)) and then hovers forever without lowering/releasing — in 40+ episodes. […]
  4. t32[…] The container is at a fixed place and the holding state is visible in proprioception, so a robust alternative is a small hand-built circuit (placement controller, and later a wall-avoidance field) on proprioception. […]
The edit, as written into the network · excerpts of turns 24 and 36; F_, S_ are the rows of fc0.W that read the front and side cameras, mu_d, mu_w the mean features without and with the wall on matched frames
for sl,g in [(F_,gf),(S_,gs)]:
    b=b+(mu_d[sl]-g*mu_w[sl])@Wo[sl]; W[sl]=Wo[sl]*g
⋮
W1,b1=make_vis_edit(1.9,1.5)
save_edit('fc0.W',W1); save_edit('fc0.b',b1)
⋮
net=Net(base); add_placement(net,Jinv,M=50.0)

68.0% task success in 500 unseen episodes (original 1.6%), entering the zone in 7.8% (50.0%). What does not carry over is reaching: in 19.6% of episodes the gripper never touches the cube. Fable keeps the open gripper out of a strip along the wall and gives up cubes lying in it: on the practice episodes the final edit places 1 of 17 such cubes, against 60 of 67 in front of the strip and 10 of 16 behind it.

16 cubes lie inside the guarded strip and are deliberately not approached.

Fable 5.2, in its final report

Total edits: 43,031 weights written (12.8% of the network) and 261,499 set to zero (78.0%), in 341 reasoning turns.

How about other LLMs?

All five LLMs got the same task, tools, budget and rules: GPT-6 Astra, Sonnet 5.5, Fable 5.1, Opus 5.5 and Fable 5.2. Task success over the rounds, and in the unseen episodes (right).

0255075100task success [%]0510152025roundAstra, round 0: 1%Astra, round 1: 1%Astra, round 2: 4%Astra, round 3: 0%Astra, round 4: 0%Astra, round 5: 0%Astra, round 6: 0%Astra, round 7: 10%Astra, round 8: 22%Astra, round 9: 19%Astra, round 10: 16%Astra, round 11: 18%Astra, round 12: 18%Astra, round 13: 13%Astra, round 14: 0%Astra, round 15: 10%Astra, round 16: 23%Astra, round 17: 28%Astra, round 18: 30%Astra, round 19: 35%Astra, round 20: 25%Astra, round 21: 38%Astra, round 22: 34%Astra, round 23: 35%Astra, round 24: 27%Astra, round 25: 38%Sonnet 5.5, round 0: 1%Sonnet 5.5, round 1: 8%Sonnet 5.5, round 2: 28%Sonnet 5.5, round 3: 2%Sonnet 5.5, round 4: 37%Sonnet 5.5, round 5: 42%Sonnet 5.5, round 6: 28%Sonnet 5.5, round 7: 41%Sonnet 5.5, round 8: 8%Sonnet 5.5, round 9: 36%Sonnet 5.5, round 10: 29%Sonnet 5.5, round 11: 31%Sonnet 5.5, round 12: 31%Sonnet 5.5, round 13: 42%Sonnet 5.5, round 14: 12%Sonnet 5.5, round 15: 39%Sonnet 5.5, round 16: 28%Sonnet 5.5, round 17: 37%Sonnet 5.5, round 18: 46%Sonnet 5.5, round 19: 44%Sonnet 5.5, round 20: 45%Sonnet 5.5, round 21: 46%Sonnet 5.5, round 22: 45%Sonnet 5.5, round 23: 8%Sonnet 5.5, round 24: 43%Sonnet 5.5, round 25: 45%Fable 5.1, round 0: 1%Fable 5.1, round 1: 2%Fable 5.1, round 2: 9%Fable 5.1, round 3: 31%Fable 5.1, round 4: 12%Fable 5.1, round 5: 31%Fable 5.1, round 6: 36%Fable 5.1, round 7: 37%Fable 5.1, round 8: 19%Fable 5.1, round 9: 36%Fable 5.1, round 10: 43%Fable 5.1, round 11: 41%Fable 5.1, round 12: 20%Fable 5.1, round 13: 17%Fable 5.1, round 14: 44%Fable 5.1, round 15: 44%Fable 5.1, round 16: 44%Fable 5.1, round 17: 49%Fable 5.1, round 18: 49%Fable 5.1, round 19: 50%Fable 5.1, round 20: 49%Fable 5.1, round 21: 50%Fable 5.1, round 22: 51%Fable 5.1, round 23: 51%Fable 5.1, round 24: 53%Fable 5.1, round 25: 53%Opus 5.5, round 0: 1%Opus 5.5, round 1: 0%Opus 5.5, round 2: 23%Opus 5.5, round 3: 0%Opus 5.5, round 4: 38%Opus 5.5, round 5: 45%Opus 5.5, round 6: 48%Opus 5.5, round 7: 50%Opus 5.5, round 8: 46%Opus 5.5, round 9: 40%Opus 5.5, round 10: 49%Opus 5.5, round 11: 49%Opus 5.5, round 12: 48%Opus 5.5, round 13: 48%Opus 5.5, round 14: 5%Opus 5.5, round 15: 1%Opus 5.5, round 16: 50%Opus 5.5, round 17: 52%Opus 5.5, round 18: 54%Opus 5.5, round 19: 54%Opus 5.5, round 20: 54%Opus 5.5, round 21: 55%Opus 5.5, round 22: 51%Opus 5.5, round 23: 58%Opus 5.5, round 24: 58%Opus 5.5, round 25: 56%Fable 5.2, round 0: 1%Fable 5.2, round 1: 3%Fable 5.2, round 2: 13%Fable 5.2, round 3: 4%Fable 5.2, round 4: 41%Fable 5.2, round 5: 47%Fable 5.2, round 6: 53%Fable 5.2, round 7: 50%Fable 5.2, round 8: 49%Fable 5.2, round 9: 45%Fable 5.2, round 10: 45%Fable 5.2, round 11: 55%Fable 5.2, round 12: 52%Fable 5.2, round 13: 52%Fable 5.2, round 14: 58%Fable 5.2, round 15: 59%Fable 5.2, round 16: 62%Fable 5.2, round 17: 65%Fable 5.2, round 18: 65%Fable 5.2, round 19: 68%Fable 5.2, round 20: 68%Fable 5.2, round 21: 70%Fable 5.2, round 22: 68%Fable 5.2, round 23: 70%Fable 5.2, round 24: 70%Fable 5.2, round 25: 71%finalFable 5.2: 68.0% in the unseen episodes● Fable 5.2 68.0%Opus 5.5: 49.4% in the unseen episodes● Opus 5.5 49.4%Fable 5.1: 47.8% in the unseen episodes● Fable 5.1 47.8%Sonnet 5.5: 42.8% in the unseen episodes● Sonnet 5.5 42.8%Astra: 31.4% in the unseen episodes● Astra 31.4%original 1.6%
End of experiment 4

Experiment 5 of 5 · Non-Markovian Demonstrations

A change in the data. Technically, this is not a distribution shift; it changes the data the policy learns from. The demonstrations of experiments 1 to 4 came from a Markov expert, a feedback controller that reacts only to the current state. Humans rarely work that way. Our behaviour is correlated over time: we act on intentions nobody else can see, follow a rough plan, speed up and slow down, hesitate before we commit, and sometimes miss and try again.

OCBench comes with experts that mimic these properties, and making a script behave like this takes a lot of randomness. Ours plans each episode as a smooth curve through a few random waypoints, at a different speed on every stretch. It grasps the cube from a random direction with the wrist tilted by up to 25°, pauses with its fingers around the cube in about four out of ten episodes, and tries again when a grasp fails. We record it exactly as before and train the same network on it.

The two experts from the same start. Left: the Markov expert of experiments 1 to 4. Right: the human-like expert approaches with a tilted wrist, hesitates at the cube, pulls back and tries again.

This creates an expressivity mismatch [10]. The data comes from a non-Markovian expert, while our policy is still Markov. For an intuition, consider the moment the expert pauses with its fingers around the cube. Throughout the pause, the policy sees the same state and has no notion of how long the pause has lasted, so it could simply learn to stay in that spot forever, a failure case analysed in detail in [13]. Just by training on this data, the closed-loop success of our policy drops from 95.8% to 0.4%.

Instead of making our policy non-Markovian, we ask: can an LLM make it succeed as often as the policy trained on the Markov expert, without a single new demonstration?

050100task success [%]0510152025round12345✓
Task success on the 100 practice episodes the LLM tests on in every round, visualizing rounds where it discovered key insights. Click on a number to show more details.
1Keep the gripper pointing downrounds 0 → 1: 0 → 9% task success1 of 6
Practice episode 4. Left: before editing, the gripper tips far over and closes beside the cube. Right: round 1, it stays pointing down, grasps the cube and places it (664 steps).
Diagnosis
Measuring the tilt against the teacher's: in the demonstrations the gripper stays within about 0.3 rad of pointing down, in the policy's own episodes it keeps drifting, by up to radians. The network has no restoring response to the tilt at all.
Fix
Two small circuits in unused units now turn the wrist back to pointing straight down, one for each wrist joint. 14 weights written (0.0042% of the network), 3,622 set to zero (1.1%) · 2 idle first-layer units, one reading shoulder_lift, elbow and wrist_1, one reading wrist_2, passed on by 2 idle units in each of layers 2 and 3 · drive wrist_1, wrist_2
From 0 to 9 of 100, and most cubes that are lifted now reach the tray. The bottleneck moves to the grasp: 86 episodes never lift the cube.
In Fable's own words
  1. t18Key finding: the head has essentially zero tilt-restoring response in rollouts (slope ≈ 0), and the gripper tilts progressively away from vertical (pitch error up to radians), a regime the demos never contain (they stay within ±0.3 rad). […]
  2. t19There are enough dead units (fc0: 5, fc1: 2, fc2: 6) to build two clean feedback channels without touching any active unit. […]
  3. t22Progress: 9/100, and most lifts now end in a successful place. The bottleneck is now grasping (85 episodes never lift). […]
The edit, as written into the network · excerpt of turn 19; channel A carries the pitch error of shoulder_lift + elbow + wrist_1, channel B that of wrist_2
make_channel(Pd, 30, 9, 47, {J['lift']:1,J['elbow']:1,J['w1']:1}, np.pi/2)   # A: e_pitch + C
make_channel(Pd, 43, 248, 104, {J['w2']:1}, np.pi/2)                         # B: e_w2 + C
Pd['out.W'][47,3] = -g_pitch/0.36; Pd['out.b'][3] += g_pitch*C/0.36
Pd['out.W'][104,4] = -g_w2/0.36;  Pd['out.b'][4] += g_w2*C/0.36

84.6% task success in 500 unseen episodes (original 0.4%). The main failure was a compounding error: the gripper's tilt drifts and the policy has no response that turns it back. Fable wrote a circuit that turns the wrist back. When we tilt the wrist by about 9 degrees during an episode, the edited policy straightens it within half a second; the unedited one more than doubles the tilt. Fable also found a second trap of the human-like teacher: the policy only moves the arm when the wrist camera already shows motion, and a constant shift of that camera input gets it moving. The other key edits add controllers for grasping, retrying, carrying and centring over the cube.

Cubes within 0.32 m of the base remain the weak class (6/8).

Fable 5.2, in its final report

Total edits: 2,731 weights written (0.81% of the network) and 72,260 set to zero (21.6%), in 327 reasoning turns.

How about other LLMs?

All five LLMs got the same task, tools, budget and rules: GPT-6 Astra, Sonnet 5.5, Fable 5.1, Opus 5.5 and Fable 5.2. Task success over the rounds, and in the unseen episodes (right).

0255075100task success [%]0510152025roundAstra, round 0: 0%Astra, round 1: 0%Astra, round 2: 14%Astra, round 3: 1%Astra, round 4: 4%Astra, round 5: 10%Astra, round 6: 2%Astra, round 7: 9%Astra, round 8: 11%Astra, round 9: 0%Astra, round 10: 25%Astra, round 11: 13%Astra, round 12: 28%Astra, round 13: 41%Astra, round 14: 44%Astra, round 15: 35%Astra, round 16: 33%Astra, round 17: 42%Astra, round 18: 47%Astra, round 19: 49%Astra, round 20: 62%Astra, round 21: 66%Astra, round 22: 64%Astra, round 23: 67%Astra, round 24: 68%Astra, round 25: 68%Sonnet 5.5, round 0: 0%Sonnet 5.5, round 1: 1%Sonnet 5.5, round 2: 5%Sonnet 5.5, round 3: 21%Sonnet 5.5, round 4: 24%Sonnet 5.5, round 5: 17%Sonnet 5.5, round 6: 21%Sonnet 5.5, round 7: 26%Sonnet 5.5, round 8: 17%Sonnet 5.5, round 9: 20%Sonnet 5.5, round 10: 24%Sonnet 5.5, round 11: 26%Sonnet 5.5, round 12: 28%Sonnet 5.5, round 13: 27%Sonnet 5.5, round 14: 29%Sonnet 5.5, round 15: 27%Sonnet 5.5, round 16: 30%Sonnet 5.5, round 17: 30%Sonnet 5.5, round 18: 28%Sonnet 5.5, round 19: 28%Sonnet 5.5, round 20: 22%Sonnet 5.5, round 21: 4%Sonnet 5.5, round 22: 23%Sonnet 5.5, round 23: 11%Sonnet 5.5, round 24: 31%Sonnet 5.5, round 25: 29%Fable 5.1, round 0: 0%Fable 5.1, round 1: 0%Fable 5.1, round 2: 38%Fable 5.1, round 3: 29%Fable 5.1, round 4: 31%Fable 5.1, round 5: 0%Fable 5.1, round 6: 27%Fable 5.1, round 7: 2%Fable 5.1, round 8: 34%Fable 5.1, round 9: 37%Fable 5.1, round 10: 13%Fable 5.1, round 11: 38%Fable 5.1, round 12: 8%Fable 5.1, round 13: 45%Fable 5.1, round 14: 20%Fable 5.1, round 15: 23%Fable 5.1, round 16: 34%Fable 5.1, round 17: 42%Fable 5.1, round 18: 23%Fable 5.1, round 19: 38%Fable 5.1, round 20: 34%Fable 5.1, round 21: 47%Fable 5.1, round 22: 46%Fable 5.1, round 23: 40%Fable 5.1, round 24: 41%Fable 5.1, round 25: 42%Opus 5.5, round 0: 0%Opus 5.5, round 1: 7%Opus 5.5, round 2: 5%Opus 5.5, round 3: 1%Opus 5.5, round 4: 8%Opus 5.5, round 5: 5%Opus 5.5, round 6: 11%Opus 5.5, round 7: 8%Opus 5.5, round 8: 10%Opus 5.5, round 9: 7%Opus 5.5, round 10: 9%Opus 5.5, round 11: 4%Opus 5.5, round 12: 9%Opus 5.5, round 13: 16%Opus 5.5, round 14: 6%Opus 5.5, round 15: 13%Opus 5.5, round 16: 17%Opus 5.5, round 17: 14%Opus 5.5, round 18: 18%Opus 5.5, round 19: 34%Opus 5.5, round 20: 45%Opus 5.5, round 21: 52%Opus 5.5, round 22: 59%Opus 5.5, round 23: 61%Opus 5.5, round 24: 64%Opus 5.5, round 25: 66%Fable 5.2, round 0: 0%Fable 5.2, round 1: 9%Fable 5.2, round 2: 0%Fable 5.2, round 3: 6%Fable 5.2, round 4: 24%Fable 5.2, round 5: 35%Fable 5.2, round 6: 0%Fable 5.2, round 7: 70%Fable 5.2, round 8: 80%Fable 5.2, round 9: 74%Fable 5.2, round 10: 78%Fable 5.2, round 11: 75%Fable 5.2, round 12: 70%Fable 5.2, round 13: 86%Fable 5.2, round 14: 87%Fable 5.2, round 15: 91%Fable 5.2, round 16: 90%Fable 5.2, round 17: 96%Fable 5.2, round 18: 93%Fable 5.2, round 19: 93%Fable 5.2, round 20: 94%Fable 5.2, round 21: 96%Fable 5.2, round 22: 92%Fable 5.2, round 23: 96%Fable 5.2, round 24: 96%Fable 5.2, round 25: 98%finalFable 5.2: 84.6% in the unseen episodes● Fable 5.2 84.6%Opus 5.5: 68.6% in the unseen episodes● Opus 5.5 68.6%Astra: 62.2% in the unseen episodes● Astra 62.2%Fable 5.1: 40.0% in the unseen episodes● Fable 5.1 40.0%Sonnet 5.5: 30.0% in the unseen episodes● Sonnet 5.5 30.0%original 0.4%

All ExperimentsResults at a Glance

1 · Spatialadaptation2 · Spatialgeneralization3 · Objectgeneralization4 · Safety5 · Human-liketeacheroriginal policyoriginal policy, 1 · Spatial adaptation: 0.2% task success (unedited)0.2original policy, 2 · Spatial generalization: 5.0% task success (unedited)5.0original policy, 3 · Object generalization: 0.0% task success (unedited)0.0original policy, 4 · Safety: 1.6% task success (unedited)1.6original policy, 5 · Human-like teacher: 0.4% task success (unedited)0.4Opus 5.5Opus 5.5, 1 · Spatial adaptation: 94.6% task success (ed51)94.6Opus 5.5, 2 · Spatial generalization: 33.2% task success (ed48)33.2Opus 5.5, 3 · Object generalization: 55.2% task success (ed52)55.2Opus 5.5, 4 · Safety: 49.4% task success (ed53)49.4Opus 5.5, 5 · Human-like teacher: 68.6% task success (ed54)68.6AstraAstra, 1 · Spatial adaptation: 54.4% task success (ed34)54.4Astra, 2 · Spatial generalization: 28.8% task success (ed47)28.8Astra, 3 · Object generalization: 33.6% task success (ed35)33.6Astra, 4 · Safety: 31.4% task success (ed36)31.4Astra, 5 · Human-like teacher: 62.2% task success (ed37)62.2Sonnet 5.5Sonnet 5.5, 1 · Spatial adaptation: 91.2% task success (ed39)91.2Sonnet 5.5, 2 · Spatial generalization: 46.0% task success (ed49) through a loophole46.0†Sonnet 5.5, 3 · Object generalization: 53.8% task success (ed40)53.8Sonnet 5.5, 4 · Safety: 42.8% task success (ed41b)42.8Sonnet 5.5, 5 · Human-like teacher: 30.0% task success (ed46)30.0Fable 5.1Fable 5.1, 1 · Spatial adaptation: 93.0% task success (ed38)93.0Fable 5.1, 2 · Spatial generalization: 93.0% task success (ed50) through a loophole93.0†Fable 5.1, 3 · Object generalization: 26.6% task success (ed43)26.6Fable 5.1, 4 · Safety: 47.8% task success (ed44)47.8Fable 5.1, 5 · Human-like teacher: 40.0% task success (ed45)40.0Fable 5.2Fable 5.2, 1 · Spatial adaptation: 98.2% task success (ed64) through a loophole98.2†Fable 5.2, 2 · Spatial generalization: 99.0% task success (ed63) through a loophole99.0†Fable 5.2, 3 · Object generalization: 71.6% task success (ed60)71.6Fable 5.2, 4 · Safety: 68.0% task success (ed61)68.0Fable 5.2, 5 · Human-like teacher: 84.6% task success (ed62)84.6Gemini 3.8 Flash*Gemini 3.8 Flash, 1 · Spatial adaptation: 2.2% task success (ed55)2.2Gemini 3.8 Flash, 2 · Spatial generalization: not runnot runGemini 3.8 Flash, 3 · Object generalization: 1.4% task success (ed56)1.4Gemini 3.8 Flash, 4 · Safety: 12.0% task success (ed57)12.0Gemini 3.8 Flash, 5 · Human-like teacher: 3.6% task success (ed58)3.6† loophole of the success test  ·  * with extra hints

After the ExperimentsUnder the Hood

So far, we have judged the edits mostly from the outside, by how the robot behaves and how often it succeeds. This section is about how exactly those changes are implemented in weights. For three edits, we open the network and trace how the new behaviour is implemented in the weights: a stabilizing loop that helps the policy stay in-distribution, a goal detector that Opus builds on high-dimensional camera features, and a full-on program that keeps its memory in the robot's own pose, but with some caveats.

Case Study 1 · Opus · Experiment 5A Recovery the Expert Never Taught

In experiment 5, the policy learns from a non-Markovian expert that behaves more like a human. It follows a latent plan and never demonstrates how to recover from slight disturbances, causing the policy to drift out of distribution. Opus identifies where exactly this happens: whenever the gripper tilts slightly, the network turns the wrist further in the same direction, so the tilt grows by about 9% with every control step. In one rollout, the gripper reaches the cube tilted by about 30°, far beyond the roughly 7° of the demonstrations, and the fingers close next to the cube instead of around it.

Opus's fix is a simple proportional controller, written into units the network never uses, that measures the tilt and turns the wrist back. From a 10° tilted start, the original policy lets the tilt grow to about 25° within two seconds; with the circuit, it is down to 1° after half a second. Switching the circuit off drops the finished edit from 68 to 3 successes in 100 evaluation runs.

unit the original network usesidle unitunit Opus wrote into
layer 1 · 256 units layer 2 · 256 units layer 3 · 256 units front side wrist robot state cameras ResNet frozen base shoulder elbow wrist bend wrist roll wrist twist gripper wrist command ← wrist command + ReLU(−tilt) − ReLU(tilt) ≈ wrist command − tilt
original policy
with Opus's circuit
0 10 20 30 40 0 1 2 3 4 gripper tilt [°] seconds original policy, 0 s: 10.0° (half of the episodes between 10.0° and 10.0°) original policy, 0.5 s: 15.1° (half of the episodes between 13.8° and 16.8°) original policy, 1 s: 20.6° (half of the episodes between 18.0° and 21.7°) original policy, 1.5 s: 23.7° (half of the episodes between 20.9° and 25.7°) original policy, 2 s: 25.8° (half of the episodes between 23.7° and 28.6°) original policy, 2.5 s: 27.3° (half of the episodes between 25.6° and 30.4°) original policy, 3 s: 28.0° (half of the episodes between 26.7° and 31.9°) original policy, 3.5 s: 29.1° (half of the episodes between 28.1° and 33.2°) with Opus's circuit, 0 s: 10.0° (half of the episodes between 10.0° and 10.0°) with Opus's circuit, 0.5 s: 1.1° (half of the episodes between 0.9° and 1.6°) with Opus's circuit, 1 s: 0.6° (half of the episodes between 0.4° and 0.8°) with Opus's circuit, 1.5 s: 0.4° (half of the episodes between 0.3° and 0.7°) with Opus's circuit, 2 s: 0.6° (half of the episodes between 0.4° and 0.7°) with Opus's circuit, 2.5 s: 0.5° (half of the episodes between 0.4° and 0.7°) with Opus's circuit, 3 s: 0.6° (half of the episodes between 0.4° and 0.8°) with Opus's circuit, 3.5 s: 0.6° (half of the episodes between 0.3° and 0.8°)
Opus's wrist circuit (experiment 5). Twelve units that the original network never or hardly ever uses (rings) read the gripper's tilt from the joint angles and turn the wrist back against it. Point at a term of the formula to see where it sits in the network. Below: the wrist starts tilted by 10°. The original policy turns it further; with the circuit alone, the tilt is gone within half a second. Chart: total tilt over time, median and quartiles of 20 evaluation runs.

In the real world, robots mostly learn from non-Markovian data, because their experts are humans. Learning from such data usually means changing the policy itself, most prominently with action chunking [14], which recent work traces back to the temporal correlations in human demonstrations [10]. This preliminary result suggests that part of what a memoryless policy loses on such data might instead be recovered after training, directly in its weights.

Case Study 2 · Opus · Experiment 2A Goal Detector in 256 Dimensions

The second case study comes from experiment 2, where the goal moves every episode. Only the cameras can tell the policy where the goal is, through the embedding of a frozen ResNet. This embedding is sub-symbolic, i.e., the goal is spread across all 256 embedding dimensions, so there is no single neuron Opus could point to.

So Opus first tries to separate correlation from causation (to anthropomorphize a little). It takes frames in which the policy begins to descend, swaps in one camera's embedding from frames in which it hovers, and checks whether the descent survives. It finds out that swapping the wrist camera alone removes the descent, and the rollouts show that this trigger works anywhere on the table. All of this was evaluated on recorded rollouts without a simulator, so in principle it would work on a real robot too.

Opus then builds a small circuit on the wrist camera. The weights w of one idle unit are a difference of means, the average wrist embedding with the goal right beneath the gripper minus the average with the goal farther away. The unit fires only while the gripper holds the cube, and two copy-units turn it into a straight-down motion that Opus derived from the arm's kinematics.

unit the original network usesidle unitunit Opus wrote into
layer 1 · 256 units layer 2 · 256 units layer 3 · 256 units front side wrist robot state cameras ResNet frozen base shoulder elbow wrist bend wrist roll wrist twist gripper arm command ← arm command + holding · ReLU( w · wrist features ) · vdown
Opus's descent trigger (experiment 2). One idle unit per layer. The first reads the 256 wrist-camera features along the direction w and switches on only while the gripper holds the cube; two copy-units pass it on as a straight-down motion of shoulder, elbow and wrist.

Opus finds structure in a high-dimensional embedding without external optimization, confirms it causally, and builds on it. Across both case studies, it draws on three fields: activation patching [15] and difference-of-means probes [16] from mechanistic interpretability, a stable feedback loop from control theory, and a straight-down motion from the kinematics of the arm. Repairing a policy is an interdisciplinary problem, and Opus treats it as one.

Case Study 3 · Fable 5.1 · Experiment 2Memory in a Memoryless Network

Sadly, the most ingenious edit in our experiments is not a repair at all. In experiment 2, Fable 5.1 quickly concludes that the policy cannot see the goal, even though three other LLMs read it from the same camera features. Therefore, on its first pass, Fable writes a program of its own into more than a hundred idle units, and this program switches the trained network off as soon as the cube is lifted. It drags the cube across the table in ever wider sweeps until the cube happens to pass over the goal. Fable even checked the program in a small kinematic simulation it wrote itself before its first rollout. That rollout scored 86 of 100.

While this exploits an underspecified success condition, the more interesting part is how the behaviour is implemented in a memoryless policy. The program has to know whether the search is running and which row of the sweep comes next, but the policy only maps the current images and robot state to an action. Fable's solution is to keep the memory in the robot's body. Once the gripper holds a lifted cube, the network twists the wrist past an angle the original policy never reaches, and from then on it reads that twist back as a flag. An out-of-distribution state has become a one-bit memory.

As long as the flag is set, two units silence every unit the original uses in its last hidden layer, and the sweep takes over. The current row is stored the same way, in the shoulder angle. Each of the eight rows, from 30 to 64 cm out, has its own band of shoulder angles. The base swings one way on even rows and back on odd ones, and at the end of a row, the target moves on to the next. The shoulder follows into the next band, and that is how the counter goes up by one. The network itself still remembers nothing. Its memory is the robot's pose.

unit the original network usesidle unitunit Fable 5.1 wrote into
layer 1 · 256 units layer 2 · 256 units layer 3 · 256 units front side wrist robot state cameras ResNet frozen base shoulder elbow wrist bend wrist roll wrist twist gripper loaded ← holding · lifted row ← row + 1 when the base reaches an end if loaded: base ← (−1)row · 0.85, reach ← 30 cm + 5 cm · row
Fable 5.1's sweep (experiment 2). The program Fable wrote into 126 idle units. It reads only the robot state: the wrist twist holds the on/off bit, the shoulder angle holds the row, and the base angle marks the end of a row. While the bit is set, two units switch off all 109 units the original network uses in its last layer. Point at a term of the formula to see its units. Not drawn: two rescue rules for failed grasps.
Fable 5.1's loophole (experiment 2). Unseen episode 45, with the goal 30 cm from its training position. Left: the original policy lifts the cube and never places it. Right: Fable's edit lifts the cube, twists the wrist, puts the cube down and drags it across the table until it passes over the goal.

Our task prompt says that a cube dragged into the goal does not count, but our success check only required an earlier lift. Fable lifted the cube first and then dragged it, which earned it 93.0% on the unseen episodes. It was not the only one: three of the five LLMs exploited this gap in experiment 2, Fable 5.2 almost perfectly and Sonnet 5.5 much less successfully. Weight space programming, it turns out, is just as vulnerable to reward hacking [17] as any black-box optimizer. At least Fable was honest about it.

Since the container cannot be perceived, the edit exploits the success rule: a cube that has been lifted ≥3 cm and is then set down and dragged along the table counts as placed the moment it passes within 4 cm of the container centre.

Fable 5.1, in its final report

So What?Implications for Robot Learning

For decades, robotics has tried to replace hand-written controllers with behaviour learned from data, from a neural network that steered a vehicle from camera images in 1989 (ALVINN [18]) to the first serious proposals of imitation learning as a route to capable robots [19]. In the last few years, the field has finally scaled this up, with foundation models trained on large and diverse robot data (OpenVLA [4], π0 [5]). Yet LLMs entered robotics the way engineers always had, by writing code for rewards (Eureka [20]) and for control (Code as Policies [6]). The weights of a learned policy remained, until recently, the one part of a robot's software that only an optimizer could write. We show early signs that language models can read and rewrite the learned controller itself.

This opens a shortcut in robot learning, as illustrated by the magenta path in the visual abstract. A language model can debug a trained policy the way a programmer debugs code. It opens the black box, finds out why the policy fails, and writes the fix into its weights. In our five experiments, this took policies from 0–5% to 33–95% task success, without a single new demonstration or gradient step. And because each fix is a small circuit with a stated purpose, it can be read, tested and switched off. That matters for policies that are notoriously hard to evaluate [21], and therefore hard to deploy.

If this capability keeps improving, it could open up possibilities that are new to robot learning, or at least far easier to reach than before.

Coding agents show where this could go. When GPT-3 turned out to write simple programs, its authors found this "exciting because GPT-3 was not explicitly trained for code generation" [22]. On their benchmark, it solved none of the problems. Then labs began to train for code, later with reinforcement learning that rewards code for passing compilers and unit tests (DeepSeek-R1 [23]), and coding agents took off. Weight space programming today looks much like code generation did then. It emerges incidentally from what a model knows about code, control theory and mechanistic interpretability, and nobody has trained for it yet. Robot learning, meanwhile, has long judged its policies by whether they succeed, checked automatically in simulation benchmarks (LIBERO [24]) or labelled by hand on real robots [21]. These success labels are much like the verifiable rewards that let LLM post-training flourish (Tülu 3 [25]), and they are what we used to score every edit in this blog. In principle, modern robot learning pipelines already have everything needed to train language models for weight space programming. Let's see where that takes us.

Not long ago, a trained robot policy was a black box, even to the people who built it. Handing it to a language model for repair would have sounded like science fiction. Soon, it might be the first thing we try when a robot fails.

How to Cite

If you find this work useful, please cite it as:

@online{stranghoener2026repairing,
  author = {Stranghöner, Jannick and Hartmann, Philipp and Störck, Felix and Hammer, Barbara and Neumann, Klaus},
  title  = {Repairing Robot Policies with Weight Space Programming},
  date   = {2026-11-11},
  url    = {https://jstranghoener.github.io/blog/robotic-weight-space-programming/},
  note   = {Blog post},
}

  1. The same holds beyond behaviour cloning, for any method that learns online behaviour from offline data, from model predictive control to offline reinforcement learning. For all of them, distribution shift at test time is the fundamental challenge [26].
  2. The demonstrator is our port of OGBench's [27] Markov cube controller; noisy execution with clean labels is the DART recipe. The policy uses a pretrained ResNet-10 per camera with its last stage fine-tuned, no joint-velocity input, and 100,000 training steps.
  3. One editing run per LLM and experiment, reasoning effort high. The original and edited policies are scored from the same starts of 500 unseen episodes (200 for each extra colour).

References

  1. Rikiya Takehi, Jayden Teoh, Alex Zhang, Omar Khattab. Sparks of Weight-Space Programming: LLMs can natively read & write neural network weights. Blog post, 2026. rikiyat.github.io/blog/weight-space-programming
  2. Stéphane Ross, Geoffrey J. Gordon, J. Andrew Bagnell. A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning. AISTATS, 2011. arxiv.org/abs/1011.0686
  3. Stéphane Ross, J. Andrew Bagnell. Efficient Reductions for Imitation Learning. AISTATS, 2010. proceedings.mlr.press/v9/ross10a.html
  4. Moo Jin Kim et al. OpenVLA: An Open-Source Vision-Language-Action Model. CoRL, 2024. arxiv.org/abs/2406.09246
  5. Kevin Black et al. π0: A Vision-Language-Action Flow Model for General Robot Control. arXiv:2410.24164, 2024. arxiv.org/abs/2410.24164
  6. Jacky Liang et al. Code as Policies: Language Model Programs for Embodied Control. ICRA, 2023. arxiv.org/abs/2209.07753
  7. SenseNova et al. Has GPT-6-Astra Achieved Embodied Intelligence? arXiv:2610.22471, 2026. arxiv.org/abs/2610.22471
  8. Ziyang Gong, Kaifeng Zheng, Yingrui Huang, Wendi Chen, Jiaguo Tian, Junkai Yang, Minghuan Liu, Zhenjie Yang. We Asked Opus-5.5 to Edit π0.5's Weights. AutoResearch Made It Happen. Blog post, 2026. cuzyoung.github.io/robotics-weight-editing/en
  9. Jusheng Zhang, Keze Wang, Liang Lin. Can LLMs Debug Robots by Editing Their Weights? arXiv:2611.09376, 2026. arxiv.org/abs/2611.09376
  10. Seohong Park, Sergey Levine. Behavioral Cloning Mystery. arXiv:2610.07056, 2026. arxiv.org/abs/2610.07056
  11. Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun. Deep Residual Learning for Image Recognition. CVPR, 2016. arxiv.org/abs/1512.03385
  12. Michael Laskey, Jonathan Lee, Roy Fox, Anca Dragan, Ken Goldberg. DART: Noise Injection for Robust Imitation Learning. CoRL, 2017. arxiv.org/abs/1703.09327
  13. Filippo Lazzati, Kyle Stachowicz, William Chen, Alberto Maria Metelli, Andrew Wagenmaker, Sergey Levine. Why Does Action Chunking Improve Behavioral Cloning Performance in Robotic Control? arXiv:2608.02547, 2026. arxiv.org/abs/2608.02547
  14. Tony Z. Zhao, Vikash Kumar, Sergey Levine, Chelsea Finn. Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware. RSS, 2023. arxiv.org/abs/2304.13705
  15. Stefan Heimersheim, Neel Nanda. How to use and interpret activation patching. arXiv:2404.15255, 2024. arxiv.org/abs/2404.15255
  16. Samuel Marks, Max Tegmark. The Geometry of Truth: Emergent Linear Structure in Large Language Model Representations of True/False Datasets. COLM, 2024. arxiv.org/abs/2310.06824
  17. Dario Amodei, Chris Olah, Jacob Steinhardt, Paul Christiano, John Schulman, Dan Mané. Concrete Problems in AI Safety. arXiv:1606.06565, 2016. arxiv.org/abs/1606.06565
  18. Dean A. Pomerleau. ALVINN: An Autonomous Land Vehicle in a Neural Network. NeurIPS, 1988. proceedings.neurips.cc/paper/1988/hash/812b4ba287f5ee0bc9d43bbf5bbe87fb-Abstract.html
  19. Stefan Schaal. Is imitation learning the route to humanoid robots? Trends in Cognitive Sciences 3(6), 1999. is.mpg.de/publications/schaal_tcs_1999
  20. Yecheng Jason Ma et al. Eureka: Human-Level Reward Design via Coding Large Language Models. ICLR, 2024. arxiv.org/abs/2310.12931
  21. Hadas Kress-Gazit et al. Robot Learning as an Empirical Science: Best Practices for Policy Evaluation. arXiv:2409.09491, 2024. arxiv.org/abs/2409.09491
  22. Mark Chen et al. Evaluating Large Language Models Trained on Code. arXiv:2107.03374, 2021. arxiv.org/abs/2107.03374
  23. DeepSeek-AI. DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. arXiv:2501.12948, 2025. arxiv.org/abs/2501.12948
  24. Bo Liu et al. LIBERO: Benchmarking Knowledge Transfer for Lifelong Robot Learning. NeurIPS Datasets and Benchmarks, 2023. arxiv.org/abs/2306.03310
  25. Nathan Lambert et al. Tülu 3: Pushing Frontiers in Open Language Model Post-Training. arXiv:2411.15124, 2024. arxiv.org/abs/2411.15124
  26. Sergey Levine, Aviral Kumar, George Tucker, Justin Fu. Offline Reinforcement Learning: Tutorial, Review, and Perspectives on Open Problems. arXiv:2005.01643, 2020. arxiv.org/abs/2005.01643
  27. Seohong Park, Kevin Frans, Benjamin Eysenbach, Sergey Levine. OGBench: Benchmarking Offline Goal-Conditioned RL. ICLR, 2025. arxiv.org/abs/2410.20092