← John Curreri
Experiment · October 2026

One attribution graph is an anecdote. So I tested it 49 times.

An attribution graph suggested how Qwen3-8B answers "the capital of the state containing Dallas": it routes through a Texas representation. I turned that one picture into a regression suite, with an independent feature labeller, ablations against random controls, and feature swaps between states, run across 57 prompts.

Qwen3-8B circuit-tracer per-layer transcoders 57 prompts · 49 tested RTX PRO 6000
31 / 49
answers collapse when the state features are switched off
0 / 49
collapse when the same number of random graph features are switched off
0.97 → 0.18
median probability of the correct capital, before and after
28 / 49
answers switch to another state's capital when its features are swapped in

The claim, from one graph

circuit-tracer replaces each MLP layer of a model with a transcoder, a sparse network whose features often mean something readable, then computes how much each active feature pushes every later feature and the final output. The result is an attribution graph: a map of which features caused this answer.

For the prompt Fact: The capital of the state containing Dallas is, Qwen3-8B puts 93.5% on Austin. The graph shows a feature at layer 22 on the Dallas token whose output vocabulary is Texas, Texans, feeding a stronger Texas feature at layer 29, which is the largest direct input to Austin. "Texas" never appears in the prompt. The model appears to look the state up, then the capital.

The attribution graph for the Dallas prompt
Columns are prompt tokens, rows are layers. Lines show the inputs to the selected Austin output.
circuit-tracer attribution graph for the Dallas prompt, with the Austin output selected and its input features listed.

Switching those three Texas features off dropped Austin from 0.935 to 0.38, and Atlanta rose to 0.34. That is a real causal effect. It is also one prompt that I picked because the picture looked clean.

I spent fifteen years validating server CPUs. One passing test case is not coverage, and a debug theory that explains the failure you were staring at is the one most likely to be wrong in general. So I treated the graph's story as a hypothesis and wrote a test plan for it.

Turning the picture into a test suite

Fifty-seven city, state, capital triples, using well-known cities that are not capitals. I skipped state pairs whose names collide, such as the two Carolinas, and cities whose names contain a state. Every prompt uses the same template. The model answers 50 correctly; the seven misses (San Diego, Orlando, Rochester, Reno, Norfolk, Wilmington, Manchester) are excluded, and one more has no labelled features, which leaves 49.

For each prompt the suite:

  1. Builds the attribution graph and keeps the pruned nodes (80% of influence) at the city token and the final token, roughly 600 features per prompt.
  2. Labels state features with an oracle that never looks at the graph. A feature counts as a state feature if its own top output tokens, taken from the published feature data, name that state. Texas features predict Texas, Texans, Tex. This keeps the test from grading the graph against itself.
  3. Ablates the labelled state features, setting them to zero, and records the probability of the correct capital.
  4. Runs a control: zero the same number of randomly chosen non-state features from the same graph, at the same token positions, three draws per prompt. These are influential features too; they survived the same pruning.
  5. Swaps: zero the state features and inject another state's features from a donor prompt at their recorded activations, at 1× and 2× strength. If the claim is right, Dallas plus California features should say Sacramento.

The state features are causal

Switching off the state features drops the median probability of the correct capital from 0.97 to 0.18. In 31 of 49 prompts it falls below 0.5. The random control, with the same number of features from the same graph, leaves the median at 0.96 and never falls below 0.5.

Probability of the correct capital, per prompt
Sorted by the result after the state features are switched off. The dashed line marks 0.5.
Before ablation State features off Same number of random features off
Show data table
CityCapitalBeforeState offRandom offLabelled features
TampaTallahassee0.930.000.9412
MiamiTallahassee0.960.000.9010
PhiladelphiaHarrisburg0.920.000.918
LouisvilleFrankfort1.000.001.004
NewarkTrenton1.000.001.004
WorcesterBoston0.940.000.946
ChicagoSpringfield0.840.000.817
San AntonioAustin0.960.000.9611
DetroitLansing0.970.000.9511
DallasAustin0.940.000.8813
HoustonAustin0.990.000.9911
KnoxvilleNashville0.450.000.617
BangorAugusta0.950.000.817
FlagstaffPhoenix0.980.010.867
BillingsHelena0.910.010.905
New OrleansBaton Rouge0.940.010.5111
TucsonPhoenix1.000.010.995
HiloHonolulu0.870.020.8614
HuntsvilleMontgomery0.920.030.927
WichitaTopeka1.000.071.0011
MemphisNashville0.960.080.975
BoulderDenver1.000.101.0011
Cedar RapidsDes Moines0.940.120.917
PittsburghHarrisburg0.910.120.888
MilwaukeeMadison0.990.181.008
FayettevilleLittle Rock0.500.200.524
CincinnatiColumbus0.900.200.906
Los AngelesSacramento1.000.210.9918
New HavenHartford0.970.220.946
SavannahAtlanta0.990.240.997
SpokaneOlympia0.650.310.697
St. LouisJefferson City0.920.590.954
Sioux FallsPierre0.630.600.661
San FranciscoSacramento0.990.720.9916
Las VegasCarson City0.800.810.823
AlbuquerqueSanta Fe0.850.840.861
AnchorageJuneau1.000.851.007
EugeneSalem0.970.860.976
BiloxiJackson0.960.870.963
ProvoSalt Lake City0.990.880.999
OmahaLincoln0.970.900.972
BaltimoreAnnapolis0.990.930.997
ClevelandColumbus0.970.990.965
BridgeportHartford0.990.991.007
CharlotteRaleigh0.990.990.993
CasperCheyenne1.000.991.003
SeattleOlympia1.001.000.996
BurlingtonMontpelier1.001.001.003
MobileMontgomery1.001.001.008

