Session-Management & Kompaktierung (Deep Dive)
Dieses Dokument erläutert, wie OpenClaw Sessions Ende-zu-Ende verwaltet:- Session-Routing (wie eingehende Nachrichten einem
sessionKeyzugeordnet werden) - Session-Store (
sessions.json) und was er erfasst - Transkript-Persistenz (
*.jsonl) und ihre Struktur - Transkript-Hygiene (anbieterspezifische Korrekturen vor Läufen)
- Kontextlimits (Kontextfenster vs. erfasste Tokens)
- Kompaktierung (manuell + Auto-Kompaktierung) und wo Vorarbeiten vor der Kompaktierung einzuhängen sind
- Stilles Housekeeping (z. B. Speicher-Schreibvorgänge, die keine nutzersichtbare Ausgabe erzeugen sollen)
Quelle der Wahrheit: das Gateway
OpenClaw ist um einen einzelnen Gateway-Prozess herum konzipiert, der den Session-Status besitzt.- UIs (macOS-App, Web-Control-UI, TUI) sollten das Gateway nach Session-Listen und Token-Zählungen 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)- Key/Value-Map:
sessionKey -> SessionEntry - Klein, veränderlich, sicher zu bearbeiten (oder Einträge zu löschen)
- Erfasst Session-Metadaten (aktuelle Session-ID, letzte Aktivität, Toggles, Token-Zähler usw.)
- Key/Value-Map:
-
Transkript (
<sessionId>.jsonl)- Append-only-Transkript mit Baumstruktur (Einträge haben
id+parentId) - Speichert die eigentliche Konversation + Tool-Aufrufe + Kompaktierungszusammenfassungen
- Wird verwendet, um den Modellkontext für zukünftige Turns neu aufzubauen
- Append-only-Transkript mit Baumstruktur (Einträge haben
Ablageorte auf Datenträger
Pro Agent, auf dem Gateway-Host:- Store:
~/.openclaw/agents/<agentId>/sessions/sessions.json - Transkripte:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- Telegram-Themen-Sessions:
.../<sessionId>-topic-<threadId>.jsonl
- Telegram-Themen-Sessions:
src/config/sessions.ts auf.
Session-Schlüssel (sessionKey)
Ein sessionKey identifiziert, in welchem Konversations-Bucket Sie sich befinden (Routing + Isolation).
Gängige Muster:
- Haupt-/Direktchat (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 Transkriptdatei, die die Konversation fortsetzt).
Faustregeln:
- Reset (
/new,/reset) erstellt eine neuesessionIdfür diesensessionKey. - Täglicher Reset (Standard 4:00 Uhr Ortszeit auf dem Gateway-Host) erstellt eine neue
sessionIdbei der nächsten Nachricht nach der Reset-Grenze. - Leerlaufablauf (
session.reset.idleMinutesoder legacysession.idleMinutes) erstellt eine neuesessionId, wenn nach dem Leerlauffenster eine Nachricht eintrifft. Wenn täglich + Leerlauf beide konfiguriert sind, gewinnt der zuerst ablaufende.
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 Transkript-ID (Dateiname wird hiervon abgeleitet, sofernsessionFilenicht gesetzt ist)updatedAt: Zeitstempel der letzten AktivitätsessionFile: optionale explizite Überschreibung des TranskriptpfadschatType:direct | group | room(hilft UIs und der Sende-Policy)provider,subject,room,space,displayName: Metadaten für Gruppen-/Kanalbeschriftung- Toggles:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(Override pro Session)
- Modellauswahl:
providerOverride,modelOverride,authProfileOverride
- Token-Zähler (Best-Effort / anbieterabhängig):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: wie oft die Auto-Kompaktierung für diesen Session-Schlüssel abgeschlossen wurdememoryFlushAt: Zeitstempel des letzten Pre-Kompaktions-Memory-FlushmemoryFlushCompactionCount: Kompaktierungszähler beim letzten Flush
Transkriptstruktur (*.jsonl)
Transkripte werden von @mariozechner/pi-coding-agent’s SessionManager 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: user/assistant/toolResult-Nachrichtencustom_message: von Extensions injizierte Nachrichten, die in den Modellkontext eingehen (können in der UI verborgen sein)custom: Extension-Status, der nicht in den Modellkontext eingehtcompaction: persistierte Kompaktierungszusammenfassung mitfirstKeptEntryIdundtokensBeforebranch_summary: persistierte Zusammenfassung beim Navigieren eines Baumzweigs
SessionManager zum Lesen/Schreiben.
Kontextfenster vs. erfasste Tokens
Zwei unterschiedliche Konzepte sind relevant:- Modell-Kontextfenster: harte Obergrenze pro Modell (für das Modell sichtbare Tokens)
- Session-Store-Zähler: rollierende Statistiken, die in
sessions.jsongeschrieben werden (verwendet für /status und Dashboards)
- Das Kontextfenster stammt aus dem Modellkatalog (und kann per Konfiguration überschrieben werden).
contextTokensim Store ist ein Laufzeit-Schätzwert für Reporting; behandeln Sie ihn nicht als strikte Garantie.
Kompaktierung: was sie ist
Kompaktierung fasst ältere Konversationen in einen persistiertencompaction-Eintrag im Transkript zusammen und belässt aktuelle Nachrichten unverändert.
Nach der Kompaktierung sehen zukünftige Turns:
- Die Kompaktierungszusammenfassung
- Nachrichten nach
firstKeptEntryId
Wann Auto-Kompaktierung stattfindet (Pi-Runtime)
Im eingebetteten Pi-Agenten wird die Auto-Kompaktierung in zwei Fällen ausgelöst:- Overflow-Recovery: Das Modell liefert einen Kontext-Overflow-Fehler → komprimieren → erneut versuchen.
- Schwellenwert-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
Kompaktierungseinstellungen (reserveTokens, keepRecentTokens)
Pis Kompaktierungseinstellungen befinden sich in den Pi-Einstellungen:
- Wenn
compaction.reserveTokens < reserveTokensFloor, erhöht OpenClaw diesen. - Standard-Mindestwert sind
20000Tokens. - Setzen Sie
agents.defaults.compaction.reserveTokensFloor: 0, um den Mindestwert zu deaktivieren. - Ist er bereits höher, lässt OpenClaw ihn unverändert.
ensurePiCompactionReserveTokens() in src/agents/pi-settings.ts
(aufgerufen von src/agents/pi-embedded-runner.ts).
Nutzersichtbare Oberflächen
Sie können Kompaktierung und Session-Status beobachten über:/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 Zwischenausgaben sehen soll.
Konvention:
- Der Assistent beginnt seine Ausgabe mit
NO_REPLY, um „keine Antwort an den Nutzer ausliefern“ zu signalisieren. - OpenClaw entfernt/unterdrückt dies in der Auslieferungsschicht.
2026.1.10 unterdrückt OpenClaw außerdem Draft/Typing-Streaming, wenn ein partieller Chunk mit NO_REPLY beginnt, sodass stille Operationen keine Teilausgaben während des Turns preisgeben.
Pre-Kompaktions-„Memory-Flush“ (implementiert)
Ziel: Bevor Auto-Kompaktierung stattfindet, einen stillen agentischen Turn ausführen, der dauerhaften Zustand auf Datenträger schreibt (z. B.memory/YYYY-MM-DD.md im Agent-Workspace), damit Kompaktierung keinen kritischen Kontext löschen kann.
OpenClaw verwendet den Ansatz des Pre-Threshold-Flush:
- Überwachen der Session-Kontextnutzung.
- Beim Überschreiten einer „Soft-Schwelle“ (unterhalb von Pis Kompaktierungsschwelle) einen stillen „Jetzt Speicher schreiben“-Befehl an den Agenten ausführen.
NO_REPLYverwenden, sodass der Nutzer nichts sieht.
agents.defaults.compaction.memoryFlush):
enabled(Standard:true)softThresholdTokens(Standard:4000)prompt(User-Nachricht 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 zur Unterdrückung der Auslieferung. - Der Flush läuft einmal pro Kompaktierungszyklus (nachverfolgt in
sessions.json). - Der Flush läuft nur für eingebettete Pi-Sessions (CLI-Backends überspringen ihn).
- Der Flush wird übersprungen, wenn der Session-Workspace schreibgeschützt ist (
workspaceAccess: "ro"oder"none"). - Siehe Memory für das Layout der Workspace-Dateien und Schreibmuster.
session_before_compact-Hook in der Extension-API bereit, aber OpenClaws
Flush-Logik befindet sich heute auf der Gateway-Seite.
Checkliste zur Fehlerbehebung
- Session-Schlüssel falsch? Beginnen Sie mit /concepts/session und bestätigen Sie den
sessionKeyin/status. - Store vs. Transkript inkonsistent? Bestätigen Sie den Gateway-Host und den Store-Pfad aus
openclaw status. - Kompaktierungs-Spam? Prüfen Sie:
- Modell-Kontextfenster (zu klein)
- Kompaktierungseinstellungen (
reserveTokenszu hoch für das Modellfenster kann frühere Kompaktierung verursachen) - Tool-Result-Aufblähung: Session-Pruning aktivieren/feinjustieren
- Stille Turns lecken? Bestätigen Sie, dass die Antwort mit
NO_REPLY(exaktes Token) beginnt und Sie eine Build-Version mit dem Streaming-Unterdrückungs-Fix verwenden.