AI 程式設計教程中文版
從原理到實戰

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,mainisolatedcurrent 要分清。
  • Webhooks 按 hook 隔離,除非配置覆蓋;不要讓外部隨意選擇 session。

這裡有兩個核心 ID:

  • sessionKey 是路由桶,決定“這條訊息屬於哪段對話”。
  • sessionId 是當前 transcript 檔案,reset 後會換一個新的 sessionId

常見 key 形態:

常見例子包括 agent:main:mainagent:ops:whatsapp:group:120363403215116621agent:ops:slack:channel:C1234567890cron:morning-briefhook:uuid

狀態由 Gateway 持有。UI、TUI、Web 控制台都應該問 Gateway,不應該自己猜本地檔案。

官方給出的磁碟位置是:

~/.openclaw/agents/agentId/sessions/sessions.json~/.openclaw/agents/agentId/sessions/sessionId.jsonl

sessions.json 是小型 mutable store,記錄當前 sessionKey -> SessionEntrysessionId.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 跑過什麼,可以回頭查。
  • 一次性 at job 預設成功後自動刪除,它更像提醒,不是長期任務。
  • 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 分鐘;要整點用 --exactschedule.staggerMs = 0

舊稿裡的時區判斷過粗。atcron 的無時區行為不同。

9. Cron 的四種 Session 目標

Cron 不只有 main 和 isolated。

目標上下文邊界適合任務
main進入下一次 heartbeat turnreminders、system events
isolatedcron: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 \
  --announce

main 的本質是 enqueue system event,並可選擇 wake nownext-heartbeatisolated 的本質是專門起一個 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_REPLYno_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 doctor

11. 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 生命週期從 queuedrunning,最後進入 succeededfailedtimed_outcancelledlost

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 --apply

Terminal task records 預設保留 7 天后自動清理。

14. 怎麼選機制

按需求選,不按名字選:

需求機制為什麼
每天 9 點準時發報告Cron時間點明確
20 分鐘後提醒我Cron --at一次性提醒
每 30 分鐘順手看 inbox、calendar、notificationsHeartbeat週期醒來,自查是否需要提醒
每次工具呼叫前做安全攔截Plugin hooks 或 tool policy攔截點在工具生命週期
/reset 時儲存一份摘要到 memoryinternal hook事件來自 Gateway 內部
GitHub PR 建立後立刻 reviewWebhook外部系統主動通知
重分析很重,不想汙染主對話Cron isolated 或 sub-agentfresh session,隔離上下文
只想知道後臺跑過什麼TasksTask 是 ledger,不是 scheduler

一個穩妥預設:

  • 私人 Agent:Session: main,Heartbeat 可用 30m1htargetnonelast,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: truelightContext: 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,讓它檢查自己的時間系統:

  1. 執行 openclaw statusopenclaw sessions --json,說明當前 session store 路徑、最近活動、dmScope
  2. 檢查 session.reset 配置,說明 daily reset、idle reset、manual reset 的實際邊界。
  3. 讀取 HEARTBEAT.md;如果不存在、為空、過長或含敏感資訊,請指出。
  4. 檢查 agents.defaults.heartbeatagents.list[].heartbeat,說明 everytargetactiveHourslightContextisolatedSession 是否合理。
  5. 執行 openclaw cron statusopenclaw cron listopenclaw cron runs,列出所有 job 的 schedule、timezone、session target、delivery mode、agentId、model override。
  6. 檢查是否存在多使用者 DM 但仍使用 main session 的風險。
  7. 檢查 openclaw tasks listopenclaw tasks audit,說明後臺任務是否有 failedtimed_outlost
  8. 給出最小修改建議,不要直接改配置。

17. 本章自檢

讀完這一章,你應該能回答:

  1. sessionKeysessionId 的區別是什麼?
  2. main DM scope 為什麼只適合單使用者?
  3. /new/reset、daily reset、idle reset 分別什麼時候換 session?
  4. Heartbeat 為什麼不是伺服器健康探針?
  5. HEARTBEAT_OK 為什麼能避免訊息噪音?
  6. Cron 的 atcron 無時區時分別怎麼處理?
  7. Cron mainisolated 的上下文邊界有什麼不同?
  8. Webhook 和 internal hook 的邊界是什麼?
  9. 為什麼 Tasks 是 ledger,不是 scheduler?

過關標準:能用一句話說清“OpenClaw 用 Session 管上下文,用 Heartbeat 做週期自查,用 Cron 做精確排程,用 Webhook 接外部事件,用 Tasks 留後臺臺賬”。

18. 接下來去哪

19. 官方資料

本頁目錄