心跳(Gateway)
心跳 vs Cron? 要了解什麼時候用哪個,請參閱 Cron vs 心跳。
心跳會在主 session 中執行定期 agent 回合,讓模型能主動提醒你需要關注的事項,而不至於一直干擾你。
疑難排解:/automation/troubleshooting
快速開始(新手)
- 保持心跳啟用(預設
30m,Anthropic OAuth/setup-token 時預設1h),或設定你想要的頻率。 - 在 agent workspace 中建立一個簡單的
HEARTBEAT.md檢查清單(可選但建議)。 - 決定心跳訊息要發到哪裡(
target: "none"是預設值;設定target: "last"發送到上一個聯絡對象)。 - 可選:啟用心跳推理過程的傳遞,增加透明度。
- 可選:在心跳只需要
HEARTBEAT.md時使用輕量啟動上下文。 - 可選:將心跳限制在活躍時段(當地時間)。
設定範例:
{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last", // 明確發送到上一個聯絡對象(預設 "none")
directPolicy: "allow", // 預設:允許直接/DM 目標;設 "block" 可禁止
lightContext: true, // 可選:啟動檔案中只保留 HEARTBEAT.md
// activeHours: { start: "08:00", end: "24:00" },
// includeReasoning: true, // 可選:同時發送推理過程訊息
},
},
},
}
預設值
- 間隔:
30m(偵測到 Anthropic OAuth/setup-token 驗證模式時為1h)。可在agents.defaults.heartbeat.every或 per-agentagents.list[].heartbeat.every設定;用0m停用。 - Prompt 內容(可透過
agents.defaults.heartbeat.prompt自訂):Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK. - 心跳 prompt 會逐字作為使用者訊息發送。系統 prompt 中會包含「Heartbeat」區段,該回合在內部也會被標記。
- 活躍時段(
heartbeat.activeHours)會以設定的時區檢查。在視窗外,心跳會被跳過直到下一次排程落在視窗內。
心跳 prompt 的用途
預設 prompt 刻意設計得比較寬泛:
- 背景任務:「考慮未完成的任務」促使 agent 檢視後續跟進(收件匣、行事曆、提醒、排隊工作),並提醒任何緊急事項。
- 人際關懷:「白天偶爾關心一下你的使用者」促使偶爾發個輕量的「有需要幫忙的嗎?」訊息,但會利用你設定的當地時區避免夜間打擾(參閱 /concepts/timezone)。
如果你要心跳做特定的事情(例如「檢查 Gmail PubSub 統計」或「驗證 gateway 健康狀態」),可以把 agents.defaults.heartbeat.prompt(或 agents.list[].heartbeat.prompt)設為自訂內容(逐字發送)。
回應約定
- 如果沒有需要關注的事,回覆
HEARTBEAT_OK。 - 在心跳回合中,OpenClaw 會在回覆的開頭或結尾出現
HEARTBEAT_OK時視為確認。該 token 會被移除,如果剩餘內容 ≤ackMaxChars(預設 300),整個回覆會被丟棄。 - 如果
HEARTBEAT_OK出現在回覆中間,不會做特殊處理。 - 如果是警報,不要包含
HEARTBEAT_OK;只回傳警報文字。
心跳以外的場景中,訊息開頭或結尾出現的 HEARTBEAT_OK 會被移除並記錄;只包含 HEARTBEAT_OK 的訊息會被丟棄。
設定
{
agents: {
defaults: {
heartbeat: {
every: "30m", // 預設:30m(0m 停用)
model: "anthropic/claude-opus-4-6",
includeReasoning: false, // 預設:false(有推理過程時另外發送 Reasoning: 訊息)
lightContext: false, // 預設:false;true 時只從 workspace 啟動檔案保留 HEARTBEAT.md
target: "last", // 預設:none | 選項:last | none | <channel id>(核心或外掛,例如 "bluebubbles")
to: "+15551234567", // 可選的頻道專屬覆寫
accountId: "ops-bot", // 可選的多帳號頻道 id
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
ackMaxChars: 300, // HEARTBEAT_OK 後允許的最大字元數
},
},
},
}
範圍與優先順序
agents.defaults.heartbeat設定全域心跳行為。agents.list[].heartbeat在其上合併;如果任何 agent 有heartbeat區塊,只有那些 agent 會執行心跳。channels.defaults.heartbeat設定所有頻道的可見性預設值。channels.<channel>.heartbeat覆寫頻道預設值。channels.<channel>.accounts.<id>.heartbeat(多帳號頻道)覆寫每頻道設定。
Per-agent 心跳
如果任何 agents.list[] 項目包含 heartbeat 區塊,只有那些 agent 會執行心跳。Per-agent 區塊會合併在 agents.defaults.heartbeat 之上(所以你可以設定一次共用預設值,然後依 agent 覆寫)。
範例:兩個 agent,只有第二個執行心跳。
{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last", // 明確發送到上一個聯絡對象(預設 "none")
},
},
list: [
{ id: "main", default: true },
{
id: "ops",
heartbeat: {
every: "1h",
target: "whatsapp",
to: "+15551234567",
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
},
},
],
},
}
活躍時段範例
將心跳限制在特定時區的上班時間:
{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last", // 明確發送到上一個聯絡對象(預設 "none")
activeHours: {
start: "09:00",
end: "22:00",
timezone: "America/New_York", // 可選;有設 userTimezone 時用那個,否則用主機時區
},
},
},
},
}
在此視窗外(東部時間早上 9 點前或晚上 10 點後),心跳會被跳過。下一次落在視窗內的排程會正常執行。
全天候設定
如果你要心跳全天不間斷執行,可以用以下任一方式:
- 完全不設
activeHours(沒有時間限制;這是預設行為)。 - 設定全天視窗:
activeHours: { start: "00:00", end: "24:00" }。
不要把 start 和 end 設成一樣(例如 08:00 到 08:00)。那會被當作零寬度視窗,心跳永遠會被跳過。
多帳號範例
用 accountId 指定多帳號頻道上的特定帳號,例如 Telegram:
{
agents: {
list: [
{
id: "ops",
heartbeat: {
every: "1h",
target: "telegram",
to: "12345678:topic:42", // 可選:路由到特定的 topic/thread
accountId: "ops-bot",
},
},
],
},
channels: {
telegram: {
accounts: {
"ops-bot": { botToken: "YOUR_TELEGRAM_BOT_TOKEN" },
},
},
},
}
欄位說明
every:心跳間隔(duration 字串;預設單位 = 分鐘)。model:可選的心跳回合模型覆寫(provider/model)。includeReasoning:啟用時,也傳遞另外的Reasoning:訊息(格式同/reasoning on)。lightContext:為 true 時,心跳回合使用輕量啟動上下文,workspace 啟動檔案中只保留HEARTBEAT.md。session:可選的心跳回合 session key。main(預設):agent 主 session。- 明確的 session key(從
openclaw sessions --json或 sessions CLI 複製)。 - Session key 格式:參閱 Sessions 和 Groups。
target:last:發送到上一個使用的外部頻道。- 明確頻道:
whatsapp/telegram/discord/googlechat/slack/msteams/signal/imessage。 none(預設):執行心跳但不對外發送。
directPolicy:控制直接/DM 發送行為:allow(預設):允許直接/DM 心跳發送。block:禁止直接/DM 發送(reason=dm-blocked)。
to:可選的收件者覆寫(頻道專屬 id,例如 WhatsApp 用 E.164 或 Telegram 的 chat id)。Telegram topics/threads 用<chatId>:topic:<messageThreadId>。accountId:多帳號頻道的可選帳號 id。當target: "last"時,帳號 id 適用於解析出的最後頻道(如果支援帳號的話),否則忽略。如果帳號 id 與解析出的頻道的已設定帳號不匹配,發送會被跳過。prompt:覆寫預設 prompt 內容(不合併)。ackMaxChars:HEARTBEAT_OK後允許的最大字元數,超過則發送。suppressToolErrorWarnings:為 true 時,心跳回合中不發送工具錯誤警告。activeHours:將心跳限制在特定時間視窗。物件包含start(HH:MM,含該時間;用00:00表示當天開始)、end(HH:MM,不含;24:00表示當天結束),以及可選的timezone。- 省略或
"user":使用你的agents.defaults.userTimezone(如果有設的話),否則退回主機系統時區。 "local":永遠使用主機系統時區。- 任何 IANA 識別符(例如
America/New_York):直接使用;無效時退回"user"行為。 start和end相等時不構成有效視窗;相等值被視為零寬度(永遠在視窗外)。- 在活躍視窗外,心跳會被跳過直到下一次排程落在視窗內。
- 省略或
發送行為
- 心跳預設在 agent 的主 session 中執行(
agent:<id>:<mainKey>), 或在session.scope = "global"時為global。設定session可覆寫為特定的頻道 session(Discord/WhatsApp 等)。 session只影響執行上下文;發送由target和to控制。- 要發送到特定頻道/收件者,設定
target+to。用target: "last"時,發送到該 session 最後使用的外部頻道。 - 心跳發送預設允許直接/DM 目標。設定
directPolicy: "block"可禁止直接目標的發送,同時心跳回合仍會執行。 - 如果主佇列忙碌,心跳會被跳過並稍後重試。
- 如果
target解析不到外部目的地,回合仍會執行但不發送外部訊息。 - 純心跳回覆不會讓 session 保活;最後的
updatedAt會恢復,讓閒置逾期行為正常運作。
可見性控制
預設情況下,HEARTBEAT_OK 確認會被隱藏,而警報內容會被發送。你可以按頻道或帳號調整:
channels:
defaults:
heartbeat:
showOk: false # 隱藏 HEARTBEAT_OK(預設)
showAlerts: true # 顯示警報訊息(預設)
useIndicator: true # 發出指示器事件(預設)
telegram:
heartbeat:
showOk: true # 在 Telegram 上顯示 OK 確認
whatsapp:
accounts:
work:
heartbeat:
showAlerts: false # 此帳號不發送警報
優先順序:per-account → per-channel → channel defaults → 內建預設值。
各旗標的作用
showOk:模型回傳純 OK 回覆時,發送HEARTBEAT_OK確認訊息。showAlerts:模型回傳非 OK 回覆時,發送警報內容。useIndicator:發出 UI 狀態面的指示器事件。
如果三個都是 false,OpenClaw 會完全跳過心跳回合(不呼叫模型)。
Per-channel vs per-account 範例
channels:
defaults:
heartbeat:
showOk: false
showAlerts: true
useIndicator: true
slack:
heartbeat:
showOk: true # 所有 Slack 帳號
accounts:
ops:
heartbeat:
showAlerts: false # 只針對 ops 帳號禁止警報
telegram:
heartbeat:
showOk: true
常見模式
| 目標 | 設定 |
|---|---|
| 預設行為(隱藏 OK,警報開啟) | (不需要設定) |
| 完全靜音(不發訊息、不發指示器) | channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false } |
| 只有指示器(不發訊息) | channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true } |
| 只在某個頻道顯示 OK | channels.telegram.heartbeat: { showOk: true } |
HEARTBEAT.md(可選)
如果 workspace 中存在 HEARTBEAT.md 檔案,預設 prompt 會告訴 agent 去讀取它。把它當作你的「心跳檢查清單」:小型、穩定、適合每 30 分鐘包含一次。
如果 HEARTBEAT.md 存在但實質上是空的(只有空行和 markdown 標題如 # Heading),OpenClaw 會跳過心跳回合以節省 API 呼叫。
如果檔案不存在,心跳仍會執行,由模型決定做什麼。
保持它精簡(短檢查清單或提醒),避免 prompt 膨脹。
HEARTBEAT.md 範例:
# 心跳檢查清單
- 快速掃描:收件匣有什麼緊急的嗎?
- 如果是白天,沒有其他待辦時做個輕量關懷。
- 如果某個任務卡住了,寫下_缺什麼_,下次問 Peter。
Agent 可以更新 HEARTBEAT.md 嗎?
可以——只要你告訴它。
HEARTBEAT.md 就是 agent workspace 中的普通檔案,所以你可以在一般對話中跟 agent 說:
- 「更新
HEARTBEAT.md,加上每天檢查行事曆。」 - 「重寫
HEARTBEAT.md,讓它更精簡,專注在收件匣跟進。」
如果你希望這件事自動發生,也可以在心跳 prompt 中加一句:「如果檢查清單變得過時,更新 HEARTBEAT.md 為更好的版本。」
安全提醒:不要在 HEARTBEAT.md 中放機密資訊(API 金鑰、電話號碼、私有 token)——它會成為 prompt 上下文的一部分。
手動喚醒(隨需)
你可以排入系統事件並立即觸發心跳:
openclaw system event --text "Check for urgent follow-ups" --mode now
如果多個 agent 有設定 heartbeat,手動喚醒會立即執行每個 agent 的心跳。
用 --mode next-heartbeat 等到下一次排程的心跳再執行。
推理過程傳遞(可選)
預設情況下,心跳只傳遞最終的「回答」內容。
如果你想要更透明,啟用:
agents.defaults.heartbeat.includeReasoning: true
啟用後,心跳也會傳遞一則以 Reasoning: 為前綴的獨立訊息(格式同 /reasoning on)。當 agent 管理多個 sessions/codexes 時,這有助於看清它為什麼決定通知你——但也可能洩漏比你預期更多的內部細節。建議在群組聊天中關閉。
費用考量
心跳會執行完整的 agent 回合。間隔越短,消耗的 token 越多。讓 HEARTBEAT.md 保持精簡,考慮使用較便宜的 model,或在只需要內部狀態更新時設定 target: "none"。