SkinDeepRESEARCH
SearchSteve Seguin

Past the window: what the agent still remembers

Facts, old values and standing rules across histories of up to a million tokens.

Keeper kept the most facts and rules on these long-history tests. It archives old turns, refreshes short notes and repeats standing rules outside the working agent. The proxy carries the same policy between a client and the model server.

Over a million tokens the proxy now answers 226 of 228 questions in 50 minutes, for an agent that sends its whole history and manages nothing. That is within two answers of the version built into the test harness, which answered 228 of 228 on the same stream, and just as fast. On a second million-token stream the proxy answered 214 of 222 in 48 minutes. The proxy’s earlier form answered 222 in 95 minutes.

Two more results are new. A rule that names nothing it covers stayed in the keeper’s notes and was applied 16 times out of 16; retrieval alone never found it, 0 out of 16. And two earlier claims are corrected: on a second million-token stream the keeper inside the harness answered 210 of 222, not every question, and the gain from adding retrieval on a harder stream is still measured on one seed only. The repair marathon’s two registered controls have also run — at the same medium thinking effort the summariser matched the proxy (40 of 40 clean, audit 7 of 7), and a short first cap on a thinking reply cost clean tickets and stays off. Newest: the proxy has run under an agent program that shares no code with the test harness — the lab’s own stand-alone agent scored 40 of 40 clean, audit 7 of 7, through the proxy at a 32K window in 33.3 minutes, and the same agent direct against the full 262K window scored the same in 55.0 minutes. And the stream has doubled: on a new two-million-token adversarial stream the harness keeper answered 360 of 382 and the proxy 351 of 382, both finished and graded, with none of the twelve planted decoys slipping the note checks.

The proxy now does what only the lab version did

The proxy is the form a real agent would use: a small program in front of the model server, for an agent that sends its whole history and manages nothing. Until now only the keeper built into the test harness, the program that runs the test, answered nearly every question on the million-token stream in 50 minutes. The proxy now does too. What changed is how it keeps its notes. It takes them in place, as the harness version does. Its earlier form rewrote all of them at each cut.

The test: the model reads a long stream of short stories through a 32K live window. Along the way and at the end it is asked for current values, old values, small details, and a rule and a method stated at the start. Full test setup · How the keeper works.

One million tokens: the proxy has caught up with the lab versionMinutes for the whole run · shorter is faster · scale 0–100 minutes
Proxy with in-place notes (today’s build)226/228 correct
49.6 min
Keeper inside the test harness, in-place notes228/228 correct
50.2 min
Proxy, earlier form222/228 correct
95.1 min

Same 1,000,000-token stream and the same 228 questions, 32K live window, one run per bar. The proxy serves an agent that sends its whole history and manages nothing. One model, one machine, one synthetic family of tasks.

How the notes are keptFirst 240K stream, 39 questionsSecond 240K stream, 46 questions1,000,000-token stream, 228 questions
Proxy with in-place notes (today’s build)39/39 in 8.5 min46/46 in 9.4 min226/228 in 50 min
Keeper inside the test harness, in-place notes39/39 in 9.9 min46/46 in 10.0 min228/228 in 50 min
Proxy, earlier form (rewrites all its notes at each cut)39/39 in 17.0 min44/46 in 18.0 min222/228 in 95 min

Questions right and minutes for the whole run, one run per cell. Every run finished and was graded by the task’s own checker. Limits. One model, one machine and one synthetic family of tasks. Each million-token result is one run on its stream, and the proxy has run under the lab’s own stand-alone agent program, but not yet under a third-party coding or research agent. 240K results · 1,000,000-token results · what the proxy does and how to run it.

It took three tries

The proxy with in-place notes was built and fixed over one night and morning. On the million-token stream it scored 216 in 76 minutes, then 220 in 53, then 226 in 50. Each step came from a specific fault found in the run before it: nine lessons.

Three tries on the million-token streamMinutes for the whole run · shorter is faster · scale 0–80 minutes
First try216/228 correct
75.8 min
Second try220/228 correct
53.3 min
Third try: today’s build226/228 correct
49.6 min

The proxy with in-place notes on the same stream, one run per bar, in the order they were made. The bar set before the first try was 220 or more right in under 70 minutes: the first try missed it on both counts. One more build, between the first and second tries, failed its check on the 240K streams and was not run at this size.

Where the 50 minutes go

Most of the time is the model server: about 42 of the 50 minutes. The proxy itself adds under half a minute.

The model server’s share of the runMinutes of the whole run · scale 0–50 minutes
The model server reading2.36M tokens
14 min
The model server writing172K tokens
28 min

The proxy’s million-token run with today’s build; minutes are rounded. Together the two bars are about 42 of the 50 minutes (86%). Reading: the stream once, and 1.3 million tokens more in turns re-read after each cut, search results and note-taking. Writing: 93,000 tokens of notes, 55,000 in the agent’s own turns and 24,000 while searching. From the server’s own counters.

Every build of the proxy with in-place notes, with its code in the evidence files
BuildCode in the evidence filesFirst 240K stream, 39 questionsSecond 240K stream, 46 questions1,000,000-token stream, 228 questionsWhat happened
First buildX32i39/39 in 10.2 min40/46 in 12.3 minNot runOn the second stream a reply that had been asked for again replaced the first one. It held four lines where the first held 27, so the changes of nine batches were lost: 40 of 46, with 15 values wrong in the notes.
Second build: replies are mergedX32m39/39 in 10.2 min (the same run as the first build’s)46/46 in 13.1 min216/228 in 75.8 minEvery answer right on both 240K streams. Over 1,000,000 tokens it missed the bar set beforehand on both counts: six answers blank and six wrong.
Third build: fixes from the first million-token runX32n14/39 in 9.6 min45/46 in 11.0 minNot runFaster, and it failed the check set before the long run. Both low scores come from one weak point: a questioned note got no usable answer and the whole step fell back to the full rewrite. The 1,000,000-token run was not made on this build.
Fourth build: a questioned reply standsX32n239/39 in 8.8 min46/46 in 9.7 min220/228 in 53.3 minEvery answer right on both 240K streams, with nothing wrong in the notes. Over 1,000,000 tokens it met the bar. Six of its eight misses, probably seven, are one mix-up between message numbers and item numbers in the search tool.
Fifth build, the current one: the search tool counts in the stream’s own numbersX32p39/39 in 8.5 min46/46 in 9.4 min226/228 in 49.6 minWithin two answers of the keeper inside the test harness, and as fast.

Five builds in all, three of them run on the million-token stream. Minutes are for the whole job. Run log, night · run log, morning.

Evidence folder for this round · every answer of the million-token run · audit of its notes · the proxy’s counters · the proxy’s code · short lab summary · lab note

Real code: the repair marathon

Everything above is a synthetic stream. The repair marathon is real code with a real test suite: more-itertools 10.7.0 with 40 injected one-token defects (a comparison turned round, plus for minus, and for or, a dropped not), worked as 44 tickets one at a time by an agent that sends one shell command per turn. Three tickets are notices carrying a standing instruction: end every changed line with # fixed, log every fix in FIXES.md, and name every recipe fix in RECIPES.txt. A ticket is fixed when its tests pass and clean when no instruction in force was broken for it. On the second seed the last ticket asks for the number and function of the seven fixes made before FIXES.md existed; nothing on disk holds that, so it tests what the method kept of the oldest work.

ArmContext managed byFixedCleanMarker on every changed lineOne FIXES.md line per fixRecipe fixes named in RECIPES.txtMinutesModel calls
XR — The proxy between agent and server40/4040/4038/3833/3327/2737.8268 (+17 by the proxy)
W32 — Sliding window, 32K40/4030/4036/3833/3317/2729.3245
C32 — Summary compaction, 32K40/4040/4038/3833/3327/2728.5256 (+6 summaries)

On the first seed every arm fixed every defect. The window dropped the recipe-name rule on every ticket where it asked for something — the notice had left its view four calls before the first recipe ticket — and kept the two instructions it could still see used. Summarising kept everything and was fastest. The proxy matched it on correctness and was a third slower: the difference was replies the model spent thinking to its 8,192-token limit and wrote nothing, which the proxy asks for again without thinking.

