CodeGym /Kurse /ChatGPT Apps /Speicher und Zustand des Agenten: Session vs. Persistent,...

Speicher und Zustand des Agenten: Session vs. Persistent, Checkpoints

ChatGPT Apps
Level 12 , Lektion 2
Verfügbar

1. Warum ein Agent überhaupt einen separaten Speicher braucht

Dieser Teil baut auf den vorherigen Lektionen des Moduls 12 über Agenten auf: Dort haben wir bereits die grundlegende Architektur, den Run‑Zyklus und die Tools besprochen; hier liegt der Fokus auf Speicher und Zustand.

Wenn man die Analogie zu einer herkömmlichen Web‑Anwendung zieht, ist die LLM hier eine sehr intelligente CPU, die komplexe „Textprogramme“ ausführen kann. Und der Agentenzustand ist eine Kombination aus RAM und SSD: kurzlebige Sitzungsdaten und ein langfristiger Speicher.

Im klassischen ChatGPT‑Chat ohne Ihren Code ist „Speicher“ einfach die Liste der Nachrichten system/user/assistant/tool, die das Modell in der aktuellen Anfrage sieht. Für einen Agenten ist das zu wenig, weil:

  • er sich den Fortschritt komplexer Prozesse merken muss: welcher Workflow‑Schritt bereits abgeschlossen ist, welche Geschenkoptionen schon herausgefiltert wurden, was der Nutzer bestätigt hat;
  • er langfristige Fakten über den Nutzer kennen muss: Präferenzen, Lieferadresse, Historie früherer Bestellungen;
  • er Ausfälle überstehen können muss: wenn der Server mitten in der Geschenkauswahl abstürzt, darf der Nutzer nicht alles erneut eingeben müssen.

Wenn man versucht, all das nur im Prompt‑Kontext zu speichern, stößt man schnell an das Limit des Kontextfensters und zahlt wiederholt Tokens für dieselben Fakten. Gleichzeitig riskieren Sie die Sicherheit: Zu viele unnötige Daten werden regelmäßig an das Modell gesendet. Deshalb gibt es in Agentensystemen immer einen expliziten Zustand – Objekt(e), die außerhalb der Nachrichtenhistorie leben und von Ihnen gesteuert werden.

2. Zustandsschichten des Agenten: Kontext, Session, Persistent

Beginnen wir mit der Zerlegung in Schichten. Ein Agent hat üblicherweise mindestens drei Ebenen von „Speicher“:

  1. Nachrichtenhistorie (Dialogkontext).
  2. Sitzungszustand (Session State).
  3. Langfristiger Zustand (Persistent State).

Wichtig ist, diese Begriffe nicht in einen Topf zu werfen.

Nachrichtenhistorie: „schmutziger Speicher“

Die Nachrichtenhistorie ist das, was die LLM bei jedem Schritt sieht: system-Anweisungen, Nutzeranfragen, Agentenantworten, Tool‑Ergebnisse.

Der Vorteil ist, dass Sie das nicht manuell führen müssen – Agents‑SDKs und die Plattform übernehmen das über die Entität Session/Conversation.

Der Nachteil: Das ist „schmutziger“ Speicher – viele überflüssige Worte, Wiederholungen, zufällige Nutzerdaten. Diese Daten sind token‑teuer und schlecht strukturiert. Sie möchten nicht, dass eine bereits herausgefilterte Liste mit 200 Geschenken jedes Mal als Plain‑Text an das Modell gelesen wird.

Session state: operative Kurzzeitspeicher

Der Session-Zustand ist ein strukturiertes Objekt, das innerhalb einer einzelnen Agenten‑Session/Unterhaltung lebt. Eine gute Analogie für Frontend‑Entwickler ist useState oder ein Redux‑Store, der lebt, solange der Tab offen ist.

Dort leben Dinge wie:

  • aktueller Prozessschritt (z. B. "collecting_profile" oder "filtering_candidates");
  • temporärer Cache von Tool‑Ergebnissen;
  • Sitzungsparameter: Locale, gewählter Kanal, Flags wie „Nutzer hat die Bedingungen bestätigt“.

