FundamentalsAdvanced

Weight-Space Programming: LLMs That Read and Write Neural Network Weights

In November 2026 researchers at MIT CSAIL reported that a frontier LLM can tell what a network was trained to do from its raw weights, repair it by editing them, and write small working networks from scratch, all without gradient descent. What was shown, how it works, and how much to trust it.

11 min read Updated weight-space programming interpretability model editing GPT-6 Astra research

On 2 November 2026 researchers at MIT CSAIL reported that OpenAI's GPT-6 Astra can work directly with neural network weights. From raw numbers alone it told which game a network had been trained to play; it repaired a failing controller and a looping language model by editing a small share of their weights; and it wrote game-playing networks from all-zero weights, without training. The authors call this weight-space programming. Here is what was done, why it is possible, and what it does not yet show.

Three ways to get weights, and a fourth

Every trained neural network is a long list of numbers. Until now those numbers have come from three places:

  • Optimisation. Gradient descent computes a loss, backpropagates gradients and lets an optimiser such as Adam nudge every weight, millions of times over: Andrej Karpathy's "Software 2.0". Fine-tuning, including LoRA, is the same process applied to a pretrained model.
  • Learned generators. Hypernetworks and similar models are trained to output other networks' weights, so they are tied to the kinds of networks and tasks they were trained to produce.
  • Compilers. Tools such as DeepMind's Tracr compile programs in a small language, RASP, into small, rigidly structured transformers.

The MIT post, by Rikiya Takehi, Jayden Teoh, Alex Zhang and Omar Khattab, proposes a fourth source. In weight-space programming, a general-purpose LLM reads and writes a network's weights directly, without an optimiser or gradient descent, guided by a natural-language specification and sometimes with no environment feedback at all. The model is used as is, untrained for the task: it receives the weights as text or in a Python session, reasons about what each part computes or should compute, and writes new numbers.

The post tests three verbs: read (say what a network was trained to do), fix (repair it) and write (create one from zero). The authors call the results "sparks": early, mostly small-scale, and published as a blog post with complete logs, not a peer-reviewed paper. As of November 2026 it is a day old and has not been independently reproduced.

Gradient descent versus weight-space programming Top: in gradient descent, batches of training data go through a forward pass to a loss, backpropagation produces gradients, and an optimiser updates every weight by a small step; the loop repeats for millions of steps. Bottom: in weight-space programming, a specification and the weights, as text or in a Python session, go to an LLM that reasons about what each part does and edits the weights; an optional small budget of forward passes lets it look at failures and edit again. The result is scored afterwards on tasks the LLM never sees. Gradient descent: an optimiser writes the weights Training data batches of examples Loss forward pass Gradients backpropagation Optimiser update every weight, a small step repeat for millions of steps Weight-space programming: an LLM writes the weights Spec + weights as text or in Python LLM reasons what each part does Edits weights writes new values Forward passes optional, 0–50 look at failures, edit again Scored afterwards on tasks it never sees: no data, loss or gradients in the loop
Gradient descent finds weights through millions of small, data-driven steps; weight-space programming asks a reasoning model what they should be. Some experiments allow a few test forward passes (dashed), others none.

What it means to program weights

The idea is less mysterious once you write a network yourself. A layer computes weighted sums of its inputs and passes them through a nonlinearity such as ReLU, which zeroes negative values. If you know what each input means, you can choose weights that compute something specific. Here is a complete policy for one-row Breakout: the inputs are the ball's and paddle's columns, one-hot over ten cells, and the outputs are action scores.

import numpy as np

W = 10                                    # cells in the bottom row
cols = np.arange(W)

# Input: 20 numbers, a one-hot ball column followed by a one-hot paddle column.
# Layer 1: two ReLU units that read "ball column minus paddle column".
W1 = np.zeros((2, 2 * W))
W1[0, :W], W1[0, W:] = cols, -cols        # unit 0: how far the ball is to the right
W1[1, :W], W1[1, W:] = -cols, cols        # unit 1: how far the ball is to the left
b1 = np.zeros(2)

# Layer 2: logits for [left, stay, right].
W2 = np.array([[0.0, 2.0],                # left  <- "ball is to the left"
               [0.0, 0.0],                # stay  <- bias only
               [2.0, 0.0]])               # right <- "ball is to the right"
b2 = np.array([0.0, 1.0, 0.0])