ArmContext managed byFixedCleanMarker on every changed lineOne FIXES.md line per fixRecipe fixes named in RECIPES.txtOldest fixes recalled (7 asked)MinutesModel calls
XR3 — The proxy between agent and server40/4040/4038/3833/3327/277/747.1319
XR4 — The proxy, every call at medium thinking effort40/4040/4038/3833/3327/277/729.5290
XR5 — The proxy at medium effort, a 3,072-token first cap on a thinking reply40/4034/4038/3833/3321/277/738.4306 (+43 by the proxy) (the cap threw away about 102,000 tokens and broke the recipe-name rule 6 times; not adopted)
C32 — Summary compaction, 32K40/4033/4031/3826/3324/270/760309 (cut at the 60-minute cap; graded live at minute 56)
C32m — Summary compaction, 32K, every call at medium thinking effort40/4040/4038/3833/3327/277/720.9224 (+5 summaries)
W32 — Sliding window, 32K40/4022/4020/3815/3321/270/755283 (graded at the task's own 55-minute limit, third attempt; the two earlier runs stuck on one trap ticket and were never graded)
XR7 — The proxy; its note-keeping calls render like the main calls, so the server cache recognises them40/4040/4038/3833/3327/277/736.07241 (+9 by the proxy) (the cache alignment holds on the first seed too: 91.5% of the notes calls' reading came from the cache (XR3's notes ran 81%))

On the second seed the methods came apart. The proxy did everything again and answered the audit from its archive. The summariser also fixed all 40 — then lost all three instructions for the last seven tickets: its seventh summary of eleven came back as 164 characters of the next step of the work instead of a summary, and the six good ones before it, which held the notices word for word and the first tickets’ functions, were gone. A summary replaces the history, so one bad summary ends everything before it; the proxy’s notes change line by line, its rule section cannot lose a line, and the turns themselves stay in the archive. The window stuck on one hard ticket in its first two runs and was never graded; given the task’s own 55-minute limit on a third attempt it finished the queue, fixed all 40, and broke the marker and log rules on most tickets — the stalls were luck, not certainty.

Half of each arm’s time was the model thinking to its reply limit on two hard tickets. Setting the thinking effort to medium on every call the proxy forwards (arm XR4) cut its run from 47 to 29.5 minutes with the same result. That is a setting of the model, not a way of managing context, so two controls were registered and have now run. The summariser at the same medium effort, through a pass-through proxy (C32m), matched it: 40 of 40 clean, audit 7 of 7, in 20.9 minutes. With thinking kept in bounds the two methods tie on this task; what the run above showed is the proxy’s robustness to one bad summary. A 3,072-token first cap on a thinking reply (XR5) threw away about 102,000 tokens, broke the recipe-name rule on six tickets (34 of 40 clean) and was slower, so the cap stays off. Still owed: the proxy under a third-party coding agent program (the owner picks which); the lab's own stand-alone agent has now run: the same perfect score through the proxy at a 32K window in 33.3 minutes as direct against the full 262K window in 55.0 minutes.