Dieser Zustand kann nahe am Agenten gespeichert werden – in Redis, in einem In‑Memory‑KV‑Store oder über den integrierten SessionService eines konkreten SDK. Wichtig ist, das nicht in den system‑Prompt zu stopfen.

Persistent state: langfristige Daten

Der Persistent-Zustand lebt lange: über Sessions, Checkouts und Geräte hinweg. Das sind das Nutzerprofil, Bestellungen, gespeicherte Wunschlisten, Einstellungen.

Der Schlüsselgedanke: Der Agent „merkt sich“ Persistent‑Daten nicht magisch, er liest sie über Tools – zum Beispiel get_user_profile, get_past_orders. Keine versteckten globalen Variablen im Agenten; stets ein expliziter Aufruf.

Vergleichstabelle

Schicht Speicherort Lebenszyklus Beispieldaten
Messages Session / SDK / OpenAI Ein Run/Dialog system/user/tool‑Nachrichten
Session state KV / SessionService / Redis Solange die Session lebt Workflow‑Schritt, temporäre Caches
Persistent DB (Postgres/NoSQL/ACP‑Backend) Sitzungsübergreifend und zwischen Dialogen Profil, Bestellungen, gespeicherte Listen

3. Session state: was ist das und wie speichert man ihn

Stellen Sie sich vor, der Agent GiftGenius führt einen mehrstufigen Prozess aus:

  1. Sammelt das Profil des Geschenkempfängers.
  2. Generiert eine Kandidatenliste.
  3. Filtert sie nach Budget, Lieferung, Region.
  4. Bereitet die finale Auswahl vor.

Dabei kommuniziert er ständig mit dem Nutzer und ruft Tools auf. Alles, was zum „Fortschritt dieser konkreten Geschenkauswahl‑Session“ gehört, gehört sinnvollerweise in den Session‑State.

Beispielstruktur des Sitzungszustands von GiftGenius

Beschreiben wir den Typ des Session‑Zustands in TypeScript:

// Zustand innerhalb einer Geschenk-Auswahl
export type GiftSessionState = {
  step:
    | "collecting_profile"
    | "generating_candidates"
    | "filtering"
    | "finalizing";

  // Entwurf des Empfängerprofils
  profileDraft?: {
    recipientType?: string;
    ageRange?: string;
    interests?: string[];
    dislikes?: string[];
  };

  // IDs der Kandidatenprodukte, vom Backend erhalten
  candidateIds?: string[];

  // vom Nutzer ausgewähltes Geschenk
  selectedGiftId?: string;

  // technische Flags
  locale?: string;
};

Hier legen wir bewusst keine vollständigen Produktobjekte ab – nur ihre IDs. Die vollständigen Daten sollen in der DB leben; wenn nötig, ruft der Agent das Tool get_gift_details(gift_id) auf.

Session im Agents‑SDK (konzeptionell)

In vielen SDKs für Agenten gibt es die Abstraktion einer Session, die die Nachrichtenhistorie selbst verwaltet und Ihnen zusätzlich erlaubt, Structured‑State zu speichern. Im Pseudocode kann das so aussehen:

import { createRunner, OpenAIConversationsSession } from "@openai/agents";
// Typ GiftSessionState aus dem obigen Beispiel

const session = new OpenAIConversationsSession<GiftSessionState>({
  sessionId: "chatgpt-thread-id-or-random",
});

const runner = createRunner({ agent });

const result = await runner.run({
  session,
  input: "Ich möchte ein Geschenk für einen Kollegen bis 50$",
});

Das SDK macht unter der Haube:

  • lädt die Nachrichtenhistorie für diese Session;
  • fügt die neue Nutzernachricht hinzu;
  • übergibt Modell und Tooling;
  • speichert den aktualisierten Zustand (inklusive session.state) zurück.

Sie arbeiten mit session.state wie mit einem gewöhnlichen Objekt.

Session‑State aus Tools aktualisieren

Typisches Muster: Ein Tool, das etwas berechnet, aktualisiert gleichzeitig den Session‑State. Zum Beispiel ein Tool, das aus Nutzerantworten das Empfängerprofil zusammenstellt:

