Session-Verwaltung
OpenClaw behandelt eine Direktchat-Session pro Agent als primaer. Direktchats werden auf agent:<agentId>:<mainKey> (Standard main) zusammengefuehrt, waehrend Gruppen-/Kanal-Chats eigene Keys bekommen. session.mainKey wird beruecksichtigt.
Nutze session.dmScope, um zu steuern, wie Direktnachrichten gruppiert werden:
main(Standard): Alle DMs teilen sich die Hauptsession fuer Kontinuitaet.per-peer: Isolation nach Absender-ID kanaluebergreifend.per-channel-peer: Isolation nach Kanal + Absender (empfohlen fuer Multi-User-Posteingaenge).per-account-channel-peer: Isolation nach Account + Kanal + Absender (empfohlen fuer Multi-Account-Posteingaenge). Nutzesession.identityLinks, um provider-praefixierte Peer-IDs auf eine kanonische Identitaet abzubilden, damit dieselbe Person beiper-peer,per-channel-peeroderper-account-channel-peerkanaluebergreifend eine DM-Session teilt.
Sicherer DM-Modus (empfohlen fuer Multi-User-Setups)
Sicherheitswarnung: Wenn dein Agent DMs von mehreren Personen empfangen kann, solltest du dringend den sicheren DM-Modus aktivieren. Ohne ihn teilen sich alle Nutzer denselben Gespraechskontext, was private Informationen zwischen Nutzern leaken kann.
Beispiel des Problems mit Standardeinstellungen:
- Alice (
<SENDER_A>) schreibt deinem Agent ueber ein privates Thema (zum Beispiel einen Arzttermin) - Bob (
<SENDER_B>) schreibt deinem Agent “Worueber haben wir geredet?” - Weil beide DMs dieselbe Session teilen, antwortet das Modell Bob moeglicherweise mit Alices Kontext.
Die Loesung: Setze dmScope, um Sessions pro Nutzer zu isolieren:
// ~/.openclaw/openclaw.json
{
session: {
// Sicherer DM-Modus: DM-Kontext pro Kanal + Absender isolieren.
dmScope: "per-channel-peer",
},
}
Wann du das aktivieren solltest:
- Du hast Pairing-Genehmigungen fuer mehr als einen Absender
- Du nutzt eine DM-Allowlist mit mehreren Eintraegen
- Du hast
dmPolicy: "open"gesetzt - Mehrere Telefonnummern oder Accounts koennen deinem Agent schreiben
Hinweise:
- Standard ist
dmScope: "main"fuer Kontinuitaet (alle DMs teilen die Hauptsession). Das ist fuer Single-User-Setups in Ordnung. - Lokales CLI-Onboarding schreibt
session.dmScope: "per-channel-peer"als Standard, wenn nicht gesetzt (bestehende explizite Werte bleiben erhalten). - Fuer Multi-Account-Posteingaenge auf demselben Kanal bevorzuge
per-account-channel-peer. - Wenn dieselbe Person dich ueber mehrere Kanaele kontaktiert, nutze
session.identityLinks, um deren DM-Sessions in eine kanonische Identitaet zusammenzufuehren. - Du kannst deine DM-Einstellungen mit
openclaw security auditueberpruefen (siehe security).
Das Gateway ist die Wahrheitsquelle
Alle Session-Zustaende gehoeren dem Gateway (dem “Master”-OpenClaw). UI-Clients (macOS-App, WebChat usw.) muessen das Gateway fuer Session-Listen und Token-Zaehler abfragen, statt lokale Dateien zu lesen.
- Im Remote-Modus lebt der relevante Session-Store auf dem Remote-Gateway-Host, nicht auf deinem Mac.
- Token-Zaehler in UIs stammen aus den Store-Feldern des Gateways (
inputTokens,outputTokens,totalTokens,contextTokens). Clients parsen keine JSONL-Transkripte, um Summen zu “korrigieren”.
Wo der Zustand lebt
- Auf dem Gateway-Host:
- Store-Datei:
~/.openclaw/agents/<agentId>/sessions/sessions.json(pro Agent).
- Store-Datei:
- Transkripte:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(Telegram-Topic-Sessions nutzen.../<SessionId>-topic-<threadId>.jsonl). - Der Store ist eine Map
sessionKey -> { sessionId, updatedAt, ... }. Eintraege zu loeschen ist sicher; sie werden bei Bedarf neu erstellt. - Gruppeneintraege koennen
displayName,channel,subject,roomundspaceenthalten, um Sessions in UIs zu beschriften. - Session-Eintraege enthalten
origin-Metadaten (Label + Routing-Hinweise), damit UIs erklaeren koennen, woher eine Session stammt. - OpenClaw liest keine Legacy-Pi/Tau-Session-Ordner.
Wartung
OpenClaw wendet Session-Store-Wartung an, um sessions.json und Transkript-Artefakte ueber die Zeit begrenzt zu halten.
Standardwerte
session.maintenance.mode:warnsession.maintenance.pruneAfter:30dsession.maintenance.maxEntries:500session.maintenance.rotateBytes:10mbsession.maintenance.resetArchiveRetention: Standard istpruneAfter(30d)session.maintenance.maxDiskBytes: nicht gesetzt (deaktiviert)session.maintenance.highWaterBytes: Standard ist80%vonmaxDiskBytes, wenn Budgetierung aktiviert ist
So funktioniert es
Wartung laeuft waehrend Session-Store-Schreibvorgaengen, und du kannst sie bei Bedarf mit openclaw sessions cleanup ausloesen.
mode: "warn": meldet, was bereinigt werden wuerde, veraendert aber keine Eintraege/Transkripte.mode: "enforce": wendet die Bereinigung in dieser Reihenfolge an:- veraltete Eintraege aelter als
pruneAfterbereinigen - Eintragsanzahl auf
maxEntriesbegrenzen (aelteste zuerst) - Transkript-Dateien fuer entfernte Eintraege archivieren, die nicht mehr referenziert werden
- alte
*.deleted.<timestamp>- und*.reset.<timestamp>-Archive nach Aufbewahrungsrichtlinie bereinigen sessions.jsonrotieren, wenn sierotateBytesueberschreitet- wenn
maxDiskBytesgesetzt ist, Disk-Budget bishighWaterBytesdurchsetzen (aelteste Artefakte zuerst, dann aelteste Sessions)
- veraltete Eintraege aelter als
Performance-Hinweis fuer grosse Stores
Grosse Session-Stores sind bei High-Volume-Setups ueblich. Wartungsarbeit ist Write-Path-Arbeit, sodass sehr grosse Stores die Schreib-Latenz erhoehen koennen.
Was die Kosten am meisten erhoet:
- sehr hohe
session.maintenance.maxEntries-Werte - lange
pruneAfter-Fenster, die veraltete Eintraege am Leben halten - viele Transkript-/Archiv-Artefakte in
~/.openclaw/agents/<agentId>/sessions/ - Disk-Budgets (
maxDiskBytes) aktivieren ohne vernuenftige Pruning-/Cap-Limits
Was du tun kannst:
mode: "enforce"im Produktivbetrieb nutzen, damit das Wachstum automatisch begrenzt ist- sowohl Zeit- als auch Anzahl-Limits setzen (
pruneAfter+maxEntries), nicht nur eins von beiden maxDiskBytes+highWaterBytesfuer harte Obergrenzen in grossen Deployments setzenhighWaterBytesdeutlich untermaxDiskByteshalten (Standard: 80%)openclaw sessions cleanup --dry-run --jsonnach Config-Aenderungen ausfuehren, um die prognostizierten Auswirkungen zu pruefen, bevor du durchsetzt- bei haeufig aktiven Sessions
--active-keybei manueller Bereinigung uebergeben
Beispiele
Konservative Enforce-Richtlinie:
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "45d",
maxEntries: 800,
rotateBytes: "20mb",
resetArchiveRetention: "14d",
},
},
}
Hartes Disk-Budget fuer das Sessions-Verzeichnis:
{
session: {
maintenance: {
mode: "enforce",
maxDiskBytes: "1gb",
highWaterBytes: "800mb",
},
},
}
Fuer groessere Installationen optimieren (Beispiel):
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "14d",
maxEntries: 2000,
rotateBytes: "25mb",
maxDiskBytes: "2gb",
highWaterBytes: "1.6gb",
},
},
}
Wartung per CLI pruefen oder erzwingen:
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce
Session-Pruning
OpenClaw kuerzt standardmaessig alte Tool-Ergebnisse im In-Memory-Kontext direkt vor LLM-Aufrufen. Das veraendert nicht die JSONL-Historie. Siehe /concepts/session-pruning.
Pre-Compaction Memory Flush
Wenn eine Session sich der Auto-Kompaktierung naehert, kann OpenClaw eine stille Memory-Flush-Runde ausfuehren, die das Modell daran erinnert, dauerhafte Notizen auf die Festplatte zu schreiben. Das laeuft nur, wenn der Workspace beschreibbar ist. Siehe Memory und Compaction.
Zuordnung von Transporten zu Session-Keys
- Direktchats folgen
session.dmScope(Standardmain).main:agent:<agentId>:<mainKey>(Kontinuitaet ueber Geraete/Kanaele).- Mehrere Telefonnummern und Kanaele koennen auf denselben Agent-Main-Key abgebildet werden; sie fungieren als Transporte in eine Konversation.
per-peer:agent:<agentId>:direct:<peerId>.per-channel-peer:agent:<agentId>:<channel>:direct:<peerId>.per-account-channel-peer:agent:<agentId>:<channel>:<accountId>:direct:<peerId>(accountId ist standardmaessigdefault).- Wenn
session.identityLinkseine provider-praefixierte Peer-ID matched (zum Beispieltelegram:123), ersetzt der kanonische Key<peerId>, sodass dieselbe Person kanaluebergreifend eine Session teilt.
- Gruppenchats isolieren den Zustand:
agent:<agentId>:<channel>:group:<id>(Raeume/Kanaele nutzenagent:<agentId>:<channel>:channel:<id>).- Telegram-Forum-Themen haengen
:topic:<threadId>an die Gruppen-ID fuer Isolation an. - Legacy-
group:<id>-Keys werden weiterhin fuer die Migration erkannt.
- Telegram-Forum-Themen haengen
- Eingehende Kontexte koennen weiterhin
group:<id>nutzen; der Kanal wird ausProviderabgeleitet und in die kanonischeagent:<agentId>:<channel>:group:<id>-Form normalisiert. - Andere Quellen:
- Cron-Jobs:
cron:<job.id> - Webhooks:
hook:<uuid>(sofern nicht explizit vom Hook gesetzt) - Node-Laeufe:
node-<nodeId>
- Cron-Jobs:
Lebenszyklus
- Reset-Richtlinie: Sessions werden wiederverwendet, bis sie ablaufen, und der Ablauf wird bei der naechsten eingehenden Nachricht geprueft.
- Taeglicher Reset: Standard ist 4:00 Uhr Ortszeit auf dem Gateway-Host. Eine Session gilt als veraltet, sobald ihre letzte Aktualisierung vor dem letzten taeglichen Reset-Zeitpunkt liegt.
- Idle-Reset (optional):
idleMinutesfuegt ein gleitendes Idle-Fenster hinzu. Wenn sowohl taeglicher als auch Idle-Reset konfiguriert sind, erzwingt der zuerst ablaufende eine neue Session. - Legacy Idle-only: Wenn du
session.idleMinutesohnesession.reset/resetByType-Config setzt, bleibt OpenClaw aus Gruenden der Abwaertskompatibilitaet im Idle-only-Modus. - Pro-Typ-Overrides (optional):
resetByTypeerlaubt das Ueberschreiben der Richtlinie fuerdirect-,group- undthread-Sessions (Thread = Slack/Discord-Threads, Telegram-Themen, Matrix-Threads, wenn vom Connector bereitgestellt). - Pro-Kanal-Overrides (optional):
resetByChannelueberschreibt die Reset-Richtlinie fuer einen Kanal (gilt fuer alle Session-Typen dieses Kanals und hat Vorrang vorreset/resetByType). - Reset-Trigger: exaktes
/newoder/reset(plus Extras inresetTriggers) starten eine neue Session-ID und leiten den Rest der Nachricht weiter./new <model>akzeptiert einen Model-Alias,provider/modeloder Provider-Namen (Fuzzy-Match) zum Setzen des neuen Session-Modells. Wenn/newoder/resetallein gesendet wird, fuehrt OpenClaw eine kurze “Hallo”-Begruessungsrunde aus, um den Reset zu bestaetigen. - Manueller Reset: bestimmte Keys aus dem Store loeschen oder das JSONL-Transkript entfernen; die naechste Nachricht erstellt sie neu.
- Isolierte Cron-Jobs erzeugen immer eine neue
sessionIdpro Lauf (keine Idle-Wiederverwendung).
Send Policy (optional)
Zustellung fuer bestimmte Session-Typen blockieren, ohne einzelne IDs auflisten zu muessen.
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } },
// Den rohen Session-Key matchen (einschliesslich des `agent:<id>:`-Praefixes).
{ action: "deny", match: { rawKeyPrefix: "agent:main:discord:" } },
],
default: "allow",
},
},
}
Runtime-Override (nur Owner):
/send on— fuer diese Session erlauben/send off— fuer diese Session verweigern/send inherit— Override loeschen und Config-Regeln verwenden Sende diese als eigenstaendige Nachrichten, damit sie registriert werden.
Konfiguration (optionales Umbenennungsbeispiel)
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // Gruppen-Keys separat halten
dmScope: "main", // DM-Kontinuitaet (fuer Shared Inboxes per-channel-peer/per-account-channel-peer setzen)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"],
},
reset: {
// Standards: mode=daily, atHour=4 (Gateway-Host-Ortszeit).
// Wenn du zusaetzlich idleMinutes setzt, gewinnt der zuerst ablaufende.
mode: "daily",
atHour: 4,
idleMinutes: 120,
},
resetByType: {
thread: { mode: "daily", atHour: 4 },
direct: { mode: "idle", idleMinutes: 240 },
group: { mode: "idle", idleMinutes: 120 },
},
resetByChannel: {
discord: { mode: "idle", idleMinutes: 10080 },
},
resetTriggers: ["/new", "/reset"],
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
mainKey: "main",
},
}
Inspektion
openclaw status— zeigt Store-Pfad und aktuelle Sessions.openclaw sessions --json— gibt jeden Eintrag aus (filtern mit--active <minutes>).openclaw gateway call sessions.list --params '{}'— Sessions vom laufenden Gateway abrufen (nutze--url/--tokenfuer Remote-Gateway-Zugriff).- Sende
/statusals eigenstaendige Nachricht im Chat, um zu sehen, ob der Agent erreichbar ist, wie viel des Session-Kontexts belegt ist, aktuelle Thinking/Fast/Verbose-Toggles und wann deine WhatsApp-Web-Credentials zuletzt aktualisiert wurden (hilft bei der Erkennung, wann ein Relink noetig ist). - Sende
/context listoder/context detail, um zu sehen, was im System-Prompt und den injizierten Workspace-Dateien steckt (und die groessten Kontext-Verbraucher). - Sende
/stop(oder eigenstaendige Abbruchphrasen wiestop,stop action,stop run,stop openclaw), um den aktuellen Lauf abzubrechen, eingereihte Followups fuer diese Session zu loeschen und Sub-Agent-Laeufe zu stoppen, die davon gestartet wurden (die Antwort enthaelt die Anzahl gestoppter Laeufe). - Sende
/compact(optionale Anweisungen) als eigenstaendige Nachricht, um aelteren Kontext zusammenzufassen und Fensterplatz freizugeben. Siehe /concepts/compaction. - JSONL-Transkripte koennen direkt geoeffnet werden, um vollstaendige Runden zu pruefen.
Tipps
- Halte den primaeren Key fuer 1:1-Traffic reserviert; lass Gruppen ihre eigenen Keys behalten.
- Wenn du Bereinigung automatisierst, loesche einzelne Keys statt den ganzen Store, um Kontext anderswo zu erhalten.
Session-Origin-Metadaten
Jeder Session-Eintrag zeichnet auf, woher er stammt (Best-Effort) in origin:
label: menschenlesbares Label (aufgeloest aus Gespraechslabel + Gruppenbetreff/Kanal)provider: normalisierte Kanal-ID (einschliesslich Erweiterungen)from/to: Roh-Routing-IDs aus dem eingehenden EnvelopeaccountId: Provider-Account-ID (bei Multi-Account)threadId: Thread-/Topic-ID, wenn der Kanal sie unterstuetzt Die Origin-Felder werden fuer Direktnachrichten, Kanaele und Gruppen befuellt. Wenn ein Connector nur das Delivery-Routing aktualisiert (zum Beispiel um eine DM-Hauptsession aktuell zu halten), sollte er trotzdem eingehenden Kontext liefern, damit die Session ihre Erklaerungsmetadaten behaelt. Erweiterungen koennen das tun, indem sieConversationLabel,GroupSubject,GroupChannel,GroupSpaceundSenderNameim eingehenden Kontext senden undrecordSessionMetaFromInboundaufrufen (oder denselben Kontext anupdateLastRouteuebergeben).