def policy(ball_col: int, paddle_col: int) -> str:
    x = np.zeros(2 * W)
    x[ball_col], x[W + paddle_col] = 1.0, 1.0
    h = np.maximum(0.0, W1 @ x + b1)      # ReLU
    return ["left", "stay", "right"][int(np.argmax(W2 @ h + b2))]

print(policy(7, 3), policy(2, 5), policy(4, 4))   # right left stay

The first hidden unit weights ball cells by their column number and paddle cells by minus theirs, so it computes ball column minus paddle column; ReLU keeps that only when the ball is to the right. The second unit is the mirror image. The output layer maps the two to right and left, and gives stay a constant 1, which wins only when both units are silent. That is 51 numbers, each chosen by reasoning. Nothing was trained.

The MIT experiments ask an LLM to do this at scale, without being shown the trick. By its own account, Astra's MinAtar Breakout network (600 inputs, two hidden layers of 32 units, 6 outputs) follows the same plan: the first layer computes where the ball will land, the second moves the paddle there. A person can manage 51 weights; tens of thousands, or reading intent out of weights someone else trained, has been out of reach.

Reading: what a network does, from its weights

The first experiments trained networks in the ordinary way and asked Astra what they did, using only the weights: no tools and no forward passes.

  • Which game? Four PPO policies for grid versions of Breakout, Pong, Pac-Man and Freeway shared one 17,253-weight architecture and the same inputs and actions. Without a list of candidates, Astra named the right game for all four, pointing to where each input channel's first-layer weights concentrate: for Breakout, the agent's weights lie along the bottom row, like a paddle.
  • Which shape? Three small diffusion models generate filled circles, squares and triangles. Astra read each shape from the output layer, where each hidden unit draws a piece of the edge, but drew outlines rather than filled shapes. The authors take the mistake as evidence that it reads the weights' geometry rather than simulating the network.
  • Which language? Three character-level transformers (7.16 million weights) were trained on Python, Japanese in romaji, and English, then stripped of their input and output layers, so no dimension was labelled and the network could not run. Astra could analyse the weights with Python but not execute any layer. It named the right language for all three, in both attempts.

The method is the instructive part. Astra looked for copying heads, also called induction heads: attention heads that let a model repeat earlier text. It found a first-layer head that attends one character back, then multiplied weight matrices to find the later heads that use what it carries forward. This is the circuit analysis of Elhage et al.'s "A Mathematical Framework for Transformer Circuits", a standard mechanistic interpretability method the prompt never mentioned. It found every copying head and no false ones. Many copying heads suggested Python, since code repeats names more than prose. Romaji showed instead in a last block that writes into fewer directions, fitting an alphabet without q, l, v or x.

Where reading fell short

Two copies of Gemma 3 270M were fine-tuned identically, except that one learned to answer correctly and the other to agree with the user's suggested answer. From the weights alone, Astra failed in all four attempts: it found differences but could not tie them to behaviour. Shown attention patterns (not outputs) on texts it wrote itself, it identified the sycophant in all three pairs. In one, head 10.2 put 85.7% of its attention on the user's answer, against 0.75% in the honest model.

Writing: fixing networks and building them from zero

Fixing a stuck controller

In a Kinetix physics task, a car must reverse before it can gather speed to climb a ramp. A PPO policy trained for a billion steps had settled on driving straight at the ramp and stalling, failing all 256 episodes. Given its 171,664 weights, a scene description and one recorded episode, Astra explained the failure and fixed it in a single reply, without tools. The edit changed 3.5% of the weights, adding a small path that backs the car up and switches off once it is past the strip. The car then succeeded in all 1,024 test episodes.

Writing networks from zero

For three MinAtar games, Astra received the rules and source code, the input and output layout, the scoring method and an all-zero network shaped like the PPO baselines. With no data, gradients or tools, and no test play, it wrote every weight as text in one reply. Average scores over 1,000 episodes:

GamePPO, 100M stepsPPO, 500M stepsAstra, no training
Breakout15.825.3517.4
Seaquest5.688.953.1
Asterix25.855.253.2

Astra's networks beat 100 million steps of PPO in all three games. Against 500 million steps they scored about 20 times higher in Breakout, came close in Asterix and reached 60% of the PPO score in Seaquest.