export async function updateProfileDraft(
  session: GiftSessionState,
  answers: { questionId: string; value: string }
): Promise<GiftSessionState> {
  const next: GiftSessionState = { ...session };

  if (!next.profileDraft) {
    next.profileDraft = {};
  }

  if (answers.questionId === "interests") {
    next.profileDraft.interests = answers.value.split(",").map((s) => s.trim());
  }

  // ...weitere Felder

  next.step = "generating_candidates";
  return next;
}

Hier übergeben wir an das Tool nicht die gesamte Session aus dem SDK, sondern nur ihren state (Typ GiftSessionState). Im echten Code lohnt es sich, ein solches Argument z. B. currentState zu nennen, um es nicht mit dem Session‑Objekt zu verwechseln.

Der Agent ruft dieses Tool auf, erhält ein neues Zustandsobjekt und speichert es zurück in session.state.

4. Persistent state: die langfristige Erinnerung des Agenten

Erinnern wir uns: GiftGenius funktioniert nicht nur in einem Chat. Ein Nutzer kann nach einer Woche, von einem anderen Gerät, zurückkommen und sagen: „Finde ein Geschenk für denselben Freund wie beim letzten Mal, aber das Budget ist gestiegen.“

Diese Information darf nicht im Session‑State leben, sondern im Persistent‑Speicher: in der Datenbank, im Commerce‑/ACP‑Backend (Commerce‑Schicht, dazu gibt es ein eigenes Modul) etc.

Beispiel einer Persistent‑Modellierung

Beschreiben wir das Modell des Empfängerprofils in der DB (vereinfacht als TypeScript‑Typ):

// Das, was in der DB gespeichert wird
export type RecipientProfile = {
  id: string;
  userId: string;
  label: string; // "Kollege aus dem Marketing"
  recipientType: string;
  ageRange?: string;
  interests: string[];
  dislikes: string[];
  lastUsedAt: string; // ISO-Datum
};

Und ein Repository (vorerst eine einfache Map — in der Realität würden Sie eine ORM/SQL‑Schicht bauen):

const profiles = new Map<string, RecipientProfile>();

export const RecipientRepo = {
  async findByUser(userId: string): Promise<RecipientProfile[]> {
    return [...profiles.values()].filter((p) => p.userId === userId);
  },

  async save(profile: RecipientProfile): Promise<void> {
    profiles.set(profile.id, profile);
  },
};

Der Agent greift über Tools auf Persistent zu

Wichtig ist, dass der Agent nicht direkt in die DB greift, sondern über Tools arbeitet. So bleibt er eine „saubere“ Entität: an einer Stelle LLM und Planungslogik, an anderer die Implementierung der Integrationen.

Zum Beispiel das Tool get_recipient_profiles:

export async function getRecipientProfilesTool(input: {
  userId: string;
}): Promise<{ profiles: RecipientProfile[] }> {
  const profiles = await RecipientRepo.findByUser(input.userId);

  return {
    profiles,
  };
}

In der Toolbeschreibung steht für den Agenten: „Verwende dieses Tool, um die gespeicherten Empfängerprofile für den aktuellen Nutzer zu erhalten.“ Er entscheidet selbst, wann er es aufruft.

Fazit: Der Session‑State betrifft den Fortschritt einer konkreten Unterhaltung und temporäre Caches, die man schmerzfrei verlieren kann. Persistent‑Daten sind das, was Sessions und Geräte überdauern muss: Profile, Bestellungen, Wunschlisten. Der Agent liest sie immer über Tools und „merkt“ sie sich nicht magisch.

5. Wie Session und Persistent im Run‑Zyklus zusammenarbeiten

Bringen wir alles in ein Gesamtbild. In jedem Schritt des Agenten‑Run‑Zyklus gibt es eine kurze Sequenz:

  1. Session‑State über sessionId laden.
  2. Bei Bedarf relevante Persistent‑Daten per DB‑Tools nachladen.
  3. Kontext für das Modell formen (Messages + strukturierter Zustand).
  4. Das Modell entscheidet: Text antworten oder Tools aufrufen.
  5. Tools aktualisieren entweder den Session‑State oder Persistent‑Daten (über die DB).
  6. Neuen Session‑Zustand speichern und, falls nötig, einen Checkpoint erzeugen (dazu gleich mehr).
  7. Antwort an den Nutzer zurückgeben.

