





















openclaw遇到问题:
OPENCLAW TERMINATE SOCKET: Ping Pong does not transfer heartbeat within heartbeat intervall

找了一下,看起来很多人也都遇到了这个问题,尝试修改配置与解决,记录如下:
修改点:
# 需要更新到最新版本(包含 PR fix: keep reconnecting after runtime reconnect cycle failure #96 的修复)
# 可选配置优化(针对网络不稳定的环境):
{
"channels": {
"dingtalk": {
"maxConnectionAttempts": 20,
"initialReconnectDelay": 1000,
"maxReconnectDelay": 60000,
"reconnectJitter": 0.3
}
}
}
# 已知限制:8 秒心跳间隔是 dingtalk-stream SDK 硬编码的,无法在插件层面修改。如果网络延迟持续超过 8 秒,断连仍会发生,但新版本保证了自动恢复。
此问题发生在 OpenClaw 的 Ping/Pong 心跳机制未能在预期时间间隔内收到 pong 响应时,导致 WebSocket 连接终止。这在长时间空闲或网络不稳定的情况下会发生。
示例:
TERMINATE SOCKET: Ping Pong does not transfer heartbeat within heartbeat intervall
ERROR: WebSocket was closed before the connection was established
根本原因通常与 dingtalk-stream SDK 硬编码的 8 秒心跳间隔有关。如果在此时间内未收到 pong 响应,SDK 将关闭连接。空闲期间的 NAT 超时或路由器重置等网络变化都可能触发此问题。
首先检查心跳是否已启用并正常运行:
openclaw system heartbeat last
openclaw config get agents.defaults.heartbeat
openclaw channels status --probe
如果看到跳过原因如 quiet-hours(安静时段)、requests-in-flight(请求进行中)或 empty-heartbeat-file(心跳文件为空),请相应调整配置。
PR #96 引入了一个关键修复,改进了重连逻辑。在此补丁之前,重连失败可能导致系统卡在 FAILED 状态,直到手动重启。更新后确保即使多次失败也能持续重试直至恢复。强烈建议更新到最新版本。
您还可以针对不稳定网络优化重连设置:
{
"channels": {
"dingtalk": {
"maxConnectionAttempts": 20,
"initialReconnectDelay": 1000,
"maxReconnectDelay": 60000,
"reconnectJitter": 0.3
}
}
}
虽然无法在插件层面更改 8 秒的心跳间隔,但这些设置可确保断开连接后自动恢复。
补充部分参考命令:
Automation Troubleshooting
本页面用于解决调度器和投递相关问题(cron + heartbeat)。
openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probe
然后运行自动化检查:
openclaw cron status
openclaw cron list
openclaw system heartbeat last
openclaw cron status
openclaw cron list
openclaw cron runs --id <jobId> --limit 20
openclaw logs --follow
正常输出示例:
cron status 显示已启用(enabled)且有未来的 nextWakeAtMscron runs 显示 ok 或明确的跳过原因常见特征:
| 特征 | 含义 |
|---|---|
cron: scheduler disabled; jobs will not run automatically |
配置/环境中禁用了 cron |
cron: timer tick failed |
调度器 tick 崩溃;检查周围的堆栈/日志上下文 |
reason: not-due(在 run 输出中) |
未使用 --force 调用手动运行,且任务尚未到期 |
openclaw cron runs --id <jobId> --limit 20
openclaw cron list
openclaw channels status --probe
openclaw logs --follow
正常输出示例:
ok常见特征:
| 特征 | 含义 |
|---|---|
运行成功但投递模式为 none |
不期望外部消息 |
| 投递目标缺失/无效(channel/to) | 运行可能在内部成功,但跳过 outbound |
| 通道认证错误(unauthorized, missing_scope, Forbidden) | 通道凭据/权限阻止了投递 |
openclaw system heartbeat last
openclaw logs --follow
openclaw config get agents.defaults.heartbeat
openclaw channels status --probe
正常输出示例:
ran(或跳过原因可理解)常见特征:
| 特征 | 含义 |
|---|---|
heartbeat skipped with reason=quiet-hours |
超出 activeHours 时间范围 |
requests-in-flight |
主通道繁忙;心跳被推迟 |
empty-heartbeat-file |
间隔心跳被跳过,因为 HEARTBEAT.md 无可操作内容,且无标记的 cron 事件在队列中 |
alerts-disabled |
可见性设置抑制了 outbound 心跳消息 |
openclaw config get agents.defaults.heartbeat.activeHours
openclaw config get agents.defaults.heartbeat.activeHours.timezone
openclaw config get agents.defaults.userTimezone || echo "agents.defaults.userTimezone not set"
openclaw cron list
openclaw logs --follow
快速规则:
agents.defaults.userTimezone 表示该键未设置;心跳回退到主机时区(或如果设置了则使用 activeHours.timezone)--tz 的 Cron:使用网关主机时区常见特征:
activeHours.timezone 设置错误,白天期间心跳总是被跳过相关文档:
/automation/cron-jobs/gateway/heartbeat/automation/cron-vs-heartbeat/concepts/timezone心跳 vs Cron? 请参阅 Cron vs Heartbeat 了解何时使用哪种机制。
心跳在主会话中定期运行 Agent 轮次,使模型能够在不打扰你的情况下提示任何需要注意的事项。
故障排查: /automation/troubleshooting
target: "none" 为默认值;设置 target: "last" 路由到最后联系人)。配置示例:
{
"agents": {
"defaults": {
"heartbeat": {
"every": "30m",
"target": "last", // 显式投递到最后联系人(默认为 "none")
"directPolicy": "allow", // 默认:允许直接/私信目标;设为 "block" 以抑制
// "activeHours": { "start": "08:00", "end": "24:00" },
// "includeReasoning": true, // 可选:同时发送单独的 `Reasoning:` 消息
}
}
}
}
| 配置项 | 说明 |
|---|---|
| 间隔 | 30 分钟(检测到 Anthropic OAuth/设置令牌认证模式时为 1 小时)。设置 agents.defaults.heartbeat.every 或每个 Agent 的 agents.list[].heartbeat.every;使用 0m 禁用。 |
| 提示主体 | 可通过 agents.defaults.heartbeat.prompt 配置:如果存在则读取 HEARTBEAT.md(工作区上下文)。严格遵循。不要从之前的对话中推断或重复旧任务。如果无需关注,回复 HEARTBEAT_OK。 |
| 活跃时段 | 心跳提示作为用户消息原样发送。系统提示包含"Heartbeat"部分,且运行被内部标记。heartbeat.activeHours 在配置的时区中检查。窗口期外,心跳跳过直到下一个窗口内的 tick。 |
默认提示故意设计得较为宽泛:
如果你希望心跳执行非常具体的操作(例如"检查 Gmail PubSub 统计"或"验证网关健康"),设置 agents.defaults.heartbeat.prompt(或 agents.list[].heartbeat.prompt)为自定义主体(原样发送)。
HEARTBEAT_OK。HEARTBEAT_OK 出现在回复开头或结尾时,OpenClaw 将其视为确认。该标记被剥离,如果剩余内容 ≤ ackMaxChars(默认:300),则丢弃回复。HEARTBEAT_OK 出现在回复中间,则不特殊处理。HEARTBEAT_OK;仅返回告警文本。HEARTBEAT_OK 被剥离并记录;仅包含 HEARTBEAT_OK 的消息被丢弃。{
"agents": {
"defaults": {
"heartbeat": {
"every": "30m", // 默认:30 分钟(0m 禁用)
"model": "anthropic/claude-opus-4-6",
"includeReasoning": false, // 默认:false(可用时投递单独的 Reasoning: 消息)
"target": "last", // 默认:none | 选项:last | none | <频道 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 有心跳块,则仅这些 Agent 运行心跳。channels.defaults.heartbeat 设置所有频道的可见性默认值。channels.<channel>.heartbeat 覆盖频道默认值。channels.<channel>.accounts.<id>.heartbeat(多账号频道)覆盖每频道设置。如果任何 agents.list[] 条目包含心跳块,则仅这些 Agent 运行心跳。每个 Agent 的块在 agents.defaults.heartbeat 上合并(因此你可以一次性设置共享默认值,并按 Agent 覆盖)。
示例: 两个 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 点后),心跳跳过。窗口期内的下一个计划 tick 将正常运行。
如果你希望心跳全天运行,使用以下模式之一:
activeHours(无时间窗口限制;这是默认行为)。activeHours: { start: "00:00", end: "24:00" }。使用 accountId 定位多账号频道(如 Telegram)上的特定账号:
{
"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 相同格式)。 |
session |
心跳运行的可选会话密钥。 - main(默认):Agent 主会话。- 显式会话密钥(从 openclaw sessions --json 或 sessions CLI 复制)。会话密钥格式:参见 Sessions and Groups。 |
target |
- last:投递到最后使用的外部频道。- 显式频道: whatsapp / telegram / discord / googlechat / slack / msteams / signal / imessage。- none(默认):运行心跳但不外部投递。 |
directPolicy |
控制直接/私信投递行为: - allow(默认):允许直接/私信心跳投递。- block:抑制直接/私信投递(reason=dm-blocked)。 |
to |
可选的收件人覆盖(频道特定 id,例如 WhatsApp 的 E.164 或 Telegram 聊天 id)。对于 Telegram 话题/线程,使用 <chatId>:topic:<messageThreadId>。 |
accountId |
多账号频道的可选账号 id。当 target: "last" 时,账号 id 应用于解析后的最后频道(如果支持账号);否则被忽略。如果账号 id 与解析频道的配置账号不匹配,投递跳过。 |
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" 行为。- start 和 end 对于活跃窗口不能相等;相等值被视为零宽度(始终在窗口外)。- 活跃窗口外,心跳跳过直到窗口内的下一个 tick。 |
agent:<id>:<mainKey>),或当 session.scope = "global" 时为全局。设置 session 以覆盖到特定频道会话(Discord/WhatsApp 等)。session 仅影响运行上下文;投递由 target 和 to 控制。target + to。使用 target: "last" 时,投递使用该会话的最后外部频道。directPolicy: "block" 以在仍运行心跳轮次的同时抑制直接目标发送。target 解析为无外部目标,运行仍发生但不发送出站消息。last 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 # 抑制此账号的告警投递
优先级: 每账号 → 每频道 → 频道默认值 → 内置默认值。
| 标志 | 作用 |
|---|---|
showOk |
当模型返回仅 OK 的回复时,发送 HEARTBEAT_OK 确认。 |
showAlerts |
当模型返回非 OK 回复时,发送告警内容。 |
useIndicator |
为 UI 状态界面发送指示器事件。 |
如果三个都为 false,OpenClaw 完全跳过心跳运行(无模型调用)。
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 文件,默认提示告诉 Agent 读取它。将其视为你的"心跳检查清单":小巧、稳定,且每 30 分钟包含一次是安全的。
# Heading),OpenClaw 跳过心跳运行以节省 API 调用。如果文件缺失,心跳仍运行,模型决定做什么。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.
可以——如果你要求它这样做。
HEARTBEAT.md 只是 Agent 工作区中的一个普通文件,因此你可以在正常聊天中告诉 Agent:
"Update HEARTBEAT.md to add a daily calendar check."
"Rewrite HEARTBEAT.md so it's shorter and focused on inbox follow-ups."
如果你希望这主动发生,还可以在心跳提示中包含显式行,如:"If the checklist becomes stale, update HEARTBEAT.md with a better one."
安全提示: 不要将机密(API 密钥、电话号码、私有令牌)放入 HEARTBEAT.md —— 它会成为提示上下文的一部分。
你可以排队系统事件并立即触发心跳:
openclaw system event --text "Check for urgent follow-ups" --mode now
如果多个 Agent 配置了心跳,手动唤醒会立即运行每个 Agent 的心跳。
使用 --mode next-heartbeat 等待下一个计划 tick。
默认情况下,心跳仅投递最终的"答案"负载。
如果你想要透明度,启用:
"agents.defaults.heartbeat.includeReasoning": true
启用时,心跳还将投递前缀为 Reasoning: 的单独消息(与 /reasoning on 相同格式)。这在 Agent 管理多个会话/法典且你想了解它为何决定 ping 你时很有用——但也可能泄露比你想要的更多内部细节。建议在群聊中保持关闭。
心跳运行完整的 Agent 轮次。更短的间隔消耗更多 token。保持 HEARTBEAT.md 小巧,并考虑如果你只想要内部状态更新,使用更便宜的模型或 target: "none"。
tbd...
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。