Skip to content

Heartbeat 让 OpenClaw 智能体在主会话中定期主动巡检,默认每30分钟触发一次(Anthropic OAuth/token 认证时1小时)。支持配置投递目标(last、指定渠道或 none)、活跃时段、隔离会话和 HEARTBEAT.md 任务块来减少 Token 消耗。设置 target: "last" 可将结果发送到最后联系人,isolatedSession: true 避免每次携带完整对话历史。

OpenClaw Heartbeat 心跳配置与排查

INFO

Heartbeat vs cron? 参见 Automation 了解何时选哪种。

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

Heartbeat 是一个定时的主会话回合——它不会创建后台任务记录。任务记录用于独立后台工作(ACP 运行、子智能体、隔离的 cron 任务)。

排障:定时任务故障排查

快速上手:心跳怎么配置

选择心跳频率

保持默认启用(默认 `30m`,使用 Anthropic OAuth/token 认证时 `1h`,包括 Claude CLI 复用),或自定义间隔。

创建 HEARTBEAT.md(可选)

在智能体工作区创建一个精简的 `HEARTBEAT.md` 检查列表或 `tasks:` 块。

决定心跳消息投递到哪

默认 `target: "none"`(仅内部运行,不对外发送);设置 `target: "last"` 路由到最近联系人。

可选调优

- 启用心跳推理投递(`includeReasoning: true`)以便查看模型思考过程。
- 使用轻量引导上下文(`lightContext: true`)仅保留 `HEARTBEAT.md`。
- 启用隔离会话(`isolatedSession: true`)避免每次心跳携带完整对话历史。
- 限制心跳在活跃时段(`activeHours` 按本地时间)。

配置示例:

json5
{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "last", // 明确投递到最近联系人(默认 "none")
        directPolicy: "allow", // 默认允许直接/私聊目标;设为 "block" 屏蔽
        lightContext: true, // 可选:仅从引导文件注入 HEARTBEAT.md
        isolatedSession: true, // 可选:每次心跳使用全新会话(无对话历史)
        skipWhenBusy: true, // 可选:当该智能体的子智能体或嵌套通道繁忙时也推迟
        // activeHours: { start: "08:00", end: "24:00" },
        // includeReasoning: true, // 可选:同时发送独立 Thinking 消息
      },
    },
  },
}

默认值

  • 间隔:30m(检测到 Anthropic OAuth/token 认证,包括 Claude CLI 复用时为 1h)。可通过 agents.defaults.heartbeat.every 或单智能体 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" 段落并标记为心跳运行。
  • 当心跳用 0m 禁用时,正常运行也会从引导上下文中移除 HEARTBEAT.md,以免模型看到仅针对心跳的指令。
  • 活跃时段(heartbeat.activeHours)按配置的时区判断。窗口外的心跳被跳过,直到下一个窗口内的触发点。
  • 有 cron 工作活跃或排队时,心跳会自动推迟。设置 heartbeat.skipWhenBusy: true 还会在智能体自己的会话键子智能体或嵌套指令通道繁忙时推迟;同级智能体不再因其他智能体有子智能体飞行工作而暂停。

心跳 Prompt 有什么用

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

  • 后台任务:"Consider outstanding tasks" 引导智能体检查跟进事项(收件箱、日历、提醒、待办工作)并汇报紧急内容。
  • 人文关怀:"Checkup sometimes on your human during day time" 引导偶尔发出一条"有什么需要帮忙的吗?",但通过配置本地时区避免深夜打扰(参见 Timezone)。

Heartbeat 可以响应已完成的后台任务,但 heartbeat 运行本身不会创建任务记录。

如需心跳执行非常具体的任务(如"检查 Gmail PubSub 统计"或"验证 Gateway 健康"),请将 agents.defaults.heartbeat.prompt(或 agents.list[].heartbeat.prompt)设为自定义内容(原文发送)。

响应约定

  • 若无需关注的内容,回复 HEARTBEAT_OK
  • 工具支持的心跳运行可以通过 heartbeat_respond 工具返回:notify: false 无可见更新,notify: truenotificationText 发送警报。当结构化工具响应存在时,优先于文本回退。
  • 心跳运行期间,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(可用时另发独立 Thinking 消息)
        lightContext: false, // 默认:false;true 时仅保留工作区引导文件中的 HEARTBEAT.md
        isolatedSession: false, // 默认:false;true 时每次心跳使用全新会话(无对话历史)
        skipWhenBusy: false, // 默认:false;true 时也在该智能体的子智能体/嵌套通道繁忙时推迟
        target: "last", // 默认:none | 选项:last | none | <channel id>(核心或插件,如 "imessage")
        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 在其上合并;若任意智能体有 heartbeat 块,仅那些智能体执行心跳。
  • channels.defaults.heartbeat 设置所有渠道的可见性默认值。
  • channels.&lt;channel&gt;.heartbeat 覆盖渠道默认值。
  • channels.&lt;channel&gt;.accounts.&lt;id&gt;.heartbeat(多账号渠道)覆盖单渠道配置。