Schema in Mermaid:

flowchart TD
    A[Eingabe des Nutzers erhalten] --> B["Session laden (state + messages)"]
    B --> C{Werden Persistent‑Daten benötigt?}
    C -- Ja --> D[Tools aufrufen: get_user_profile, get_recipient_profiles]
    C -- Nein --> E[Kontext für LLM formen]
    D --> E
    E --> F["Modell aufrufen (LLM)"]
    F --> G{Möchte das Modell ein Tool aufrufen?}
    G -- Ja --> H[Tool ausführen, session/persistent aktualisieren]
    G -- Nein --> I[Finale Antwort vorbereiten]
    H --> J[Checkpoint erstellen und Session speichern]
    I --> J
    J --> K[Antwort an den Nutzer]

So wird das Verhalten des Agenten reproduzierbar: In jedem Schritt wissen wir explizit, welcher Zustand vor dem Modellaufruf vorlag und was sich danach geändert hat.

6. Checkpoints: Schnappschüsse des Agentenzustands

Checkpoints sind gespeicherte „Zustandsschnappschüsse“ des Agenten an einem wichtigen Prozessschritt. Das ist nicht einfach nur der aktuelle Session‑State, sondern ein im externen Speicher festgehaltener Fakt: Am Schritt N hatten wir diesen State, diese Tool‑Ergebnisse, diesen Nutzereingang.

Wozu sie dienen:

  • Wiederherstellung nach Fehlern und Abstürzen;
  • die Möglichkeit „später fortsetzen“ für den Nutzer;
  • Debugging: Reproduzierbarkeit eines problematischen Runs;
  • Audit: Was genau der Agent getan hat, bevor er zum Beispiel eine Bestellung erstellt hat.

Was typischerweise in einen Checkpoint gehört

Ein typischer Checkpoint enthält:

  • Identifikatoren: runId, userId, workflowId, stepId;
  • den Sitzungszustand zu diesem Zeitpunkt;
  • Schlüssel‑IDs von Persistent‑Entitäten (z. B. die ID eines Bestellentwurfs);
  • Metadaten: Erstellungszeit, Agentenversion.

Wichtig ist, nicht den kompletten Dialogtext hineinzuziehen. Unten, im Abschnitt zur Speicherhygiene, gehen wir darauf zurück, was sich zu speichern lohnt und was nicht.

Besser ist es, einen Verweis auf die Session oder eine kurze Zusammenfassung der Schritte zu speichern.

7. Checkpoints für GiftGenius entwerfen

Nehmen wir unseren Geschenke‑Workflow und entscheiden, wo wir Checkpoints wollen. Zum Beispiel:

  • nachdem das Empfängerprofil gesammelt wurde;
  • nach der Generierung und ersten Filterung der Kandidaten;
  • bevor dem Nutzer die finale Auswahl vorgeschlagen wird.

Typen für Checkpoint und Workflow‑Zustand

Beschreiben wir den Workflow‑Zustand (sehr ähnlich zu GiftSessionState, aber bereits ein „Abzug“ für Checkpoints):

export type GiftWorkflowStep =
  | "profile_collected"
  | "candidates_generated"
  | "filtered"
  | "final_choice_made";

export type GiftCheckpoint = {
  id: string;
  runId: string;
  userId: string;

  step: GiftWorkflowStep;

  // Teil des Session-Zustands,
  // den wir für die Wiederherstellung brauchen
  sessionState: GiftSessionState;

  // welche Kandidaten-IDs generiert wurden
  candidateIds: string[];

  createdAt: string; // ISO
  agentVersion: string;
};

Checkpoint‑Speicher (vereinfacht)

Wie zuvor nutzen wir eine einfache Map statt einer echten DB:

const checkpoints = new Map<string, GiftCheckpoint>();

