Skip to content

Heartbeat(Gateway)

Heartbeat 还是 Cron? 参见 Cron vs Heartbeat 了解何时选哪种。

Heartbeat 在主会话中周期性触发 Agent 回合,让模型在不刷屏的前提下主动汇报需要关注的内容。

排障:/openclaw/automation/troubleshooting

快速上手(新手)

  1. 保持心跳启用(默认 30m,使用 Anthropic OAuth/setup-token 时为 1h),或自定义间隔。
  2. 在 Agent 工作区创建一个小巧的 HEARTBEAT.md 检查列表(可选但推荐)。
  3. 决定心跳消息发送到哪里(target: "none" 为默认值;设置 target: "last" 路由到最近联系人)。
  4. 可选:启用心跳推理透明度投递。
  5. 可选:使用轻量引导上下文(心跳仅需 HEARTBEAT.md)。
  6. 可选:启用隔离会话,避免每次心跳都附带完整对话历史。
  7. 可选:将心跳限制在活跃时段(本地时间)。

配置示例:

json5
{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "last", // 明确投递到最近联系人(默认为 "none")
        directPolicy: "allow", // 默认:允许直接/私聊目标;设为 "block" 可屏蔽
        lightContext: true, // 可选:仅从引导文件注入 HEARTBEAT.md
        isolatedSession: true, // 可选:每次心跳使用独立会话(无对话历史)
        // activeHours: { start: "08:00", end: "24:00" },
        // includeReasoning: true, // 可选:同时发送独立 `Reasoning:` 消息
      },
    },
  },
}

默认值

  • 间隔:30m(检测到 Anthropic OAuth/setup-token 时为 1h)。可通过 agents.defaults.heartbeat.every 或单 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 作为用户消息原文发送,系统提示中会附加 "Heartbeat" 段落并标记为心跳运行。
  • 活跃时段(heartbeat.activeHours)按配置的时区判断,窗口外的心跳会被跳过,等待下一个窗口内的触发点。

心跳 Prompt 的用途

默认 Prompt 故意设计得很宽泛:

  • 后台任务:"考虑待处理事项"引导 Agent 检查跟进事项(收件箱、日历、提醒、待办工作)并汇报紧急内容。
  • 人文关怀:"白天偶尔做一次轻量问候"引导偶尔发出一条"有什么需要帮忙的吗?",但通过配置时区避免深夜打扰(见 /openclaw/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 的消息会被丢弃。

配置

json5
{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m", // 默认:30m(0m 禁用)
        model: "anthropic/claude-opus-4-6",
        includeReasoning: false, // 默认:false(可用时另发独立 Reasoning: 消息)
        lightContext: false, // 默认:false;true 时仅保留工作区引导文件中的 HEARTBEAT.md
        isolatedSession: false, // 默认:false;true 时每次心跳使用全新会话(无对话历史)
        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(多账号渠道)覆盖单渠道配置。

按 Agent 配置心跳

若任意 agents.list[] 条目含 heartbeat 块,仅那些 Agent 执行心跳。单 Agent 的 heartbeat 块在 agents.defaults.heartbeat 之上合并(可在全局设置共享默认值后按 Agent 覆盖)。

示例:两个 Agent,只有第二个执行心跳。

json5
{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "last",
      },
    },
    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.",
        },
      },
    ],
  },
}

活跃时段示例

将心跳限制在特定时区的工作时间:

json5
{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "last",
        activeHours: {
          start: "09:00",
          end: "22:00",
          timezone: "America/New_York", // 可选;未设置时使用 userTimezone,否则使用主机时区
        },
      },
    },
  },
}

该窗口外(东部时间 9 点前或 22 点后)心跳会被跳过,下一个窗口内的调度点才会运行。

全天候模式

如需全天心跳,可使用以下任一方式:

  • 完全省略 activeHours(不限时间窗口;这是默认行为)。
  • 设置全天窗口:activeHours: { start: "00:00", end: "24:00" }

不要将 startend 设为相同时间(如 08:0008:00),这会被视为零宽度窗口,心跳永远被跳过。

多账号示例

accountId 指定 Telegram 等多账号渠道中的特定账号:

json5
{
  agents: {
    list: [
      {
        id: "ops",
        heartbeat: {
          every: "1h",
          target: "telegram",
          to: "12345678:topic:42", // 可选:路由到特定话题/线程
          accountId: "ops-bot",
        },
      },
    ],
  },
  channels: {
    telegram: {
      accounts: {
        "ops-bot": { botToken: "YOUR_TELEGRAM_BOT_TOKEN" },
      },
    },
  },
}

字段说明

  • every:心跳间隔(时长字符串;默认单位为分钟)。
  • model:心跳运行的可选模型覆盖(provider/model)。
  • includeReasoning:启用时,同时投递可用的独立 Reasoning: 消息(格式与 /reasoning on 相同)。
  • lightContext:为 true 时,心跳运行使用轻量引导上下文,仅保留工作区引导文件中的 HEARTBEAT.md
  • isolatedSession:为 true 时,每次心跳在无历史对话的全新会话中运行。与 cron sessionTarget: "isolated" 使用相同的隔离模式。可大幅降低每次心跳的 token 消耗。结合 lightContext: true 效果最佳。投递路由仍使用主会话上下文。
  • session:心跳运行的可选会话键。
    • main(默认):Agent 主会话。
    • 显式会话键(从 openclaw sessions --jsonSessions CLI 复制)。
    • 会话键格式:参见 SessionsGroups
  • target
    • last:投递到最近使用的外部渠道。
    • 显式渠道:whatsapp / telegram / discord / googlechat / slack / msteams / signal / imessage
    • none(默认):执行心跳但不外部投递
  • directPolicy:控制直接/私聊投递行为:
    • allow(默认):允许直接/私聊心跳投递。
    • block:屏蔽直接/私聊投递(reason=dm-blocked)。
  • to:可选收件人覆盖(渠道专属 ID,如 WhatsApp 的 E.164 格式或 Telegram 的 chat ID)。Telegram 话题/线程格式:<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" 行为。
    • startend 相等时视为零宽度窗口(始终在窗口外)。
    • 在活跃窗口外时,心跳被跳过,直到下一个窗口内的调度点。

