08 · Session 與心跳:時間如何進入 Agent
解釋 OpenClaw 的 Session、Heartbeat、Cron、Webhooks 與 Tasks:誰負責上下文,誰負責定時,誰只做臺賬。
前面幾章已經說明了 Agent 的空間結構:Workspace 放人格和工作檔案,Gateway 接訊息,Session 承載當前上下文。
這一章補上時間結構。
OpenClaw 不是一個永遠攤開的聊天視窗。它把對話分成可重置的 Session,用 Heartbeat 週期性喚醒主會話,用 Cron 精確排程後臺任務,用 Webhooks 接外部事件,再用 Tasks 記錄那些脫離主對話執行的工作。理解這幾層,你才知道什麼時候讓 Agent “記住”,什麼時候讓它“清空”,什麼時候讓它“到點辦事”,什麼時候只需要一條審計記錄。
這一篇只解決一個判斷:Session 管上下文,Heartbeat 管週期醒來,Cron 管精確排程,Webhook 管外部事件,Task 只做後臺臺賬。
1. 先把五個詞分清楚
這五個詞容易混在一起:
| 概念 | 更像什麼 | 負責什麼 | 不負責什麼 |
|---|---|---|---|
Session | 對話桶 | 決定訊息進入哪段上下文 | 不儲存長期記憶 |
Heartbeat | 週期巡檢 | 定期喚醒主會話,讓 Agent 自查 | 不保證精確到秒 |
Cron | 鬧鐘 / 排班表 | 精確時間、一次性提醒、後臺任務 | 不理解業務本身 |
Webhook | 外部門鈴 | 接收外部系統主動打來的事件 | 不主動輪詢外部系統 |
Task | 後臺臺賬 | 記錄 detached work 的狀態 | 不負責定時觸發 |
flowchart LR
User["使用者訊息"] --> Session["Session<br/>上下文桶"]
Heartbeat["Heartbeat<br/>週期醒來"] --> Session
Cron["Cron<br/>精確排程"] --> Run["Agent run"]
Webhook["Webhook<br/>外部事件"] --> Run
Run --> Task["Task ledger<br/>後臺臺賬"]
Session --> Run
style Session fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
style Heartbeat fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
style Cron fill:#dcfce7,stroke:#22c55e,stroke-width:2px
style Webhook fill:#dcfce7,stroke:#22c55e,stroke-width:2px
style Task fill:#f3f4f6,stroke:#6b7280,stroke-width:2px
一句話:
- 你問 Agent,它進入某個
sessionKey。 - 到了 Heartbeat 時間,Gateway 讓主會話自己檢查一次。
- 到了 Cron 時間,Gateway 按 job 執行任務。
- 外部系統有事件,就透過 Webhook 喚醒或啟動 isolated run。
- 後臺 run 發生後,Task ledger 記錄它有沒有成功。
2. Session 是路由結果,不是聊天視窗 UI
OpenClaw 官方把 conversations 組織成 sessions。每條訊息會根據來源進入一個 session。
預設行為可以這樣看:
- Direct messages 預設共享一個 DM session,多使用者時要檢查
dmScope。 - Group chats 按 group 隔離,群裡誰能觸發要看 group policy。
- Rooms / channels 按 room 或 channel 隔離,thread/topic 會影響 session key。
- Cron jobs 每次執行使用 fresh session,
main、isolated、current要分清。 - Webhooks 按 hook 隔離,除非配置覆蓋;不要讓外部隨意選擇 session。
這裡有兩個核心 ID:
sessionKey是路由桶,決定“這條訊息屬於哪段對話”。sessionId是當前 transcript 檔案,reset 後會換一個新的sessionId。
常見 key 形態:
常見例子包括 agent:main:main、agent:ops:whatsapp:group:120363403215116621、agent:ops:slack:channel:C1234567890、cron:morning-brief 和 hook:uuid。
狀態由 Gateway 持有。UI、TUI、Web 控制台都應該問 Gateway,不應該自己猜本地檔案。
官方給出的磁碟位置是:
~/.openclaw/agents/agentId/sessions/sessions.json 和 ~/.openclaw/agents/agentId/sessions/sessionId.jsonl。
sessions.json 是小型 mutable store,記錄當前 sessionKey -> SessionEntry。sessionId.jsonl 是 append-only transcript,儲存真實訊息、工具呼叫、工具結果、compaction summary 等內容。
3. Reset 換的是當前 Session,不是記憶
Session 會複用,直到觸發 reset。
官方生命週期規則:
- Daily reset 預設開啟,在 Gateway host 的本地時間凌晨 4 點之後建立新 session。
- Idle reset 是可選項,透過
session.reset.idleMinutes設定。 - 手動 reset 透過聊天裡的
/new或/reset觸發。 /new model還可以順帶切換模型。- Daily reset 和 idle reset 同時存在時,先到期的規則生效。
- 使用 provider-owned CLI session 的活躍會話,不會被 implicit daily default 直接切斷;需要
/reset或顯式配置session.reset。
這句話很關鍵:reset 建立新的 sessionId,不等於刪除 memory,也不等於刪除舊 transcript。
所以不要把 reset 理解成“失憶”。更準確地說,它是給同一個 sessionKey 換一份新的當前 transcript。長期偏好、人物設定、重要事實應該在 Workspace memory 或檔案裡,Session 只負責當前對話上下文。
Reset 是“換當前稿紙”,不是“燒掉檔案櫃”。真正要長期儲存的東西,應落到 memory 或 workspace 檔案裡。
4. DM isolation 是安全邊界
OpenClaw 預設所有 DM 共享一個 session。這個設計適合單使用者私人 Agent,因為連續性最好:你從不同時間點私信它,它都在同一段上下文裡。
但只要多個人能私信同一個 Agent,預設 main 就有隱私風險。
官方建議多使用者場景啟用 DM isolation:
{
"session": {
"dmScope": "per-channel-peer"
}
}四種模式:
dmScope | 隔離粒度 | 適合場景 |
|---|---|---|
main | 所有 DM 共享一個 session | 單使用者私人 Agent |
per-peer | 按傳送者隔離 | 同一人跨渠道連續性重要 |
per-channel-peer | 按渠道 + 傳送者隔離 | 多使用者 shared inbox 的預設選擇 |
per-account-channel-peer | 按賬號 + 渠道 + 傳送者隔離 | 多賬號閘道器、多 bot 場景 |
如果同一個人會從多個渠道聯絡你,可以用 session.identityLinks 顯式關聯身份。改完之後用 openclaw security audit 檢查配置。
判斷標準很簡單:
- 只有你一個人用,
main可以接受。 - 兩個人以上能 DM,預設改
per-channel-peer。 - 多 bot、多賬號、多租戶,考慮
per-account-channel-peer。 - 跨渠道連續性是產品需求時,再顯式配置
identityLinks。
5. Heartbeat 是週期性主會話 turn
Heartbeat 不是伺服器健康探針。它是 Gateway 週期性發起的一次 Agent turn,讓模型在主會話上下文裡檢查有沒有事情需要提醒你。
官方預設值:
- 預設 interval 是
30m。 - Anthropic OAuth/token,包括 Claude CLI reuse,預設是
1h。 - 關閉 heartbeat 用
every: "0m"。 - 預設 delivery target 是
none。
最小配置示例:
{
"agents": {
"defaults": {
"heartbeat": {
"every": "30m",
"target": "last",
"lightContext": true,
"isolatedSession": true
}
}
}
}欄位含義:
every控制心跳間隔,先用預設值,不要為了“主動”盲目縮短。target控制投遞目標,預設none;要通知最近渠道才用last。lightContext控制是否輕量上下文,常駐巡檢建議開啟。isolatedSession控制是否 fresh session,避免心跳攜帶完整主對話歷史。activeHours控制執行時間視窗,防止半夜打擾和無意義呼叫。model控制心跳專用模型,簡單巡檢可用便宜模型。includeReasoning控制是否投遞 Reasoning,群聊裡要謹慎,避免洩漏思考內容。
這裡要注意一個反直覺點:isolatedSession: true 並不改變投遞路由。它只是讓心跳執行時不要帶完整主對話歷史;結果仍然可以按主 session 的 last route 傳送。
Heartbeat 的核心不是“伺服器還活著嗎”,而是“Agent 到點醒來,看有沒有值得提醒你的事”。
6. HEARTBEAT.md 要短
如果 workspace 裡有 HEARTBEAT.md,預設 heartbeat prompt 會要求 Agent 讀取它。它適合放小而穩定的檢查清單。
示例:
# Heartbeat checklist
- Scan inbox for urgent follow-ups.
- Check calendar items in the next 2 hours.
- If nothing needs attention, reply HEARTBEAT_OK.官方還有幾個細節:
HEARTBEAT.md缺失時,heartbeat 仍然可以執行,由模型判斷要做什麼。- 檔案只有空行和 Markdown 標題時,會跳過本次心跳,原因是
empty-heartbeat-file。 - 不要把金鑰、token、手機號、私密憑據寫進
HEARTBEAT.md,它會進入 prompt context。 - 如果清單變長,優先拆成
tasks:block 或改用 Cron,不要把 heartbeat 變成萬能指令碼。
tasks: block 適合把多個週期檢查放在同一個 heartbeat 檔案裡:
tasks:
- name: inbox-triage
interval: 30m
prompt: "Check for urgent unread emails."
- name: calendar-scan
interval: 2h
prompt: "Check upcoming meetings."
# Additional instructions
- Keep alerts short.
- If nothing needs attention, reply HEARTBEAT_OK.OpenClaw 會只把到期任務放進本次 heartbeat prompt。沒有任務到期時,會跳過模型呼叫,原因是 no-tasks-due。任務上次執行時間寫在 session state 的 heartbeatTaskState 裡,正常重啟後仍可延續。
7. HEARTBEAT_OK 是投遞協議
Heartbeat 的回覆有一個約定:
- 沒有事情需要提醒時,回覆
HEARTBEAT_OK。 - Heartbeat run 中,
HEARTBEAT_OK出現在開頭或結尾會被當作 ack。 - 剩餘內容不超過
ackMaxChars時,OpenClaw 會丟棄這條回覆,不打擾使用者。 - 有告警時,不要帶
HEARTBEAT_OK,只返回告警文本。 - 普通聊天裡誤發單獨的
HEARTBEAT_OK也會被丟棄。
這就是為什麼 heartbeat 可以高頻執行但不製造訊息噪音。
配置可見性時,把三件事分開:
showOk控制是否顯示 OK ack,多數情況下關閉。showAlerts控制是否顯示非 OK 告警,需要提醒時開啟。useIndicator控制是否給 UI 狀態面板發 indicator,需要可見狀態時開啟。
如果三者都為 false,OpenClaw 會直接跳過 heartbeat run,不產生模型呼叫。
8. Cron 是 Gateway scheduler
Cron 是 OpenClaw 的精確排程機制。它執行在 Gateway 裡,不執行在模型裡。
官方關鍵事實:
- Job 存在
~/.openclaw/cron/jobs.json,Gateway 重啟不會丟失已有 job。 - 所有 Cron execution 都會建立 background task 記錄,Cron 跑過什麼,可以回頭查。
- 一次性
atjob 預設成功後自動刪除,它更像提醒,不是長期任務。 - Cron 可投遞到 channel、webhook 或靜默,排程和通知是兩件事。
- Cron 可指定 Agent、模型、thinking、工具範圍,所以排程任務可以有獨立執行姿態。
三種 schedule:
at:一次性時間點,例如20m、ISO 8601 時間。every:固定間隔,例如每 2 小時跑一次。cron:日曆式排班,例如每天 7 點、每週一 6 點。
時區規則要寫準:
at無時區時按 UTC 處理;需要本地時間就顯式寫清。cron無時區時使用 Gateway host timezone;關鍵任務建議帶--tz。- top-of-hour recurring 預設最多 stagger 5 分鐘;要整點用
--exact或schedule.staggerMs = 0。
舊稿裡的時區判斷過粗。at 和 cron 的無時區行為不同。
9. Cron 的四種 Session 目標
Cron 不只有 main 和 isolated。
| 目標 | 上下文邊界 | 適合任務 |
|---|---|---|
main | 進入下一次 heartbeat turn | reminders、system events |
isolated | 在 cron:jobId dedicated session 執行 | 報告、後臺雜務、重分析 |
current | 建立 job 時繫結當前 session | 需要當前上下文的重複工作 |
session:name | 使用持久命名 session | 連續積累上下文的流程 |
示例:一次性提醒進入主會話。
openclaw cron add \
--name "Calendar check" \
--at "20m" \
--session main \
--system-event "Next heartbeat: check calendar." \
--wake now示例:每天早上固定時間跑 isolated 簡報。
openclaw cron add \
--name "Morning brief" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--channel slack \
--to "channel:C1234567890"示例:每週深度分析,指定模型和 thinking。
openclaw cron add \
--name "Deep analysis" \
--cron "0 6 * * 1" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--announcemain 的本質是 enqueue system event,並可選擇 wake now 或 next-heartbeat。isolated 的本質是專門起一個 cron:jobId agent turn,每次 fresh session,不汙染主對話歷史。
10. Delivery 不是由 Agent 自己兜底
Cron 的 delivery mode 有三種:
announce把 summary 投遞到目標 channel,isolated job 預設是 announce。webhook把完成事件 POST 到 URL,由外部系統接收完成事件。none內部保留,不投遞;不等於交給 Agent 自己外發。
對於 cron-owned isolated jobs,runner 負責最終投遞路徑。Agent 應返回 plain-text summary,由 runner 決定投遞、webhook 或靜默。--no-deliver 只是保持內部,不代表把外發責任交還給 Agent。
如果 isolated run 返回 silent token,例如 NO_REPLY 或 no_reply,OpenClaw 會抑制 direct outbound delivery,也會抑制 fallback queued summary。結果就是:這次 Cron 不會往聊天裡發訊息。
排障順序:
openclaw status
openclaw gateway status
openclaw cron status
openclaw cron list
openclaw cron runs --id job-id --limit 20
openclaw system heartbeat last
openclaw logs --follow
openclaw doctor11. Webhook 是外部事件入口
Cron 是“到點觸發”。Webhook 是“外部系統有事就通知 OpenClaw”。
Gateway 可以暴露 HTTP webhook endpoints:
{
"hooks": {
"enabled": true,
"token": "shared-secret",
"path": "/hooks"
}
}常見 endpoint:
POST /hooks/wake:enqueue system event 到 main session。POST /hooks/agent:執行 isolated agent turn。POST /hooks/name:mapped hook,透過配置把自定義 payload 轉成 wake 或 agent action。
安全規則必須硬記:
- 請求要帶
Authorization: Bearer token,也支援x-openclaw-token。 - Query-string token 會被拒絕。
- Hook endpoint 應放在 loopback、tailnet 或可信反向代理後面。
- 使用專用 hook token,不復用 Gateway auth token。
hooks.path不能用根路徑/。- 用
hooks.allowedAgentIds限制可顯式路由的 Agent。 - 不要輕易開放 caller-selected session key;需要時配合 allowed prefix。
Webhook 是執行入口,不是普通網頁回撥。公網暴露前先確認 token、反向代理、allowed agents 和 session key 約束都已收緊。
12. Internal hooks 不是 Webhooks
OpenClaw 還有內部 Hooks。它們不是外部 HTTP endpoint,而是在 Gateway 內部事件發生時執行的小指令碼。
典型事件:
command:new:使用者發出/new。command:reset:使用者發出/reset。command:stop:使用者發出/stop。session:compact:before:compaction 前。session:compact:after:compaction 後。session:patch:session 屬性修改。agent:bootstrap:workspace bootstrap 注入前。gateway:startup:channel 啟動且 hooks 載入後。message:received:任意渠道收到入站訊息。message:transcribed:音訊轉錄後。message:preprocessed:媒體和連結理解後。message:sent:出站訊息送達後。
常見用途:
/new或/reset時儲存 session-memory。- 記錄命令審計日誌。
- Gateway 啟動時執行
BOOT.md。 - Bootstrap 前注入額外 workspace 檔案。
如果你要攔截 tool call、reply dispatch、subagent delivery、plugin install 等更深的生命週期,應看 Plugin hooks,而不是內部 Hooks。
13. Tasks 是臺賬,不是排程器
Background Tasks 記錄 detached work。它不決定什麼時候執行;Cron、Sub-agent、ACP、CLI agent commands 才會產生執行。
會建立 Task 的來源:
- ACP background runs 會建立 Task;Heartbeat turns 不會。
- Subagent spawns 會建立 Task;normal interactive chat turns 不會。
- 所有 Cron executions,包括 main-session 和 isolated,都會建立 Task;direct slash command responses 不會。
- CLI operations that run through Gateway 會建立 Task。
- Agent media jobs 會建立 Task。
Task 生命週期:
Task 生命週期從 queued 到 running,最後進入 succeeded、failed、timed_out、cancelled 或 lost。
Completion 是 push-driven。Detached work 完成後,可以直接通知目標 channel,也可以 wake requester session 或 heartbeat。不要把它設計成 Agent 每隔幾秒 polling 狀態;那通常是錯誤形狀。
檢查命令:
openclaw tasks list
openclaw tasks show task-id
openclaw tasks cancel task-id
openclaw tasks audit
openclaw tasks maintenance --applyTerminal task records 預設保留 7 天后自動清理。
14. 怎麼選機制
按需求選,不按名字選:
| 需求 | 機制 | 為什麼 |
|---|---|---|
| 每天 9 點準時發報告 | Cron | 時間點明確 |
| 20 分鐘後提醒我 | Cron --at | 一次性提醒 |
| 每 30 分鐘順手看 inbox、calendar、notifications | Heartbeat | 週期醒來,自查是否需要提醒 |
| 每次工具呼叫前做安全攔截 | Plugin hooks 或 tool policy | 攔截點在工具生命週期 |
/reset 時儲存一份摘要到 memory | internal hook | 事件來自 Gateway 內部 |
| GitHub PR 建立後立刻 review | Webhook | 外部系統主動通知 |
| 重分析很重,不想汙染主對話 | Cron isolated 或 sub-agent | fresh session,隔離上下文 |
| 只想知道後臺跑過什麼 | Tasks | Task 是 ledger,不是 scheduler |
一個穩妥預設:
- 私人 Agent:
Session: main,Heartbeat 可用30m或1h,target用none或last,Cron 只放明確時間點的提醒。 - 多使用者 Agent:
Session: per-channel-peer,Heartbeat 配activeHours + target none,Cron 用isolated + explicit delivery。 - 運營 / 監控 Agent:
Session: per-account-channel-peer,Heartbeat 用 task block +lightContext,Cron 做 precise jobs + model/tool restrictions,外部事件優先 Webhook。
15. 常見誤解
誤解一:Heartbeat 越頻繁越好。
不對。Heartbeat 是 full agent turn,會消耗 token。官方建議控制成本:isolatedSession: true、lightContext: true、更便宜的 model、小型 HEARTBEAT.md、必要時 target: "none"。
誤解二:Cron 和 Heartbeat 都是定時任務,所以隨便選。
不對。Heartbeat 適合上下文相關的週期檢查;Cron 適合精確時間、一次性提醒、獨立後臺任務。
誤解三:Reset 會刪記憶。
不對。Reset 換當前 session transcript;memory 和舊 transcript 仍在。長期事實要寫進 memory 或 workspace 檔案。
誤解四:Webhook endpoint 放公網就行。
不對。Webhook 是執行入口,應該放在 loopback、tailnet 或可信反代後面,並使用專用 token 和 agent allowlist。
誤解五:Task 可以當成任務排程器。
不對。Task 是 ledger。它記錄 detached work 的狀態,不負責定時。
16. 給 Agent 的實踐任務
把這組要求發給 OpenClaw Agent,讓它檢查自己的時間系統:
- 執行
openclaw status和openclaw sessions --json,說明當前 session store 路徑、最近活動、dmScope。 - 檢查
session.reset配置,說明 daily reset、idle reset、manual reset 的實際邊界。 - 讀取
HEARTBEAT.md;如果不存在、為空、過長或含敏感資訊,請指出。 - 檢查
agents.defaults.heartbeat和agents.list[].heartbeat,說明every、target、activeHours、lightContext、isolatedSession是否合理。 - 執行
openclaw cron status、openclaw cron list、openclaw cron runs,列出所有 job 的 schedule、timezone、session target、delivery mode、agentId、model override。 - 檢查是否存在多使用者 DM 但仍使用
mainsession 的風險。 - 檢查
openclaw tasks list和openclaw tasks audit,說明後臺任務是否有failed、timed_out、lost。 - 給出最小修改建議,不要直接改配置。
17. 本章自檢
讀完這一章,你應該能回答:
sessionKey和sessionId的區別是什麼?mainDM scope 為什麼只適合單使用者?/new、/reset、daily reset、idle reset 分別什麼時候換 session?- Heartbeat 為什麼不是伺服器健康探針?
HEARTBEAT_OK為什麼能避免訊息噪音?- Cron 的
at和cron無時區時分別怎麼處理? - Cron
main和isolated的上下文邊界有什麼不同? - Webhook 和 internal hook 的邊界是什麼?
- 為什麼 Tasks 是 ledger,不是 scheduler?
過關標準:能用一句話說清“OpenClaw 用 Session 管上下文,用 Heartbeat 做週期自查,用 Cron 做精確排程,用 Webhook 接外部事件,用 Tasks 留後臺臺賬”。
18. 接下來去哪
09 · Channel 與安全
繼續看外部入口、DM 配對、群組門控、工具策略、沙箱和 Gateway 暴露面。
07 · 多 Agent 協作
回到上一篇,理解多個 Agent 如何拆任務、共享上下文和避免互相汙染。
官方教程:自動化
對照官方配置繼續看 heartbeat、cron、webhook、task 和 hooks。