心跳(Gateway)

心跳 vs Cron? 要了解什麼時候用哪個,請參閱 Cron vs 心跳

心跳會在主 session 中執行定期 agent 回合,讓模型能主動提醒你需要關注的事項,而不至於一直干擾你。

疑難排解:/automation/troubleshooting

快速開始(新手)

  1. 保持心跳啟用(預設 30m,Anthropic OAuth/setup-token 時預設 1h),或設定你想要的頻率。
  2. 在 agent workspace 中建立一個簡單的 HEARTBEAT.md 檢查清單(可選但建議)。
  3. 決定心跳訊息要發到哪裡(target: "none" 是預設值;設定 target: "last" 發送到上一個聯絡對象)。
  4. 可選:啟用心跳推理過程的傳遞,增加透明度。
  5. 可選:在心跳只需要 HEARTBEAT.md 時使用輕量啟動上下文。
  6. 可選:將心跳限制在活躍時段(當地時間)。

設定範例:

{
  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-agent agents.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" }

不要把 startend 設成一樣(例如 08:0008: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 --jsonsessions CLI 複製)。
    • Session key 格式:參閱 SessionsGroups
  • 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 內容(不合併)。
  • ackMaxCharsHEARTBEAT_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" 行為。
    • startend 相等時不構成有效視窗;相等值被視為零寬度(永遠在視窗外)。
    • 在活躍視窗外,心跳會被跳過直到下一次排程落在視窗內。

發送行為

  • 心跳預設在 agent 的主 session 中執行(agent:<id>:<mainKey>), 或在 session.scope = "global" 時為 global。設定 session 可覆寫為特定的頻道 session(Discord/WhatsApp 等)。
  • session 只影響執行上下文;發送由 targetto 控制。
  • 要發送到特定頻道/收件者,設定 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 }
只在某個頻道顯示 OKchannels.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"