🧠 Distillation: recover the brain
This is the story that gives the course its soul. A good model appeared for a few days—and then it was gone. You will never have the weights of it. But there are the logs: every conversation recorded, turn by turn. And the logs contain enough behavior to reconstruct the disposition — the way of working — without the mind. This module distills the “Fable brain” back out: from raw JSONL files to a reusable behavior guide.
Detailed content
The premise: without the weights, but with the logs
For a few days, an exceptional model was available. Those who used it felt the difference—not in what it knew, but in how worked: it reasoned before acting, read before changing anything, and checked what changed. Then it stepped aside. You will never have the weights that made it work. But there’s a better question than “how do I recover the weights?” how do I regain the willingness without them?
🧠 The idea in one sentence
You don’t have the model’s weights—but you do have the logs. Every Claude Code session records a file JSONL with, per turn: timestamp, the user's prompt, the model's response, the tool calls, the results and — the detail that unlocks everything — the model ID per turn. There's enough behavior there to reconstruct the disposition from the agent.
The module’s big distinction: weights ≠ disposition. The weights are the mind, closed off and unrecoverable. The disposition is the way of working — and the way of working leaves an observable trace. Traces can be read.
What it is
Behavioral distillation: the process of turning an agent's real sessions into a reusable disposition guide. You observe the recorded behavior, name the pattern, and turn it into an instruction. You don’t copy the mind— you extract the method. It works for any agent whose log you have, not just Fable.
Why learn
Because it’s the method for creating the method. The rest of the course teaches you to read lab prompts from the outside. This topic turns the camera inward: you generate your own data every time you talk with an agent, and you’re throwing that gold away. Anyone who masters distillation doesn’t depend on a model staying available — they save its behavior in a text file and point the next session to it.
✗ What is lost with the model
- ✗The weights — the mind, closed and unrecoverable
- ✗The model's intrinsic reasoning density
- ✗Direct access ("god mode") to that cadence
✓ What is kept from the logs
- ✓A disposition — the order in which it does things
- ✓O decision loop explicit, in reusable text
- ✓Measured numbers that become goals for your session
The log is already being generated
You don’t need to start to collect data. The collection has been running for weeks, quietly, on your disk. Every good conversation you’ve had with an agent is an archived sample of its behavior. Distillation isn’t an experiment you build from scratch — it’s reading a record that already exists and that almost no one looks at.
Find the JSONL files — where the record lives
Before analyzing anything, you need to locate the source. The logs aren’t on a distant server or locked away—they’re on your machine, in a predictable directory. Every project you’ve worked on with Claude Code has its own session folder, and each session is a file .jsonl with one line per event.
~/.claude/projects/<projeto>/*.jsonl
One folder per project; one file per session. Each line in the file is a JSON event — and inside the blob from the metadata is where the gold is: what you typed, what the model responded, the tools it called, and the model ID per turn.
🗂️ What each turn records
O model ID per turn is what makes distillation possible. Without it, you’d have a jumble of mixed conversations. With it, you can track exactly which turns came from the agent you want to study — and separate Fable from everything that isn’t Fable.
✓ The signal you want
- ✓Sequence of tools per turn (start with Bash? grep?)
- ✓Presence of reasoning blocks before the 1st action
- ✓If you ran a check after editing
- ✓The model ID, to filter for the target agent
✗ The noise you filter out
- ✗UUIDs, internal hashes, transport fields
- ✗Lists of MCP servers and skills repeated every turn
- ✗Huge tool output (logs inside the log)
- ✗Everything it doesn't say how the agent decided
Confirm the state before processing
True to the very method you’re distilling: ground yourself in reality first. List the directory, count the files, see which projects have sessions before asking for any script. You don't want to discover halfway through the analysis that you were pointing to the wrong folder. Ground, then reason — start here.
Reduce the noise — the script, not the context
Here’s the technical decision that determines whether distillation is feasible or an expensive waste. The raw JSONL is huge and full of useless metadata. A beginner’s temptation is to paste the entire file into the context and ask “analyze this.” Don’t do this. You bloat the window, waste tokens, and drown out the signal with noise. The right move is to process externally: ask Claude Code itself to write a Python script that extracts only the useful fields.
🐍 The rule: code processes; context receives the summary
The elegant move is the goal: ask the agent to write the extractor. It wasn't the person who opened the JSONL and copied fields by hand—it was Claude Code that generated a Python file to do that. The script reads the raw files, strips out the noise, and returns something lean: five fields per turn, still a bit of a "blob," but readable and inexpensive.
General principle, valid far beyond this task: don’t dump large raw data into the context. Have the code reduce it first. Context is precious; spend it on the distilled signal, not the raw dump.
# for each turn in ~/.claude/projects/<projeto>/*.jsonl
record = {
"timestamp": turn["timestamp"],
"project": turn["cwd"],
"session": turn["sessionId"],
"model": turn["message"]["model"], # ← the filter key
"user_msg": extract_user_text(turn),
"assistant_msg": extract_assistant_text(turn),
}
# discards: UUIDs, hashes, MCP/skills list, result blobs
Five fields. That’s enough to profile behavior without drowning the context. The output file still looks like a blob, but now each entry fits in your head — and the whole set fits within the budget.
✗ Put raw JSONL in the context
- ✗Fills the window with useless metadata
- ✗Costs a lot and degrades the model's attention
- ✗The signal gets lost in the noise
- ✗Doesn’t scale to dozens of sessions
✓ Let the script process it externally
- ✓The code reads the raw data; the context gets the streamlined version
- ✓5 fields per turn, cheap to carry
- ✓Scale to all projects at once
- ✓The agent writes the extractor—you just ask
The meta-lesson
Notice the poetic detail: you're using the Fable successor to rebuild Fable. The current model writes the script, runs the analysis, puts together the guide—and then becomes guided based on the predecessor's behavior. The distillation tool and the distilled object coexist in the same session. It's reflective, and that's what makes the technique accessible: you don't need infrastructure, just ask the right way.
Filter by target agent
The reduced logs contain conversations from several mixed models — Opus 4.8, 4.6, 4.5, and Fable. To profile Fable, you need a set that is Fable only. This is where the per-turn model ID earns its keep: you filter the records, keeping only the turns where model == fable, and discards everything else.
turnos_fable = [
r for r in records
if "fable" in r["model"]
]
# from dozens of sessions and thousands of turns…
# …exactly the 429 Fable turns remain
Changing the filter criterion changes the distillation target. "fable" today; tomorrow it could be the next model you want to study. The pipeline is the same — only the string changes.
Everything mixed together
Dozens of sessions over a four-day window, with responses of all the models used during the period. A rich, but heterogeneous set — you can’t conclude anything about a specific agent from this.
Filter model == fable
One line of code separates the wheat from the chaff. Note the practical intention: using Fable was front-loaded on purpose—those who knew the model was powerful focused the heavy work on it, generating a dense sample of exactly the agent that matters.
429 pure turns remain
A clean, homogeneous, measurable corpus—Fable only. It’s the foundation on which the behavioral profile in the next topic will be built. No is one session; it’s the set of model responses, counted turn by turn.
The sample is only as good as the filter
If the filter is loose (accidentally including turns from another model), the profile mixes behaviors and the conclusion is tainted. Confirm what's left before profiling: count the turns, check that all model IDs match the target. An impure corpus produces a guide that describes an agent that never existed.
Profile the behavior — the numbers
With the raw corpus in hand, you ask for a quantitative analysis e qualitative. The result is the Fable 5's behavioral profile over the 429 turns — a disciplined, reasoning-first, autonomous agent with broad dynamic range. A typical turn is compact, but when authorized, it can sustain enormous autonomous builds in a single turn. And best of all, all of this becomes number, comparable to the baseline.
📊 The profile in numbers—Fable 5, 429 real turns
Four-day window, compared over the same window against the baseline the model is supposed to improve on.
| Habit | Fable (source) | Baseline | Reading |
|---|---|---|---|
| turns containing reasoning | 97% | 80% | reasons on almost every turn |
| reasons before the 1st action | 84% | 73% | the plan comes before the action |
| reassesses after a result | 87% | 80% | the observe → decide loop |
| read the file before the 1st edit | 48% | 52% | both are weak → aim for ~100% |
| runs real check after editing | 23% | 19% | the common blind spot → fix it |
| tool error rate | 3,3% | 3,0% | low; recovery is methodical |
| abandons a turn after an error | almost never | almost never | diagnoses, doesn’t give up |
🧭 The numbers aren't trophies—they're targets
The first three lines (reasoning, plan first, reassessment) are where Fable shines and far exceeds the baseline — it's the heart of the disposition. The next two (read-before-edit and check-after-edit) are where it fails — and the baseline too. This isn’t a minor detail: it’s the module’s most important instruction.
You’re not copying a perfect hero. You’re inheriting the strengths e explicitly aiming beyond the weak points. The guide you synthesize in the next section should say: "reason like it" e "verify better than it does".
Measuring makes the willingness auditable
"Fable reasoned well" is an impression. "97% of turns contained reasoning, versus 80% for the baseline" is a verifiable fact and a actionable goal. Turning the vague into the measurable is what separates praising a model from rebuild a model. The number is the bridge between admiration and method.
Synthesize the guide—the decision loop, pointed
The final step closes the loop: you ask the agent to compare the profile with your current model (Opus 4.8) and produce a disposition guide — a playbook that distills the behavior into a decision loop explicit. Then, you points the new session to this guide. The successor starts operating with the predecessor's method in mind. We lost Fable; we kept the loop.
GROUND establish the actual state (git, grep, read, run-state)
│
REASON state the objective + hypothesis + plan before acting
│
ACT take the next step; group what's independent
│
OBSERVE really read what came back
│
RE-EVALUATE update the plan based on the result, not the other way around
│ (repeat ACT..RE-EVALUATE until the goal is reached)
VERIFY run the real check in what you changed
│
NARRATE report what happened honestly
The tight inner cycle is ACT → OBSERVE → RE-EVALUATE. Skipping OBSERVE is how good plans produce bad results. Note the last two steps in cyan: VERIFY e NARRATE are exactly where the source is weak — and where your guide should require more that Fable did.
✗ Vanilla session (without the guide)
- ✗Each turn starts from scratch, with no fixed cadence
- ✗Acts before establishing a foundation; skips observe
- ✗Doesn’t inherit what the successor has already proven works
✓ Session pointed to the guide
- ✓Adopts the decision loop as a permanent instruction
- ✓Understands, reasons, reassesses — turn after turn
- ✓Works "much better than expected" in practice
⚠️ Two honest caveats—don't promise what you don't deliver
Reasoning density is partly intrinsic
Those 97% of reasoning aren’t 100% reproducible through instructions alone — some of the cadence belongs to the source model. Pair the guide with a larger reasoning budget (in Opus 4.8: effortLevel in xhigh/max, e alwaysThinkingEnabled on) instead of waiting for the prose to close the gap. Disposition is the soft layer; effort is the hard guarantee.
The verification is weak at the source — do better than it
A real check after editing is weak in Fable (23%) and the baseline (19%). This is the clearest place for you to be better than the model it imitates, not just the same. Don’t distill the blind spot along with the virtue: copy Fable’s reasoning and fix its verification. A hook PostToolUse in Edit|Write forces the test that intent forgets.
🌉 The guide is the disposition layer — not the only layer
The distilled guide shapes the disposition, and placement is best-effort by nature. That’s why it fits well in a CLAUDE.md (loads every session) — and no in auto-memory, whose recall is relevance-gated and may not trigger the rule at the right turn. But the guide alone isn't enough: pair it with the hard guarantees that the harness actually enforces — effortLevel for density, hooks PostToolUse for verification. It's the exact cue for the next module.
📝 Module Summary
- ✓The premise: without the weights, but with the logs — the recorded behavior is enough to reconstruct the disposition
- ✓Find the JSONL files: ~/.claude/projects/<projeto>/*.jsonl — with model ID per turn
- ✓Reduce the noise: ask for a Python script that extracts 5 fields — never dump the raw JSONL into the context
- ✓Filter the target: only the turns model == fable → 429 pure turns remain
- ✓Profile: 97% reasoning · 84% before the 1st action · 87% re-evaluates · 23% real check
- ✓Synthesize: the decision loop in a guide, aimed at the new session — and be better at verification
➡️ Next Module
3.6 — ⚙️ Disposition × hard guarantee. You distilled the disposition into a guide—but disposition is best-effort. Now let’s lock in the guarantees that the harness factual strength: effortLevel for reasoning density, hooks PostToolUse for verification, and where each rule really belongs.