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:
-
Session 儲存(
sessions.json)- 鍵值對應:
sessionKey -> SessionEntry - 精簡、可變、安全可編輯(或刪除項目)
- 追蹤 session 中繼資料(當前 session id、最後活動、切換、token 計數器等)
- 鍵值對應:
-
轉錄(
<sessionId>.jsonl)- 僅附加的轉錄,具樹狀結構(項目有
id+parentId) - 儲存實際的對話 + 工具呼叫 + 壓縮摘要
- 用於重建未來回合的模型上下文
- 僅附加的轉錄,具樹狀結構(項目有
磁碟位置
逐代理,在 Gateway 主機上:
- 儲存:
~/.openclaw/agents/<agentId>/sessions/sessions.json - 轉錄:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- Telegram 主題 session:
.../<sessionId>-topic-<threadId>.jsonl
- Telegram 主題 session:
OpenClaw 透過 src/config/sessions.ts 解析這些。
儲存維護與磁碟控制
Session 持久化有自動維護控制(session.maintenance)用於 sessions.json 和轉錄產出物:
mode:warn(預設)或enforcepruneAfter:過期項目的年齡門檻(預設30d)maxEntries:sessions.json的項目上限(預設500)rotateBytes:過大時輪替sessions.json(預設10mb)resetArchiveRetention:*.reset.<timestamp>轉錄歸檔的保留期限(預設:與pruneAfter相同;false停用清理)maxDiskBytes:選用的 sessions 目錄預算highWaterBytes:清理後的選用目標(預設為maxDiskBytes的80%)
磁碟預算清理的強制順序(mode: "enforce"):
- 先移除最舊的已歸檔或孤立轉錄產出物。
- 若仍超過目標,驅逐最舊的 session 項目及其轉錄檔案。
- 持續直到使用量等於或低於
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.ts 的 initSessionState() 中。
壓縮:是什麼
壓縮將較舊的對話摘要為轉錄中的持久 compaction 項目,並保持近期訊息不變。
壓縮後,未來的回合會看到:
- 壓縮摘要
firstKeptEntryId之後的訊息
壓縮是持久的(不像 session 裁剪)。參見 /concepts/session-pruning。
自動壓縮何時觸發(Pi runtime)
在嵌入式 Pi 代理中,自動壓縮在兩種情況觸發:
- 溢位復原:模型回傳上下文溢位錯誤 -> 壓縮 -> 重試。
- 閾值維護:成功回合後,當:
contextTokens > contextWindow - reserveTokens
其中:
contextWindow為模型的上下文視窗reserveTokens為 prompt + 下一次模型輸出保留的空間
這些是 Pi runtime 語義(OpenClaw 消費事件,但 Pi 決定何時壓縮)。
壓縮設定(reserveTokens、keepRecentTokens)
Pi 的壓縮設定位於 Pi settings:
{
compaction: {
enabled: true,
reserveTokens: 16384,
keepRecentTokens: 20000,
},
}
OpenClaw 也為嵌入式執行強制一個安全下限:
- 若
compaction.reserveTokens < reserveTokensFloor,OpenClaw 提升它。 - 預設下限為
20000token。 - 設定
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 使用預閾值刷寫方式:
- 監控 session 上下文使用量。
- 當超過「軟閾值」(低於 Pi 的壓縮閾值)時,向代理執行靜默的「現在寫入記憶體」指示。
- 使用
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)開始,且使用包含串流抑制修復的版本。