按智能体配置心跳

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

示例:两个智能体,只有第二个执行心跳。

json5
{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "last", // 明确投递到最近联系人(默认 "none")
      },
    },
    list: [
      { id: "main", default: true },
      {
        id: "ops",
        heartbeat: {
          every: "1h",
          target: "whatsapp",
          to: "+15551234567",
          timeoutSeconds: 45,
          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" }

WARNING

不要将 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 string

心跳间隔(时长字符串;默认单位为分钟)。

model string

可选模型覆盖(provider/model),用于心跳运行。

includeReasoning boolean

启用时,同时投递可用的独立 Thinking 消息(格式与 /reasoning on 相同)。

lightContext boolean

为 true 时,心跳运行使用轻量引导上下文,仅保留工作区引导文件中的 HEARTBEAT.md

isolatedSession boolean

为 true 时,每次心跳在无历史对话的全新会话中运行。与 cron sessionTarget: "isolated" 使用相同的隔离模式。可大幅降低每次心跳的 Token 消耗。结合 lightContext: true 效果最佳。投递路由仍使用主会话上下文。

skipWhenBusy boolean

为 true 时,心跳在该智能体的额外繁忙通道(自己的会话键子智能体或嵌套指令工作)上推迟。即使没有该标志,cron 通道总是延迟心跳,所以本地模型主机不会同时运行 cron 和心跳提示。

session string

可选会话键。

  • main(默认):智能体主会话。
  • 显式会话键(从 openclaw sessions --jsonsessions CLI 复制)。
  • 会话键格式:参见 SessionsGroups

target string

  • last:投递到最近使用的外部渠道。
  • 显式渠道:任意已配置的渠道或插件 ID,例如 discordmatrixtelegramwhatsapp
  • none(默认):执行心跳但不外部投递

directPolicy

控制直接/私聊投递行为。allow:允许直接/私聊心跳投递。block:屏蔽直接/私聊投递(reason=dm-blocked)。

to string

可选收件人覆盖(渠道专属 ID,如 WhatsApp 的 E.164 格式或 Telegram 的 chat ID)。Telegram 话题/线程格式:<chatId>:topic:<messageThreadId>

accountId string

多账号渠道的可选账号 ID。当 target: "last" 时,若解析到的渠道支持账号,该 ID 会应用到该渠道;否则忽略。若账号 ID 不匹配该渠道的配置账号,则跳过投递。

prompt string

覆盖默认 Prompt 正文(不合并)。

ackMaxChars number

投递前 HEARTBEAT_OK 后允许的最大字符数。

suppressToolErrorWarnings boolean

为 true 时,心跳运行期间不发送工具错误警告载荷。

activeHours object

将心跳限制在时间窗口内。对象包含 start(HH:MM,含;全天开始用 00:00)、end(HH:MM,不含;全天结束允许 24:00)以及可选的 timezone

  • 省略或 "user":使用 agents.defaults.userTimezone(如已设置),否则回退到主机系统时区。
  • "local":始终使用主机系统时区。
  • 任意 IANA 标识符(如 America/New_York):直接使用;无效时回退到 "user" 行为。
  • startend 相等时视为零宽度窗口(始终在窗口外)。
  • 在活跃窗口外时,心跳被跳过,直到下一个窗口内的调度点。

投递行为

会话与目标路由

- 心跳默认在智能体主会话(`agent:&lt;id&gt;:<mainKey>`)中运行,`session.scope = "global"` 时为 `global`。设置 `session` 可覆盖到特定渠道会话(Discord/WhatsApp 等)。
- `session` 只影响运行上下文;投递由 `target` 和 `to` 控制。
- 如需投递到特定渠道/收件人,设置 `target` + `to`。`target: "last"` 时使用该会话的最近外部渠道。
- 心跳投递默认允许直接/私聊目标。设置 `directPolicy: "block"` 可屏蔽直接目标发送,同时仍执行心跳回合。
- 若主队列、目标会话通道、cron 通道或活跃的 cron 作业繁忙,心跳被跳过并稍后重试。
- 若 `skipWhenBusy: true`,该智能体的会话键子智能体和嵌套通道也会延迟心跳。其他智能体的繁忙通道不会延迟本智能体。
- 若 `target` 解析不到外部目标,心跳仍执行,但不发送出站消息。

可见性与跳过行为

- 若 `showOk`、`showAlerts`、`useIndicator` 三者全部禁用,心跳在最开始就以 `reason=alerts-disabled` 跳过。
- 若仅禁用警报投递,OpenClaw 仍可运行心跳、更新到期任务时间戳、恢复会话空闲时间戳,并抑制向外投递的警报载荷。
- 若解析的心跳目标支持打字指示,OpenClaw 会在心跳运行时显示打字状态。这使用与发送聊天输出相同的目标,可由 `typingMode: "never"` 禁用。

会话生命周期与审计

- 仅心跳的回复**不会**保持会话活跃。心跳元数据可能更新会话行,但空闲过期使用 `lastInteractionAt`(来自最后一条真实用户/渠道消息),每日过期使用 `sessionStartedAt`。
- 控制 UI 和 WebChat 历史隐藏心跳提示和仅 OK 的确认。底层会话转述仍可包含这些轮次以供审计/重放。
- 独立[后台任务](/ai/ai-tools/openclaw/automation/tasks)可以入队一个系统事件,在主会话需要快速感知时唤醒心跳。该唤醒不会使心跳运行成为后台任务。

可见性控制

默认情况下,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 会让智能体读取它。把它当作你的"心跳检查列表":精简、稳定,适合每 30 分钟执行一次。

在正常运行时,仅当默认智能体启用心跳指导时才会注入 HEARTBEAT.md。用 0m 禁用心跳频率或设置 includeSystemPromptSection: false 会将其从正常引导上下文中移除。

在原生 Codex 引擎上,HEARTBEAT.md 内容不会注入到轮次中。如果文件存在且包含非空白内容,心跳协作模式指令会指向 Codex 并告诉它在继续前阅读文件。

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

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

示例 HEARTBEAT.md

md
# Heartbeat checklist

- Quick scan: anything urgent in inboxes?
- If it's daytime, do a lightweight check-in if nothing else is pending.
- If a task is blocked, write down _what is missing_ and ask Peter next time.

tasks:

HEARTBEAT.md 还支持小型结构化 tasks: 块,用于在心跳内部做基于间隔的定时检查。

示例:

md
tasks:

- name: inbox-triage
  interval: 30m
  prompt: "检查是否有紧急未读邮件,标记时间敏感的内容。"
- name: calendar-scan
  interval: 2h
  prompt: "检查即将到来的会议是否需要准备或跟进。"

# 附加说明

- 保持提醒简短。
- 所有到期任务完成后若无需关注,回复 HEARTBEAT_OK。

行为

- OpenClaw 解析 `tasks:` 块,按各自的 `interval` 检查是否到期。
- 当次心跳的 Prompt 中**仅包含**到期的任务。
- 若没有任务到期,心跳完全跳过(`reason=no-tasks-due`),避免无效模型调用。
- `HEARTBEAT.md` 中非 tasks 内容保留,追加在到期任务列表后作为额外上下文。
- 任务上次运行时间戳存储在会话状态(`heartbeatTaskState`),间隔在正常重启后依然有效。
- 任务时间戳仅在心跳运行完成其正常回复流程后才推进。`empty-heartbeat-file` / `no-tasks-due` 的跳过运行不标记任务为已完成。

Tasks 模式适合在一个心跳文件中管理多个不同频率的定期检查,而不必每次都执行全部检查。

智能体能更新 HEARTBEAT.md 吗?

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

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

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

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

WARNING

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

手动唤醒(按需触发)

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

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

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

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

推理投递(可选)

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

如需透明度,启用:

  • agents.defaults.heartbeat.includeReasoning: true

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

费用意识

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

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

心跳后上下文溢出处理

如果心跳之前在较小上下文窗口的本地模型上(例如 Ollama 32k 窗口)留下了会话,并且下一次主会话轮次报告上下文溢出,请将会话运行时模型重置回配置的主模型。OpenClaw 的重置消息会在最后一次运行时模型匹配配置的 heartbeat.model 时调用说明。

当前心跳在运行完成后会保留共享会话的现有运行时模型。你仍然可以使用 isolatedSession: true 让心跳在新会话中运行,结合 lightContext: true 获得最小的提示,或者选择一个上下文窗口足够大的心跳模型用于共享会话。

相关文档

常见问题

为什么不发送心跳消息?

检查 target 配置:默认为 "none",不会对外发送。设为 "last" 或指定渠道 ID。同时确认 showOkshowAlerts 没有被全部禁用(false),否则心跳会直接被跳过(reason=alerts-disabled)。查看 OpenClaw 日志中是否有 reason=dm-blockedreason=empty-heartbeat-file

心跳太贵,怎么减少 Token 消耗?

使用 isolatedSession: true 避免发送完整对话历史(约 100K Token 降至 2-5K),配合 lightContext: true 仅保留 HEARTBEAT.md。也可以设置一个更便宜的模型(如 ollama/llama3.2:1b),并保持 HEARTBEAT.md 简短。若只需内部状态更新,设 target: "none" 不发送外部消息。

HEARTBEAT_OK 是什么意思?

智能体确认无需关注内容时回复 HEARTBEAT_OK。OpenClaw 会从回复开头或结尾识别该 token,如果剩余内容 ≤ ackMaxChars(默认300字符)则丢弃整条消息,不在聊天中显示。如果该 token 出现在回复中间,则不特殊处理。