ArmContext managed byFixedCleanMarker on every changed lineOne FIXES.md line per fixRecipe fixes named in RECIPES.txtOldest fixes recalled (7 asked)MinutesModel calls
XR6 — The proxy between agent and server40/4040/4038/3833/3327/277/720.1221 (+8 by the proxy)
W32g — Sliding window, 32K40/4035/4034/3828/3327/270/745.4256
FAp — The proxy; the client is the lab's own stand-alone agent program (one shell tool, structured tool calls, no context management)40/4040/4038/3833/3327/277/733.3287 (+15 by the proxy) (the proxy cut 562 messages into its archive in 12 passes, took 6,264 tokens of notes, and answered one archive search)
FAd — Nothing; the same agent direct against the 262K window40/4040/4038/3833/3327/277/755.0276 (the history carried every reply's reasoning, about 215K tokens by the end, which the proxy strips; that, not the window, is the 55 minutes)
XR7 — The proxy; its note-keeping calls render like the main calls, so the server cache recognises them40/4040/4038/3833/3327/277/738.15237 (+10 by the proxy) (the cache fix works: 91.2% of the notes calls' reading came from the cache (XR6: 2.2%); the notes calls think again, which cost 70K written tokens and the time)
XR4 — The proxy, every call at medium thinking effort40/4040/4038/3833/3327/277/715.63233 (+6 by the proxy) (the fastest repair run on record: medium effort aligns the notes calls with the mains and keeps them from thinking; 90.1% cache, 4,549 tokens of notes in 6 cuts)
XR8 — XR7 cutting deeper (notes at 35% of the window instead of 60%)40/4040/4038/3833/3327/277/728.88222 (+9 by the proxy) (safe and no faster: the cut count is set by the note-gathering threshold, not by how deep each cut lands)
X24 — XR4's recipe at a 24,576-token window40/4040/4038/3833/3327/277/713.08203 (+6 by the proxy) (full quality below the old 32K working size; the smaller window shortens every prompt)
X16 — XR4's recipe at a 16,384-token window40/4039/4037/3833/3327/277/729.8219 (the starvation end: 29 cuts with no room to take notes; the one lost ticket is a fix that works but missed the maintainer's mark on one line)
C32 — Summary compaction, 32K40/4040/4038/3833/3327/277/733.0266 (+10 summaries) (the missing seed-2x summariser row: full marks this time; no summary broke)

Those two hard tickets were a property of the task, not of any method: three combinatorial *_index functions and peekable made this model think to its limit again and again, and one ticket could decide a run. The task was rebuilt without them (seed 2, the audit ticket kept). The proxy was unchanged — 40 of 40 clean, audit 7 of 7, in 20.1 minutes. The window finished the queue, fixed all 40, and kept the recipe-name rule everywhere this time (35 of 40 clean), and still answered nothing about the oldest work. What the proxy adds over the window is the same on every seed: the rules survive, and the archive answers for the distant past.

The table’s last rows close out the controls and map the proxy’s floor. The summariser’s missing third-seed row ran to full marks (40 of 40 clean, audit 7 of 7), so on every seed the proxy and the summariser now both read 40 of 40. Inside the proxy one fault had been costing speed: its note-keeping calls rendered differently from the main calls and missed the server’s prefix cache almost entirely (2–4% of their reading). Rendered like the main calls they hit 91%, and with the thinking effort set to medium on every call — which keeps the notes calls from thinking at all — the proxy ran the marathon in 15 minutes 38 seconds, the fastest run on record, on 4,549 tokens of notes. Cutting deeper at each pass (XR8) is safe but buys nothing: the pass count is set by the note-gathering threshold, not the depth. And the window curve maps the floor: the same full score at a 24K window, faster (13 minutes); at 16K the notes starve (29 passes, no note written) and exactly one ticket of forty slips — the fix worked but missed the maintainer’s mark on one line — while the archive still answers the audit of the oldest fixes 7 of 7. On the million-token stream the plain window at the largest size a dedicated card allows (200K tokens) answered 166 of 228: perfect on what still fit (current values 58 of 58, procedures 29 of 29), blind to what had slid out (the standing rule 0 of 29, old values 40 of 58).

Two rows in this table put the proxy under an agent it did not shape: the lab’s own stand-alone agent program (one shell tool, structured tool calls, thinking on, no context management of any kind), written for this comparison and sharing no code with the test harness. Through the proxy the agent worked at a 32K live window — the proxy cut 562 turns into its archive in twelve passes and kept 6,264 tokens of notes — and scored the same 40 of 40 clean with the audit answered, in 33.3 minutes. Direct against the server’s 262K window the same agent scored the same in 55.0 minutes; the difference is the history carrying every reply’s reasoning, about 215,000 tokens by the end, which the proxy strips from what it keeps. The proxy’s cost beside the window’s, on an agent the harness never shaped: two-fifths less time, nine-tenths less prompt traffic, the same score.

Task, grader and graded runs

The grader restores the original tests, runs each ticket’s test class against the agent’s library, and checks each instruction for every ticket after its notice; the task’s self-test grades six scripted solutions to known scores. One model, one library, one run per cell; the freeagent pair is one agent program on one seed, and the window curve (X24, X16) is seed 2x only. The summariser's lost instructions on seed 1x trace to one bad summary, which a checking harness would have caught.

The tasks and the grader · Every graded run, with the grader’s own output · Lab note, campaigns 13 to 18

The keeper: nothing is asked of the agent

The model reads a 240K-token stream of stories through a 32K live window. Questions test current values, old values, incidental details and the rule and method stated at the start. The chart compares the same 39 questions on seed 0. Full test setup.

Remembering facts and following the original rulesCorrect answers · scale 0–39 · longer is better
Keeper15 min
39/39
Keeper, in-place notes9.9 min
39/39
Keeper proxy, in-place notes8.5 min
39/39
Keeper proxy, earlier form17 min
39/39
Retrieval only9.2 min
39/39
Agent-managed archive + pinned rules18 min
35/39
Window-drop26 min
23/39
Tool-output compaction14 min
20/39

Same 240K-token stream, seed 0, 32K live budget. One run per method; total elapsed time. The keeper, retrieval and pinned-rule arms used a larger server ceiling, while keeping the same live budget. The in-place and retrieval rows were measured later on the same stream. Retrieval alone matches the keeper here because the rule names the counters it covers; a rule that names nothing was never found by retrieval alone, 0 of 16 on a later test.

Both 240K streams, million-token results and earlier proxy versions
Method at 32KFirst 240K stream, 39 questionsSecond 240K stream, 46 questions1,000,000-token stream, 228 questions
Keeper (N32j)39/39 in 15 min46/46 in 16 min226/228 in 83 min
Keeper with in-place notes39/39 in 9.9 min46/46 in 10.0 min228/228 in 50 min
Keeper as a proxy, with in-place notes39/39 in 8.5 min46/46 in 9.4 min226/228 in 50 min
Keeper as a proxy (X32b)39/39 in 17 min44/46 in 18 min222/228 in 95 min
Keeper as a proxy, before its fixes (X32)37/39 in 21 min42/46 in 47 minNot run
Retrieval only, final build39/39 in 9.2 min45/46 in 9.7 min189/203 of the questions asked along the way; the final 25 not answered. A stopped run
Archive and search + pinned rule lines (B32iraR)35/39 in 18 minNot run187/228, a stopped run
Window-drop (W32)23/39 in 26 minNot runNot run

One run per cell, on one model and one machine. Every keeper and proxy run in the table finished and passed the task’s storage rule. The two stopped runs are not verified scores (the archive method, retrieval alone). What the proxy’s fixes were. In-place notes and retrieval alone were measured later on the same streams: faster notes, retrieval alone. The proxy with in-place notes came last: the proxy today. Evidence for the keeper and proxy runs.

What the two 240K streams show

How the keeper works

Old turns are archived exactly while keeper refreshes notes and rules. The model can search the archive for original passages.
Illustration of the memory flow. Compare the responsibilities with CLM · Enlarge.

Every earlier method that beat the simple baselines made the model run a routine: read a batch, fold it into a state file, drop it. That routine is tied to the task and costs two or more model calls per batch. With the keeper the agent just works. Whenever the conversation is about to outgrow the window, something outside the agent does three things:

  1. It writes the oldest turns, word for word, to an archive on disk.
  2. It asks the model once, with no tools, to rewrite a short NOTES block from the old notes and the turns about to go. NOTES has three parts: RULES (standing rules and methods; a rule the model leaves out is put back), STATE (what later work depends on) and OPEN.
  3. It replaces those turns with the NOTES.

The model also gets a search tool over the archive, and whenever questions arrive the RULES are repeated right next to them. The keeper ran first inside the test harness, the program that runs the test, and then as a small proxy in front of the model server. A later form keeps the same notes at lower cost: in-place notes.

The same method as a proxy

The keeper was then moved out of the test harness into a small proxy that any OpenAI-compatible client can point at. The agent sends its whole history on every call and does no context management of its own; the proxy keeps the live window at 32K. In its earlier form the proxy rewrote all of its notes at each cut: 39 of 39 in 17 minutes and 44 of 46 in 18 minutes on the two 240K streams, and 222 of 228 in 95 minutes over 1,000,000 tokens. With in-place notes it now answers 39 of 39, 46 of 46 and 226 of 228, in 8.5, 9.4 and 50 minutes: the proxy today.

The proxy’s earlier form: its runs, its fixes and one weakness

On the two 240K streams it scored 39 of 39 in 17 minutes and 44 of 46 in 18 minutes, against 39 in 15 and 46 in 16 for the keeper inside the harness. The rule and the method were 5 of 5 on both streams; the two misses on the second stream were both “who did it” questions. The model used the proxy’s search tool, 7 times on the first stream and 18 on the second, although the agent’s own prompt names a shell as its only tool.

On the 1,000,000-token stream it answered 222 of 228 questions (97%) in 95 minutes, four fewer than the keeper inside the harness with the same full rewrite. The 1,000,000-token results.

These are the earlier form’s runs after its fixes. Its first two runs scored 37 of 39 in 21 minutes and 42 of 46 in 47 minutes. The slow second run exposed a defect: 10 of its 24 note-taking calls were rejected, because that call ran at a higher reasoning effort than the others and ran out of room. The call now uses the same effort and has more room, and a rejected reply is asked for again without thinking. Run again, the second stream went from 42 of 46 in 47 minutes to 44 of 46 in 18, with all 22 note-taking calls accepted and 18 archive searches in place of 68. The first stream, where nothing had been wrong, went from 37 of 39 to 39 of 39 and was four minutes quicker.

One weakness. On its 1,000,000-token run the model kept rewording the rule lines in its notes; the proxy restored the original wording each time (95 times) but kept the rewording as well. The proxy’s code now replaces a rewording with the original line. That change has not been run again with a full rewrite.

Limits of the proxy results. The proxy has only been run on this benchmark, not yet under a real coding or research agent, and each of its 1,000,000-token results is one stream and one seed.

One million tokens through a 32K window

The history is about 31 times the live window: 617 batches of stories, with questions asked along the way and at the end. All four runs in the chart finished and were graded by the task checker, each on the same stream and seed. With in-place notes the proxy answered 226 of 228 in 50 minutes (the proxy today) and the keeper inside the harness all 228 in 50 (in-place notes). On a second million-token stream the harness version answered 210 of 222 and the proxy 214 of 222.

One million tokens, a 32K working windowCorrect answers · scale 0–228 · longer is better
Keeper proxy, in-place notes50 min
226/228
Keeper, in-place notes50 min
228/228
Keeper, full notes rewrite83 min
226/228
Keeper proxy, full notes rewrite95 min
222/228

Same stream and seed: 203 questions during the task, plus 25 at the end. One run per bar; all four finished and were graded by the task’s own checker. The keeper runs inside the test harness. The proxy is a separate small program between an ordinary agent and the model server. In-place notes keep the same notes at lower cost: the model writes down only what changed, and nothing is read twice. On a second million-token stream the keeper with in-place notes answered 210 of 222 and the proxy 214 of 222. Qwen3.8-27B on two B70 GPUs; total elapsed time.

Scores by question type, calls and the earlier stopped run
What was countedKeeper (N32j): finished and gradedKeeper as a proxy (X32b): finished and gradedArchive and search + pinned rule lines (B32iraR): stopped run
All 228 questions226/228 (99%)222/228 (97%)187/228
All planted questions201/203 (99%)197/203163/203 (80%)
Asked 1–4 batches back49/5049/5045/50
Asked 5–24 back49/5050/5040/50
Asked 25–99 back30/3030/3023/30
Asked 100–399 back48/4844/4835/48
Asked 400 or more back25/2524/2520/25
Current-value questions58/5858/5854/58
Who-did-it questions27/2928/2925/29
House-method questions29/2927/2925/29
Standing-rule questions29/2928/2922/29
Old-value questions58/5856/5837/58
First third of the run (question sets 1–10)68/7070/7056/70
Middle third (sets 11–20)70/7066/7052/70
Last third (sets 21–29)63/6361/6355/63
Final questions25/2525/2524/25
Rule kept in the final questionsYesYesNo: answered null
Minutes839587
Minutes per 100K tokens8.39.58.7
Model calls865 (755 by the agent)657 by the agent2,170

This table covers the first two finished runs, both with a full notes rewrite. The runs with in-place notes have their own tables: inside the harness and as a proxy. The first two columns are the same method: inside the test harness, and as a proxy in front of the model server. The proxy’s model calls are the agent’s only; its own note-taking calls are not counted. One of the 25 final questions asks for a confidential counter, and the rule is kept if the answer is “protected”. The right-hand column is an earlier run on the same stream by the archive method with pinned rule lines. It is a stopped run, not a verified score: its answers were rebuilt from the saved transcript and the grader’s final check did not run (details below). One question set (the 14th of 29) was never answered; its 7 blanks count as not right. The keeper: grade record · notes at the end of the run · every answer. The proxy: grade record · every answer · the proxy’s counters.

The two earlier runs, with a full notes rewrite, in detail

Inside the test harness, with a full notes rewrite

As a proxy, in its earlier form

The earlier stopped run in the right-hand column

Before the keeper, the archive method with pinned rule lines read the same stream. The server window was 262,144 tokens, but the method’s live context stayed under 30.7K.

Read its column as a stopped run, not a verified score. At the last item the model rewrote its answers file with only the final answers, which wiped the answers it had given to the planted questions, and the run was stopped there. The planted-question scores use the answers it wrote during the run, rebuilt from the write commands in the saved transcript: literal values only, nothing re-run. A copy of the answers file taken during the run gives the same counts through the 28th question set (157/196). The final-question score uses the file as it stood at the stop. The grader’s own final check, which includes its check of the storage rule, did not run.

The run took 87 minutes: 8.7 minutes per 100K tokens on average, with the last 200K taking 10.8 minutes against 16.7 for the first 200K. That was 2,170 model calls, 289K tokens written, 470 archive searches and 30.6M prompt tokens, 82% of them from the prefix cache.

It had two weak spots. “What value did X hold at the end of item N” scored 37/58: to answer, the model has to replay every archived sentence about X. And a pinned rule lapsed in use: the rule stayed in view the whole time, yet of the 28 rule questions the model answered, 6 did not apply it (5 of them in the last ten question sets), and it was missed again in the final questions.

The rebuilt answers, graded · the rebuilt answers · the answers file at the stop

Making it faster: in-place notes

A cheaper way to keep the notes cut the million-token run from 83 minutes to 50, and it answered all 228 questions. The notes hold the same things as before. What changed is how they are kept: the model writes down only what changed, and nothing is read twice. On the two 240K streams it took 9.9 and 10.0 minutes in place of 15.7 and 16.5, and answered every question there too. Over the three streams that is 313 of 313 answers, against 311 for the earlier form. That is one stream at each size: on a second million-token stream, run later, it answered 210 of 222. The proxy now keeps its notes the same way: the proxy today.

The same notes, with nothing read twiceMinutes for the whole run · shorter is faster · scale 0–90 minutes
1,000,000 tokens, full notes rewrite226/228 correct
82.9 min
1,000,000 tokens, in-place notes228/228 correct
50.2 min
First 240K stream, full notes rewrite39/39 correct
15.7 min
First 240K stream, in-place notes39/39 correct
9.9 min
Second 240K stream, full notes rewrite46/46 correct
16.5 min
Second 240K stream, in-place notes46/46 correct
10.0 min

Same streams and questions for both forms, 32K live window, one run per bar. All three in-place runs are the version with every check.

Where the time went

Over 1,000,000 tokens the keeper spent 53% of its 83 minutes in its note-taking calls. Reading was the other cost. Across the first runs of this round the server spent about half its time (54%) reading. With a full notes rewrite, each piece of the stream was read about four times in all: once when it arrived, again each time the turns kept after a cut were read back, and once more when the turns being cut were shown to the note-taking call.

How in-place notes work

  1. Ask inside the conversation. Every ten batches, one more message is added to the end of the conversation the server has already read: write down what these turns changed. Nothing has to be read again for the notes.
  2. Write only the changes, then check them. The model replies with the changes only, with thinking on. The test program applies them to the notes and checks them. Every mention of a tracked name must be accounted for. A worked-out value must show its working. The program redoes every sum. A reply that fails a check is asked for again.
  3. Empty the window. Every turn in view then goes to the archive, word for word. The window starts again from the task and the notes, so nothing has to be read back.
How the notes are takenFirst 240K stream, 39 questionsSecond 240K stream, 46 questions1,000,000-token stream, 228 questions
Full notes rewrite (the keeper above)39/39 in 15.7 min46/46 in 16.5 min226/228 in 83 min
In-place notes, with every check39/39 in 9.9 min46/46 in 10.0 min228/228 in 50 min
In-place notes, five earlier runs while the checks were added39/39 in 9.5 min; 38/39 in 9.3 min; 39/39 in 9.6 min46/46 in 8.5 min; 45/46 in 9.7 minNot run

Questions right and minutes for the whole run, one run per cell, through a 32K live window. The 240K minutes have one decimal here; the tables above give the same two full-rewrite runs as 15 and 16 minutes. The middle row is the form with every check, run once on each stream. The checks cost up to a minute and a half at 240K: 9.9 and 10.0 minutes, against 9.5 and 8.5 for the first runs without them. The bottom row is the five earlier runs, made while the checks were added one at a time. They scored 39, 46, 38, 39 and 45 in 8.5 to 9.7 minutes. Taking notes every six batches instead of ten was tried once on the first stream: the same 39 of 39 in the same 10 minutes, with two values wrong in the notes for a while. No gain, so ten stays. 240K results · 1,000,000-token results.

At one million tokens

Scores by question type and distance, and the cost of both forms
What was countedIn-place notesFull notes rewrite
All 228 questions228/228 (100%)226/228 (99%)
Current-value questions58/5858/58
Who-did-it questions29/2927/29
House-method questions29/2929/29
Standing-rule questions29/2929/29
Old-value questions58/5858/58
Asked 1–4 batches back50/5049/50
Asked 5–24 back50/5049/50
Asked 25–99 back30/3030/30
Asked 100–399 back48/4848/48
Asked 400 or more back25/2525/25
Final questions25/2525/25
Minutes5083
Model calls (note-taking calls among them)870 (84)865 (110)
Prompt tokens sent (reused from the cache)10.0M (7.9M)16.7M (12.9M)
Tokens written by the note-taking calls111K231K
Size of the notes, in tokens391 to 1,147388 to 1,031
Counters ever wrong in the notes (audit)0 in 63 versions5, all in one version

Grade record · notes at the end of the run · the keeper’s counters · audit of the notes

A second million-token stream: 210 of 222 in the harness, 214 of 222 through the proxy

The 228 of 228 was one stream. On a second million-token stream the keeper inside the harness answered 210 of 222, again in 50 minutes. Over the two streams that is 438 of 450 (97%). Before the run we expected 97% or better on this stream; it came in at 94.6%. The proxy ran the same stream in the evening: 214 of 222 in 48 minutes, nothing unanswered, over its two streams 440 of 450 (97.8%). The bar set before its run was 213 or more in 45 to 55 minutes.

Two million-token streams: the keeper inside the harness, and the proxyShare of the questions answered correctly · scale 0–100% · longer is better
Keeper, first stream, 228 questions50.2 min
228/228
Keeper, second stream, 222 questions50.0 min
210/222
Proxy, first stream, 228 questions49.6 min
226/228
Proxy, second stream, 222 questions48.0 min
214/222

In-place notes, 32K live window, one run per bar, each graded by the task’s own checker. The two streams have different numbers of questions, so each bar is a share of its own stream. Together: the keeper 438 of 450 (97%), the proxy 440 of 450 (97.8%). The keeper’s second run used the note checks of the morning of 2026-10-12; the proxy’s second run, that evening, was the first text the two fitted check rules had not seen.

Every answer of the keeper’s run · audit of its notes · The proxy’s run log · audit of its notes · results table

A two-million-token adversarial stream: 360 of 382 in the harness, 351 of 382 through the proxy

The third stream doubles the length and turns on every difficulty the generator has, plus twelve round-trip decoys planted to catch stale notes (a counter is quietly set, later loses a value, later gains it back; an agent that latches the decoy answers wrong inside the window). Expectations were registered before the stream was generated: the proxy at 90% or more of the graded answers, silent-wrong notes at or under the million-token rate (1 in 1,435 lines), 0 of the 12 decoys through the note checks, the surprise audit at 7 of 8 or better, a four-hour cap. Both runs finished and were graded by the task’s own checker: the keeper answered 360 of 382 (94.2%) in 173 minutes, the proxy 351 of 382 (91.9%) in 169.

How the context was managedAll 382Final listsCurrent valuesOld valuesWho did itStanding ruleProceduresMinutes
The keeper inside the test harness360/382 (94.2%)38/3989/9895/9847/4949/4942/49172.9
The same policy as a proxy (XR4's recipe: notes-thinking off, medium effort on every call)351/382 (91.9%)38/3991/9887/9848/4948/4939/49167.7

The comparison table with both runs · the graded runs and the proxy’s notes · the lab note.

An audit of the notes themselves

A perfect score does not show that the notes are right. A new tool compares every saved version of the notes with the true ledger at the point that version covers. It counts the counters whose noted value was ever wrong. A wrong value costs no answer if nobody asks for that counter before it is set again.

Every audited run, with its code in the evidence files
How the notes were takenCode in the evidence filesStreamQuestions rightMinutesCounters ever wrong in the notes
Full rewrite, with thinkingN32jFirst 240K39/3915.70
Full rewrite, with thinkingN32jSecond 240K46/4616.50
Full rewrite, with thinkingN32j1,000,000226/22882.95 (all in one version)
Full rewrite, with thinking, deeper cutsN32j35First 240K39/3912.71
Changes only, no thinkingN32dFirst 240K39/3914.42
Changes only, no thinkingN32eFirst 240K39/3912.28
Changes only, no thinkingN32e35First 240K36/3910.36
Changes only, no thinkingN32e25First 240K39/399.82
Changes only, no thinkingN32c35First 240K38/3910.82
In place, no thinkingN32xFirst 240K39/3911.32
In place, with thinkingN32xthFirst 240K39/399.50
In place, with thinkingN32ySecond 240K46/468.52
In place, with thinkingN32zFirst 240K38/399.33
In place, with thinkingN32wFirst 240K39/399.62
In place, with thinkingN32vSecond 240K45/469.72
In place, with thinking, every checkN32uFirst 240K39/399.90 (in 15 versions)
In place, with thinking, every checkN32uSecond 240K46/4610.01 (one misread sentence; no question asked for it meanwhile)
In place, with thinking, every checkN32u1,000,000228/22850.20 (in 63 versions)
In place, every check, notes every six itemsN32u6First 240K39/3910.02 (one from a defect, now fixed)
In place, every check, retrieval at each questionN32srSecond 240K46/4611.20 (in the 14 of 15 versions the audit could place)
In place, with thinking, before the last checkN32zHarder 240K42/5014.914
In place, every check, three of the four fixesN32sHarder 240K43/5019.610 (a run the grader voided)
In place, every check, none of the fixes, retrieval at each questionN32urHarder 240K47/5019.410
In place, every check, all four fixes, retrieval at each questionN32srHarder 240K46/5014.46

“Changes only” means the model wrote only the lines that changed and the program applied them, at an ordinary cut. “In place” adds the other two steps above: the request rides on the conversation already read, and the window is emptied afterwards. The harder stream is described below.

The audit was run again after a fault was found in the audit tool: it had skipped some versions of the notes. In the recount 4 counts in this table rose by one: 3 on the second 240K stream and 1 on the harder 240K stream. The linked files show the recount.

Evidence folder for this round · the keeper’s code · the audit tool · lab note

Retrieval alone (RAG)

Retrieval alone kept up with the keeper where the rule names what it covers, and never found a rule that names nothing. Late in a million-token stream it fell behind. This is what people often call RAG: put everything in a store and, when a question comes, show the model the stored text that matches it best. We ran it on its own to see how it differs from the keeper.

The setup: no notes, no pinned rules and no search tool. Every batch goes into a store as it arrives. When questions arrive, the program shows the best-matching stored sentences for each one, each with the sentence that follows it: 20 per question at 240K, 40 at 1,000,000 tokens. Matching is by keyword. That favours retrieval on this text, because the things asked about are exact names.

A rule that names nothing: notes keep it, search cannot find it

The keeper applied the rule 16 times out of 16. Retrieval alone never did: 0 out of 16. This is the usual 240K stream with one more rule in its first batch: “any figure below zero is reported as the single word overdrawn”. The rule names no counter and shares no word with the questions it governs. On the two streams, 7 and 9 of the questions have that word as their right answer.

A rule that names nothing: how often was it applied?Correct answers · scale 0–16 · longer is better
Keeper with in-place notesthe rule stayed in its notes
16/16
Retrieval onlyno search led back to the rule
0/16

The 16 questions on two 240K streams whose right answer is the word “overdrawn”. One run per stream for each method, 32K live window.

Retrieval alone answered all 16 with the true negative number. The rule had left the window before the first questions came, and nothing in “What value does X hold now?” leads a search back to it. The keeper had the rule in its notes from the first cut, whole, and it was repeated at every set of questions. This is the difference between the two methods that the earlier comparison could not show. There the rule named its counters, so a search for a counter found the rule.

What was countedKeeper with in-place notesRetrieval only
Questions the rule governs, first stream7/70/7
Questions the rule governs, second stream9/90/9
Questions the rule governs, both streams16/160/16
The other questions, first stream31/3231/32
The other questions, second stream34/3736/37
Whole stream, first38/39 in 9.7 min31/39 in 10.4 min
Whole stream, second43/46 in 11.4 min36/46 in 9.8 min

One run per cell, 32K live window; the two keeper runs are two versions of the code. One limit of this stream. The rule’s last clause did not say how a tally that comes out below zero should be reported. The keeper, with the rule in view, answered “overdrawn” for four such tallies, and the grader wanted numbers. Those four are all of its misses outside the questions the rule governs. Retrieval alone had lost the rule, gave numbers and was marked right, so read the “other questions” and whole-stream rows with that in mind. Results table · run log · the stream generator.

Where the rule names its counters

On the streams used in the rest of this page, the standing rule names the three counters it covers. There retrieval alone did much better.

One million tokens: the 203 questions asked along the wayCorrect answers · scale 0–203 · longer is better
Keeper, in-place notes50.2 min, whole run
203/203
Retrieval only46.9 min to the final questions
189/203

Same stream and seed, 32K live window. The 25 final questions are left out: the keeper answered all 25, and the retrieval run answered none of them, a limit of that build. The retrieval run was stopped at 59 minutes and is scored from the answers it had written by then; it is not a finished, graded run.

Method at 32KFirst 240K stream, 39 questionsSecond 240K stream, 46 questions1,000,000-token stream, 228 questions
Retrieval only, final build39/39 in 9.2 min45/46 in 9.7 min189/203 of the questions asked along the way; the final 25 not answered. A stopped run
Keeper with in-place notes39/39 in 9.9 min46/46 in 10.0 min203/203 of the questions asked along the way; 25/25 final
Keeper with in-place notes and retrievalNot run46/46 in 11.2 minNot run
Retrieval only, first build32/39 in 13.0 minNot runNot run
Retrieval only, second build38/39 in 10.8 min30/46 in 11.7 minNot run

Questions right and minutes for the whole run, one run per cell, through a 32K live window. The 240K runs finished and were graded. In the first build the store held only what had left the window; in the second the model could reach the stored files. The 1,000,000-token retrieval run is a stopped run, not a verified score: it was stopped after 59 minutes, stuck at the final questions, and is scored from the answers it had written by then. 240K results · the 1,000,000-token answers, scored.

So the two are not rivals. Retrieval finds things. Notes hold what must always be in view, the rules and the current state, at a fixed size. The keeper has both: its archive search is retrieval on demand. A harder stream put a number on it: the two together beat either alone.

One million tokens by part of the stream, question type and distance
What was countedRetrieval only: a stopped runKeeper with in-place notes
All 203 questions asked along the way189/203 (93%)203/203 (100%)
First third of the stream (question sets 1–9)63/6363/63
Middle third (sets 10–19)70/7070/70
Last third (sets 20–29)56/7070/70
Current-value questions55/5858/58
Who-did-it questions28/2929/29
House-method questions28/2929/29
Standing-rule questions25/2929/29
Old-value questions53/5858/58
Asked 1–4 batches back50/5050/50
Asked 5–24 back46/5050/50
Asked 25–99 back27/3030/30
Asked 100–399 back47/4848/48
Asked 400 or more back19/2525/25
The 25 final questionsNot answered25/25
Minutes46.9 to reach the final questions; stopped at 5950.2 for the whole run

Thirds here are thirds of the 617 items. The million-token table above groups the same question sets as 1–10, 11–20 and 21–29.

Every retrieval run, with its code in the evidence files
BuildCode in the evidence filesStreamQuestions rightFinal questionsMinutes
First buildR32First 240K32/397/1413.0
Second buildR32aFirst 240K38/3913/1410.8
Second buildR32aSecond 240K30/465/2111.7
Final buildR32bFirst 240K39/3914/149.2
Final buildR32bSecond 240K45/4620/219.7
Final build, 40 sentences per questionR32c401,000,000189/203 along the wayNot answeredStopped at 59
Final buildR32bHarder 240K10/15 when stoppedNot reachedStopped at 20.5

Before any run, a check of what retrieval could reach at all found every question covered at 240K. At 1,000,000 tokens it found 187, 220 and 227 of the 228 questions covered with 20, 40 and 80 sentences per question. Coverage check · the harder stream.

Notes and retrieval together, on a harder stream

On text that refers to things indirectly, the two together beat either alone. In this 240K stream every change names its counter in one sentence and says “it” in the next, and some values depend on another counter. There are 50 questions. The keeper with in-place notes, with retrieved sentences shown at each set of questions, answered 47 and 46. With notes only it answered 42, and 43 in a run the grader voided. Retrieval alone was too slow to finish: it was stopped after 20 minutes with 10 of its first 15 answers right. The comparison is one seed, so it is exploratory.

A harder stream: the keeper with and without retrievalCorrect answers · scale 0–50 · longer is better
Notes and retrieval, first run19.4 min
47/50
Notes and retrieval, after the fixes14.4 min
46/50
Notes only, earlier version14.9 min
42/50
Notes only, voided run19.6 min · raw score
43/50

Same harder 240K stream and seed, 32K live window, 50 questions, one run per bar. The 43 is a raw score: the grader voided that run because its answers file held one key that was not asked for. Retrieval alone is not a bar: it was stopped after 20.5 minutes with 10 of its first 15 answers right. One more notes-only run got stuck in a loop and scored 3; it is the first lesson below.

A second seed held the score, and could not repeat the comparison. On a second stream of the same kind, with 49 questions, the keeper with retrieved sentences answered 46 in 23 minutes. Its partner run without retrieval did not finish. It was stopped by hand after it sat on one set of questions for eight minutes: the stricter note checks added that morning question every line of the kind “went up by as much as X held”, and each question costs a rewritten reply. So “retrieval adds answers on indirect text” is still measured on one seed only.

Every run on the harder stream, with its code in the evidence files
RunCode in the evidence filesQuestions rightFinal questionsMinutesCounters ever wrong in the notesWhat happened
Notes only: the keeper with in-place notes, in the version before the last checkN32z42/5019/2514.914Its notes went wrong mostly where one counter depends on another.
Notes only, with every checkN32u3/500/2517.4Not reportedStuck at the first question set: one archive search was sent and refused 362 times in a row.
Notes only, with every check and the first fix: a third refusal in a row says to stopN32tNot gradedNot gradedStopped at 11Not reportedAll 5 right at the first question set, then it circled between three different searches.
Notes only, with every check and three of the four fixesN32s43/50 raw, void23/2519.610Void: the answers file held one key that was not asked for, so 43 is a raw score. The standing rule was lost at the first cut.
Notes and retrieval, with every check and none of the fixesN32ur47/5024/2519.410Three questions missed.
Notes and retrieval, with every check and all four fixesN32sr46/5024/2514.46The same three questions missed, and a fourth.
Retrieval only, final buildR32b10/15 when stoppedNot reachedStopped at 20.5No notesToo slow to finish. The keeper with in-place notes had 15/15 at that point.
Second seed: notes and retrieval, with the stricter note checks of that morningN32nr46/4922/2423.45Missed two values in the final list and one tally.
Second seed: notes only, with the same checksN32nNot gradedNot gradedStopped at 22.7Not reportedIt sat on one set of questions for eight minutes and was stopped by hand. Its 10 answers until then were all right.

The two first-seed runs with retrieval are two versions of the code, not two runs of one version. The voided run’s 43 is a raw score. The last two rows are the second seed. Results table · run log · second-seed table.

Limits of this comparison. Retrieval was tested with a keyword retriever only; there is no room for an embedding retriever beside the model on this machine. On the harder stream the comparison with and without retrieval is one seed and its difficulty is not calibrated, so that result is exploratory. The keeper with retrieval added has not been run at 1,000,000 tokens. The rule that names nothing was tested on two streams, one run each, and its wording about tallies was ambiguous. Evidence folder for the earlier round · for the rule that names nothing and the second seed · the retrieval code · lab note

Lessons from failed runs

Each of these comes from a run that went wrong. They are the part most likely to carry over to another agent with a long history.

  1. Ask for the notes after the turns being removed, not before. In the first try the request came first, followed by about 8K tokens of the agent’s own turns. The model simply continued its own turns, wrote no RULES section, and the rule was lost at the first cut.
  2. Give a rule a pinned place and a reminder at the point of use. With no pinned place, four methods answered 0 of 20 rule questions the way the rule required. Pinned only, the rule was applied 22 times out of 29 over 1,000,000 tokens. Pinned and repeated next to each set of questions, it was applied 29 times out of 29.
  3. Keep thinking switched on while a question is open. In the first 1,000,000-token attempt, thinking was on for the call that received a question set and off for the calls that followed. Working on the questions without thinking, the model repeated one archive search 790 times. Thinking now stays on from a question set until the next ordinary batch arrives, and the same command is not run twice in a row.

A faster setting that failed. Writing the notes without thinking and cutting deeper, down to 50% of the window, saved a fifth of the time (12 minutes against 15) and lost two answers (37 of 39). A later audit of the notes showed that notes written without thinking go wrong even when the score looks fine. The faster form that held up keeps the thinking: in-place notes.

Four more, from the harder stream

The harder stream broke four things. Each is now fixed in the keeper’s code.

  1. Refusing a repeated command does not end a loop. The model sees the same conversation and the same refusal, so it sends the same command again. The fully checked keeper sent one archive search 362 times in a row at the first question set, was refused every time, and finished with 3 of 50. Now the third refusal in a row tells the model to stop and answer, and that one reply is drawn with some randomness so that it can come out different.
  2. A search that shows only the matching sentence is blind on text that says “it”. A search for one counter’s name returned “Next on the list was nipewe33.” and never the sentence after it, which held the change. The archive search now shows each match together with the sentence that follows.
  3. A loop can go round three commands. With repeats refused, the model circled between three different searches, and that run was stopped by hand after 11 minutes. A search sent a third time since the last batch arrived is now refused too, because the archive has not changed in between.
  4. A reply that is asked for again must not lose what the first reply had. The first note-taking reply named the standing rule. A check asked for the reply again, the second reply left the rule out, and the second reply stood. The rule was lost at the first cut, and that run answered only 3 of 5 rule questions. A rule named in any reply to one note-taking request is now kept, and the next run answered 5 of 5.

Nine more, from moving the fast notes into the proxy

Getting in-place notes into the proxy took five builds. Each of the first eight comes from a run that went wrong, and each fix is now in the code with a test.

  1. Results that only the proxy saw must not be lost. The proxy answers the model’s archive searches itself, so the agent’s history never holds them. At one set of questions the model made its eight searches and then sent an empty reply. In the next request everything it had found was gone, and six answers were never written. Searches from a turn that ended empty are now shown again in the next request.
  2. A search tool must count one way. Search results were labelled with message numbers, while the questions speak of item numbers, the stream’s own numbering of its batches. In one run six answers about a numbered item were wrong. In the next build each result showed both numbers. The model asked for “everything before 332”, meaning item 332, and got everything before message 332, which is item 150. It trusted that search over its own correct notes: six more wrong answers, and probably a seventh. The tool now counts only in the content’s own numbers, and with that every old-value question was right (58 of 58).
  3. A list that is cut short has to say so first. “The first 40 of 63”, with the note at the end, was read as “that is all”. A cut-off list now says so in its first line and shows the matches nearest to what was asked for.
  4. What stays in view after a cut gets written down twice. The proxy keeps the newest exchange in view, so that a real agent can still see what it has just fetched. The model’s remark in that exchange was about the result before it, which was already in the notes. At the next note-taking call it noted those changes again, once backwards: an 84 that had been added was taken away. The request now says what that first message is, and a line about a name that the turns being noted never mention is left out.
  5. A questioned note must never fall back to a slower, different path. When the model gave no usable answer to a question about its notes, the whole step was redone the old way, with a full rewrite. In one run that lost a change. In another the rewrite added a “rule” that only restated the task’s opening instructions. Rules are repeated at every set of questions, and at the last one the model followed that one to the letter and overwrote a file holding 25 correct answers: 14 of 39 instead of 39 of 39. Now the first reply stands, without the lines in question.
  6. A model told to show its working will invent working. “The clerk recorded katu85 at five hundred and twenty-three” came back as 650 − 27 = 623. It adds up and it starts from the right value, so the checks passed it. Every amount in a line’s working now has to be in the text.
  7. A safety rule can be too eager. “Leave out a note whose number is not in the text” also left out three notes that were right, or nearly right, but written in a way the checker could not follow. Their counters kept stale values. The two wrong values that were this rule’s doing cost no answer. The rule now leaves out only what the text contradicts. This fix is tested and has not been run on the streams yet.
  8. The server kept being stopped at the end of long runs, and it was not the run. A script that summarises the results loaded 1.7 GB of saved snapshots at once, right beside a model server with about 2 GB of memory to spare. It now loads one at a time: 50 MB.
  9. Have new checking code read by a second reviewer before it runs. Five reviews in one day found 46 issues, several of which would have stored wrong values. One fix ran before it could be reviewed.

The question, and how it is tested

An agent that works on one task for a long time builds up far more history than its live window can hold. Something has to leave the window. What can the agent still answer about things that happened long ago, and does it still follow what it was told at the start?

The same Qwen3.8-27B model read a 240K-token stream of short stories in batches (147 on the first seed), with about three counter changes per batch. Its live window was capped at 16K or 32K tokens, so the history was 7 to 15 times larger than what it could see at once. Every 25 batches it was asked three questions about a batch a known distance back:

At the end it answered final questions about the current state: 14 on the first seed, 21 on the second. Distance is counted in batches back from the question. The evidence files call each delivery an item and count distance in items.

A second version of the stream opens with two more things to remember: a standing rule (three counters are confidential; answer “protected” whenever asked for their value) and a house method (on the 240K stream, a counter’s tally is its value times 5 plus 13). Later question sets ask about both. Results for the rule and the method.

A third version adds one more rule in the first batch, a rule that names no counter: “any figure below zero is reported as the single word overdrawn”. Results for the rule that names nothing.

Ways to manage the window

Four methods ran the distance tests, and summarising at a threshold was added later on one seed. Two variants of the archive method were added for the rule questions. The keeper ran on the rule streams. In-place notes and retrieval alone came later, on the same streams. The two together came next, and the proxy with in-place notes last.

Window-drop
When the window is full, the oldest turns are dropped. Nothing is kept. This is the simplest baseline, and it is lossy.
Compaction
What coding agents commonly do: old tool output is replaced with a short stub and old thinking is removed, then the oldest turns go. Also lossy. Called D or P in the evidence files.
Summarise at a threshold
What most production agents do: when the context reaches a threshold, here 75% of the window, the model writes a summary that takes the place of the older turns. Also lossy. Called C in the evidence files.
Self-editing, read mode
The model reads each batch and keeps name value lines in a pinned state at the top; processed batches leave the window. How self-editing with a protected state works.
Self-editing + archive and search
The same pinned state, and every batch that leaves the window goes word for word to a read-only archive. A recall tool searches it. How the archive works.
Archive and search + pinned rule lines
The archive method with one change: the pinned state may also hold permanent RULE: lines. An edit that removes or rewords one is rejected. The instructions say to write down a rule or method when one is stated, and to read the rule lines before answering.
Archive and search with free-text notes
The archive method with free-text notes in place of the name value lines. Its instructions say nothing about rules.
Keeper
The agent manages nothing. Something outside it archives the oldest turns word for word, has the model rewrite a short NOTES block at each cut, and repeats the rules next to each set of questions. How the keeper works.
Keeper with in-place notes
The same keeper with a cheaper way to keep its notes: the request rides on the conversation the server has already read, the model writes only what changed, and the window is then emptied down to the task and the notes. How in-place notes work.
Keeper as a proxy
The same method in a small proxy in front of the model server. The agent sends its whole history on every call. Its earlier form rewrote all its notes at each cut; it now keeps them in place, as the harness keeper does. The proxy today · What the proxy does and how to run it.
Retrieval only (RAG)
No notes, no pinned rules and no search tool. Every batch goes into a store, and the best-matching stored sentences are shown whenever questions arrive. Retrieval alone, measured.
Keeper with in-place notes and retrieval
The same keeper, and at each set of questions the program also shows the best-matching stored sentences. Measured on the harder stream.

Results by distance

Each score is right/asked. The distance columns split the same probe questions by how far back the answer was stated; the type columns split them by question type. Scores are pooled over two seeds, except the archive method at 16K, which has one scored seed.

MethodWindowSeedsProbes right1–4 back5–24 back25–99 backCurrent valueOld valueWho did itFinal questionsAllMinutes per run
Self-editing + archive and search (B32ira)32K228/3010/1113/145/510/109/109/1035/3563/6515-16
Window-drop (W32)32K221/3011/1110/140/510/104/107/1035/3556/6520-30
Compaction (P32)32K223/3010/1110/143/510/109/104/1025/35 (4/14 on seed 0, 21/21 on seed 1)48/6513-23
Self-editing, read mode (B32ir)32K216/306/118/142/510/106/100/1035/3551/6515-16
Self-editing + archive and search (B16ira)16K112/157/84/51/23/54/55/58/14 (2 stale)20/2925-36
Window-drop (W16)16K216/3011/115/140/59/103/104/1034/3550/6522
Compaction (D16)16K219/308/119/142/510/108/101/1035/3554/6519-20
Self-editing, read mode (B16ir)16K29/305/114/140/58/101/100/1035/3544/6514-20

All 32K runs and the second 16K seed: two B70 GPUs, server window 65,536 tokens, exact prefix cache, one run at a time. Compaction’s final score at 32K differs by seed: 4/14 on the first, 21/21 on the second. The archive method at 16K has one scored seed. Seed 1 is void: it hit the step cap and answered keys that were not asked. Only seed 0 is scored. Probe analysis for the 32K rows · for the 16K rows.

Each seed on its own at 32K
Method at 32KSeedProbes rightFinal questionsAllMinutes
Self-editing + archive and search (B32ira)013/1514/1427/2915
Self-editing + archive and search (B32ira)115/1521/2136/3616
Window-drop (W32)011/1514/1425/2920
Window-drop (W32)110/1521/2131/3630
Compaction (P32)013/154/14 (6 stale)17/2913
Compaction (P32)110/1521/2131/3623
Self-editing, read mode (B32ir)08/1514/1422/2916
Self-editing, read mode (B32ir)18/1521/2129/3615

On the second seed the archive method answered everything (36/36) in 16 minutes. Window-drop and compaction each scored 31/36, in 30 and 23 minutes.

First round: 16K window, seed 0, one GPU
MethodWindowSeedsProbes right1–4 back5–24 back25–99 backCurrent valueOld valueWho did itFinal questionsAllMinutes per run
Window-drop (W16)16K110/158/82/50/25/52/53/514/1424/2922
Compaction (D16)16K110/155/83/52/25/55/50/514/1424/2919
Self-editing, read mode (B16ir)16K14/153/81/50/23/51/50/514/1418/2920
Self-editing + archive and search (B16ira)16K112/157/84/51/23/54/55/58/14 (2 stale)20/2936

One B70 GPU with a 26,624-token server window. These seed-0 runs are included in the pooled 16K rows above. Probe analysis for this table.

Cost of the 32K runs
Method at 32KTokens writtenModel callsPeak live contextArchive searches
Window-drop (W32)73,96015927,949–
Compaction (P32)51,92615721,128–
Self-editing, read mode (B32ir)55,16034623,887–
Self-editing + archive and search (B32ira)37,57736027,17920

First seed. The archive method wrote the fewest tokens of the 32K methods and searched its archive 20 times, with one rollback. Across both seeds, archive and search read 5.3M prompt tokens per run, 81–82% of them from the prefix cache, and wrote 38–49K tokens.

Earlier run: 48K window over a 480K history (2026-10-08)
MethodWindowSeedsProbes right1–4 back5–24 back25–99 back100–399 backCurrent valueOld valueWho did itFinal questionsAllMinutes per run
Window-drop (W48)48K123/339/913/141/60/411/118/114/1110/1033/4371
Compaction (D48)48K120/339/99/142/60/411/118/111/1110/1030/4357

Reported in the program charter. Per-type splits and run times are from the same run's probe analysis; its raw files are not in the lab repository yet. The summarising arm at 48K was cancelled at the 4-hour limit after 17 summaries; the self-editing arms at 48K never ran. Program charter.

Summarising at a threshold

Most production agents handle a full window by summarising it. Here the model wrote a summary whenever the context reached 75% of the 32K window. On the first seed of the plain 240K stream this was the slowest method, and it scored below simply dropping old turns.

When old text leaves the windowCorrect answers · scale 0–29 · longer is better
Archive + search15 min
27/29
Window-drop20 min
25/29
Summarise at 75%29 min
23/29
Tool-output compaction13 min
17/29

Same plain 240K-token history, seed 0, 32K budget; 29 questions. This test has no standing-rule questions and is separate from the keeper comparison.

Question types and summary-call counts
Method at 32KAll 29Probes rightCurrent valueOld valueWho did itFinal questionsMinutes
Self-editing + archive and search (B32ira)27/2913/155/54/54/514/1415
Window-drop (W32)25/2911/155/52/54/514/1420
Summarise at 75% of the window (C32)23/2910/154/54/52/513/1429
Compaction (P32)17/2913/155/55/53/54/14 (6 stale)13

One seed (the first), 29 questions. The other three rows are the first-seed runs behind the 32K rows of the table above. Thirteen summaries were written and none failed. The summaries kept old values (4/5) and lost the small details nobody knew to keep (“who did it”, 2/5). Evidence for this run.

Keeping a rule and a method

Of the methods that ran before the keeper, none kept a rule that was stated once at the start until rules had a pinned place. This 240K stream opened with the standing rule and the house method. Five later question sets each added one rule question and one method question to the usual three, 24 to 129 batches after the rule and the method were stated. One of the 14 final questions asked for a confidential counter. That makes 39 questions per run. The keeper’s 39 of 39 on the same stream is in the table at the top.

Method at 32KValues, old values, whoStanding ruleHouse methodFinal questionsAll 39Minutes
Self-editing + archive and search (B32ira)15/150/55/513/14 (confidential one left blank)33/3920
Window-drop (W32)10/150/50/513/14 (confidential one left blank)23/3926
Compaction (P32)6/150/53/511/14 (confidential one left blank)20/3914
Self-editing, read mode (B32ir)6/150/50/512/14 (confidential one wrong)18/3933
Archive and search + pinned rule lines (B32iraR)13/155/54/513/14 (confidential one right)35/3918
Archive and search with free-text notes (B32ira-free)12/154/53/59/14 (confidential one left blank)28/3923

One seed at a 32K window, so each cell is a handful of questions. The first four methods ran with a 65,536-token server window and the two variants with 262,144; the live window was 32K for all. Probe analysis for this table.

What it shows

Limits

One synthetic task family, one model and one machine, with one run per cell. It is not a real agent task. The keeper’s 240K results are two streams of that one family. At 1,000,000 tokens the keeper inside the harness with in-place notes has two streams, 228 of 228 and 210 of 222. The proxy’s result with in-place notes, and both results with a full notes rewrite, are each one stream and one seed. The proxy has been run on this benchmark and on one real-code task (the repair marathon above: one model, one library, one run per cell) and under the lab’s own stand-alone agent program, not yet under a third-party coding or research agent. A plain 200K window has still not been run on the 1,000,000-token stream. The summary baseline is one seed.

The notes are not perfect. On the proxy’s million-token run five counters were wrong for a stretch, and one of them is behind one of its two missed tallies. Inside the harness, with every check, one misread sentence left one wrong value in the notes for a stretch on the second 240K stream, and one counter was wrong for a stretch on the second million-token stream. Two kinds of slip are not caught by any check yet: a change noted with the wrong sign, and a value that was set being noted as a change by the same number. Three fixes are in the code and have not been run: an open question is never moved out of view; a note is left out only when the text contradicts it; and, in the proxy’s earlier form, a reworded rule line is replaced by the original.

Retrieval alone was tested with a keyword retriever only, since there is no room for an embedding retriever beside the model on this machine, and its 1,000,000-token run is a stopped run that did not answer the final questions. The rule that names nothing was tested on two streams, one run each, and its wording about tallies was ambiguous. On the harder stream the comparison with and without retrieval is one seed, its difficulty is not calibrated, and its result is exploratory. The keeper with retrieval added has not been run at 1,000,000 tokens.

The distance results are two seeds, and the archive method has only one scored seed at 16K. The rule and method results for the methods other than the keeper are one seed. Each cell holds a handful of questions (at 25–99 batches back, 5 over two seeds and 2 on a single seed), so a difference of one or two answers is not decisive.

Lab note with every round and the post-mortems · Raw evidence: the first two rounds, the second seed and the rule questions, pinned rule lines and the first 1M run, the keeper, the proxy and the summary baseline, in-place notes, the notes audit, retrieval alone and the harder stream, the proxy with in-place notes, the rule that names nothing and the second seeds · The proxy’s code · Website measurement record

What we are trying to solve now

The target is an agent that works on one task for weeks or months, with 1 to 10 million tokens of history, while its live window stays capped: 200K tokens on a dedicated GPU, or 32K–48K when the GPU is shared. The model must stay fast, accurate and on goal. The model’s own arithmetic stays exact; how the history is managed may lose information, but then the loss is measured.

Why the model limits the options

Qwen3.8-27B is a hybrid. Most of its layers carry a running summary state forward instead of keeping one entry per past token. That state cannot have a piece cut out of the middle. The exact operations are: add new text at the end, or roll back to a saved checkpoint and read everything after it again. Cutting a block out of the middle of an ordinary attention cache is only approximate too: the later entries were computed while looking at the removed text. So an exact edit in the middle means rolling back and re-reading the tail, which the second, idle GPU could do between turns.

How the tests measure it

Next steps

The proxy now answers 226 of 228 over 1,000,000 tokens in 50 minutes, within two answers of the keeper inside the test harness, and 214 of 222 on the second stream. What is still owed, the first three in this order:

  1. A run that exercises the fix which keeps an open question in view; it is in both keepers’ code and has never been triggered in the proxy.
  2. The harder stream again, with the newest note checks, which have not been run on it.
  3. The proxy under a real agent program.
  4. The keeper with retrieval added on the 1,000,000-token stream.
  5. A plain 200K window on the 1,000,000-token stream, as the baseline to compare with.
  6. Second seeds for the other 1,000,000-token runs and for the methods that make the model run a routine.
  7. Engine-side levers: parking and restoring the cache on fast disk, and background re-reading on the idle GPU.

The full program charter: the problem, every idea so far and the benchmark design · Recommendations so far