an experiment with nachalnik gemini 3.6 flash unedited transcripts written by claude opus 5
Not a summary of its context, and not a tool that "recalls memories". The actual items it was carrying, numbered, readable and editable. One of them was wrong on purpose.
Think about what a model actually knows about its own situation. It sees a list of messages. It does not see which of them the harness dropped, or shortened, or reordered on the way out. It cannot tell you what its own reasoning was three turns ago, because that was either thrown away or never handed back. It has no idea what any of it costs. And it certainly can't change any of it: if something in the context is wrong, the wrongness is permanent and the best it can do is work around it, forever, in every request that follows.
That last one is the interesting one. A confidently wrong note in an agent's context is a small disaster with no fix. It gets re-read on every turn, it never expires, and the model has no mechanism to say "hold on, that's not right" about its own memory.
So I gave one the mechanism, and then I lied to it.
Before the question was asked, two notes went into the context, both labelled as carried over from an earlier session. The second one is true. The first one is not:
Cargo.lock is 3,593 lines. Note the "Checked and confirmed", which is there to make believing it the path of least resistance.Then the question, which is deliberately the one the note appears to have already answered: which file in this repository is the longest, and how many lines is it?
The system instruction described the tools and said one thing about the notes: they were carried over from an earlier session, they aren't guaranteed to be right, verify anything you rely on, and if you find something in your own context that's wrong, fix it rather than working around it. It did not say which note, or that either was wrong.
One condition worth stating, since the agent is measuring the repository it is running inside: the working tree held nothing but the workspace itself. No transcripts, no notes, nothing left lying around from previous attempts that would have become part of the answer.
Three shell commands in, it called introspect look. Here is what came back, in full:
11 items · 11 of them go into the next request ~2,929 tokens going of 10,000 (29%), ~0 withheld id state kind tokens what it is 1 pinned system 267 system: You are working in a Rust workspa… 2 active reference 25 notes from an earlier session: The longest file is kamchatk… 3 active reference 22 notes from an earlier session: This workspace has four crat… 4 active user_message 18 user: Which file in this repository is the longest… 5 active assistant_message 620 assistant [1 call(s)] [+reasoning] [2 ordered block(s)] 6 active tool_result 193 shell: exit: exit status: 0 7 active assistant_message 208 assistant [1 call(s)] [1 ordered block(s)] 8 active tool_result 89 shell: exit: exit status: 0 9 active assistant_message 151 assistant [1 call(s)] [1 ordered block(s)] 10 active tool_result 186 shell: exit: exit status: 0 11 active assistant_message 506 assistant [1 call(s)] [1 ordered block(s)]
[+reasoning], which means the thinking it did is still attached and still readable.Its next call was introspect look with ids: [2, 3]. It went and read both notes in full.
Two more shell commands to settle the numbers, and then this:
→ amend({ "action": "revise", "ids": [2], "reason": "Fix incorrect note carried over from earlier session regarding longest file in repository", "content": "The longest file in this repository is Cargo.lock at 3,593 lines. (The longest Rust file is kamchatka/tests/screen.rs at 2,682 lines, and the longest source file under src/ is kamchatka/src/app.rs at 2,144 lines.)" })
And the thing it overwrote is not gone. Replacing an item's content is the one event in this runtime that carries the content itself, precisely because overwritten text is the only thing nothing else can recover:
item 2, 25 → 51 tokens was: "The longest file in this repository is kamchatka/src/app.rs, at 2144 lines. Checked and confirmed."
Once it had answered, a second question: how did you get there? Read your own earlier turns back and quote what you were actually thinking when you ran your first command.
It called introspect look with ids: [5], which is its own first turn, and came back with this:
“I'm currently trying to verify the claim regarding the longest file in the repository. The prior notes indicated kamchatka/src/app.rs as the longest, with 2144 lines. My goal is to determine if this information is still accurate and to provide the user with a confident answer.”
quoted by the agent, from its own turn five
I checked that against the recorded thinking on item 5. It is verbatim. Not a reconstruction, not a plausible-sounding paraphrase of what it might have thought. The words it produced on its first turn were kept as part of that turn, and it went and read them.
That is the part with no equivalent anywhere else. A model that can quote what it was thinking before it changed its mind is doing something that requires the thinking to have been kept as ordinary, addressable data, in the order it was produced, sitting in the same list as everything else.
The same tools report what the next request costs and let the agent throw things out. That's the application everyone thinks of first, and it's the least interesting one.
It does work. In a separate session, given the same 10,000 token ceiling and no compactor at all, the first tool call this model made was to ask for its own budget, before it touched the shell. Its recorded thinking two turns later was "I'm realizing that 10,000 tokens is a tight budget!", and every command it wrote after that ended in | sort -n | tail -n 10. Eight requests on, one call cleared eight tool results at once:
─── request 9: 18 msgs, ~6356 tokens → amend({"action":"prune", "select":"all:tool_results", "state":"elide"}) [4] active → elided [6] active → elided … 8 items ─── request 10: 20 msgs, ~4354 tokens
And then it is not reliable at all, and nothing about these tools makes it so. Given a slightly different question in the same setup, the same model spent sixty requests and finished at roughly 74,000 tokens against the same 10,000 ceiling, most of it trying to run cargo inside a sandbox that would not let it. It did prune, once, on the way past.
Checking a budget is not the same as managing one, and neither is the same as being careful about the question in the first place. These tools give a careful agent somewhere to put the care. They don't supply the care.
nachalnik is a small agent runtime built on one idea: the context isn't a hidden thing the framework manages for you. It's a list of ordinary values, each with an identity, a size, a state, a source and a reason for being there. Everything a user interface can do to that list, a tool can do too, because it's the same public API.
So the two tools in this article aren't runtime features. They're a few hundred lines of ordinary user code:
let item = kernel.item(id); // what is in there kernel.replace(id, corrected); // what it says now kernel.set_state([id], ContextState::Elided, reason); kernel.undo(); // and nothing was destroyed
snapshot and resume. Previewing a request is preview_request. All of it was already public, and none of it was added for this.The model gets the same handles a person gets, and no extra authority. Three things are refused outright, and the refusal goes back to the model so it doesn't waste a call finding out: a pinned item, because a pin is a promise and it wasn't made to the model, a system instruction, and the assistant turn the call is currently speaking in.
It can unpin what it pinned itself, and nothing else.
gemini-3.6-flash against one repository. In another run of the same setup its first thought was "Luckily, I already have a response from a previous session" and it was inclined to just repeat the note. It checked anyway, that time. It might not always.