-
-
Notifications
You must be signed in to change notification settings - Fork 52.7k
Description
Bug
When a cron agent (e.g. heartbeat-30m) returns multiple text payloads before a final HEARTBEAT_OK, the delivery suppression fails and all payloads are delivered to the user.
Steps to reproduce
- Configure a cron job with
delivery.mode: "announce"andsessionTarget: "isolated" - The agent reads files, runs checks, narrates its work across multiple assistant text blocks
- Agent concludes with
HEARTBEAT_OKas its final payload - All payloads (including narration) are delivered to Telegram
Root cause
isHeartbeatOnlyResponse() in src/cron/isolated-agent/helpers.ts uses .every() to check if ALL payloads are heartbeat tokens. When the agent emits narration payloads before the final HEARTBEAT_OK, .every() returns false because the narration payloads are not heartbeat tokens.
Real transcript from a heartbeat run:
Payload 1: "It's 12:49 AM — quiet hours. Let me run the checks quickly."
Payload 2: "Emails: Just 2 calendar invites from Adnan. Not urgent at 12:49 AM."
Payload 3: "HEARTBEAT_OK"
isHeartbeatOnlyResponse returns false → delivery proceeds → user gets spammed.
Expected behavior
If any payload contains HEARTBEAT_OK, the response should be treated as a heartbeat ack (nothing needs attention). The narration payloads are internal tool/work summaries, not user-facing content.
Related
- HEARTBEAT_OK leaks into user-visible replies when cron announcements queue during active conversation #32013 fixed a different
HEARTBEAT_OKleak path (system events intimer.ts) - This is the delivery dispatch path in
isolated-agent/helpers.ts
Environment
- OpenClaw 2026.3.1 (2a8ac97)
- Cron job: heartbeat-30m, delivery.mode: announce, sessionTarget: isolated