投递行为

  • 心跳默认在 Agent 主会话(agent:<id>:<mainKey>)中运行,session.scope = "global" 时为 global。设置 session 可覆盖到特定渠道会话(Discord/WhatsApp 等)。
  • session 只影响运行上下文;投递由 targetto 控制。
  • 如需投递到特定渠道/收件人,设置 target + totarget: "last" 时使用该会话的最近外部渠道。
  • 心跳投递默认允许直接/私聊目标。设置 directPolicy: "block" 可屏蔽直接目标发送,同时仍执行心跳回合。
  • 主队列繁忙时,心跳被跳过,稍后重试。
  • target 解析不到外部目标,心跳仍执行,但不发送出站消息。
  • 仅心跳的回复不会保持会话活跃;updatedAt 恢复原值,空闲过期行为正常。

可见性控制

默认情况下,HEARTBEAT_OK 确认消息被屏蔽,而警报内容正常投递。可按渠道或账号调整:

yaml
channels:
  defaults:
    heartbeat:
      showOk: false # 隐藏 HEARTBEAT_OK(默认)
      showAlerts: true # 显示警报消息(默认)
      useIndicator: true # 发送指示器事件(默认)
  telegram:
    heartbeat:
      showOk: true # 在 Telegram 上显示 OK 确认
  whatsapp:
    accounts:
      work:
        heartbeat:
          showAlerts: false # 该账号不投递警报

优先级:单账号 → 单渠道 → 渠道默认 → 内置默认。

各标志说明

  • showOk:模型返回纯 OK 回复时发送 HEARTBEAT_OK 确认消息。
  • showAlerts:模型返回非 OK 回复时发送警报内容。
  • useIndicator:为 UI 状态面板发送指示器事件。

三者全部为 false,OpenClaw 会完全跳过心跳运行(不调用模型)。

按渠道/按账号示例

yaml
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(可选)

若工作区中存在 HEARTBEAT.md,默认 Prompt 会让 Agent 读取它。把它当作你的"心跳检查列表":精简、稳定,适合每 30 分钟执行一次。

HEARTBEAT.md 实际为空(仅含空行和 Markdown 标题如 # Heading),OpenClaw 会跳过心跳运行以节省 API 调用。若文件不存在,心跳仍正常运行,由模型自行决策。

保持文件简短(短列表或提醒),避免 Prompt 膨胀。

HEARTBEAT.md 示例:

md
# 心跳检查列表

- 快速扫描:收件箱有紧急内容吗?
- 如果是白天,若无其他待处理事项,做一次轻量问候。
- 如果某个任务被阻塞,记录下"缺少什么",下次遇到 Peter 时询问。

Agent 能更新 HEARTBEAT.md 吗?

可以——只要你让它这样做。

HEARTBEAT.md 只是 Agent 工作区中的普通文件,你可以在普通对话中这样说:

  • "更新 HEARTBEAT.md,加入每日日历检查。"
  • "重写 HEARTBEAT.md,让它更简短,专注于收件箱跟进。"

如需主动更新,也可在心跳 Prompt 中加入这样一行:"若检查列表已过时,更新 HEARTBEAT.md。"

安全提示:不要在 HEARTBEAT.md 中放置密钥(API Key、电话号码、私密 Token)——它会成为 Prompt 上下文的一部分。

手动唤醒(按需触发)

可以入队一个系统事件并立即触发心跳:

bash
openclaw system event --text "检查是否有紧急跟进" --mode now

若多个 Agent 配置了 heartbeat,手动唤醒会立即触发每个 Agent 的心跳。

使用 --mode next-heartbeat 等待下一个计划触发点。

推理投递(可选)

默认情况下,心跳只投递最终"答案"载荷。

如需透明度,启用:

  • agents.defaults.heartbeat.includeReasoning: true

启用后,心跳还会额外投递一条以 Reasoning: 为前缀的独立消息(格式与 /reasoning on 相同)。这在 Agent 管理多个会话/代码库时很有用——你可以看到它为什么决定 Ping 你——但也可能暴露比你想要的更多内部细节。在群聊中建议保持关闭。

费用意识

心跳运行完整的 Agent 回合,间隔越短消耗的 Token 越多。降低费用的方式:

  • 使用 isolatedSession: true,避免发送完整对话历史(从约 10 万 Token 降至约 2-5K)。
  • 使用 lightContext: true,将引导文件限制为仅 HEARTBEAT.md
  • 设置更便宜的 model(如 ollama/llama3.2:1b)。
  • 保持 HEARTBEAT.md 简短。
  • 若只需内部状态更新,使用 target: "none"