Was sich in einem langen Lauf ansammelt

Ein Coding-Agent schickt bei jedem Schritt den gesamten bisherigen Verlauf an das Modell: die Aufgabe, jede gelesene Datei, jeden Befehl und jede Ausgabe. In einem Benchmark mit schwereren Aufgaben las unser Agent 2,57 Millionen Token und schrieb 158.000. Der Verlauf bildet also den Hauptposten im Speicher und in der Zahl der verarbeiteten Token, und er wächst mit jedem Werkzeugaufruf. Ein Modell auf eigener Hardware hat ein kleineres Fenster und eine harte Grenze. Überschreitet eine Anfrage das Fenster um ein einziges Token, lehnt der Server sie ab, und die Runde ist verloren.

Unsere Kontextverwaltung arbeitet deshalb in zwei Stufen. Die erste prüft bei jedem Schritt und kürzt, was alt und sperrig ist. Die zweite greift ab einer Schwelle und ersetzt den alten Verlauf durch eine Zusammenfassung. Beide bauten wir anhand von Laufprotokollen mehrfach um. Das Programm um das Modell, das Werkzeuge ausführt und den Verlauf führt, nennen wir im Folgenden das Gerüst.

Stufe eins: kürzen, ohne zum Wiederholen einzuladen

Die erste Stufe ersetzt alte Werkzeugausgaben durch einen Platzhalter. Die ursprüngliche Fassung lautete sinngemäß: „Ausgabe entfernt, Werkzeug erneut aufrufen, um sie zu sehen.“ Das Modell befolgte das, und in einer einzigen Runde las der Agent dieselbe Datei 55-mal, weil jeder Platzhalter ihn dazu aufforderte. Seitdem nennt der Platzhalter den Aufruf, behält die ersten 240 und die letzten 120 Zeichen der Ausgabe und fordert zu nichts auf.

Der zweite Fehler lag in der Richtung des Kürzens. In einem Protokoll standen 152 Kilobyte an Aufrufargumenten ungekürzt im Verlauf, während die Ergebnisse dieser Aufrufe auf 38 Kilobyte gekürzt waren. Der Verlauf behielt also, was der Agent getippt hatte, und verwarf, was er dabei gelernt hatte. In einer anderen Sitzung füllten Aufrufargumente 55,6 % des Fensters, und 51,4 % entfielen allein auf Schreib- und Bearbeitungsaufrufe. Der Inhalt einer geschriebenen Datei liegt aber auf der Platte und lässt sich jederzeit lesen, während der Agent die Kopie im Verlauf bei jedem Schritt nur erneut mitschickt. Erledigte Schreibaufrufe schrumpfen seitdem auf den Vermerk, dass sie angewendet wurden.

Der dritte lag im geschützten Bereich. Stufe eins kürzt die jüngsten Nachrichten nicht, und dieser Bereich war fest auf 12.000 Token eingestellt. Bei einem Fenster von 130.000 Token entsprach das etwa den letzten drei gelesenen Dateien. Eine Aufgabe, die mehr gleichzeitig im Blick braucht, konnte das nie halten, und der Agent las im Kreis. Der geschützte Bereich umfasst jetzt ein Drittel des Fensters.

Stufe zwei: zusammenfassen, was war, und nichts auftragen

Ab 80.000 Token fasst ein eigener Modellaufruf ohne Werkzeuge den alten Verlauf zusammen. Die Anweisung dafür verlangt eine Niederschrift in der Vergangenheitsform und verbietet ausdrücklich nächste Schritte. Eine Zusammenfassung mit einer Liste offener Punkte würde diese Punkte noch einfordern, wenn sie längst erledigt sind, und der Agent würde sie ein zweites Mal erledigen. Offene Arbeit steht deshalb in einer getrennt geführten Aufgabenliste, die nach jeder Zusammenfassung wörtlich wieder eingefügt wird, zusammen mit den Notizen des Agenten und dem aktuellen Planschritt aus dem Meilensteinmodus.

