Erklärung des Agentenmemorys: Kontextfenster, RAG und persistenter Zustand
Das Agentenmemory umfasst drei verschiedene Komponenten. Erfahren Sie, wie sich das Kontextfenster, die Informationsabrufung und der persistente Zustand voneinander unterscheiden, was jede Komponente kostet und wie man zunächst die richtige auswählt.
Quellen: Agent Memory Explained
Nur wenige Begriffe verursachen bei der Entwicklung von Agenten so viel Verwirrung wie „Gedächtnis“. Wenn jemand sagt, sein Agent habe ein Gedächtnis, könnte das bedeuten, dass die Konversation lang ist, dass eine Vektordatenbank verbunden ist oder dass Fakten in einer Datei gespeichert werden, die auch nach einem Neustart erhalten bleibt. Das sind drei getrennte Systeme mit unterschiedlichen Kosten, verschiedenen Ausfallmöglichkeiten und unterschiedlichen Existenzgründen.
Eine einzige Aussage beseitigt den größten Teil der Verwirrung. Das Modell verfügt über kein Gedächtnis, nur über eine Eingabe – und das, was die Leute als Gedächtnis bezeichnen, ist lediglich eine Strategie zur Auswahl dessen, was in diese Eingabe gelangt.
Das Modell ist zustandslos. Jeder API-Aufruf beginnt von Null aus, ohne Erinnerung an Ihre letzte Nachricht, Ihre letzte Sitzung oder den Namen, den Sie ihm gegeben haben. Was es während eines Aufrufs weiß, ist ausschließlich das, was in der Anfrage enthalten ist – und nichts anderes.
Daher lautet die wichtige Frage nicht, ob der Agent ein Gedächtnis hat. Vielmehr geht es darum, was in dieser Anfrage einen Platz erhält und woher es stammt. Es gibt drei Antworten, und die Aufgabe besteht darin, sie voneinander zu unterscheiden.
Stateless-Modell, stateful-Anwendung
Anfänger gehen davon aus, dass das Modell ein Gespräch führt. Das ist nicht der Fall. Die Anwendung führt das Gespräch und wiedergibt es. Wenn Sie eine vierte Chat-Nachricht senden, überträgt Ihr Code jedes Mal alle Nachrichten 1, 2, 3 und 4. Das Gefühl der Kontinuität entsteht durch das Wiederversenden der Historie, wobei das Modell einfach eine längere Eingabe als zuvor erhält.
Angesichts dessen sind die drei Ebenen nicht mehr abstrakt:
- Das Kontextfenster ist das, was derzeit in der Anfrage enthalten ist.
- Retrieval (RAG) ist die Methode, mit der man Material findet, um es in die Anfrage aufzunehmen.
Ein Container, eine Abfragefunktion und ein Speicher – drei unterschiedliche Elemente. Wenn man diese miteinander vermischt, führt das dazu, dass eine Vektordatenbank für Probleme eingesetzt wird, die mit einer preferences.json-Datei gelöst werden könnten.
Ebene 1: das Fenster, oder der Schreibtisch des Modells
Betrachten Sie das Fenster als alles, was das Modell derzeit sehen kann. Der Systemprompt, die Historie, Definitionen von Tools, Ausgaben von Tools, abgerufte Dokumente sowie die gerade geschriebene Antwort nutzen alle denselben gemeinsamen Token-Budget.
Stellen Sie sich einen Schreibtisch vor. Alles, worüber das Modell nachdenken muss, muss physisch darauf liegen – ein Aktenschrank in einem anderen Raum zählt nicht dazu.
Seine Stärke: Unmittelbarkeit. Alles, was im Fenster zu sehen ist, ist ohne zusätzliche Abfragen vollständig sichtbar, und das Modell kann gleichzeitig über alles nachdenken. Bei einer Aufgabe mit begrenztem, bekanntem Material ist das Befüllen des Fensters der einfachste und oft auch richtige Weg.
Kosten:
- Geld und Latenz hängen davon ab, was erneut gesendet wird. Das Umwandeln von 51 Nachrichten einer langen Unterhaltung bedeutet, dass 50 Nachrichten der Vorgeschichte erneut gesendet werden. Ein langer Kontext ist nicht kostenlos, nur weil er hineinpasst.
- Die Aufmerksamkeit ist ungleichmäßig verteilt. Modelle nutzen in der Regel am zuverlässigsten den Anfang und das Ende eines langen Eingabetextes und am wenigsten die Mitte – das weit verbreitete Phänomen des „Verlorengehens in der Mitte“. Ein Fakt, der 60 % des Weges in einer sehr langen Anfrage versteckt ist, existiert zwar, wird aber möglicherweise nie effektiv genutzt. Hineinpassen bedeutet nicht, gelesen zu werden.
Die gesamte Funktionsweise lässt sich in wenigen Zeilen beschreiben:
messages = []
def turn(user_text):
messages.append(
{"role": "user",
"content": user_text}
)
# every call resends
# the ENTIRE history
reply = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=messages,
)
messages.append(
{"role": "assistant",
"content": reply.content[0].text}
)
return reply
# messages grows forever.
# so does your bill.
Diese Liste ist hier die „Erinnerung“. Sie existiert nur innerhalb Ihres Prozesses, sodass sie mit Ende des Prozesses ebenfalls verschwindet.
Das Fenster allein reicht aus, wenn die Aufgabe kurz ist, das benötigte Material begrenzt und im Voraus bekannt ist sowie nichts über die Sitzung hinaus bestehen muss. Ein Zusammenfasser, ein Prüfer für eine Datei oder eine einmalige Extraktion benötigen nichts weiter. Fügen Sie dort keine zusätzlichen Komponenten hinzu.
Ebene 2: Abruf, die Referenzbibliothek
Schneller oder später passt das Material nicht mehr oder lohnt sich die Bezahlung nicht mehr. Es könnte sich um 10.000 Support-Tickets, eine interne Wiki oder einen Codebase handeln. Sie können nicht alles in jeder Anfrage berücksichtigen – und sollten es auch nicht.
Durch generatives Verfahren mit Abrufunterstützung wird die Arbeit aufgeteilt: Zunächst wird ein Index im Voraus erstellt, anschließend werden Informationen abgerufen, wenn eine Frage gestellt wird.
Zuvor teilen Sie die Dokumente in Abschnitte auf, wandeln jeden Abschnitt in einen Embedding um (einen numerischen Vektor, der die Bedeutung erfassen kann), und speichern ihn. Wenn eine Frage eintrifft, wandeln Sie diese in einen Embedding um, finden die Abschnitte, deren Vektoren am nächsten liegen, und fügen diese wenigen in das Kontextfenster neben der Frage ein.
# 1. AHEAD OF TIME (once, offline)
for chunk in split(documents):
store.add(
text=chunk,
vector=embed(chunk),
)
# 2. AT QUESTION TIME (every request)
def answer(question):
hits = store.search(
embed(question), top_k=5
)
context = "\n\n".join(h.text for h in hits)
return client.messages.create(
model="claude-opus-5",
max_tokens=1024,
# retrieved chunks land in the same request
messages=[{
"role": "user",
"content": f"{context}\n\nQ: {question}",
}],
)
Achten Sie darauf, was tatsächlich passiert ist. RAG hat dem Modell kein Gedächtnis bereitgestellt. Es lieferte Ihnen lediglich eine Auswahlstrategie für das Fenster. Die abgerufenen Fragmente landen in derselben Anfrage wie alles andere, wodurch RAG lediglich ein Kanal in Schicht 1 darstellt und keine Alternative dazu ist.
Vorteile: Skalierbarkeit und Aktualität. Millionen von Dokumenten können unabhängig von Ihrem Code geändert werden, während das Modell nur die wenigen betrachtet, die für diese Frage relevant sind.
Kosten:
- Das Ergebnis wird früh entschieden. Die Größe der Fragmente, das Embedding-Modell sowie die Indexstruktur sind bereits bei der Erstellung des Index festgelegt. Ein Fakt, der sich über zwei Fragmente erstreckt oder anders formuliert ist als die Frage der Benutzer, wird einfach nicht gefunden, und das Modell antwortet dann selbstbewusst auf der Grundlage dessen, was es erhalten hat. Für einen Beobachter sehen mangelhafte Informationsabrufung und Halluzinationen identisch aus.
Retrieval eignet sich dann, wenn die Wissensbasis groß ist, für alle Benutzer gemeinsam und selten ändert – beispielsweise Dokumentationen, Richtlinien, Produktkataloge und Code. Ein Indikator dafür ist, dass ein einziges Korpus allen Benutzern dient. Wenn das, was man sich merken möchte, einem einzelnen Benutzer gehört und im Laufe des Gesprächs ändert sich, eignet sich Retrieval nicht gut – dann braucht man Layer 3.
Layer 3: persistenter Zustand, das Notizbuch
Der persistente Zustand ist das, was übrig bleibt, wenn der Prozess beendet wird. Es handelt sich dabei nicht um das, was der Agent über die Welt weiß, sondern um das, was er gelernt hat und was länger bestehen sollte als diese Sitzung: Benutzerpräferenzen, Zwischenstände von Aufgaben, bereits getroffene Entscheidungen, ausprobierte und aufgegebene Optionen sowie zusammenfassende Übersichten früherer Ausführungen. Dies sind kleine, spezifische, wertvolle Fakten, die der Agent selbst notiert hat.
Musterhaft verläuft dies in einem Zyklus aus Lesen, Ändern und Schreiben innerhalb der Sitzung:
# session start: load
with open("state.json") as f:
state = json.load(f)
system = (
"Known about this user:\n"
f"{json.dumps(state)}"
)
messages = []
def turn(user_text):
messages.append(
{"role": "user",
"content": user_text}
)
reply = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
system=system, # state in
messages=messages,
)
return reply
# ... along the way ...
state["prefers"] = "metric units"
state["last_checkpoint"] = "step_4_done"
# session end: save
with open("state.json", "w") as f:
json.dump(state, f)
Konzeptionell ist nichts weiter notwendig. Eine JSON-Datei gilt als echte Implementierung – genauso wie eine Datenbankzeile, ein Schlüssel-Wert-Speicher oder ein Ordner mit Markdown-Notizen. Das Medium ist der langweilige Teil, interessant ist vielmehr, wer entscheidet, was gespeichert und was wieder geladen werden soll.
Die richtige Entscheidung zu treffen, ist der schwierige Teil – und genau hier unterscheiden sich die Agent-Frameworks. Die direkteste aktuelle Option überlässt diese Aufgabe dem Modell: Mit Anthropics Speichertools erhält Claude eine kleine Reihe von Datei-Befehlen (ansehen, erstellen, str_replace, einfügen, löschen und umbenennen), die in einem abgeschotteten /memories-Verzeichnis funktionieren. So entscheidet der Agent, was gespeichert werden sollte, und liest diese Notizen zu Beginn der nächsten Sitzung. Ihre eigene Anwendung führt die Operationen auf dem von Ihnen gewählten Speicher aus. Das Tool läuft clientseitig, wodurch die Dateien in Ihren Händen bleiben.
Stärken: Kontinuität, Personalisierung und langfristige Arbeitsweise. Ein Agent, der eine mehrtägige Aufgabe dort fortsetzt, wo er aufgehört hat, benötigt dies genauso wie einer, der nicht zweimal nach Ihrer Zeitzone fragen sollte.
Kosten:
- Jemand muss die Inhalte verwalten. Schreiben Sie alles auf – dann entsteht ein unsuchbares Protokoll. Schreiben Sie zu wenig, bricht die Kontinuität. Ein guter, dauerhafter Zustand ist nur mit großer Sorgfalt zu gewährleisten.
- Veraltete Informationen sind schlimmer als gar keine. Eine acht Monate alte Präferenz, die nie wieder überprüft wird, wird weiterhin zuverlässig angewendet. Fehlschläge bei der Abrufung führen zu Unklarheiten, während veralteter Zustand zu falschem Verhalten führt.
- Das Laden ist nicht kostenlos. Was auch immer geladen wird, nimmt weiterhin Platz im Fenster ein – daher beeinflusst auch Schicht 3 Schicht 1.
Schließen Sie sich einem persistenten Zustand an, wenn derselbe Benutzer oder dieselbe Aufgabe den Agenten wiederholt auslöst und das, was bei Ausführung n gelernt wird, die Ausführung n+1 verändern sollte.
Die drei Ansätze nebeneinander
| Kontextfenster | Auswertung | Persistenter Zustand | |
|---|---|---|---|
| Rolle | Der Schreibtisch | Die Bibliothek | Das Notizbuch |
| Enthält | Alles in dieser Anfrage | Ein großes, gemeinsam genutztes Korpus | Kleine Fakten, die der Agent geschrieben hat |
| Aufgefüllt von | Ihre Anwendung, pro Aufruf | Indexierungsjob | Der Agent oder Ihr Code |
| Überlebt ein Neustart? | Nein | Ja | Ja |
| Hauptrisiko | Kosten, Datenverlust im Laufweg | Übersehene Teile | Veraltete Fakten |
Die wichtigste Zeile ist die über die Neustarts. Sie bildet die Trennlinie zwischen einem langen Chat und einem Agenten mit Gedächtnis.
Sie erstellen
Ein echter Agent verwendet alle drei Elemente, und es ist hilfreich, zu beobachten, wie sie in einer Anfrage zusammenarbeiten. Ein Support-Agent wird gefragt, ob eine Bestellung für das verlängerte Rückgabefenster in Frage kommt.
- Zuerst wird der Persistent State geladen: Dieser Kunde hat den Geschäftsplan und bevorzugt kurze Antworten. Zwei Fakten, etwa vierzig Tokens.
- Dann erfolgt die Retrieval-Phase, bei der anhand der Frage der Abschnitt zur Rückgabepolitik für Geschäftspläne sowie die beiden neuesten Ausnahmen abgerufen werden. Drei Datenblöcke, etwa tausendzweihundert Tokens.
- Schließlich wird der Context Window mit beidem, zusammen mit dem Live-Chat und den Tool-Definitionen, verwendet, wodurch das Modell über den gesamten Kontext hinweg zusammenfassend urteilen kann.
Eine Anfrage, drei Ebenen. Das Fenster ist der Ort, an dem alles landet, während Abruf und persistierender Zustand zwei getrennte Wege dorthin sind.
Deshalb wird auch empfohlen, langlaufenden Agenten Gedächtnisfunktionen mit Kontextbearbeitung zu kombinieren: Alte Tool-Ergebnisse werden aus dem Fenster gelöscht, um es übersichtlich zu halten, und die wichtigen Fakten wurden bereits gespeichert, sodass das Fenster klein bleibt, ohne Wissen zu verlieren.
Welches brauchen Sie eigentlich?
Anfänger greifen fast immer zuerst zu einer Vektordatenbank. Das ist der am meisten sichtbare Teil des Stack, doch selten die richtige Lösung. Klettern Sie lieber die Leiter hinauf.
Fangen Sie mit dem Fenster an. Passt alles Relevant in eine einzige Anfrage zu einem für Sie akzeptablen Preis? Dann hören Sie auf. Kein Index, kein Speicher.
Fügen Sie den persistenten Zustand hinzu, sobald der Agent zum zweiten Mal ausgeführt wird. Wenn die zweite Sitzung wissen sollte, was die erste Sitzung gelernt hat, ist Layer 3 erforderlich, und eine JSON-Datei ist die richtige Lösung. Erledigen Sie das vor der Abrufphase – es ist günstiger, einfacher und entspricht dem, was die meisten Menschen tatsächlich wollen, wenn sie sagen, der Agent solle sich an sie erinnern.
Fügen Sie die Abrufphase hinzu, wenn das Korpus größer ist als das Fenster. Das bedeutet viele Dokumente, die zwischen Benutzern geteilt werden und separat von Ihrem Code bearbeitet werden. Es handelt sich um die aufwendigste Schicht, die erstellt und am Laufen gehalten werden muss – nutzen Sie sie daher nur, wenn es wirklich notwendig ist.
Eine Falle, der man ausweichen muss: Die Erstellung eines RAG-Pipelines für etwas, das eigentlich ein Präferenzdatei war, und anschließend das Rätseln darüber, warum der Agent immer noch den Namen einer Person vergisst. Die Abrufsuche durchforstet ein Korpus – dieses wird niemals die Tatsache enthalten, dass eine Person Metriekonzepte bevorzugt.
Kurzfassung
- Context-Window: der Schreibtisch. Sofort sichtbar, teuer pro Token und wird sofort gelöscht, sobald die Sitzung beendet ist.
- Abruf: die Bibliothek. Sehr umfangreich, suchbar, nach einem festen Zeitplan aktualisiert und etwas, das der Agent nur liest.
- Persistenter Zustand: das Notizbuch. Klein, vom Agenten geschrieben und die einzige Schicht, die eine Lektion vom heutigen Tag auf den morgigen überträgt.
Das Modell selbst speichert nichts. Die scheinbare Erinnerung ist eine ingenieurtechnische Entscheidung, die bei jeder Anfrage neu getroffen wird: Was erhält einen Platz in diesem Window – und woher soll es stammen?
Zur weiteren Lektüre behandeln Anthropics technische Beiträge zum effektiven Kontextmanagement sowie zur Erstellung leistungsfähiger Agenten zusammen mit der Dokumentation zum Speichermittel und zur Kontextbearbeitung dieses Thema ausführlicher.