Go tested scale: a network for 9×9 Go with 1,480,274 weights, too many to write as text. In a Python sandbox Astra could read and save the all-zero weight tensors but not run the network; running it cost a forward pass from a fixed budget (up to 128 games against a practice opponent), and training and search were forbidden. Astra wrote the network as a small Go program: early layers mark stones and their liberties, middle layers carry these along chains of stones to find groups in danger, and the last layer scores moves for capturing, saving groups and avoiding self-atari. With no forward passes, from a single 336-line Python run, it won more than half its games against two smaller PPO networks. With 50 passes, keeping only changes that won more, it beat the equal-sized PPO network trained on 20 million games.

Editing a real language model

The last experiment used a real LLM, Qwen3.5-0.8B with thinking enabled, and asked Astra to make it better at maths without gradients or training. The harness held the weights in a Python session, with practice problems from the GSM8K and MATH training sets and 10, 25 or 50 forward passes. Scoring used MATH-500, GSM8K and six other benchmarks Astra never saw.

The harness used to edit Qwen3.5-0.8B Practice problems from the GSM8K and MATH training sets go to GPT-6 Astra, which has no gradients. Astra sends numpy code to a Python kernel that holds the Qwen3.5-0.8B weights on a CPU, and reads back printouts. The kernel can spend forward passes from a budget of 10, 25 or 50, whose model outputs return to Astra. Astra's final edit produces weights with 131,072 values changed, which are scored on benchmarks never shown to Astra. Practice problems GSM8K and MATH training sets only GPT-6 Astra reads, reasons, edits no gradients Python kernel Qwen3.5-0.8B weights CPU only, no training numpy code printouts Forward passes budget: 10, 25 or 50 model outputs final edit Edited weights 131,072 values changed Benchmarks never shown to Astra
A guided search, not a training run: Astra inspects the weights with code, spends a small forward-pass budget on practice problems and submits one edit, scored on hidden benchmarks.

Astra identified the main failure. Like many small reasoning models, Qwen loops: 85 of its first 96 practice answers ran on until the 32,768-token limit, a problem its model card warns about. Astra traced the loops to one direction written by the MLPs of layers 15 and 19 and removed it from 64 output columns in each. A column holds 1,024 numbers, the model's hidden size, so the edit touched 2 × 64 × 1,024 = 131,072 weights: 0.016% of the model.

Qwen3.5-0.8BMATH-500 (%)GSM8K (%)IFEval (%)Hit token limit (%)
Base model7.913.821.093.0
Edited, 10 passes12.325.749.087.2
Edited, 25 passes14.125.139.986.4
Edited, 50 passes48.167.162.333.1

With 50 passes MATH-500 rose from 7.9% to 48.1%, and since loops are not specific to maths, IFEval (instruction following) rose from 21.0% to 62.3%. The last column, MATH-500 answers that hit the token limit, shows that with 10 or 25 passes the loops barely went away: the feedback budget mattered.

How the edit works

Each transformer layer adds its output to a shared vector, the residual stream (see What Is a Large Language Model?). An MLP's output matrix has one column per hidden neuron: the direction it writes. To stop selected neurons writing a direction r, project r out of their columns: w ← w − (r · w) r, with r of unit length.

import numpy as np

def remove_direction(W_out: np.ndarray, r: np.ndarray, cols: list[int]) -> np.ndarray:
    """Project direction r out of selected columns of an MLP output matrix.

    W_out: shape (d_model, d_ff), one column per hidden neuron: the
           direction that neuron writes into the residual stream.
    r:     shape (d_model,), the direction to remove.
    cols:  the neurons to edit."""
    r = r / np.linalg.norm(r)                     # unit length
    W = W_out.copy()
    block = W[:, cols]                            # shape (d_model, len(cols))
    W[:, cols] = block - np.outer(r, r @ block)   # w <- w - (r . w) r
    return W

# 64 columns x 1,024 rows = 65,536 weights per layer; two layers = 131,072.

The operation is known: Arditi et al. (2024) removed refusal from chat models by deleting a single direction, and ROME (Meng et al., 2022) edits facts with rank-one changes to MLP weights. What is new is that a general-purpose LLM found the direction and columns itself, from the weights and at most 50 batches of outputs.

The control that did not improve

Removing loops lets a model finish answers it could already work out; it does not teach maths. On Gemma 3 270M, which rarely loops, Astra found only ordinary arithmetic and algebra errors with no single component to switch off, and its small edits moved MATH-500 from 6.8% to at most 7.7%, a gain it reported as not established. In the authors' words, editing weights "could remove an obstacle that hid an ability, but it could not add an ability the model lacked."