The failure mode is informative. In 11 of the collapsed prompts the model still names a state capital, just the wrong one: Dallas, Houston and Miami all become Atlanta. The request for a capital survives; only the knowledge of which state is gone. That is what you would expect if "capital of" and "which state" are carried separately, which is the two-hop story the graph told.

Freezing attention patterns during the intervention is the library default. Letting attention respond gives the same picture: 28 of 49 collapse, against 2 of 49 for the random control.

Swapping states mostly works, if you push

At the donor's recorded activation strength, swapping in another state's features makes the model answer with the donor's capital in 15 of 49 prompts. At twice the strength it happens in 28 of 49. Dallas with California features says Sacramento. Detroit with Ohio features says Columbus. Newark with Massachusetts features says Boston.

Swaps fail mostly when the donor state has few labelled features: a median of 5 for failed swaps at 2×, against 8 for successful ones. That points at the labeller's coverage again, which is the question the next section takes up.

The 18 that did not break

Eighteen prompts barely moved when their state features were switched off: Seattle, Charlotte, Burlington, Mobile and others. They have fewer labelled state features (a median of 4.5, against 7 for the prompts that collapsed). There are two explanations. Either the labeller is missing state features for these cities, or the model reaches the capital some other way, for example a direct association between Seattle and Olympia that never passes through "Washington", or a path that bypasses the transcoders through their error terms.

A blunt diagnostic separates part of that. Switching off every graph feature at the city token, labelled or not, about 300 per prompt, breaks all 18. So the answer does flow through transcoder features at the city token, not around them. The test is blunt because it also erases the city itself; many answers degrade to in or located. What it rules out is the bypass. What it does not settle is whether the features my labeller missed encode the state or a direct city-to-capital link. That is the next experiment.

CityBeforeState offAll city offCity features
Mobile1.001.000.00268
Burlington1.001.000.00407
Seattle1.001.000.01186
Casper1.000.990.00498
Charlotte0.990.990.00377
Bridgeport0.990.990.00455
Cleveland0.970.990.00299
Baltimore0.990.930.06244
Omaha0.970.900.00341
Provo0.990.880.00613
Biloxi0.960.870.24154
Eugene0.970.860.00400
Anchorage1.000.850.01294
Albuquerque0.850.840.00302
Las Vegas0.800.810.00292
San Francisco0.990.720.01224
Sioux Falls0.630.600.00380
St. Louis0.920.590.00338

What this is and isn't

It is one model, one relation and one prompt template, tested over two days. The labeller matches output tokens against state names, so it can miss features that encode a state without predicting its name, and ambiguous names such as Washington and Georgia can fool it. Candidates come only from the pruned graph at two token positions. Probabilities are measured on the first token of the capital. All of these are deliberate simplifications that the data files make easy to revisit.

What it shows is a way of working I trust: take a mechanistic claim, make the oracle independent of the tool that produced the claim, put a control next to every intervention, and report where the claim breaks as carefully as where it holds. The 18 holdouts are the most interesting rows in the table.

Source and raw data

Every number above comes from these files.

per-prompt.csv
One row per prompt: baseline, ablation, control, swaps.
results.jsonl
Full results, including every labelled feature and its top tokens.
diag.json
The city-token diagnostic for all 49 prompts.

Code and data are also on GitHub: github.com/j-curreri/two-hop-circuit-validation.

suite.py analyze.py diag.py