Session 管理與壓縮(深度剖析)

本文件說明 OpenClaw 如何端對端管理 session:

  • Session 路由(入站訊息如何對應至 sessionKey
  • Session 儲存sessions.json)及其追蹤的內容
  • 轉錄持久化*.jsonl)及其結構
  • 轉錄衛生(執行前的供應商專屬修正)
  • 上下文限制(上下文視窗 vs 追蹤的 token)
  • 壓縮(手動 + 自動壓縮)以及在哪裡掛載壓縮前的工作
  • 靜默維護(如不應產生使用者可見輸出的記憶體寫入)

若需要較概略的概覽,先從以下開始:


事實來源:Gateway

OpenClaw 圍繞單一 Gateway 行程設計,由其掌管 session 狀態。

  • UI(macOS 應用、web 控制 UI、TUI)應向 Gateway 查詢 session 清單和 token 計數。
  • 在遠端模式下,session 檔案位於遠端主機;「檢查你的本地 Mac 檔案」不會反映 Gateway 的實際使用。

兩層持久化

OpenClaw 以兩層持久化 session:

  1. Session 儲存(sessions.json

    • 鍵值對應:sessionKey -> SessionEntry
    • 精簡、可變、安全可編輯(或刪除項目)
    • 追蹤 session 中繼資料(當前 session id、最後活動、切換、token 計數器等)
  2. 轉錄(<sessionId>.jsonl

    • 僅附加的轉錄,具樹狀結構(項目有 id + parentId
    • 儲存實際的對話 + 工具呼叫 + 壓縮摘要
    • 用於重建未來回合的模型上下文

磁碟位置

逐代理,在 Gateway 主機上:

  • 儲存:~/.openclaw/agents/<agentId>/sessions/sessions.json
  • 轉錄:~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl
    • Telegram 主題 session:.../<sessionId>-topic-<threadId>.jsonl

OpenClaw 透過 src/config/sessions.ts 解析這些。


儲存維護與磁碟控制

Session 持久化有自動維護控制(session.maintenance)用於 sessions.json 和轉錄產出物:

  • modewarn(預設)或 enforce
  • pruneAfter:過期項目的年齡門檻(預設 30d
  • maxEntriessessions.json 的項目上限(預設 500
  • rotateBytes:過大時輪替 sessions.json(預設 10mb
  • resetArchiveRetention*.reset.<timestamp> 轉錄歸檔的保留期限(預設:與 pruneAfter 相同;false 停用清理)
  • maxDiskBytes:選用的 sessions 目錄預算
  • highWaterBytes:清理後的選用目標(預設為 maxDiskBytes80%

磁碟預算清理的強制順序(mode: "enforce"):

  1. 先移除最舊的已歸檔或孤立轉錄產出物。
  2. 若仍超過目標,驅逐最舊的 session 項目及其轉錄檔案。
  3. 持續直到使用量等於或低於 highWaterBytes

mode: "warn" 下,OpenClaw 回報可能的驅逐但不修改儲存/檔案。

按需執行維護:

openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce

Session key(sessionKey

sessionKey 識別_你在哪個對話桶_中(路由 + 隔離)。

常見模式:

  • 主/直接聊天(逐代理):agent:<agentId>:<mainKey>(預設 main
  • 群組:agent:<agentId>:<channel>:group:<id>
  • 房間/頻道(Discord/Slack):agent:<agentId>:<channel>:channel:<id>...:room:<id>
  • Cron:cron:<job.id>
  • Webhook:hook:<uuid>(除非被覆寫)

正規規則記載於 /concepts/session


Session id(sessionId

每個 sessionKey 指向一個當前的 sessionId(繼續對話的轉錄檔案)。

經驗法則:

  • 重置/new/reset)為該 sessionKey 建立新的 sessionId
  • 每日重置(預設 gateway 主機本地時間上午 4:00)在重置邊界後的下一則訊息建立新的 sessionId
  • 閒置過期session.reset.idleMinutes 或舊有 session.idleMinutes)在閒置視窗後收到訊息時建立新的 sessionId。當每日 + 閒置都設定時,先到期的為準。
  • 執行緒父系分叉保護session.parentForkMaxTokens,預設 100000)在父 session 已過大時跳過父轉錄分叉;新執行緒從頭開始。設 0 停用。

實作細節:決定發生在 src/auto-reply/reply/session.tsinitSessionState() 中。


壓縮:是什麼

壓縮將較舊的對話摘要為轉錄中的持久 compaction 項目,並保持近期訊息不變。

壓縮後,未來的回合會看到:

  • 壓縮摘要
  • firstKeptEntryId 之後的訊息

壓縮是持久的(不像 session 裁剪)。參見 /concepts/session-pruning


自動壓縮何時觸發(Pi runtime)

在嵌入式 Pi 代理中,自動壓縮在兩種情況觸發:

  1. 溢位復原:模型回傳上下文溢位錯誤 -> 壓縮 -> 重試。
  2. 閾值維護:成功回合後,當:

contextTokens > contextWindow - reserveTokens

其中:

  • contextWindow 為模型的上下文視窗
  • reserveTokens 為 prompt + 下一次模型輸出保留的空間

這些是 Pi runtime 語義(OpenClaw 消費事件,但 Pi 決定何時壓縮)。


壓縮設定(reserveTokenskeepRecentTokens

Pi 的壓縮設定位於 Pi settings:

{
  compaction: {
    enabled: true,
    reserveTokens: 16384,
    keepRecentTokens: 20000,
  },
}

OpenClaw 也為嵌入式執行強制一個安全下限:

  • compaction.reserveTokens < reserveTokensFloor,OpenClaw 提升它。
  • 預設下限為 20000 token。
  • 設定 agents.defaults.compaction.reserveTokensFloor: 0 停用下限。
  • 若已較高,OpenClaw 不做更改。

原因:為壓縮不可避免前的多回合「維護」(如記憶體寫入)留足夠空間。

實作:src/agents/pi-settings.ts 中的 ensurePiCompactionReserveTokens()(從 src/agents/pi-embedded-runner.ts 呼叫)。


使用者可見的介面

可透過以下觀察壓縮和 session 狀態:

  • /status(在任何聊天 session 中)
  • openclaw status(CLI)
  • openclaw sessions / sessions --json
  • 詳細模式:Auto-compaction complete + 壓縮計數

靜默維護(NO_REPLY

OpenClaw 支援背景任務的「靜默」回合,使用者不應看到中間輸出。

慣例:

  • 助理以 NO_REPLY 開始其輸出,表示「不要將回覆投遞給使用者」。
  • OpenClaw 在投遞層去除/抑制此內容。

2026.1.10 起,當部分區塊以 NO_REPLY 開始時,OpenClaw 也會抑制草稿/打字串流,避免靜默操作在回合中洩漏部分輸出。


壓縮前「記憶體刷寫」(已實作)

目標:在自動壓縮發生前,執行一個靜默的代理回合,將持久狀態寫入磁碟(如代理工作區中的 memory/YYYY-MM-DD.md),讓壓縮不會抹除關鍵上下文。

OpenClaw 使用預閾值刷寫方式:

  1. 監控 session 上下文使用量。
  2. 當超過「軟閾值」(低於 Pi 的壓縮閾值)時,向代理執行靜默的「現在寫入記憶體」指示。
  3. 使用 NO_REPLY 讓使用者看不到。

設定(agents.defaults.compaction.memoryFlush):

  • enabled(預設:true
  • softThresholdTokens(預設:4000
  • prompt(刷寫回合的使用者訊息)
  • systemPrompt(刷寫回合附加的額外系統 prompt)

說明:

  • 預設 prompt/系統 prompt 包含 NO_REPLY 提示以抑制投遞。
  • 每個壓縮週期僅刷寫一次(在 sessions.json 中追蹤)。
  • 僅對嵌入式 Pi session 執行(CLI 後端跳過)。
  • 工作區為唯讀(workspaceAccess: "ro""none")時跳過。
  • 工作區檔案佈局和寫入模式參見 記憶體

Pi 在擴充 API 中也提供 session_before_compact 掛鉤,但 OpenClaw 的刷寫邏輯目前位於 Gateway 側。


故障排除檢查清單

  • Session key 不對?從 /concepts/session 開始,在 /status 中確認 sessionKey
  • 儲存與轉錄不一致?確認 Gateway 主機和 openclaw status 中的儲存路徑。
  • 壓縮過頻?檢查:
    • 模型上下文視窗(太小)
    • 壓縮設定(reserveTokens 對模型視窗來說太高可能導致較早壓縮)
    • 工具結果膨脹:啟用/調校 session 裁剪
  • 靜默回合洩漏?確認回覆以 NO_REPLY(精確 token)開始,且使用包含串流抑制修復的版本。