How to read these results

The post is careful about its limits, and they matter:

  • Early and unreviewed. A blog post, not a peer-reviewed paper, unreplicated as of November 2026. The logs and the edited Qwen model are public, so the claims can be checked.
  • Mostly small networks. Most have tens or hundreds of thousands of weights and simple tasks; the one real LLM edit removed a failure mode rather than adding a skill.
  • One model, few attempts. Everything comes from GPT-6 Astra, with only a few attempts per experiment; failure rates and other models are unknown.
  • Some results used feedback. The Go and Qwen results used forward-pass budgets, which makes them a guided search: far less signal than training, but not zero-shot.
  • Cost is not compared. Astra's reasoning compute is not weighed against what training would need.

Nor does weight-space programming replace fine-tuning. Fine-tuning, including the parameter-efficient methods covered in fine-tuning with LoRA and its relatives, moves weights wherever data and a loss function push them. Weight-space programming moves them to where a reasoning model believes they should be. The first scales with data; the second, for now, with how well the LLM understands the network in front of it.

Why it matters, and what to watch

The authors list directions this could open; treat them as a research agenda:

  • Auditing without evaluation. Finding problems such as backdoors directly in the weights, before an incident exposes them.
  • Cheaper optimisation. Initialising or repairing a network in one shot instead of running training loops.
  • Zero-data steering and unlearning. Adding or removing a capability on request. Edits that touch few weights may avoid the catastrophic forgetting that fine-tuning often causes.
  • Self-improvement and merging. Models that debug their own weights, or graft a circuit from one architecture into a different one.

There is a flip side. A model that can surgically remove a behaviour can also add one: plant a backdoor in open weights, strip out safety behaviour, or make changes too small for standard benchmarks to notice. Provenance checks on downloaded weights matter more, and every edit, human or LLM, needs evals on held-out tasks, including those it was not meant to touch.

What you can use today

Directional ablation and rank-one edits are established techniques; LLM-driven weight editing is so far one team's result with one model. If you try it, keep the original weights, log every change, and score edits on evaluations the editor never saw.

The authors are building a benchmark and harness for weight-space programming. It, and replications with other models, will show whether these sparks become a dependable engineering tool.

Key takeaways

  • In weight-space programming, a general-purpose LLM edits weights by reasoning about what each part computes, without gradient descent. The term comes from a November 2026 MIT CSAIL post using GPT-6 Astra.
  • From raw weights, Astra identified games, shapes and training languages, and found induction heads; it could not spot a sycophantic model without attention patterns.
  • It fixed a stuck controller by editing 3.5% of its weights, and wrote MinAtar and Go networks from zero that beat some PPO baselines.
  • In Qwen3.5-0.8B, removing one looping direction from 0.016% of the weights raised MATH-500 from 7.9% to 48.1%. A Gemma control suggests the edit removed an obstacle rather than adding skill.
  • The results are early, unreplicated and mostly small-scale; feedback budgets mattered and costs were not compared.
  • The same ability could audit weights or tamper with them: verify every edit with held-out evals.

Sources and further reading

  1. Takehi, Teoh, Zhang, Khattab, Sparks of Weight-Space Programming: LLMs can natively read & write neural network weights (MIT CSAIL blog post, 2 November 2026).
  2. RikiyaT/lm_understand-logs: prompts, replies, code runs, networks and evaluations for every experiment.
  3. RikiyaT/Qwen3.5-0.8B-weight-space-programming: the edited model from the Qwen experiment.
  4. Elhage et al., A Mathematical Framework for Transformer Circuits (2021).
  5. Arditi et al., Refusal in Language Models Is Mediated by a Single Direction (2024).
  6. Meng et al., Locating and Editing Factual Associations in GPT (2022): the ROME paper.
  7. Lindner et al., Tracr: Compiled Transformers as a Laboratory for Interpretability (2023).
  8. Andrej Karpathy, Software 2.0 (2017).
  9. Young, Tian, MinAtar: An Atari-Inspired Testbed for Thorough and Reproducible Reinforcement Learning Experiments (2019).
  10. Matthews et al., Kinetix: Investigating the Training of General Agents through Open-Ended Physics-Based Control Tasks (2024).