Die Anweisung verlangt außerdem, dass Befunde mit ihrem Wert überleben: eine gemessene Zahl, eine Fundstelle mit Datei und Zeile, eine korrigierte Formel. Mit einem Satz wie „der Abstand ist zu klein“ kann der Agent nach der Zusammenfassung nichts mehr anfangen, und er misst neu.

Auch hier war eine Einstellung falsch. Die Zusammenfassung behielt die letzten 24 Nachrichten wörtlich, und die umfassten in einem langen Build 20.000 bis 35.000 Token. Nach einer Zusammenfassung lag der Verlauf deshalb noch bei 50.000 bis 65.000 Token und erreichte die Schwelle etwa fünfzehn Aufrufe später wieder. In 236 Aufrufen lief die Zusammenfassung fünfzehnmal, und jedes Mal wuchs nach, was sie gerade entfernt hatte. Bei lokalen Modellen begrenzt die Verwaltung den wörtlich behaltenen Rest jetzt auf ein Achtel des Fensters, sodass sie seltener und tiefer zusammenfasst.

Der Notfall: ein Token zu viel

Übrig bleibt der Fall, in dem keine der beiden Stufen rechtzeitig greift. Im ersten längeren Lauf mit einem lokalen Modell lehnte der Server zweimal eine Anfrage mit 32.769 Token ab, bei 32.768 erlaubten. Die Kürzung lief erst nach dem Absenden, und eine einzelne Testausgabe von rund 14.000 Token war als jüngste Ausgabe geschützt. Seitdem prüft die Verwaltung vor jeder Anfrage gegen die harte Grenze des Servers und kürzt im Notfall auch im geschützten Bereich, die neueste Ausgabe aber nie.

Die Schwelle dafür korrigierten wir zweimal. Die Verwaltung schätzt die Tokenzahl mit dem Tokenizer eines anderen Modells, und die Schätzung lag gemessen knapp zehn Prozent zu niedrig, bei 83.000 geschätzten gegenüber 91.000 vom Server gezählten Token. Mit zehn Prozent Abstand zur Grenze griff der Notfall erst bei rund 128.000 echten Token von 130.000. Der Abstand beträgt jetzt 20 %.

Die zweite Korrektur traf die Reserve für die Antwort. Reserviert eine Anfrage Platz für die Antwort, verlangt der Server, dass Anfrage und Reserve zusammen ins Fenster passen. Eine Runde mit 270 Werkzeugaufrufen wuchs auf 105.425 Token, dazu kamen 24.576 reservierte, zusammen 130.001 bei 130.000 erlaubten. Seitdem zieht die Verwaltung die Reserve exakt ab.

Kürzen kostet den Zwischenspeicher

Jede Kürzung in der Mitte des Verlaufs kostet etwas, das in keiner Tokenzahl steht. Der Server bewahrt die Verarbeitung eines Anfrageanfangs auf, solange dieser Anfang gleich bleibt; im genannten Benchmark kamen 74 % der gelesenen Token aus diesem Zwischenspeicher. Wer alte Nachrichten umschreibt, entwertet alles dahinter. Stufe eins kürzt bei lokalen Modellen deshalb nur, wenn sie mindestens ein Achtel des Fensters zurückgewinnt. Verfehlt ein Kürzungsdurchgang diese Schwelle, nimmt sie ihn vollständig zurück, statt halbe Änderungen stehen zu lassen.

Grenzen

Jede Zusammenfassung verliert etwas, und was verloren ging, merkt man erst, wenn der Agent es neu herleitet. Wir stellten die Schwellen an wenigen langen Läufen ein, überwiegend mit einem Modell und einem Fenster von 130.000 Token; für andere Modelle sind es Startwerte. Die Schätzung der Tokenzahl bleibt eine Schätzung, und der Abstand von 20 % ist bezahlter Platz, der im Normalfall ungenutzt bleibt. Fällt der Aufruf für die Zusammenfassung aus, greift eine mechanische Kurzfassung, die als solche gekennzeichnet ist. Ob die Zusammenfassung selbst etwas Falsches behauptet, prüft niemand.