Appearance
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: true加notificationText发送警报。当结构化工具响应存在时,优先于文本回退。 - 心跳运行期间,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.<channel>.heartbeat覆盖渠道默认值。channels.<channel>.accounts.<id>.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
不要将 start 和 end 设为相同时间(如 08:00 到 08: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 --json或 sessions CLI 复制)。 - 会话键格式:参见 Sessions 和 Groups。
target string
last:投递到最近使用的外部渠道。- 显式渠道:任意已配置的渠道或插件 ID,例如
discord、matrix、telegram、whatsapp。 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"行为。 start和end相等时视为零宽度窗口(始终在窗口外)。- 在活跃窗口外时,心跳被跳过,直到下一个窗口内的调度点。
投递行为
会话与目标路由
- 心跳默认在智能体主会话(`agent:<id>:<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 } |
| 仅在某渠道显示 OK | channels.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 获得最小的提示,或者选择一个上下文窗口足够大的心跳模型用于共享会话。
相关文档
- Automation — 所有自动化机制一览
- Background Tasks — 独立后台工作如何跟踪
- Timezone — 时区如何影响心跳调度
- Troubleshooting — 调试自动化问题
常见问题
为什么不发送心跳消息?
检查 target 配置:默认为 "none",不会对外发送。设为 "last" 或指定渠道 ID。同时确认 showOk 和 showAlerts 没有被全部禁用(false),否则心跳会直接被跳过(reason=alerts-disabled)。查看 OpenClaw 日志中是否有 reason=dm-blocked 或 reason=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 出现在回复中间,则不特殊处理。