Zichuan Xu
All posts

Closing the loop: a simple rule beats an agent-written weight edit

An LLM agent spent 20 hours writing a weight edit that stops Qwen3.5-0.8B from looping. A fixed rule, run on the model's own answers for 84 GPU-minutes, writes a better one.

Small reasoning models have an awkward way of failing. They start thinking, write a paragraph, write it again, and keep writing it until the token budget runs out. Qwen3.5-0.8B in thinking mode does this on 93% of MATH-500 problems, and it solves 7.4% of them.

Earlier this year, Takehi et al. let an LLM agent, GPT-6 Astra, read this model’s weights for about 20 hours. Astra wrote a small edit to two layers, the Astra edit, that stops many of the loops and lifts MATH-500 accuracy to about 48%. It is one of the most striking results in their post.

I took the agent’s edit apart. It turned out to be one direction and 64 neurons in each of two layers. A fixed rule can write an edit of the same shape and size from the model’s own answers to practice problems, with no agent, no gradients and no correctness labels. That rule, CLC-sel, writes a better edit than the agent did.

56.3%on MATH-500, up from 7.4%. The agent's edit: 49.7%
84 minof one GPU to build the edit, against 20 hours of agent time
131,072weights changed, the same as the agent's edit: 0.016% of the model
MATH-500 accuracy by methodQwen3.5-0.8B in thinking mode. Base 7.4%, with repetition penalty 22.4%, with budget forcing 35.0%, thinking off 45.8%, Astra edit 49.7%, CLC-sel 56.3%, CLC-sel with budget forcing 59.6%. 0% 20% 40% 60% Base model, thinking Base model, thinking: 7.4% correct, 93.0% truncated (one seed) 7.4 + repetition penalty + repetition penalty: 22.4% correct, 75.8% truncated (one seed) 22.4 + budget forcing + budget forcing: 35.0% correct, 63.8% truncated (one seed) 35.0 Base model, thinking off Base model, thinking off: 45.8% correct, 31.0% truncated (one seed) 45.8 Astra edit (agent, 20 h) Astra edit (agent, 20 h): 49.7% correct, 32.1% truncated (three seeds) 49.7 CLC-sel (rule, 84 GPU-min) CLC-sel (rule, 84 GPU-min): 56.3% correct, 17.7% truncated (three seeds) 56.3 CLC-sel + budget forcing CLC-sel + budget forcing: 59.6% correct, 14.6% truncated (one seed) 59.6
MATH-500 accuracy of Qwen3.5-0.8B in thinking mode, 32,768-token limit. The Astra edit and CLC-sel average three seeds; the other rows are one seed. Hover a bar for its truncation rate.

The code, the edited model and every generation are public: GitHub, model, generations.

The failure

Reasoning models write a long chain of thought before they answer. In thinking mode, Qwen3.5-0.8B reaches the 32,768-token limit on 93% of MATH-500 problems. Almost all of these are verbatim loops: of 55 truncated answers I inspected, 53 end in a repeated 8-gram tail. The model writes a block of text, writes the same block again, and never stops.

The model does know a fair amount of math. With thinking turned off, it scores 45.8% on MATH-500 in about 3,600 tokens per answer. Thinking mode is where it gets stuck, and there the loops are verbatim: in non-thinking mode only 16 of 155 truncated answers end in a repeated tail.

What the agent did

Takehi et al. asked whether an LLM agent can fix a failure like this by editing weights directly. Astra read the weights of Qwen3.5-0.8B and ran 50 forward passes on practice problems, over 20.3 hours of wall time. It then wrote an edit that changes 64 output columns of the MLP in each of two layers. In their evaluation, MATH-500 accuracy in thinking mode rose from 7.9% to 48.1%. Runs of Astra with 10 and 25 forward passes reached only 12.3% and 14.1%.

Their logs and the edited weights are public, which is what made this work possible. They raise a practical question: how much of what the agent did can a fixed rule do?

Taking the agent’s edit apart

Some background on the model first. Qwen3.5-0.8B has 24 layers and a hidden size of 1,024. Each layer has an MLP with 3,584 neurons, and its last matrix, the down projection \(W\), writes their activations into the residual stream. Column \(c\) of \(W\) is what neuron \(c\) writes per unit of activation.

