Problem
When a heartbeat fires and the agent responds with HEARTBEAT_OK (no actionable tasks), the full heartbeat prompt + response pair is persisted in the session transcript:
user: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly..." (~30 tokens)
assistant: "HEARTBEAT_OK" (~5 tokens)
These no-op exchanges accumulate over time. With the default 30-minute heartbeat interval, this adds ~1,700 tokens/day of zero-information-content messages to the session history.
Impact
- Context waste: In long-running sessions (e.g., Discord DMs that persist for days), hundreds of HEARTBEAT_OK pairs consume significant context window space.
- Compaction inefficiency: When compaction triggers, it must summarize these no-op exchanges alongside real conversation. The compaction summary ends up including noise like "the agent checked heartbeat multiple times and found nothing to do."
- Contributes to context overflow: Combined with other context growth, heartbeat accumulation can push sessions toward the context limit faster than necessary, especially on models with smaller context windows (e.g., 200k).
Expected Behavior
HEARTBEAT_OK exchanges where no action was taken should either:
- Be stripped from the session transcript after delivery (they have been processed, there is no reason to keep them in context), or
- Be marked as pruneable so compaction can drop them entirely rather than summarizing them, or
- Not be persisted to the transcript at all when the response is purely HEARTBEAT_OK with no other content.
Current Behavior
The stripHeartbeatToken function strips the HEARTBEAT_OK token from the reply text before delivery, but the full user prompt + assistant response pair remains in the session transcript and is included in future LLM context.
Suggested Fix
Before appending a heartbeat turn to the session transcript, check if the response is effectively just HEARTBEAT_OK (using the existing isHeartbeatContentEffectivelyEmpty or similar). If so, skip persisting both the heartbeat prompt and the response to the transcript.
Alternatively, add a post-hoc pruning step that removes completed HEARTBEAT_OK pairs from the message history before sending context to the LLM.
Environment
- OpenClaw 2026.2.x
- Any model/provider
- Heartbeat interval: 30m (default)
- Long-running sessions (multi-day)
Problem
When a heartbeat fires and the agent responds with
HEARTBEAT_OK(no actionable tasks), the full heartbeat prompt + response pair is persisted in the session transcript:These no-op exchanges accumulate over time. With the default 30-minute heartbeat interval, this adds ~1,700 tokens/day of zero-information-content messages to the session history.
Impact
Expected Behavior
HEARTBEAT_OK exchanges where no action was taken should either:
Current Behavior
The
stripHeartbeatTokenfunction strips the HEARTBEAT_OK token from the reply text before delivery, but the full user prompt + assistant response pair remains in the session transcript and is included in future LLM context.Suggested Fix
Before appending a heartbeat turn to the session transcript, check if the response is effectively just HEARTBEAT_OK (using the existing
isHeartbeatContentEffectivelyEmptyor similar). If so, skip persisting both the heartbeat prompt and the response to the transcript.Alternatively, add a post-hoc pruning step that removes completed HEARTBEAT_OK pairs from the message history before sending context to the LLM.
Environment