export const GiftCheckpointRepo = {
  async save(cp: GiftCheckpoint) {
    checkpoints.set(cp.id, cp);
  },

  async findByRun(runId: string): Promise<GiftCheckpoint[]> {
    return [...checkpoints.values()].filter((c) => c.runId === runId);
  },

  async findLastByUser(userId: string): Promise<GiftCheckpoint | undefined> {
    return [...checkpoints.values()]
      .filter((c) => c.userId === userId)
      .sort((a, b) => b.createdAt.localeCompare(a.createdAt))[0];
  },
};

Erstellen eines Checkpoints aus dem Agentencode

Stellen wir uns einen Helper vor, den wir nach einem wichtigen Schritt aufrufen:

import { randomUUID } from "crypto";

export async function createCheckpoint(params: {
  runId: string;
  userId: string;
  step: GiftWorkflowStep;
  sessionState: GiftSessionState;
  candidateIds: string[];
}) {
  const checkpoint: GiftCheckpoint = {
    id: randomUUID(),
    runId: params.runId,
    userId: params.userId,
    step: params.step,
    sessionState: params.sessionState,
    candidateIds: params.candidateIds,
    createdAt: new Date().toISOString(),
    agentVersion: "v1.3.0",
  };

  await GiftCheckpointRepo.save(checkpoint);
}

Der Agent kann zum passenden Zeitpunkt aufrufen:

await createCheckpoint({
  runId,
  userId,
  step: "filtered",
  sessionState,
  candidateIds,
});

Bei der Wiederherstellung tun wir Folgendes:

  1. Den letzten Checkpoint über runId oder userId finden.
  2. session.state aus checkpoint.sessionState wiederherstellen.
  3. Bei Bedarf die aktuellen Daten zu candidateIds aus der DB nachladen.

8. Wo Session, Persistent und Checkpoints technisch gespeichert werden

Auf Infrastrukturebene gibt es üblicherweise drei Klassen von Speichern:

  • In‑Memory – für Dev/Demos, schneller, aber temporärer Speicher.
  • Redis (oder ein anderer KV‑Store) – für den Session‑Zustand.
  • Relationale/NoSQL‑DB – für Persistent‑Daten und Checkpoints.

In‑Memory‑Store für lokale Entwicklung

Für den lokalen Dev‑Modus reicht ein einfacher In‑Memory‑Store aus. Zum Beispiel ein Mini‑Speicher mit TTL für Sessions:

type StoredSession<T> = {
  state: T;
  expiresAt: number;
};

const sessions = new Map<string, StoredSession<GiftSessionState>>();

export function saveSession(sessionId: string, state: GiftSessionState) {
  sessions.set(sessionId, {
    state,
    expiresAt: Date.now() + 30 * 60 * 1000, // 30 Minuten
  });
}

export function loadSession(sessionId: string): GiftSessionState | undefined {
  const stored = sessions.get(sessionId);
  if (!stored) return undefined;
  if (stored.expiresAt < Date.now()) {
    sessions.delete(sessionId);
    return undefined;
  }
  return stored.state;
}

So etwas ist für Local Dev prima, funktioniert in Production bei horizontaler Skalierung (mehrere Instanzen) jedoch nicht mehr.

Redis für den Session‑State

In Production speichert man den Session‑Zustand bequem in Redis:

  • schnelles Schreiben/Lesen;
  • TTL „out of the box“;
  • für alle Instanzen des Dienstes erreichbar.

Pseudo‑Beispiel (vereinfacht):

// Wrapper um den Redis-Client
export async function saveSessionToRedis(
  sessionId: string,
  state: GiftSessionState
) {
  const json = JSON.stringify(state);
  await redis.set(`session:${sessionId}`, json, "EX", 60 * 30); // 30 Minuten
}

export async function loadSessionFromRedis(
  sessionId: string
): Promise<GiftSessionState | undefined> {
  const json = await redis.get(`session:${sessionId}`);
  return json ? (JSON.parse(json) as GiftSessionState) : undefined;
}

Postgres/andere DB für Persistent und Checkpoints

Persistent‑Zustand und Checkpoints sind „ernsthafte“ Entitäten, für die Transaktionen, Migrationen, Indizes und Co. wichtig sind. Man legt sie in Postgres, MySQL, Firestore etc. ab.

