网关
Heartbeat
Heartbeat 会在主会话中运行周期性智能体轮次,使模型能够主动发现任何需要关注的事项,同时避免向你发送过多消息。
Heartbeat 是按计划运行的主会话轮次——它不会创建后台任务记录。任务记录用于脱离主会话执行的工作(ACP 运行、子智能体、隔离的 cron 作业)。
故障排查:定时任务
快速开始(初学者)
Pick a cadence
保持 Heartbeat 启用(默认为 30m;配置 Anthropic OAuth/令牌身份验证时为 1h,包括复用 Claude CLI),或设置你自己的运行频率。
Add HEARTBEAT.md (optional)
在 Agent 工作区中创建一个简短的 HEARTBEAT.md 检查清单或 tasks: 块。
Decide where heartbeat messages should go
默认值为 target: "none";设置 target: "last" 可将消息路由到最近的联系人。
Optional tuning
- 启用 Heartbeat 推理过程传递,以提高透明度。
- 如果 Heartbeat 运行只需要
HEARTBEAT.md,请使用轻量级引导上下文。 - 启用隔离会话,避免每次 Heartbeat 都发送完整的对话历史记录。
- 将 Heartbeat 限制在活跃时段(本地时间)。
配置示例:
{ agents: { defaults: { heartbeat: { every: "30m", target: "last", // explicit delivery to last contact (default is "none") directPolicy: "allow", // default: allow direct/DM targets; set "block" to suppress lightContext: true, // optional: only inject HEARTBEAT.md from bootstrap files isolatedSession: true, // optional: fresh session each run (no conversation history) skipWhenBusy: true, // optional: also defer when this agent's subagent or nested lanes are busy // activeHours: { start: "08:00", end: "24:00" }, // includeReasoning: true, // optional: send separate `Thinking` message too }, }, },}默认值
- 间隔:
30m。应用 Anthropic 提供商默认值后,如果解析出的身份验证模式为 OAuth/令牌(包括复用 Claude CLI),间隔会增加到1h,但仅在未设置heartbeat.every时生效。可设置agents.defaults.heartbeat.every或各智能体的agents.list[].heartbeat.every;使用0m可禁用。 - 提示词正文(可通过
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. - 超时:未单独设置的 Heartbeat 轮次会在
agents.defaults.timeoutSeconds已配置时使用该值。否则,它们使用 Heartbeat 运行间隔,但上限为 600 秒。若 Heartbeat 工作需要更长时间,请设置agents.defaults.heartbeat.timeoutSeconds或各智能体的agents.list[].heartbeat.timeoutSeconds。 - Heartbeat 提示词会作为用户消息原样发送。仅当默认智能体启用了 Heartbeat(且
includeSystemPromptSection不为false)时,系统提示词才会包含“Heartbeats”部分,并且该运行会在内部进行标记。 - 使用
0m禁用 Heartbeat 后,常规运行也会从引导上下文中省略HEARTBEAT.md,使模型不会看到仅用于 Heartbeat 的指令。 - 活跃时段(
heartbeat.activeHours)会按照配置的时区进行检查。在时间窗口之外,Heartbeat 会被跳过,直到窗口内的下一个周期。 - 当 cron 工作正在运行或排队时,Heartbeat 会自动延后。设置
heartbeat.skipWhenBusy: true后,如果某个智能体自身基于会话键的子智能体或嵌套命令通道正忙,也会延后该智能体的 Heartbeat;其他同级智能体不会再仅仅因为另一个智能体正在执行子智能体工作而暂停。
Heartbeat 提示词的用途
默认提示词有意保持宽泛:
- 后台任务:“考虑尚未完成的任务”会促使智能体检查待办事项(收件箱、日历、提醒、排队的工作),并主动报告任何紧急事项。
- 主动关心用户:“白天偶尔询问用户的情况”会促使智能体偶尔发送简短的“有什么需要吗?”消息,同时使用你配置的本地时区来避免在夜间频繁打扰(请参阅时区)。
Heartbeat 可以响应已完成的后台任务,但 Heartbeat 运行本身不会创建任务记录。
如果希望 Heartbeat 执行非常具体的操作(例如“检查 Gmail PubSub 统计信息”或“验证 Gateway 健康”),请将 agents.defaults.heartbeat.prompt(或 agents.list[].heartbeat.prompt)设置为自定义正文(将原样发送)。
响应约定
- 如果没有需要关注的事项,请回复
HEARTBEAT_OK。 - Heartbeat 运行也可以改为调用
heartbeat_respond:使用notify: false表示不提供可见更新,或使用notify: true并附带notificationText发出提醒。如果存在结构化工具响应,它的优先级高于文本回退响应。 - 在 Heartbeat 运行期间,如果
HEARTBEAT_OK出现在回复的开头或结尾,OpenClaw 会将其视为确认。该令牌会被移除;如果剩余内容的长度不超过ackMaxChars(默认值:300),整条回复会被丢弃。 - 如果
HEARTBEAT_OK出现在回复的中间,则不会受到特殊处理。 - 对于提醒,不要包含
HEARTBEAT_OK;只返回提醒文本。
在 Heartbeat 之外,如果消息开头或结尾意外出现 HEARTBEAT_OK,它会被移除并记入日志;仅包含 HEARTBEAT_OK 的消息会被丢弃。
配置
{ agents: { defaults: { heartbeat: { every: "30m", // default: 30m (0m disables) model: "anthropic/claude-opus-4-6", includeReasoning: false, // default: false (deliver separate Thinking message when available) lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files isolatedSession: false, // default: false; true runs each heartbeat in a fresh session (no conversation history) skipWhenBusy: false, // default: false; true also waits for this agent's subagent/nested lanes target: "last", // default: none | options: last | none | <channel id> (core or plugin, e.g. "imessage") to: "+15551234567", // optional channel-specific override accountId: "ops-bot", // optional multi-account channel 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.", includeSystemPromptSection: true, // default: true; false omits the ## Heartbeats system prompt section for the default agent ackMaxChars: 300, // max chars allowed after HEARTBEAT_OK }, }, },}作用域和优先级
agents.defaults.heartbeat设置全局 Heartbeat 行为。agents.list[].heartbeat在此基础上合并;如果任何智能体包含heartbeat块,则只有这些智能体会运行 Heartbeat。channels.defaults.heartbeat设置所有渠道的可见性默认值。channels.<channel>.heartbeat覆盖渠道默认值。channels.<channel>.accounts.<id>.heartbeat(多账户渠道)覆盖各渠道设置。
各智能体的 Heartbeat
如果任何 agents.list[] 条目包含 heartbeat 块,则只有这些智能体会运行 Heartbeat。各智能体的配置块会在 agents.defaults.heartbeat 基础上合并(因此你可以统一设置共享默认值,并为各智能体覆盖这些值)。
示例:两个智能体中,只有第二个智能体运行 Heartbeat。
{ agents: { defaults: { heartbeat: { every: "30m", target: "last", // explicit delivery to last contact (default is "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.", }, }, ], },}活跃时段示例
将 Heartbeat 限制在指定时区的工作时间内:
{ agents: { defaults: { heartbeat: { every: "30m", target: "last", // explicit delivery to last contact (default is "none") activeHours: { start: "09:00", end: "22:00", timezone: "America/New_York", // optional; uses your userTimezone if set, otherwise host tz }, }, }, },}在此时间窗口之外(美国东部时间上午 9 点之前或晚上 10 点之后),Heartbeat 会被跳过。窗口内的下一个计划周期会正常运行。
全天候设置
如果希望 Heartbeat 全天运行,请使用以下任一方式:
- 完全省略
activeHours(不限制时间窗口;这是默认行为)。 - 设置全天时间窗口:
activeHours: { start: "00:00", end: "24:00" }。
多账户示例
在 Telegram 等多账户渠道上,使用 accountId 指定特定账户:
{ agents: { list: [ { id: "ops", heartbeat: { every: "1h", target: "telegram", to: "12345678:topic:42", // optional: route to a specific topic/thread accountId: "ops-bot", }, }, ], }, channels: { telegram: { accounts: { "ops-bot": { botToken: "YOUR_TELEGRAM_BOT_TOKEN" }, }, }, },}字段说明
everystringHeartbeat 间隔(持续时间字符串;默认单位为分钟)。
modelstringHeartbeat 运行的可选模型覆盖值(provider/model)。
includeReasoningbooleandefault: false启用后,在可用时还会传递单独的 Thinking 消息(格式与 /reasoning on 相同)。
lightContextbooleandefault: false为 true 时,Heartbeat 运行会使用轻量级引导上下文,并且仅从工作区引导文件中保留 HEARTBEAT.md。
isolatedSessionbooleandefault: false为 true 时,每次 Heartbeat 都会在没有先前对话历史记录的新会话中运行。它使用与 cron sessionTarget: "isolated" 相同的隔离模式。这会大幅降低每次 Heartbeat 的令牌成本。与 lightContext: true 配合使用可最大程度节省成本。传递路由仍然使用主会话上下文。
skipWhenBusybooleandefault: false为 true 时,如果该智能体的额外繁忙通道正在工作,Heartbeat 运行会延后:包括其自身基于会话键的子智能体或嵌套命令工作。即使没有此标志,cron 通道也始终会延后 Heartbeat,因此本地模型主机不会同时运行 cron 和 Heartbeat 提示词。
sessionstringHeartbeat 运行的可选会话键。
targetstringlast:传递到最近使用的外部渠道。- 显式渠道:任何已配置的渠道或插件 ID,例如
discord、matrix、telegram或whatsapp。 none(默认):运行 Heartbeat,但不向外部传递。
directPolicy"allow" | "block"default: allow控制直接消息/私信的传递行为。allow:允许通过直接消息/私信传递 Heartbeat。block:禁止通过直接消息/私信传递(reason=dm-blocked)。
tostring可选的收件人覆盖值(特定于渠道的 ID,例如 WhatsApp 使用 E.164,Telegram 使用聊天 ID)。对于 Telegram 话题/线程,请使用 <chatId>:topic:<messageThreadId>。
accountIdstring多账户渠道的可选账户 ID。当 target: "last" 时,如果解析出的最后一个渠道支持账户,该账户 ID 将应用于该渠道;否则会被忽略。如果账户 ID 与解析出的渠道中已配置的账户不匹配,则跳过投递。
promptstring覆盖默认提示词正文(不会合并)。
includeSystemPromptSectionbooleandefault: true是否注入默认智能体系统提示词中的 ## Heartbeats 部分。设为 false 可保留 Heartbeat 运行时行为(频率、投递、HEARTBEAT.md),同时从智能体系统提示词中省略 Heartbeat 指令。
ackMaxCharsnumberdefault: 300投递前,HEARTBEAT_OK 后允许的最大字符数。
suppressToolErrorWarningsboolean为 true 时,在 Heartbeat 运行期间抑制工具错误警告载荷。
timeoutSecondsnumberdefault: global timeout or min(every, 600)Heartbeat 智能体轮次在中止前允许运行的最大秒数。保持未设置时,如果已设置 agents.defaults.timeoutSeconds,则使用该值;否则使用 Heartbeat 频率,且上限为 600 秒。
activeHoursobject将 Heartbeat 运行限制在某个时间窗口内。对象包含 start(HH:MM,包含该时刻;使用 00:00 表示一天开始)、end(HH:MM,不包含该时刻;允许使用 24:00 表示一天结束)以及可选的 timezone。
- 省略或设为
"user":如果已设置agents.defaults.userTimezone,则使用该值;否则回退到主机系统时区。 "local":始终使用主机系统时区。- 任意 IANA 标识符(例如
America/New_York):直接使用;如果无效,则回退到上述"user"行为。 - 对于有效时间窗口,
start和end不得相同;相同的值会被视为零宽度窗口(始终处于窗口外)。 - 在有效时间窗口之外,将跳过 Heartbeat,直到窗口内的下一个触发时刻。
投递行为
会话和目标路由
- Heartbeat 默认在智能体的主会话中运行(
agent:<id>:<mainKey>);当session.scope = "global"时则在global中运行。设置session可覆盖为特定的渠道会话(Discord、WhatsApp 等)。 session仅影响运行上下文;投递由target和to控制。- 要投递到特定渠道/收件人,请设置
target+to。使用target: "last"时,投递将使用该会话最后使用的外部渠道。 - Heartbeat 投递默认允许直接目标/私信目标。设置
directPolicy: "block"可抑制向直接目标发送消息,同时仍运行 Heartbeat 轮次。 - 如果主队列、目标会话通道、cron 通道或某个正在运行的 cron 作业繁忙,则跳过 Heartbeat,并在稍后重试。
- 如果设置
skipWhenBusy: true,该智能体按会话键区分的子智能体通道和嵌套通道也会推迟 Heartbeat 运行。其他智能体的繁忙通道不会推迟此智能体。 - 如果
target未解析到任何外部目的地,运行仍会发生,但不会发送出站消息。
可见性和跳过行为
- 如果
showOk、showAlerts和useIndicator均被禁用,则运行会预先以reason=alerts-disabled为由跳过。 - 如果仅禁用了提醒投递,OpenClaw 仍可运行 Heartbeat、更新到期任务时间戳、恢复会话空闲时间戳,并抑制对外提醒载荷。
- 如果解析出的 Heartbeat 目标支持输入状态,OpenClaw 会在 Heartbeat 运行期间显示正在输入。它使用 Heartbeat 原本会向其发送聊天输出的同一目标,并可通过
typingMode: "never"禁用。
会话生命周期和审计
- 仅由 Heartbeat 产生的回复不会使会话保持活跃。Heartbeat 元数据可能会更新会话行,但空闲过期使用上次真实用户/渠道消息的
lastInteractionAt,每日过期使用sessionStartedAt。 - Control UI 和 WebChat 历史记录会隐藏 Heartbeat 提示词和仅含 OK 的确认。底层会话记录仍可包含这些轮次,以供审计/重放。
- 分离的后台任务可以将系统事件加入队列,并在主会话需要快速注意某件事时唤醒 Heartbeat。该唤醒操作不会使 Heartbeat 运行变成后台任务。
可见性控制
默认情况下,HEARTBEAT_OK 确认会被抑制,而提醒内容会正常投递。你可以按渠道或账户调整此行为:
channels: defaults: heartbeat: showOk: false # Hide HEARTBEAT_OK (default) showAlerts: true # Show alert messages (default) useIndicator: true # Emit indicator events (default) telegram: heartbeat: showOk: true # Show OK acknowledgments on Telegram whatsapp: accounts: work: heartbeat: showAlerts: false # Suppress alert delivery for this account优先级:按账户 → 按渠道 → 渠道默认值 → 内置默认值。
每个标志的作用
showOk:当模型仅返回 OK 回复时,发送HEARTBEAT_OK确认。showAlerts:当模型返回非 OK 回复时,发送提醒内容。useIndicator:为 UI 状态界面发出指示器事件。
如果三者全部为 false,OpenClaw 将完全跳过 Heartbeat 运行(不会调用模型)。
按渠道与按账户示例
channels: defaults: heartbeat: showOk: false showAlerts: true useIndicator: true slack: heartbeat: showOk: true # all Slack accounts accounts: ops: heartbeat: showAlerts: false # suppress alerts for the ops account only 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 文件,默认提示词会要求智能体读取该文件。可以将它视为你的“Heartbeat 检查清单”:内容简短、稳定,并且适合每 30 分钟检查一次。
在正常运行中,仅当默认智能体启用了 Heartbeat 指引时,才会注入 HEARTBEAT.md。使用 0m 禁用 Heartbeat 频率或设置 includeSystemPromptSection: false,会将其从正常的引导上下文中省略。
在原生 Codex harness 中,HEARTBEAT.md 的内容不会像其他引导文件那样注入轮次。如果该文件存在且包含非空白内容,Heartbeat 协作模式说明会将 Codex 指向该文件,并要求其在继续之前读取文件。
如果 HEARTBEAT.md 存在但实际上为空(仅包含空行、Markdown/HTML 注释、类似 # Heading 的 Markdown 标题、围栏标记或空的检查清单占位项),OpenClaw 会跳过 Heartbeat 运行以节省 API 调用。该跳过会报告为 reason=empty-heartbeat-file。如果文件不存在,Heartbeat 仍会运行,由模型决定要执行的操作。
保持内容精简(简短的检查清单或提醒),以避免提示词膨胀。
HEARTBEAT.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: 块,用于在 Heartbeat 内执行基于时间间隔的检查。
示例:
tasks: - name: inbox-triage interval: 30m prompt: "Check for urgent unread emails and flag anything time sensitive."- name: calendar-scan interval: 2h prompt: "Check for upcoming meetings that need prep or follow-up." # Additional instructions - Keep alerts short.- If nothing needs attention after all due tasks, reply HEARTBEAT_OK.行为
- OpenClaw 会解析
tasks:块,并根据每项任务自己的interval检查任务。 - 只有到期任务会包含在该次触发的 Heartbeat 提示词中。
- 如果没有任务到期,则完全跳过 Heartbeat(
reason=no-tasks-due),以避免浪费一次模型调用。 HEARTBEAT.md中的非任务内容会保留,并在到期任务列表之后作为附加上下文追加。- 任务上次运行时间戳存储在会话状态(
heartbeatTaskState)中,因此时间间隔状态可在正常重启后保留。 - 只有 Heartbeat 运行完成正常回复流程后,任务时间戳才会向前更新。被跳过的
empty-heartbeat-file/no-tasks-due运行不会将任务标记为已完成。
当你希望用一个 Heartbeat 文件保存多项定期检查,又不想在每次触发时为所有检查付出调用成本时,任务模式非常有用。
智能体可以更新 HEARTBEAT.md 吗?
可以——只要你要求它这样做。
HEARTBEAT.md 只是智能体工作区中的普通文件,因此你可以在正常聊天中告诉智能体,例如:
- “更新
HEARTBEAT.md,添加每日日历检查。” - “重写
HEARTBEAT.md,使其更简短,并专注于收件箱跟进事项。”
如果你希望主动执行此操作,也可以在 Heartbeat 提示词中包含明确的一行,例如:“如果检查清单已经过时,请用更好的内容更新 HEARTBEAT.md。”
手动唤醒(按需)
使用 openclaw system event 将系统事件加入队列,并可选择立即触发一次 Heartbeat:
openclaw system event --text "Check for urgent follow-ups" --mode now| 标志 | 说明 |
|---|---|
--text <text> |
系统事件文本(必需)。 |
--mode <mode> |
now 会立即运行一次 Heartbeat;next-heartbeat(默认)会等待下一个计划触发时刻。 |
--session-key <sessionKey> |
将事件发送到特定会话;默认为智能体的主会话。 |
--json |
输出 JSON。 |
如果未提供 --session-key,并且多个智能体配置了 heartbeat,则 --mode now 会立即运行其中每个智能体的 Heartbeat。
同一 CLI 组中的相关 Heartbeat 控制命令:
openclaw system heartbeat last # show the last heartbeat eventopenclaw system heartbeat enable # enable heartbeatsopenclaw system heartbeat disable # disable heartbeats推理投递(可选)
默认情况下,Heartbeat 仅传送最终的“回答”载荷。
如果你希望提高透明度,请启用:
agents.defaults.heartbeat.includeReasoning: true
启用后,Heartbeat 还会传送一条单独的消息,并以 Thinking 为前缀(格式与 /reasoning on 相同)。当智能体管理多个会话或 Codex 实例,而你想了解它为何决定向你发送提醒时,这会很有用;但它也可能泄露超出你预期的内部细节。在群聊中,建议保持关闭。
成本考量
Heartbeat 会运行完整的智能体轮次。间隔越短,消耗的 token 越多。要降低成本:
- 使用
isolatedSession: true,避免发送完整的对话历史记录(每次运行的 token 数可从约 10 万降至约 2,000–5,000)。 - 使用
lightContext: true,将引导文件限制为仅HEARTBEAT.md。 - 设置成本更低的
model(例如ollama/llama3.2:1b)。 - 尽量精简
HEARTBEAT.md。 - 如果只需要内部状态更新,请使用
target: "none"。
Heartbeat 后上下文溢出
Heartbeat 运行完成后,会保留共享会话中现有的运行时模型。因此,如果某次 Heartbeat 将会话切换到上下文窗口较小的本地模型(例如上下文窗口为 32k 的 Ollama 模型),该模型可能会继续用于主会话的下一轮对话。如果下一轮随后报告上下文溢出,并且会话上次使用的运行时模型与配置的 heartbeat.model 相同,OpenClaw 的恢复消息会指出 Heartbeat 模型残留很可能是原因,并建议修复方法。
要避免此问题:使用 isolatedSession: true 在新会话中运行 Heartbeat(还可搭配 lightContext: true,以获得最精简的提示词),或者选择上下文窗口足以容纳共享会话的 Heartbeat 模型。