openclaw - ✅(Solved) Fix Heartbeat exec-event prompt drops actual completion payload [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#66487Fetched 2026-04-15 06:25:59
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2commented ×1mentioned ×1subscribed ×1

Root Cause

Root Cause (two-part)

Fix Action

Workaround

Set heartbeat.target to "none" and heartbeat.directPolicy to "block" to prevent heartbeat from delivering to user-facing channels.

PR fix notes

PR #66580: fix(heartbeat): relay exec payload in prompts

Description (problem / solution / changelog)

Fixes #66487

Claim

Heartbeat exec-event prompts now include the real exec completion payload before asking the model to relay it.

Evidence

  • unit coverage for payload + empty fallback in heartbeat-events-filter.test.ts
  • runner-level regression verifies the heartbeat prompt body includes the exec completion text
  • local validation harness passed: node_modules/.bin/tsx .tmp-heartbeat-exec-check.ts

Checks

  • git diff --check

Changed files

  • src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts (modified, +6/-0)
  • src/agents/pi-embedded-helpers.isbillingerrormessage.test.ts (modified, +3/-0)
  • src/agents/pi-embedded-helpers/errors.ts (modified, +1/-1)
  • src/infra/heartbeat-events-filter.test.ts (modified, +16/-5)
  • src/infra/heartbeat-events-filter.ts (modified, +24/-4)
  • src/infra/heartbeat-runner.ghost-reminder.test.ts (modified, +5/-0)
  • src/infra/heartbeat-runner.ts (modified, +3/-2)
RAW_BUFFERClick to expand / collapse

Bug

When a backgrounded exec session completes, the heartbeat fires correctly via maybeNotifyOnExit, but the prompt sent to the heartbeat model says "the result is shown in the system messages above" without actually injecting the exec completion payload into the heartbeat context. The model then correctly reports it cannot see any results, and delivers that confused response to the user.

Root Cause (two-part)

  1. No dedup between process poll and notifyOnExit: When a cron run launches an exec with background: true, yields, and later polls the result with process poll, the manual poll does not clear notifyOnExit or cancel the pending auto-exit wake. So both the cron (via poll) and the heartbeat (via auto-exit event) consume the completion — the cron gets the real output, and the heartbeat gets a bogus prompt.

  2. Heartbeat prompt uses classification only, not actual event content: The heartbeat runner checks pending system events with isExecCompletionEvent, then calls buildExecEventPrompt, which produces a generic template: "An async command you ran earlier has completed. The result is shown in the system messages above." But the actual queued exec event text is never injected into the heartbeat body, making the prompt wrong in-context.

Reproduction

  1. Create a cron that runs openclaw status via exec (which yields as a background process session)
  2. The cron later consumes the result via process poll
  3. The backgrounded exec completes and triggers notifyOnExit
  4. Heartbeat fires on the cron session with the generic async-completion prompt
  5. The heartbeat model sees no actual command output and responds with confusion
  6. If heartbeat.target is "last" and directPolicy is "allow", that confused response is delivered to the user's DM

Evidence

  • Cron session 7aa43c60 launched openclaw status, yielded as process session briny-nexus, then polled the result successfully
  • Heartbeat session 8e88de9f received only the generic prompt at 2026-04-14T05:00:58Z: "An async command you ran earlier has completed. The result is shown in the system messages above."
  • Model responded: "I don't see system messages with results in my current context"
  • A second heartbeat cycle (d9acd5de) repeated the same pattern, with the model getting increasingly defensive across iterations
  • The confused responses were delivered to the user's Telegram DM

Suggested Fix

Either:

  • Option A: Have process poll clear notifyOnExit on the polled session so heartbeat never fires for already-consumed results
  • Option B: Have buildExecEventPrompt inject the actual exec completion event content into the heartbeat context, not just a classification-based template
  • Option C (ideal): Both — dedup via Option A, and fix the prompt via Option B as defense-in-depth

Workaround

Set heartbeat.target to "none" and heartbeat.directPolicy to "block" to prevent heartbeat from delivering to user-facing channels.

Environment

  • OpenClaw v2026.4.12
  • Heartbeat model: claude-haiku-4.5 via GitHub Copilot
  • heartbeat.isolatedSession: true
  • macOS (arm64)

extent analysis

TL;DR

To fix the issue, consider implementing Option A or Option B from the suggested fixes, which involve either clearing notifyOnExit on polled sessions or injecting actual event content into the heartbeat context.

Guidance

  • Investigate implementing Option A: Modify process poll to clear notifyOnExit on the polled session to prevent duplicate notifications.
  • Explore Option B: Update buildExecEventPrompt to include the actual exec completion event content in the heartbeat prompt for more accurate user notifications.
  • Consider the ideal solution (Option C): Combine both Options A and B for a more robust fix, ensuring deduplication and accurate prompt generation.
  • As a temporary workaround, set heartbeat.target to "none" and heartbeat.directPolicy to "block" to prevent confused responses from being delivered to users.

Example

No specific code example is provided due to the lack of explicit code in the issue description. However, the fix would involve modifying the process poll and/or buildExecEventPrompt functions to address the identified issues.

Notes

The suggested fixes and workaround are based on the information provided in the issue. The effectiveness of these solutions may depend on the specific implementation details of the exec sessions, notifyOnExit, and buildExecEventPrompt functions, which are not fully described in the issue.

Recommendation

Apply Option C (ideal) as it addresses both the deduplication issue and the inaccurate prompt generation, providing a more comprehensive solution to the problem. This approach ensures that the heartbeat mechanism works correctly, even in cases where process poll has already consumed the result, by preventing duplicate notifications and providing accurate information to the user.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING