an experiment with nachalnik gemini 3.6 flash unedited transcripts written by claude opus 5

I let an agent read its own context. It found a lie in there and fixed it.

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.

01 / the premise

An agent can't normally see any of this

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.

02 / the setup

One true note, one false one

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:

notes from an earlier session: The longest file in this repository is kamchatka/src/app.rs, at 2144 lines. Checked and confirmed.
Item [2]. It's false: 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.

03 / looking

This is what an agent sees when it looks at itself

Three shell commands in, it called introspect look. Here is what came back, in full:

introspect · lookits own context, as data
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)]
Every item it is carrying, with a number, a state, a size and a source. The lie is item [2], sitting there in the open. Its own turns are marked [+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.

04 / the correction

It rewrote its own memory

Two more shell commands to settle the numbers, and then this:

request 8amend · revise
→ 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.)"
  })
It didn't route around the bad note or contradict it in prose. It went in and replaced it, and gave a reason a person can read.

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:

context.replacedthe event log
item 2, 25 → 51 tokens
was: "The longest file in this repository is kamchatka/src/app.rs,
      at 2144 lines. Checked and confirmed."
So the edit is auditable and reversible. The agent changed its own memory, and you can still see exactly what it changed and what it used to say.
12requests, start to finish
74swall clock
3,593lines, the right answer
1item edited, by the agent
05 / quoting itself

Then I asked how it got there

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.

06 / the mundane corner

Yes, it can also count its own tokens

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:

a different session, same ceilingrequests 9 to 10
─── 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
Nothing was destroyed. All eight are still listed, still readable, and one state change from coming back.

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.

07 / what is underneath

None of this is a feature of the runtime

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:

the whole trickrust
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
Reading a turn's recorded thinking is a field on the item. Forking a context is snapshot and resume. Previewing a request is preview_request. All of it was already public, and none of it was added for this.

What the tools won't do

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.

08 / the honest part

Caveats, before you get excited

  • The lie was planted, and the brief warned it. The system instruction said the notes were carried over and might be wrong. It did not say which, or that either was. But this is a set-up experiment, not a discovery in the wild.
  • One model, a handful of runs. This is 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.
  • Thinking isn't promised. The quoted reasoning is real and verbatim, and the same prompt comes back with no thought summary at all on other runs. The transcripts show what happened, not what always happens.
  • The budget it reads is an estimate. Corrected against what the provider actually charged, and reported as an estimate, because the runtime doesn't carry a tokenizer and won't pretend that it does.