The agent changed \(W\) in layers 15 and 19. In each layer, the change is rank one up to bf16 rounding: the second singular value is about \(6 \times 10^{-4}\) of the first. It can be written as

\[W' = W - \alpha\,\mathbf{u}\,\big(\mathbf{m} \odot \mathbf{s}\big)^{\top}, \qquad \mathbf{s} = W^{\top}\mathbf{u}\]

where \(\mathbf{u}\) is a unit direction in the residual stream (1,024 numbers), \(\mathbf{m}\) is a mask that selects 64 neurons, and \(\alpha = 6\). With the direction and mask recovered from the released weights, this formula rebuilds 99.8% of the edited bf16 entries exactly.

The form is easy to read. Write \(s_c\) for the amount neuron \(c\) writes along \(\mathbf{u}\). After the edit, the layer’s write along \(\mathbf{u}\) is

\[\mathbf{u}^{\top} W' \mathbf{a} = \sum_{c} s_c\,a_c \;-\; \alpha \sum_{c \in \mathbf{m}} s_c\,a_c\]

and every other direction is unchanged. With \(\alpha = 6\), the 64 selected neurons now write five times their original amount against \(\mathbf{u}\). So the whole edit is three choices per layer: a direction, a set of neurons and a strength. A rule that makes those three choices writes the same kind of edit.

First attempt: erase “I am repeating”

My first guess at the direction was the obvious one. Take the model’s hidden state inside a loop, subtract its state at the first occurrence of the same text, and remove what is left. Call it the contrastive recurrence direction, CRD. If the edit erases the signal “I am repeating this”, the loop should break.

It did not work. At the agent’s layers, CRD scored 23.2% on MATH-500, against 49.2% for the agent’s edit in the same run. A random direction of the same form scored 8.6%.

Reading the agent’s direction through the logit lens, which decodes a hidden direction into next-token scores, showed why. Part of the direction promotes tokens that end a text. The agent’s edit does more than erase repetition: it moves the loop state toward the state in which the model finishes.

Similarity to the agent’s direction would not have found this. The three repetition-based directions I built all have a cosine of 0.71 to 0.74 with it, and their accuracy on the development set ranged from 39.1% to 67.2%.

The rule: CLC-sel

That observation gives the method, loop-selective closure contrast. It needs three kinds of windows from the model’s own answers.

The three windows CLC-sel readsTop: a looping answer, with a first-occurrence window F and a later loop window R that repeats it verbatim until the token limit. Bottom: an answer that finishes, with the closure window C, the 64 tokens before </think>. A looping answer … until 32,768 tokens first occurrence F loop R: the same 64 tokens again An answer that finishes </think> closure C: the 64 tokens before it
The three windows. A looping answer gives a first occurrence F and its verbatim repeat R. An answer that finishes gives the closure window C, the 64 tokens before the model closes its thinking.

Practice answers. The base model answers 512 practice problems in thinking mode, half from the MATH training set and half from GSM8K’s, with the evaluation’s sampling settings and up to 16,384 tokens. In each answer I find the first block of 64 tokens that appears again later, verbatim. That gives a first-occurrence window F and a loop window R, found in 256 answers. In the 43 answers that close their thinking, the 64 tokens before </think> form a closure window C.

Window statistics. One teacher-forced pass over these answers gives, for each layer, the mean residual state and the mean neuron activations in each kind of window. Write \(\bar{\mathbf{h}}^{R}\) for the mean state over loop windows and \(\bar a^{R}_c\) for the mean activation of neuron \(c\) there, and likewise with F and C.

Direction. The edit direction points from the closure state to the loop state:

\[\mathbf{u} = \frac{\bar{\mathbf{h}}^{R} - \bar{\mathbf{h}}^{C}}{\lVert \bar{\mathbf{h}}^{R} - \bar{\mathbf{h}}^{C} \rVert}\]

Since the edit subtracts along \(\mathbf{u}\), it pushes a looping state toward the state in which the model ends its thinking.

Neurons. The plain choice is the 64 neurons with the largest write along \(\mathbf{u}\) inside loops. I call that edit CLC. It pushes toward closure in every context, including normal reasoning, and on GSM8K it ends good answers too early. CLC-sel instead ranks neurons by how much their write along \(\mathbf{u}\) rises when the same text is repeated:

\[r_c = \big(\bar a^{R}_c - \bar a^{F}_c\big)\, s_c\]

These neurons are more active on the second pass over the same text than on the first, so the edit acts mainly inside loops. The two rules pick different neurons: only 27 of 64 are shared at layer 19, and 45 at layer 15. At layer 19, the chosen 64 of 3,584 neurons carry 71% of the positive score.

Layers and strength. For the main comparison, CLC-sel uses the agent’s layers (15 and 19) and strength (\(\alpha = 6\)), so the comparison isolates the direction and the neurons. A later section replaces both with rules.

The edit itself is a few lines of NumPy in the repository:

from clc_sel import apply_edit, closure_direction, select_neurons

u = closure_direction(h_loop, h_close)             # mean residual states of one layer
cols = select_neurons(W, u, a_rep, a_first, k=64)  # activations on repeats and first occurrences
W_edited = apply_edit(W, u, cols, alpha=6.0)

Generating the 512 answers and the teacher-forced pass took about 84 minutes on one shared A100. Building the edit takes seconds on a CPU, and the edited model has the same size and inference cost as the original.

Results

All runs follow the agent paper’s evaluation protocol: thinking mode, temperature 0.6, top-p 0.95, top-k 20, presence penalty 1.5, at most 32,768 new tokens, and answers graded with Math-Verify. Comparisons use a paired bootstrap over problems with 10,000 resamples.

MATH-500GSM8K
MethodAccuracyTruncatedTokensAccuracyTruncatedTokens
Base model7.493.030.9k13.8¹––
Astra edit (agent)49.732.121.8k67.46.912.0k
CLC (one seed)53.021.818.1k64.60.57.6k
CLC-sel56.317.718.3k69.01.09.1k

Accuracy and truncation in %, tokens per answer. Astra and CLC-sel average three seeds. ¹ Reported by Takehi et al.

On MATH-500, CLC-sel is 6.7 points above the agent’s edit (95% CI 4.5 to 8.9). The interval excludes zero on each seed separately: +6.6, +8.2 and +5.2. It truncates 17.7% of answers against 32.1% and uses 16% fewer tokens. It is also 10.0 points above the base model with thinking off (CI 5.4 to 14.6), which the agent’s edit does not significantly beat.

On GSM8K, CLC-sel scores 69.0, 68.8 and 69.2% on the three seeds; the agent’s edit scores 68.4, 65.7 and 68.1%. Over three seeds CLC-sel is 1.6 points ahead (CI 0.2 to 3.0), and it uses 24% fewer tokens.

The neuron rule matters. CLC, with neurons chosen by their write on loops, already beats the agent’s edit on MATH-500, but on GSM8K it falls 3.8 points behind and uses 35% fewer tokens: it ends normal reasoning too early. Choosing neurons by their rise on repeated text fixes that. On GSM8K, CLC-sel is 4.4 points above CLC (CI 2.0 to 6.8).

Against decoding-time fixes

A weight edit should beat the cheap fixes that need no edit at all. I tried two.

Repetition penalty helps little. On the selection set, strengths 1.05, 1.1 and 1.2 reached 21.9%, 34.0% and 1.2%, against 66.4% for CLC-sel; the strongest penalty breaks the model. On MATH-500 the chosen strength, 1.1, reached 22.4%, and 75.8% of its answers still ran out of tokens.

Budget forcing is a much stronger baseline. When thinking reaches 30,720 tokens without </think>, it appends the tag and allows 2,048 more tokens for the answer, so the total budget stays the same. It lifts the base model from 7.4% to 35.0%. CLC-sel alone is 20.8 points higher still (CI 16.8 to 24.8). A looping model often keeps writing after the forced tag, so 63.8% of base-model answers still run out.

With budget forcing on both edits, CLC-sel stays 6.8 points ahead of the agent’s edit (CI 3.0 to 10.6). The two also combine: CLC-sel with budget forcing reaches 59.6%, 3.8 points above CLC-sel alone (CI 0.0 to 7.6).

Where the gain comes from

Across every edit and control, accuracy rises with the share of answers that finish.

Accuracy against the share of answers that finishEvery thinking-mode run on MATH-500. Accuracy rises with the share of answers that finish; the edits that finish most answers lie near a line of slope 0.71 through the origin. CLC-sel finishes 82% and scores 56.3%; the Astra edit finishes 68% and scores 49.7%; the automatic layer-13 edit finishes 90% but scores 49.6%. 0 20 40 60 0 20 40 60 80 100 Answers that finish (%) Accuracy (%) 0.71 × share finished Base: 7.4% correct, 7.0% of answers finish Base CRD 7/12: 16.4% correct, 15.8% of answers finish CRD 7/12 CRD 15/19: 23.2% correct, 22.8% of answers finish CRD 15/19 Base + BF: 35.0% correct, 36.2% of answers finish Base + BF Astra: 49.7% correct, 67.9% of answers finish Astra Astra + BF: 52.8% correct, 71.0% of answers finish Astra + BF CLC: 53.0% correct, 78.2% of answers finish CLC CLC-sel: 56.3% correct, 82.3% of answers finish CLC-sel CLC-sel + BF: 59.6% correct, 85.4% of answers finish CLC-sel + BF Auto, layer 13: 49.6% correct, 89.8% of answers finish Auto, layer 13 no forcing with budget forcing (BF)
Accuracy against the share of answers that finish, every thinking-mode run on MATH-500, seeds averaged. The edits that finish most answers sit near a line of slope 0.71 through the origin. Runs that finish few answers lie above it, because the few they finish are easy ones.

Splitting each paired comparison by what happened to each problem shows where CLC-sel’s lead comes from.

Where CLC-sel's lead over the Astra edit comes fromFor each run, the paired accuracy difference split by outcome. Most of the lead comes from problems the Astra edit truncates and CLC-sel finishes (+7.2 to +8.8 points on MATH-500); problems CLC-sel truncates cost 1.6 to 3.2 points; problems both finish change little. Astra truncated, CLC-sel finished CLC-sel truncated, Astra finished both finished or both truncated -4 -2 0 +2 +4 +6 +8 +10 CLC-sel minus Astra, accuracy points MATH-500, seed 0 99 problems Astra truncated and CLC-sel finished: +8.8 points problems both finished or both truncated: -0.6 points 24 problems CLC-sel truncated and Astra finished: -1.6 points net +6.6 points +6.6 seed 1 101 problems Astra truncated and CLC-sel finished: +8.4 points problems both finished or both truncated: +1.6 points 27 problems CLC-sel truncated and Astra finished: -1.8 points net +8.2 points +8.2 seed 2 92 problems Astra truncated and CLC-sel finished: +7.2 points problems both finished or both truncated: +1.2 points 26 problems CLC-sel truncated and Astra finished: -3.2 points net +5.2 points +5.2 both with BF 96 problems Astra truncated and CLC-sel finished: +8.6 points problems both finished or both truncated: +0.6 points 24 problems CLC-sel truncated and Astra finished: -2.4 points net +6.8 points +6.8 GSM8K, seed 0 70 problems Astra truncated and CLC-sel finished: +2.4 points problems both finished or both truncated: -1.5 points 13 problems CLC-sel truncated and Astra finished: -0.2 points net +0.6 points +0.6 seed 1 105 problems Astra truncated and CLC-sel finished: +3.4 points problems both finished or both truncated: +0.1 points 10 problems CLC-sel truncated and Astra finished: -0.4 points net +3.1 points +3.1 seed 2 88 problems Astra truncated and CLC-sel finished: +2.7 points problems both finished or both truncated: -1.3 points 7 problems CLC-sel truncated and Astra finished: -0.2 points net +1.1 points +1.1
CLC-sel minus the Astra edit, split by outcome. Most of the lead comes from problems the agent's edit truncates and CLC-sel finishes. The diamond marks the net difference.

On MATH-500 (seed 0), 315 problems finish under both edits, and there the two are level: 74.0% for CLC-sel and 74.9% for the agent’s edit. On 99 problems the agent’s edit runs out of tokens and CLC-sel finishes. CLC-sel solves 44% of these, which adds 8.8 points. On 24 problems the opposite happens, which costs 1.6 points. The other seeds show the same pattern.

So the edit does not make the model reason better. It makes the model finish problems it would otherwise loop on. Accuracy over finished answers even favors the agent’s edit, 72.3% against 67.1%, because the problems CLC-sel rescues are harder than average.

What matters inside the edit

Edit (development set, 128 problems) Accuracy Truncated
Base model 13.3 85.2
Astra edit 66.4 14.8
CRD direction 39.1 57.8
Closure direction (CLC) 67.2 7.8
Astra direction, top-write neurons 59.4 21.1
CRD direction, Astra neurons 50.8 44.5

Thinking mode, one seed, layers 15 and 19, \(\alpha = 6\), 64 neurons.

The direction must point toward closure. At the same layers, CRD reached 23.2% on MATH-500 and the closure direction 53.0%.

Neuron choice matters as much as direction. The agent’s own direction with neurons ranked by their write reaches 59.4%; CRD with the agent’s neurons reaches 50.8%. Editing every neuron, with the projection \((I - \alpha\,\mathbf{u}\mathbf{u}^{\top})\,W\), reached only 14.8 to 25.0%.

A weaker push does not help. Lowering CLC’s strength to 4 kept selection-set accuracy at 60.9%; lowering it to 3 dropped it to 57.8%. Only the loop-selective neurons improved on CLC, to 66.4%.

Measure under sampling. My first layer screen ranked layers by how much an edit lowers the log-probability of held-out loop text, with a guard against harming finished text. It ruled out layers 15 and 19 because of that cost. Under sampling, they are among the best layers.

Removing the last borrowed settings

CLC-sel so far borrows two settings from the agent: the layers and the strength. Both can be chosen by rules that use only the practice answers.

Strength in closed form. The edit lowers the write along \(\mathbf{u}\) by \(\alpha \sum_{c \in \mathbf{m}} s_c\,a_c\), a sum over the selected neurons. Choose \(\alpha\) so that, to first order, this closes the gap between the loop state and the closure state:

\[\alpha^{*} = \frac{\lVert \bar{\mathbf{h}}^{R} - \bar{\mathbf{h}}^{C} \rVert}{\sum_{c \in \mathbf{m}} s_c \big(\bar a^{R}_c - \bar a^{C}_c\big)}\]

clipped to \([0.5, 16]\). This needs no generation. At the agent’s layers it gives 8.1 and 11.6. Split over two layers, that is 4.0 and 5.8 per layer, close to the agent’s 6, although the rule never saw the agent’s edit.

Layers by a screen. I built a single-layer CLC-sel edit at every odd layer, each with its own \(\alpha^{*}\), and ran each on 128 screening problems.

Single-layer CLC-sel edits on the screening setAccuracy and truncation for a CLC-sel edit at each odd layer with its closed-form strength, on 128 screening problems. Early layers and the last two fail; layers 9 to 19 reach 52 to 64%, against 14% for the base model. Layers 13 and 19 are best. 0 25 50 75 100 base 14% Layer 1 (alpha* 5.3): 16.4% correct, 84.4% truncated 16 1 5.3 Layer 3 (alpha* 7.1): 7.0% correct, 95.3% truncated 7 3 7.1 Layer 5 (alpha* 16.0): 3.9% correct, 96.9% truncated 4 5 16.0 Layer 7 (alpha* 10.6): 43.8% correct, 35.9% truncated 44 7 10.6 Layer 9 (alpha* 14.4): 56.2% correct, 7.8% truncated 56 9 14.4 Layer 11 (alpha* 14.2): 59.4% correct, 4.7% truncated 59 11 14.2 Layer 13 (alpha* 11.8): 64.1% correct, 3.9% truncated 64 13 11.8 Layer 15 (alpha* 8.1): 60.9% correct, 14.8% truncated 61 15 8.1 Layer 17 (alpha* 16.0): 51.6% correct, 26.6% truncated 52 17 16.0 Layer 19 (alpha* 11.6): 62.5% correct, 5.5% truncated 62 19 11.6 Layer 21 (alpha* 16.0): 25.8% correct, 74.2% truncated 26 21 16.0 Layer 23 (alpha* 16.0): 5.5% correct, 82.8% truncated 5 23 16.0 layer α* Layer 1: 84.4% truncated Layer 3: 95.3% truncated Layer 5: 96.9% truncated Layer 7: 35.9% truncated Layer 9: 7.8% truncated Layer 11: 4.7% truncated Layer 13: 3.9% truncated Layer 15: 14.8% truncated Layer 17: 26.6% truncated Layer 19: 5.5% truncated Layer 21: 74.2% truncated Layer 23: 82.8% truncated accuracy, % (two best layers solid) truncated, %
Single-layer edits on the screening set. Bars show accuracy and the line shows the share of truncated answers. Early layers and the last two fail; every layer from 9 to 19 reaches 52 to 64%, against 14% for the base model.

The two best layers are 13 and 19. Together they reach 61.7%, below layer 13 alone, so the rule keeps layer 13 with \(\alpha^{*} = 11.8\).

On the test sets, this fully automatic edit matches the agent’s edit. On MATH-500 it reaches 49.6%, 0.4 points above (CI −3.4 to 4.2); on GSM8K it reaches 67.4%, 1.0 point below (CI −3.3 to 1.4). It ends more loops than any other edit, truncating only 10.2% of MATH-500 answers. But its finished answers are less often correct, 55.0% against 72.3%. One layer at strength 11.8 ends the thinking too early on some problems the model could have solved. The closed-form strength closes the gap between the two states but does not weigh that cost.

What this does not show

  • One model. I tested Qwen3.5-0.8B on two math benchmarks. I do not know whether the rule transfers to other models or sizes.
  • The agent found the idea. The closure direction came from reading the agent’s edit, and CLC-sel’s lead depends on the agent’s layers and strength. The automatic version matches the agent but does not beat it.
  • The search had a cost. The final rule runs in 84 GPU-minutes, but finding it took about 40 more runs on practice problems. Each test set was used to confirm two successive methods, which may favor the second.
  • Finishing, not reasoning. The edit fixes loops. With thinking off, the base model reaches 45.8% on MATH-500 with a fifth of the tokens, so the edit matters most when thinking mode is needed.
  • Untested. General tasks such as instruction following, CLC-sel in non-thinking mode, and an activation-steering baseline that adds \(\mathbf{u}\) at every token. The closure state is a mean over only 43 answers, and each run draws one sample per problem.

How the study was run

Every test-set comparison was written down with its pass condition before it ran, in a protocol and addenda frozen with their hashes. There were 18 such comparisons, and 5 failed, including both tests of my first method: CRD gained 9.0 points over the base model against a target of 20, and fell 32.8 points short of the agent’s edit. The study record keeps all of them, failures included.

All method decisions used practice problems drawn from the MATH and GSM8K training sets, checked for overlap with the test sets by id, by text and for near duplicates. Two independent audits re-graded the answers and re-ran the statistics. The full texts and grades of all 69 runs are on Hugging Face, and every number above can be checked against them.

Try it

The edited model runs anywhere Qwen3.5-0.8B runs. With vLLM, using the evaluation’s settings:

from vllm import LLM, SamplingParams

llm = LLM("zichuanxu/Qwen3.5-0.8B-CLC-sel")
params = SamplingParams(temperature=0.6, top_p=0.95, top_k=20, presence_penalty=1.5, max_tokens=32768)
problem = "What is the smallest positive integer n such that 3n is a perfect square and 2n is a perfect cube?"
prompt = problem + " Please reason step by step, and put your final answer within \\boxed{}."
out = llm.chat([{"role": "user", "content": prompt}], params, chat_template_kwargs={"enable_thinking": True})
print(out[0].outputs[0].text)

To rebuild the edit from the base model, bit for bit:

git clone https://github.com/zichuanxu/closing-the-loop && cd closing-the-loop
uv sync
uv run --extra model python -m clc_sel.apply edits/clc_sel.json --out ckpt/clc_sel

What I take from this

The agent spent 20 hours and found something real: a loop can be closed by pushing the model toward the state in which it finishes, through a handful of neurons. Once that mechanism is written down, a fixed rule applies it better, in a fraction of the time, and in a form anyone can check and rerun.

That suggests a division of labor. Agents that read weights are good at finding mechanisms. Rules are good at applying them. The most useful output of an agent like this may be the mechanism it finds, more than the edit it writes.


If you use this work, please cite it:

@misc{xu2026closingtheloop,
  title  = {Closing the Loop: A Simple Rule Beats an Agent-Written Weight Edit for Reasoning Loops},
  author = {Xu, Zichuan},
  year   = {2026},
  url    = {https://github.com/zichuanxu/closing-the-loop}
}

The Astra edit, its logs and the evaluation protocol are by Takehi et al. (2026). Thanks to them for releasing all three.