Session-Management und Kompaktierung (Deep Dive)
Dieses Dokument erklärt, wie OpenClaw Sessions Ende-zu-Ende verwaltet:- Session-Routing (wie eingehende Nachrichten einer
sessionKeyzugeordnet werden) - Session-Store (
sessions.json) und was er erfasst - Persistenz von Transcripts (
*.jsonl) und ihre Struktur - Transcript-Hygiene (anbieterspezifische Korrekturen vor Ausführungen)
- Kontextgrenzen (Kontextfenster vs. erfasste Tokens)
- Kompaktierung (manuelle + automatische Kompaktierung) und wo Arbeiten vor der Kompaktierung eingehängt werden
- Stilles Housekeeping (z. B. Memory-Schreibvorgänge, die keine für Nutzer sichtbare Ausgabe erzeugen sollen)
- /concepts/session
- /concepts/compaction
- /concepts/memory
- /concepts/memory-search
- /concepts/session-pruning
- /reference/transcript-hygiene
Quelle der Wahrheit: das Gateway
OpenClaw ist auf einen einzelnen Gateway-Prozess ausgelegt, der den Session-Status besitzt.- UIs (macOS-App, web Control UI, TUI) sollten das Gateway nach Session-Listen und Token-Zählwerten abfragen.
- Im Remote-Modus liegen Session-Dateien auf dem Remote-Host; ein „Prüfen Ihrer lokalen Mac-Dateien“ spiegelt nicht wider, was das Gateway verwendet.
Zwei Persistenzschichten
OpenClaw persistiert Sessions in zwei Schichten:-
Session-Store (
sessions.json)- Schlüssel/Wert-Zuordnung:
sessionKey -> SessionEntry - Klein, veränderbar, sicher bearbeitbar (oder Einträge löschbar)
- Erfasst Session-Metadaten (aktuelle Session-ID, letzte Aktivität, Umschalter, Token-Zählwerte usw.)
- Schlüssel/Wert-Zuordnung:
-
Transcript (
<sessionId>.jsonl)- Append-only-Transcript mit Baumstruktur (Einträge haben
id+parentId) - Speichert die eigentliche Unterhaltung + Tool-Aufrufe + Kompaktierungszusammenfassungen
- Wird verwendet, um den Modellkontext für zukünftige Turns wiederaufzubauen
- Append-only-Transcript mit Baumstruktur (Einträge haben
Speicherorte auf dem Datenträger
Pro Agent auf dem Gateway-Host:- Store:
~/.openclaw/agents/<agentId>/sessions/sessions.json - Transcripts:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- Telegram-Topic-Sessions:
.../<sessionId>-topic-<threadId>.jsonl
- Telegram-Topic-Sessions:
src/config/sessions.ts auf.
Store-Wartung und Datenträgerkontrollen
Die Session-Persistenz verfügt über automatische Wartungssteuerungen (session.maintenance) für sessions.json und Transcript-Artefakte:
mode:warn(Standard) oderenforcepruneAfter: Altersgrenze für veraltete Einträge (Standard30d)maxEntries: Obergrenze für Einträge insessions.json(Standard500)rotateBytes: rotiertsessions.json, wenn es zu groß ist (Standard10mb)resetArchiveRetention: Aufbewahrung für Transcript-Archive*.reset.<timestamp>(Standard: identisch zupruneAfter;falsedeaktiviert die Bereinigung)maxDiskBytes: optionales Budget für das Sessions-VerzeichnishighWaterBytes: optionales Ziel nach der Bereinigung (Standard80%vonmaxDiskBytes)
mode: "enforce"):
- Entfernen Sie zuerst die ältesten archivierten oder verwaisten Transcript-Artefakte.
- Wenn das Ziel weiterhin überschritten wird, entfernen Sie die ältesten Session-Einträge und ihre Transcript-Dateien.
- Fahren Sie fort, bis die Nutzung bei oder unter
highWaterBytesliegt.
mode: "warn" meldet OpenClaw mögliche Entfernungen, verändert aber den Store/die Dateien nicht.
Wartung bei Bedarf ausführen:
Cron-Sessions und Run-Logs
Isolierte Cron-Ausführungen erzeugen ebenfalls Session-Einträge/Transcripts, und dafür gibt es eigene Aufbewahrungssteuerungen:cron.sessionRetention(Standard24h) entfernt alte isolierte Cron-Run-Sessions aus dem Session-Store (falsedeaktiviert dies).cron.runLog.maxBytes+cron.runLog.keepLineskürzen Dateien~/.openclaw/cron/runs/<jobId>.jsonl(Standards:2_000_000Bytes und2000Zeilen).
Session-Schlüssel (sessionKey)
Ein sessionKey identifiziert, in welchem Gesprächs-Bucket Sie sich befinden (Routing + Isolation).
Häufige Muster:
- Haupt-/Direkt-Chat (pro Agent):
agent:<agentId>:<mainKey>(Standardmain) - Gruppe:
agent:<agentId>:<channel>:group:<id> - Raum/Kanal (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>oder...:room:<id> - Cron:
cron:<job.id> - Webhook:
hook:<uuid>(sofern nicht überschrieben)
Session-IDs (sessionId)
Jeder sessionKey verweist auf eine aktuelle sessionId (die Transcript-Datei, die die Unterhaltung fortsetzt).
Faustregeln:
- Zurücksetzen (
/new,/reset) erstellt eine neuesessionIdfür diesensessionKey. - Tägliches Zurücksetzen (standardmäßig 4:00 Uhr lokale Zeit auf dem Gateway-Host) erstellt bei der nächsten Nachricht nach der Reset-Grenze eine neue
sessionId. - Idle-Ablauf (
session.reset.idleMinutesoder Legacy-session.idleMinutes) erstellt eine neuesessionId, wenn nach dem Inaktivitätsfenster eine Nachricht eintrifft. Wenn täglich + idle beide konfiguriert sind, gilt, was zuerst abläuft. - Fork-Schutz für Thread-Parent (
session.parentForkMaxTokens, Standard100000) überspringt das Forken des Parent-Transcripts, wenn die Parent-Session bereits zu groß ist; der neue Thread beginnt frisch. Setzen Sie0, um dies zu deaktivieren.
initSessionState() in src/auto-reply/reply/session.ts.
Schema des Session-Stores (sessions.json)
Der Werttyp des Stores ist SessionEntry in src/config/sessions.ts.
Wichtige Felder (nicht vollständig):
sessionId: aktuelle Transcript-ID (Dateiname wird daraus abgeleitet, sofernsessionFilenicht gesetzt ist)updatedAt: Zeitstempel der letzten AktivitätsessionFile: optionale explizite Überschreibung des Transcript-PfadschatType:direct | group | room(hilft UIs und Sende-Richtlinien)provider,subject,room,space,displayName: Metadaten für Gruppen-/Kanallabels- Umschalter:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(Überschreibung pro Session)
- Modellauswahl:
providerOverride,modelOverride,authProfileOverride
- Token-Zählwerte (Best-Effort / anbieterabhängig):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: wie oft die automatische Kompaktierung für diesen Session-Schlüssel abgeschlossen wurdememoryFlushAt: Zeitstempel des letzten Memory-Flushs vor der KompaktierungmemoryFlushCompactionCount: Kompaktierungszähler, als der letzte Flush ausgeführt wurde
Transcript-Struktur (*.jsonl)
Transcripts werden vom SessionManager von @mariozechner/pi-coding-agent verwaltet.
Die Datei ist JSONL:
- Erste Zeile: Session-Header (
type: "session", enthältid,cwd,timestamp, optionalparentSession) - Danach: Session-Einträge mit
id+parentId(Baum)
message: Nutzer-/Assistant-/toolResult-Nachrichtencustom_message: von Erweiterungen eingefügte Nachrichten, die in den Modellkontext eingehen (können in der UI verborgen sein)custom: Erweiterungsstatus, der nicht in den Modellkontext eingehtcompaction: persistierte Kompaktierungszusammenfassung mitfirstKeptEntryIdundtokensBeforebranch_summary: persistierte Zusammenfassung beim Navigieren in einem Baumzweig
SessionManager, um sie zu lesen/zu schreiben.
Kontextfenster vs. erfasste Tokens
Zwei verschiedene Konzepte sind wichtig:- Kontextfenster des Modells: harte Obergrenze pro Modell (Tokens, die für das Modell sichtbar sind)
- Zählwerte im Session-Store: rollierende Statistiken, die in
sessions.jsongeschrieben werden (verwendet für /status und Dashboards)
- Das Kontextfenster kommt aus dem Modellkatalog (und kann per Konfiguration überschrieben werden).
contextTokensim Store ist ein Laufzeitschätzwert/Berichtswert; behandeln Sie es nicht als strikte Garantie.
Kompaktierung: was das ist
Kompaktierung fasst ältere Unterhaltung in einem persistentencompaction-Eintrag im Transcript zusammen und lässt aktuelle Nachrichten intakt.
Nach der Kompaktierung sehen zukünftige Turns:
- Die Kompaktierungszusammenfassung
- Nachrichten nach
firstKeptEntryId
Chunk-Grenzen bei der Kompaktierung und Tool-Paarung
Wenn OpenClaw ein langes Transcript in Kompaktierungs-Chunks aufteilt, hält es Assistant-Tool-Aufrufe zusammen mit ihren passendentoolResult-Einträgen gepaart.
- Wenn die tokenbasierte Aufteilung zwischen einem Tool-Aufruf und seinem Ergebnis landet, verschiebt OpenClaw die Grenze auf die Assistant-Nachricht mit dem Tool-Aufruf, statt das Paar zu trennen.
- Wenn ein nachlaufender
toolResult-Block den Chunk sonst über das Ziel hinausschieben würde, bewahrt OpenClaw diesen ausstehenden Tool-Block und lässt den nicht zusammengefassten Tail intakt. - Abgebrochene/fehlerhafte Tool-Aufruf-Blöcke halten eine ausstehende Aufteilung nicht offen.
Wann automatische Kompaktierung erfolgt (Pi-Laufzeit)
Im eingebetteten Pi-Agenten wird automatische Kompaktierung in zwei Fällen ausgelöst:- Overflow-Wiederherstellung: Das Modell gibt einen Kontext-Overflow-Fehler zurück
(
request_too_large,context length exceeded,input exceeds the maximum number of tokens,input token count exceeds the maximum number of input tokens,input is too long for the model,ollama error: context length exceededund ähnliche anbietergeformte Varianten) → kompaktieren → erneut versuchen. - Schwellwert-Wartung: nach einem erfolgreichen Turn, wenn:
contextTokens > contextWindow - reserveTokens
Dabei gilt:
contextWindowist das Kontextfenster des ModellsreserveTokensist der reservierte Puffer für Prompts + die nächste Modellausgabe
Einstellungen für Kompaktierung (reserveTokens, keepRecentTokens)
Die Kompaktierungseinstellungen von Pi befinden sich in den Pi-Einstellungen:
- Wenn
compaction.reserveTokens < reserveTokensFloorist, erhöht OpenClaw diesen Wert. - Die Standarduntergrenze ist
20000Tokens. - Setzen Sie
agents.defaults.compaction.reserveTokensFloor: 0, um die Untergrenze zu deaktivieren. - Wenn der Wert bereits höher ist, lässt OpenClaw ihn unverändert.
ensurePiCompactionReserveTokens() in src/agents/pi-settings.ts
(aufgerufen aus src/agents/pi-embedded-runner.ts).
Austauschbare Kompaktierungsanbieter
Plugins können überregisterCompactionProvider() auf der Plugin-API einen Kompaktierungsanbieter registrieren. Wenn agents.defaults.compaction.provider auf eine registrierte Anbieter-ID gesetzt ist, delegiert die Safeguard-Erweiterung die Zusammenfassung an diesen Anbieter statt an die integrierte Pipeline summarizeInStages.
provider: ID eines registrierten Kompaktierungsanbieter-Plugins. Nicht setzen für Standard-LLM-Zusammenfassung.- Das Setzen von
providererzwingtmode: "safeguard". - Anbieter erhalten dieselben Kompaktierungsanweisungen und dieselbe Richtlinie zur Beibehaltung von Identifikatoren wie der integrierte Pfad.
- Die Safeguard-Funktion bewahrt weiterhin Kontext des Suffixes aktueller Turns und getrennter Turns nach der Anbieterausgabe.
- Wenn der Anbieter fehlschlägt oder ein leeres Ergebnis zurückgibt, fällt OpenClaw automatisch auf die integrierte LLM-Zusammenfassung zurück.
- Abort-/Timeout-Signale werden erneut ausgelöst (nicht unterdrückt), um die Abbruchanforderung des Aufrufers zu respektieren.
src/plugins/compaction-provider.ts, src/agents/pi-hooks/compaction-safeguard.ts.
Für Nutzer sichtbare Oberflächen
Sie können Kompaktierung und Session-Status über Folgendes beobachten:/status(in jeder Chat-Session)openclaw status(CLI)openclaw sessions/sessions --json- Verbose-Modus:
🧹 Auto-compaction complete+ Kompaktierungszähler
Stilles Housekeeping (NO_REPLY)
OpenClaw unterstützt „stille“ Turns für Hintergrundaufgaben, bei denen der Nutzer keine Zwischenausgabe sehen soll.
Konvention:
- Der Assistant beginnt seine Ausgabe mit dem exakten stillen Token
NO_REPLY/no_reply, um „keine Antwort an den Nutzer ausliefern“ anzuzeigen. - OpenClaw entfernt/unterdrückt dies in der Zustellungsschicht.
- Die Unterdrückung des exakten stillen Tokens ist nicht case-sensitive, daher zählen
NO_REPLYundno_replybeide, wenn die gesamte Payload nur aus dem stillen Token besteht. - Dies ist nur für echte Hintergrund-/Nicht-Zustellungs-Turns gedacht; es ist keine Abkürzung für gewöhnliche, umsetzbare Nutzeranfragen.
2026.1.10 unterdrückt OpenClaw außerdem Entwurfs-/Typing-Streaming, wenn ein
partieller Chunk mit NO_REPLY beginnt, damit stille Operationen nicht mitten im Turn
partielle Ausgabe durchsickern lassen.
„Memory Flush“ vor der Kompaktierung (implementiert)
Ziel: Bevor automatische Kompaktierung erfolgt, einen stillen agentischen Turn ausführen, der dauerhaften Status auf den Datenträger schreibt (z. B.memory/YYYY-MM-DD.md im Agent-Workspace), damit die Kompaktierung
kritischen Kontext nicht löschen kann.
OpenClaw verwendet den Ansatz Flush vor dem Schwellwert:
- Überwachen Sie die Nutzung des Session-Kontexts.
- Wenn sie einen „weichen Schwellwert“ überschreitet (unterhalb des Kompaktierungsschwellwerts von Pi), führen Sie eine stille Direktive „write memory now“ für den Agenten aus.
- Verwenden Sie das exakte stille Token
NO_REPLY/no_reply, damit der Nutzer nichts sieht.
agents.defaults.compaction.memoryFlush):
enabled(Standard:true)softThresholdTokens(Standard:4000)prompt(Nutzernachricht für den Flush-Turn)systemPrompt(zusätzlicher System-Prompt, der für den Flush-Turn angehängt wird)
- Der Standard-Prompt/System-Prompt enthält einen
NO_REPLY-Hinweis, um die Zustellung zu unterdrücken. - Der Flush wird einmal pro Kompaktierungszyklus ausgeführt (erfasst in
sessions.json). - Der Flush wird nur für eingebettete Pi-Sessions ausgeführt (CLI-Backends überspringen ihn).
- Der Flush wird übersprungen, wenn der Session-Workspace schreibgeschützt ist (
workspaceAccess: "ro"oder"none"). - Unter Memory finden Sie das Dateilayout des Workspace und die Schreibmuster.
session_before_compact in der Erweiterungs-API bereit, aber die
Flush-Logik von OpenClaw lebt heute auf der Gateway-Seite.
Checkliste zur Fehlerbehebung
- Session-Schlüssel falsch? Beginnen Sie mit /concepts/session und prüfen Sie den
sessionKeyin/status. - Store stimmt nicht mit Transcript überein? Prüfen Sie den Gateway-Host und den Store-Pfad aus
openclaw status. - Kompaktierungs-Spam? Prüfen Sie:
- Kontextfenster des Modells (zu klein)
- Kompaktierungseinstellungen (
reserveTokenszu hoch für das Modellfenster kann frühere Kompaktierung verursachen) - Aufblähung durch Tool-Ergebnisse: Aktivieren/optimieren Sie Session-Pruning
- Stille Turns lecken? Prüfen Sie, ob die Antwort mit
NO_REPLYbeginnt (case-insensitive, exaktes Token) und ob Sie eine Build-Version mit dem Fix zur Streaming-Unterdrückung verwenden.