COMPUTERZUGRIFFSSYSTEM

Agenten-Gedächtnissysteme: Persistenter Kontext für Ihre KI


Jeder KI-Agent hat ein Gedächtnisproblem. Jeder Aufruf des Modells ist zustandslos. Das Modell erinnert sich nicht an die letzte Anfrage, nicht an den Namen des Benutzers, seine Präferenzen oder frühere Entscheidungen. Ohne externes Gedächtnis beginnt Ihr Agent bei jedem Zug von vorn.

Diese Anleitung behandelt vier Gedächtnisstrategien — von der einfachsten bis zur leistungsstärksten — und wann man jede verwendet. Alle Beispiele verwenden TypeScript und das Anthropic SDK.

Warum Agenten Gedächtnis benötigen

Betrachten Sie einen Code-Review-Agenten. Beim ersten Ausführen erklärt der Benutzer die Konventionen seines Teams: keine any-Typen, immer Fehler explizit behandeln, funktionalen Stil bevorzugen. Der Agent liefert eine gute Überprüfung.

Beim zweiten Ausführen reicht der Benutzer eine andere Datei ein. Der Agent hat alles vergessen. Er verfehlt dieselben Konventionsverletzungen, die er gestern markiert hatte.

Das ist das Kernproblem: Agenten sind zustandslos, aber nützliche Agenten brauchen Kontinuität.

Gedächtnis gibt Agenten drei Fähigkeiten:

  • Rückruf — Fakten aus früheren Konversationen oder Sitzungen abrufen
  • Personalisierung — sich im Laufe der Zeit an Benutzerpräferenzen anpassen
  • Koordination — in Multi-Agenten-Systemen Zustand zwischen Agenten teilen

Die vier Gedächtnistypen

TypWo gespeichertUmfangAm besten für
PufferIm Kontext (Nachrichten-Array)Aktuelle SitzungKurze Konversationen
ZusammenfassungIm Kontext (komprimiert)Aktuelle SitzungLange Konversationen
SemantischExtern (Vektor-DB)SitzungsübergreifendWissensrückruf
EpisodischExtern (Schlüssel-Wert-Speicher)SitzungsübergreifendBenutzerfakten, Präferenzen

Strategie 1: Konversationspuffer

Die einfachste Strategie ist, den vollständigen Konversationsverlauf bei jedem Modellaufruf zu übergeben.

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
interface Message {
role: "user" | "assistant";
content: string;
}
// Der Puffer enthält den vollständigen Konversationsverlauf
const buffer: Message[] = [];
async function chat(userMessage: string): Promise<string> {
// Neue Benutzernachricht zum Puffer hinzufügen
buffer.push({ role: "user", content: userMessage });
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
// Bei jedem Aufruf den vollständigen Puffer übergeben
messages: buffer,
});
const assistantMessage =
response.content[0].type === "text" ? response.content[0].text : "";
// Assistentenantwort zum Puffer hinzufügen
buffer.push({ role: "assistant", content: assistantMessage });
return assistantMessage;
}
// Verwendungsbeispiel
await chat("Mein Name ist Alex und ich bevorzuge Python gegenüber TypeScript.");
await chat("Welche Sprache sollte ich für mein nächstes Projekt verwenden?");
// Das Modell erinnert sich an die in der ersten Nachricht angegebene Präferenz

Wann verwenden: Konversationen mit weniger als 20 Zügen. Einfache Chatbots. Prototypen.

Die Grenze: Kontextfenster sind endlich. Eine lange Sitzung überschreitet schließlich das Token-Limit.

Strategie 2: Rollende Zusammenfassung

Wenn Konversationen lang werden, fassen Sie alte Züge zusammen, anstatt sie zu verwerfen.

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
interface ConversationState {
summary: string; // Komprimierter Verlauf älterer Züge
recentMessages: Array<{ role: "user" | "assistant"; content: string }>;
maxRecentTurns: number; // Die letzten N Züge wörtlich behalten
}
const state: ConversationState = {
summary: "",
recentMessages: [],
maxRecentTurns: 6, // 3 Benutzer- + 3 Assistentenzüge
};
// Ältere Züge in die rollende Zusammenfassung komprimieren
async function compressSummary(
currentSummary: string,
messagesToCompress: Array<{ role: string; content: string }>
): Promise<string> {
const formatted = messagesToCompress
.map((m) => `${m.role.toUpperCase()}: ${m.content}`)
.join("\n");
const response = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 512,
messages: [
{
role: "user",
content: `Aktualisiere die Konversationszusammenfassung mit den neuen Austauschen unten.
Gib nur die aktualisierte Zusammenfassung zurück. Halte sie unter 200 Wörtern.
Aktuelle Zusammenfassung:
${currentSummary || "(keine)"}
Neue Austausche:
${formatted}`,
},
],
});
return response.content[0].type === "text" ? response.content[0].text : currentSummary;
}
async function chat(userMessage: string): Promise<string> {
// Wenn der Puffer das Limit überschreitet, die älteste Hälfte komprimieren
if (state.recentMessages.length >= state.maxRecentTurns * 2) {
const toCompress = state.recentMessages.splice(0, state.maxRecentTurns);
state.summary = await compressSummary(state.summary, toCompress);
}
state.recentMessages.push({ role: "user", content: userMessage });
// Nachrichten-Array aufbauen: System-Zusammenfassung + letzte wörtliche Züge
const messages = [
...(state.summary
? [
{
role: "user" as const,
content: `Kontext von früher in dieser Konversation:\n${state.summary}`,
},
{
role: "assistant" as const,
content: "Verstanden. Ich werde diesen Kontext verwenden.",
},
]
: []),
...state.recentMessages,
];
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages,
});
const assistantMessage =
response.content[0].type === "text" ? response.content[0].text : "";
state.recentMessages.push({ role: "assistant", content: assistantMessage });
return assistantMessage;
}

Der Zusammenfassungsaufruf verwendet ein schnelles, günstiges Modell (Haiku). Die Hauptkonversation verwendet das fähige Modell (Sonnet). Diese Aufteilung hält die Kosten niedrig bei gleichzeitiger Qualitätserhaltung.

Wann verwenden: Sitzungen über 20 Züge. Support-Agenten. Langfristige Aufgaben-Agenten.

Strategie 3: Episodisches Gedächtnis

Episodisches Gedächtnis speichert spezifische Fakten über einen Benutzer oder eine Sitzung in einem Schlüssel-Wert-Speicher.

import Anthropic from "@anthropic-ai/sdk";
import fs from "fs/promises";
const client = new Anthropic();
// In Produktion, diesen Dateispeicher durch Redis oder eine Datenbank ersetzen
const MEMORY_PATH = "./memory.json";
interface EpisodicStore {
[userId: string]: Record<string, string>;
}
async function loadMemory(): Promise<EpisodicStore> {
try {
const data = await fs.readFile(MEMORY_PATH, "utf-8");
return JSON.parse(data);
} catch {
return {};
}
}
async function saveMemory(store: EpisodicStore): Promise<void> {
await fs.writeFile(MEMORY_PATH, JSON.stringify(store, null, 2));
}
// Strukturierte Fakten aus dem letzten Austausch extrahieren
async function extractFacts(
userMessage: string,
assistantReply: string
): Promise<Record<string, string>> {
const response = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 256,
messages: [
{
role: "user",
content: `Extrahiere persönliche Fakten, Präferenzen oder wichtige Entscheidungen aus diesem Austausch.
Gib ein JSON-Objekt aus Schlüssel-Wert-Paaren zurück. Gib {} zurück, wenn nichts erinnerungswürdig ist.
Benutzer: ${userMessage}
Assistent: ${assistantReply}`,
},
],
});
try {
const text = response.content[0].type === "text" ? response.content[0].text : "{}";
const match = text.match(/\{[\s\S]*\}/);
return match ? JSON.parse(match[0]) : {};
} catch {
return {};
}
}
function formatMemory(facts: Record<string, string>): string {
const entries = Object.entries(facts);
if (entries.length === 0) return "";
return (
"Was Sie über diesen Benutzer wissen:\n" +
entries.map(([k, v]) => `- ${k}: ${v}`).join("\n")
);
}
async function chat(userId: string, userMessage: string): Promise<string> {
const store = await loadMemory();
const userFacts = store[userId] ?? {};
const systemPrompt = formatMemory(userFacts);
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: systemPrompt || undefined,
messages: [{ role: "user", content: userMessage }],
});
const assistantMessage =
response.content[0].type === "text" ? response.content[0].text : "";
// Fakten extrahieren und für zukünftige Sitzungen persistieren
const newFacts = await extractFacts(userMessage, assistantMessage);
if (Object.keys(newFacts).length > 0) {
store[userId] = { ...userFacts, ...newFacts };
await saveMemory(store);
}
return assistantMessage;
}

Wann verwenden: Benutzerorientierte Agenten, die über mehrere Sitzungen laufen. Personalisierung. Präferenz-Tracking.

Strategie 4: Semantisches Gedächtnis (Vektorsuche)

Semantisches Gedächtnis speichert Dokumente, Code oder Konversationsfragmente, die nach Bedeutung indexiert sind.

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
interface Document {
id: string;
content: string;
embedding?: number[];
}
// Kosinus-Ähnlichkeit zwischen zwei Vektoren berechnen
function cosineSimilarity(a: number[], b: number[]): number {
const dot = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dot / (magA * magB);
}
class SemanticMemory {
private documents: Document[] = [];
// Dokument für spätere Abfrage indexieren
async add(id: string, content: string): Promise<void> {
const embedding = await embed(content); // Ein dediziertes Einbettungsmodell verwenden
this.documents.push({ id, content, embedding });
}
// Die k relevantesten Dokumente für eine Abfrage abrufen
async search(query: string, topK = 3): Promise<Document[]> {
const queryEmbedding = await embed(query);
return this.documents
.filter((doc) => doc.embedding)
.map((doc) => ({
doc,
score: cosineSimilarity(queryEmbedding, doc.embedding!),
}))
.sort((a, b) => b.score - a.score)
.slice(0, topK)
.map(({ doc }) => doc);
}
}
const memory = new SemanticMemory();
async function answerWithContext(question: string): Promise<string> {
// Relevante Dokumente abrufen
const relevant = await memory.search(question);
const context = relevant.map((d) => d.content).join("\n\n---\n\n");
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: context
? `Beantworte die Frage anhand des folgenden Kontexts:\n\n${context}`
: undefined,
messages: [{ role: "user", content: question }],
});
return response.content[0].type === "text" ? response.content[0].text : "";
}

Für den Produktionseinsatz ersetzen Sie den In-Memory-Speicher durch eine dedizierte Vektordatenbank. Pgvector ist die einfachste Option, wenn Sie bereits PostgreSQL verwenden.

Gedächtnis mit MCP verbinden

Wenn Sie der MCP-Server-Anleitung gefolgt sind, können Sie Gedächtnis als MCP-Ressource bereitstellen.

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{ name: "memory-server", version: "1.0.0" },
{ capabilities: { tools: {}, resources: {} } }
);
// Werkzeug: Eine Tatsache speichern
server.setRequestHandler("tools/call", async (request) => {
if (request.params.name === "remember") {
const { key, value, userId } = request.params.arguments as {
key: string; value: string; userId: string;
};
await storeEpisodicFact(userId, key, value);
return { content: [{ type: "text", text: `Gespeichert: ${key} = ${value}` }] };
}
if (request.params.name === "recall") {
const { userId } = request.params.arguments as { userId: string };
const facts = await loadEpisodicFacts(userId);
return { content: [{ type: "text", text: JSON.stringify(facts, null, 2) }] };
}
});
const transport = new StdioServerTransport();
await server.connect(transport);

Die richtige Strategie wählen

SituationStrategie
Einzelne Sitzung, weniger als 20 ZügePuffer
Einzelne Sitzung, langfristigZusammenfassung
Multi-Sitzung, BenutzerpräferenzenEpisodisch
Große Wissensbasis abfragenSemantisch
Alles davonKombinieren

Beginnen Sie mit dem Puffer. Fügen Sie eine Zusammenfassungsschicht hinzu, wenn Konversationen lang werden. Fügen Sie episodisches Gedächtnis hinzu, wenn Benutzer sitzungsübergreifend zurückkehren.

Fazit

Gedächtnis ist keine einzige Sache — es ist ein Stapel von Strategien. Der Puffer verwaltet die aktuelle Sitzung. Die Zusammenfassung verlängert diese Sitzung. Episodisches Gedächtnis überbrückt Sitzungen. Semantisches Gedächtnis verankert Antworten in einer Wissensbasis.

Wählen Sie die Schicht, die das Problem löst, das Sie heute haben. Wenn Ihre Agenten über MCP kommunizieren, stellen Sie Gedächtnis als gemeinsames Werkzeug bereit.


Verwandte Artikel