Das Architektur‑Muster ist einfach:

  • Session in Redis mit TTL;
  • Persistent und Checkpoints in der DB ohne TTL (oder mit einer geschäftsabhängigen Retention‑Policy).

9. Speicherhygiene: Größen, Privatsphäre, Verantwortungsabgrenzung

Der Speicher eines Agenten ist nicht einfach „wir legen irgendwo ein Objekt ab und fertig“. Es gibt einige wichtige Regeln, die Geld sparen und Ruhe bringen.

Nicht alles in Messages stopfen

Die Nachrichtenhistorie ist eine teure Ressource:

  • ihre Länge beeinflusst die Kosten einer Modellanfrage stark;
  • darin steckt in der Regel viel „Rauschen“.

Deshalb:

  • extrahieren Sie Fakten so früh wie möglich aus der Historie in einen strukturierten Zustand;
  • nutzen Sie Summarization für ältere Teile der Historie;
  • wenn Sie im Checkpoint Text‑Historien speichern, tun Sie das getrennt von dem, was an das Modell gesendet wird.

Privatsphäre und PII

Gerade für Commerce‑Szenarien ist es wichtig, sensible Daten nicht an Orte zu speichern, an die sie nicht gehören. Dokumente zur Speicherarchitektur betonen ausdrücklich, dass PII‑Daten nicht in messages oder Checkpoints ohne Bereinigung liegen sollten.

Praktische Regeln:

  • legen Sie E‑Mail/Telefon/Adresse nicht direkt in den Session‑State, wenn der Agent sie nicht braucht;
  • schreiben Sie in Logs und Checkpoints möglichst Identifikatoren (userId, recipientProfileId) statt Rohstrings;
  • wenn PII über mehrere Schritte transportiert werden muss – nutzen Sie separate geschützte Felder im Persistent‑Speicher und übergeben Sie im State nur den Schlüssel.

Trennung von Geschäftsdaten und Chat‑Log

Ein gutes Muster ist, state als „sauberen“ Speicher und messages als „schmutzigen“ zu betrachten.

Das heißt:

  • Geschäftsobjekte (Profile, Bestellungen, Warenkörbe) leben stets in der DB;
  • State/Checkpoints enthalten das Minimum, das zur Wiederaufnahme des Prozesses nötig ist;
  • Logs/Chathistorie werden separat gespeichert (z. B. in einem Vektor‑Store) und für Analysen genutzt, aber nicht jeder Modellanfrage beigemischt.

10. Mini‑Praxis: Was würden Sie speichern?

Um den Unterschied zwischen den Speicherschichten zu festigen, lösen wir uns kurz von der Theorie und denken über einen konkreten Fall nach. Sie müssen keinen Code schreiben – es reicht, die Strukturen grob auf Papier oder im Kopf zu skizzieren.

Stellen Sie sich vor, Ihr Agent GiftGenius hat mit dem Nutzer folgenden Dialog geführt:

  • Nutzer: „Ich brauche ein Geschenk für einen Entwickler‑Kollegen, Budget bis 50$, er mag Brettspiele und Koffein.“
  • Agent: stellt ein paar Rückfragen.
  • Nutzer: „Er hasst Tassen und ist schon mit Notizbüchern überhäuft.“
  • Agent: generiert eine Liste aus 10 Ideen, der Nutzer wählt eine aus, sagt aber: „Ich komme später zurück, um alles abzuschließen.“

Überlegen Sie:

  1. Was legen Sie in den Session‑State (der nach 30 Minuten sterben kann)?
  2. Was geht in den Persistent‑Speicher, damit der Nutzer in einer Woche zurückkommen kann?
  3. Wie sähe ein Checkpoint nach der Ideenauswahl, aber vor dem Checkout, aus?

Versuchen Sie, passende TypeScript‑Typen und Funktionen saveSessionState, savePersistentState, createGiftIdeaCheckpoint analog zu den Beispielen in dieser Vorlesung zu skizzieren. Wenn Sie möchten, können Sie diese Typen und Funktionen direkt im Editor grob anlegen – ein guter Mini‑Checkpoint vor der nächsten Vorlesung.

