Session 管理
OpenClaw 將每個 Agent 的一個直接對話 Session 視為主要 Session。直接對話會收斂到 agent:<agentId>:<mainKey>(預設為 main),而群組/頻道對話則各自擁有獨立的 Key。session.mainKey 會被採用。
透過 session.dmScope 控制私訊的分組方式:
main(預設):所有私訊共享主要 Session,維持對話連貫性。per-peer:依發送者 ID 跨頻道隔離。per-channel-peer:依頻道 + 發送者隔離(多使用者收件匣建議使用)。per-account-channel-peer:依帳號 + 頻道 + 發送者隔離(多帳號收件匣建議使用)。 使用session.identityLinks可將帶有供應商前綴的 Peer ID 對應到統一身分,讓同一個人在不同頻道之間共享私訊 Session(適用於per-peer、per-channel-peer或per-account-channel-peer)。
安全私訊模式(多使用者環境建議啟用)
安全警告: 如果你的 Agent 可能接收來自多人的私訊,強烈建議啟用安全私訊模式。否則所有使用者共享同一對話上下文,可能導致私人資訊在使用者之間外洩。
預設設定下的問題範例:
- Alice(
<SENDER_A>)傳訊給你的 Agent 談論私人話題(例如看診預約) - Bob(
<SENDER_B>)傳訊給你的 Agent 問「我們剛才在聊什麼?」 - 因為兩則私訊共享同一 Session,模型可能用 Alice 的對話上下文來回答 Bob
解決方式: 設定 dmScope 來隔離每位使用者的 Session:
// ~/.openclaw/openclaw.json
{
session: {
// 安全私訊模式:依頻道 + 發送者隔離私訊上下文。
dmScope: "per-channel-peer",
},
}
何時應該啟用:
- 你核准了不止一位發送者的配對
- 你的私訊允許清單有多筆項目
- 你設定了
dmPolicy: "open" - 有多支電話號碼或帳號可以傳訊給你的 Agent
注意事項:
- 預設為
dmScope: "main"以維持連貫性(所有私訊共享主要 Session)。單一使用者環境下這樣就夠了。 - 本機 CLI 初始化設定在未設定時會預設寫入
session.dmScope: "per-channel-peer"(已有明確設定值的會保留)。 - 同一頻道上的多帳號收件匣,建議使用
per-account-channel-peer。 - 如果同一個人透過不同頻道聯絡你,使用
session.identityLinks可將其私訊 Session 收斂到統一身分。 - 你可以用
openclaw security audit驗證私訊設定(參閱 security)。
Gateway 是唯一真實來源
所有 Session 狀態歸 Gateway 所有(即「主控」OpenClaw)。UI 用戶端(macOS App、WebChat 等)必須向 Gateway 查詢 Session 清單和 Token 計數,而非讀取本地檔案。
- 在遠端模式下,你關心的 Session Store 存在於遠端 Gateway 主機上,而不是你的 Mac。
- UI 中顯示的 Token 計數來自 Gateway Store 的欄位(
inputTokens、outputTokens、totalTokens、contextTokens)。用戶端不會自行解析 JSONL 對話記錄來「修正」總數。
狀態存放位置
- 在 Gateway 主機上:
- Store 檔案:
~/.openclaw/agents/<agentId>/sessions/sessions.json(每個 Agent 各一)。
- Store 檔案:
- 對話記錄:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(Telegram 主題 Session 使用.../<SessionId>-topic-<threadId>.jsonl)。 - Store 是一個
sessionKey -> { sessionId, updatedAt, ... }的 Map。刪除項目是安全的,下次訊息到達時會自動重建。 - 群組項目可能包含
displayName、channel、subject、room和space,用於在 UI 中標示 Session。 - Session 項目包含
origin後設資料(標籤 + 路由提示),讓 UI 能解釋 Session 的來源。 - OpenClaw 不會讀取舊版 Pi/Tau Session 資料夾。
維護
OpenClaw 會對 Session Store 進行維護,讓 sessions.json 和對話記錄等檔案在長期使用後維持合理的大小。
預設值
session.maintenance.mode:warnsession.maintenance.pruneAfter:30dsession.maintenance.maxEntries:500session.maintenance.rotateBytes:10mbsession.maintenance.resetArchiveRetention: 預設與pruneAfter相同(30d)session.maintenance.maxDiskBytes: 未設定(停用)session.maintenance.highWaterBytes: 啟用預算時預設為maxDiskBytes的80%
運作方式
維護在 Session Store 寫入時執行,也可用 openclaw sessions cleanup 手動觸發。
mode: "warn":報告哪些項目會被清除,但不會實際修改項目或對話記錄。mode: "enforce":依以下順序執行清理:- 清除超過
pruneAfter的過期項目 - 將項目數限制在
maxEntries(從最舊的開始) - 對已移除且不再被參照的項目,封存其對話記錄檔案
- 依保留策略清除舊的
*.deleted.<timestamp>和*.reset.<timestamp>封存檔 - 當
sessions.json超過rotateBytes時進行輪替 - 若設定了
maxDiskBytes,向highWaterBytes目標強制執行磁碟預算(從最舊的產出物開始,然後是最舊的 Session)
- 清除超過
大型 Store 的效能注意事項
高流量環境中常見大型 Session Store。維護工作屬於寫入路徑的工作,因此非常大的 Store 可能增加寫入延遲。
最影響成本的因素:
- 非常高的
session.maintenance.maxEntries值 - 過長的
pruneAfter期間讓過期項目持續存在 ~/.openclaw/agents/<agentId>/sessions/中存在大量對話記錄/封存產出物- 啟用磁碟預算(
maxDiskBytes)但未設定合理的修剪/上限值
建議做法:
- 正式環境使用
mode: "enforce",讓增長自動受限 - 同時設定時間和數量限制(
pruneAfter+maxEntries),不要只設一個 - 大型部署設定
maxDiskBytes+highWaterBytes作為硬上限 highWaterBytes應明顯低於maxDiskBytes(預設為 80%)- 修改設定後執行
openclaw sessions cleanup --dry-run --json來驗證預期影響 - 若有頻繁使用中的 Session,手動清理時加上
--active-key
自訂範例
使用保守的強制策略:
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "45d",
maxEntries: 800,
rotateBytes: "20mb",
resetArchiveRetention: "14d",
},
},
}
為 Sessions 目錄啟用硬性磁碟預算:
{
session: {
maintenance: {
mode: "enforce",
maxDiskBytes: "1gb",
highWaterBytes: "800mb",
},
},
}
針對較大規模安裝進行調校(範例):
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "14d",
maxEntries: 2000,
rotateBytes: "25mb",
maxDiskBytes: "2gb",
highWaterBytes: "1.6gb",
},
},
}
從 CLI 預覽或強制執行維護:
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce
Session 修剪
OpenClaw 預設會在每次 LLM 呼叫前,從記憶體中的上下文裁減舊的工具結果。 這不會改寫 JSONL 歷史紀錄。參閱 /concepts/session-pruning。
壓縮前的記憶刷寫
當 Session 接近自動壓縮時,OpenClaw 可以執行一輪靜默的記憶刷寫,提醒模型將重要筆記寫入磁碟。這只有在 Workspace 可寫時才會執行。參閱 Memory 和 Compaction。
傳輸層 → Session Key 的對應
- 直接對話遵循
session.dmScope(預設main)。main:agent:<agentId>:<mainKey>(跨裝置/頻道的連貫性)。- 多支電話號碼和多個頻道可對應到同一個 Agent Main Key;它們充當同一對話的傳輸層。
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 預設為default)。- 如果
session.identityLinks比對到帶有供應商前綴的 Peer ID(例如telegram:123),統一 Key 會取代<peerId>,讓同一個人跨頻道共享 Session。
- 群組對話隔離狀態:
agent:<agentId>:<channel>:group:<id>(頻道用agent:<agentId>:<channel>:channel:<id>)。- Telegram 論壇主題會在群組 ID 後加上
:topic:<threadId>進行隔離。 - 舊版
group:<id>Key 仍可識別,用於遷移。
- Telegram 論壇主題會在群組 ID 後加上
- 收到的上下文可能仍使用
group:<id>;頻道從Provider推斷並正規化為標準的agent:<agentId>:<channel>:group:<id>格式。 - 其他來源:
- Cron 工作:
cron:<job.id> - Webhook:
hook:<uuid>(除非 Hook 有明確設定) - Node 執行:
node-<nodeId>
- Cron 工作:
生命週期
- 重設策略:Session 持續使用直到過期,到期判定在下一則收到的訊息時進行。
- 每日重設:預設為 Gateway 主機當地時間凌晨 4:00。Session 的最後更新早於最近一次每日重設時間時即視為過期。
- 閒置重設(選用):
idleMinutes提供一個滑動閒置時間窗。同時設定每日和閒置重設時,先到期的那個會強制產生新 Session。 - 舊版閒置模式:如果你設定了
session.idleMinutes但沒有任何session.reset/resetByType設定,OpenClaw 會維持純閒置模式以向後相容。 - 依類型覆蓋(選用):
resetByType可針對direct、group和threadSession 分別覆蓋策略(thread = Slack/Discord 討論串、Telegram 主題、連接器提供的 Matrix 討論串)。 - 依頻道覆蓋(選用):
resetByChannel覆蓋特定頻道的重設策略(適用於該頻道的所有 Session 類型,優先於reset/resetByType)。 - 重設觸發:確切的
/new或/reset(加上resetTriggers中的額外觸發字串)會啟動新的 Session ID 並將訊息的其餘部分傳遞下去。/new <model>接受模型別名、provider/model或供應商名稱(模糊比對)來設定新 Session 的模型。若單獨送出/new或/reset,OpenClaw 會執行一個簡短的「hello」問候回合來確認重設。 - 手動重設:從 Store 中刪除特定 Key 或移除 JSONL 對話記錄;下次訊息會自動重建。
- 隔離的 Cron 工作每次執行都會產生全新的
sessionId(不會重用閒置 Session)。
傳送策略(選用)
針對特定 Session 類型阻擋投遞,無需逐一列出個別 ID。
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } },
// 比對原始 Session Key(含 `agent:<id>:` 前綴)。
{ action: "deny", match: { rawKeyPrefix: "agent:main:discord:" } },
],
default: "allow",
},
},
}
執行期間覆蓋(僅限擁有者):
/send on→ 允許此 Session/send off→ 拒絕此 Session/send inherit→ 清除覆蓋設定,使用設定規則 以獨立訊息送出以確保生效。
設定(選用重新命名範例)
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // 群組 Key 保持獨立
dmScope: "main", // 私訊連貫性(共用收件匣請設定 per-channel-peer/per-account-channel-peer)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"],
},
reset: {
// 預設:mode=daily, atHour=4(Gateway 主機當地時間)。
// 若同時設定 idleMinutes,先到期的那個生效。
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",
},
}
查看資訊
openclaw status— 顯示 Store 路徑和近期 Session。openclaw sessions --json— 匯出所有項目(可用--active <minutes>篩選)。openclaw gateway call sessions.list --params '{}'— 從運行中的 Gateway 取得 Session(遠端 Gateway 請使用--url/--token)。- 在對話中以獨立訊息送出
/status可查看 Agent 是否可達、Session 上下文使用量、當前的 thinking/fast/verbose 切換狀態,以及 WhatsApp web 憑證上次刷新時間(有助於察覺需要重新連結)。 - 送出
/context list或/context detail可查看系統提示詞和注入的 Workspace 檔案內容(以及最大的上下文貢獻者)。 - 送出
/stop(或獨立中止短語如stop、stop action、stop run、stop openclaw)可中止當前執行、清除該 Session 排隊中的後續處理,並停止由此 spawn 出的子 Agent 執行(回覆中會包含已停止的數量)。 - 以獨立訊息送出
/compact(可選說明)可摘要較舊的上下文並釋放視窗空間。參閱 /concepts/compaction。 - JSONL 對話記錄可直接開啟以檢視完整回合。
使用技巧
- 主要 Key 專供一對一對話使用;讓群組保有各自的 Key。
- 自動化清理時,刪除個別 Key 而非整個 Store,以保留其他地方的上下文。
Session 來源後設資料
每個 Session 項目會記錄它的來源(盡力而為)到 origin:
label:人類可讀標籤(從對話標籤 + 群組主題/頻道推導)provider:正規化的頻道 ID(含擴充套件)from/to:來自收到信封的原始路由 IDaccountId:供應商帳號 ID(多帳號時)threadId:頻道支援時的討論串/主題 ID 來源欄位會為私訊、頻道和群組填入。如果連接器只更新投遞路由(例如保持私訊主要 Session 的新鮮度),仍應提供收到的上下文以維護 Session 的說明性後設資料。擴充套件可透過在收到的上下文中傳送ConversationLabel、GroupSubject、GroupChannel、GroupSpace和SenderName,並呼叫recordSessionMetaFromInbound(或將同樣的上下文傳給updateLastRoute)來實現。