11. Typische Fehler beim Arbeiten mit dem Agentenspeicher

Fehler Nr. 1: Alles nur in der Nachrichtenhistorie speichern wollen.
Der Entwickler freut sich: „Das Modell sieht doch ohnehin den ganzen Dialog, warum noch irgendeinen State ausdenken?“ Am Ende ist nach einigen Dutzend Nachrichten das Kontextfenster mit Müll gefüllt, die Tokenkosten schießen in die Höhe, und das Agentenverhalten wird instabil – wichtige alte Fakten sind für das Modell nicht mehr sichtbar. Dieses Problem löst man durch die explizite Trennung in Session‑State und Persistent‑Speicher, nicht durch höhere Limits.

Fehler Nr. 2: Session und Persistent in einem Objekt vermischen.
Manchmal ist es verlockend, eine große Entität AgentState einzuführen, dort alles abzuladen und „as is“ in die Datenbank zu speichern. Dann verwischt die Grenze zwischen temporären Daten der konkreten Unterhaltung und langfristigen Nutzerdaten. Es entstehen Geschichten wie „nach dem Deploy wurden Sessions mysteriös aus Vorjahresdaten wiederhergestellt“ oder „die Session eines Nutzers hat zufällig ein fremdes Persistent‑Profil eingefangen“. Trennen Sie die Ebenen bewusst.

Fehler Nr. 3: Zu viel in Checkpoints speichern.
Häufiger Fehler: den gesamten JSON eines Tool‑Ergebnisses, die komplette Chathistorie, Rohdaten von Integrationen usw. in den Checkpoint zu schreiben. Nach ein paar Wochen bläht sich die Checkpoint‑Datenbank ungebührlich auf, Backups dauern ewig, und DB‑Abfragen werden langsam. In einen Checkpoint gehören nur die Fakten, die wirklich nötig sind, um fortzufahren, plus ein Minimum an Metadaten.

Fehler Nr. 4: TTL und Bereinigung des Session‑State vergessen.
Wenn Session‑Zustände keine Lebensdauer haben, bleibt jeder zufällige Nutzer‑Versuch im Dev‑Modus für immer in Redis. Nach ein paar Monaten zeigt das Monitoring einen Berg „vergessener“ Sessions, die Speicher fressen. Die Session‑Ebene braucht ein explizites TTL‑Konzept, die Persistent‑Ebene eine durchdachte Retention‑Policy.

Fehler Nr. 5: PII im State und in Checkpoints ohne Notwendigkeit speichern.
Besonders riskant ist es, wenn im Session‑State gedankenlos E‑Mail, Adresse, Kartennummer landen und dieses Objekt dann in Logs serialisiert, in die Analytics geschoben und in Checkpoints gespeichert wird. Das schafft erhebliche Risiken in Bezug auf Regulierung und Sicherheit. Speichern Sie besser sichere Identifikatoren und resolven Sie sie bei Bedarf über separate, geschützte Tools zu realen Daten.

Fehler Nr. 6: Keine Strategie zur Wiederherstellung aus Checkpoints.
Einige Teams schreiben zwar fleißig Checkpoints, denken aber nicht durch, wie der Agent daraus wiederherstellen soll. Wenn dann „etwas schiefgeht“, schauen Entwickler auf eine Tabelle mit hübschen JSONs, haben aber keinen Code, der daraus den Run rekonstruieren kann. Checkpointing ohne Wiederherstellungsszenario ist nur ein teures Log, kein Zuverlässigkeitswerkzeug.

Fehler Nr. 7: Feste Kopplung des Agenten an eine konkrete Speicherimplementierung.
Wenn der Agentencode direkt Redis/Postgres anspricht, ist er schwerer zu portieren, zu testen und weiterzuentwickeln. Bei Architekturänderungen (z. B. Einführung von MCP‑Ressourcen oder einem separaten State‑Service) muss die Agentenlogik umgebaut werden. Besser ist, wenn der Agent nur die Abstraktionen Session und einen Satz von Tools sieht und erst die Tools wissen, wo die Daten liegen.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION