openclaw - 💡(How to fix) Fix Bug: heartbeat exec-completion prompt references phantom system messages — agent always replies "I don't see the output" [1 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#69968Fetched 2026-04-23 07:30:54
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Participants

When an async exec command completes and triggers a heartbeat, the agent consistently replies with a variant of "I don't see any async command output in the system messages above". This is a bug in buildExecEventPrompt() — the actual exec output is never injected into the prompt.

Root Cause

When an async exec command completes and triggers a heartbeat, the agent consistently replies with a variant of "I don't see any async command output in the system messages above". This is a bug in buildExecEventPrompt() — the actual exec output is never injected into the prompt.

Code Example

"An async command you ran earlier has completed. The result is shown in the system messages above."

---

const hasExecCompletion = pendingEvents.some(isExecCompletionEvent);

---

prompt: hasExecCompletion ? buildExecEventPrompt({ deliverToUser: params.canRelayToUser }) : ...

---

function buildExecEventPrompt(opts: { deliverToUser?: boolean; execEvents?: string[] }) {
  const outputSection = opts.execEvents?.length
    ? `\n\nExec output:\n${opts.execEvents.join("\n")}`
    : "";
  if (!(opts?.deliverToUser ?? true)) {
    return `An async command you ran earlier has completed.${outputSection}\nHandle the result internally. Do not relay it to the user unless explicitly requested.`;
  }
  return `An async command you ran earlier has completed.${outputSection}\nPlease relay the command output to the user in a helpful way. If the command succeeded, share the relevant output. If it failed, explain what went wrong.`;
}

---

hasExecCompletion ? buildExecEventPrompt({
  deliverToUser: params.canRelayToUser,
  execEvents: pendingEvents.filter(isExecCompletionEvent)
}) : ...
RAW_BUFFERClick to expand / collapse

Summary

When an async exec command completes and triggers a heartbeat, the agent consistently replies with a variant of "I don't see any async command output in the system messages above". This is a bug in buildExecEventPrompt() — the actual exec output is never injected into the prompt.

Code trace

File: src/infra/heartbeat-runner.ts (compiled: dist/heartbeat-runner-CInrztfM.js)

Line 167-169buildExecEventPrompt() returns a static string:

"An async command you ran earlier has completed. The result is shown in the system messages above."

Line 512hasExecCompletion is detected from event text (correct):

const hasExecCompletion = pendingEvents.some(isExecCompletionEvent);

Line 539buildExecEventPrompt() is called with no event data:

prompt: hasExecCompletion ? buildExecEventPrompt({ deliverToUser: params.canRelayToUser }) : ...

The exec event entries are mapped to text at line 510 (pendingEvents) and checked for exec completion at line 512, but the actual event text (which contains the compactOutput) is never passed to buildExecEventPrompt(). The model is told to look at system messages that were never injected.

Reproduction

  1. Run a background exec command via the exec tool with background: true
  2. Wait for heartbeat to fire after the exec completes
  3. Observe agent replies: "I don't see any async command output in the system messages above. Could you share the result?"

Expected behaviour

The exec output should be included inline in the heartbeat prompt, so the agent can actually see and relay it.

Proposed fix

Pass the exec event entries through to buildExecEventPrompt() and include compactOutput inline:

function buildExecEventPrompt(opts: { deliverToUser?: boolean; execEvents?: string[] }) {
  const outputSection = opts.execEvents?.length
    ? `\n\nExec output:\n${opts.execEvents.join("\n")}`
    : "";
  if (!(opts?.deliverToUser ?? true)) {
    return `An async command you ran earlier has completed.${outputSection}\nHandle the result internally. Do not relay it to the user unless explicitly requested.`;
  }
  return `An async command you ran earlier has completed.${outputSection}\nPlease relay the command output to the user in a helpful way. If the command succeeded, share the relevant output. If it failed, explain what went wrong.`;
}

Then at line 539:

hasExecCompletion ? buildExecEventPrompt({
  deliverToUser: params.canRelayToUser,
  execEvents: pendingEvents.filter(isExecCompletionEvent)
}) : ...

Environment

  • OpenClaw: 2026.4.15 (041266a)
  • macOS Darwin 25.3.0 (arm64)
  • Node 24.14.0

Impact

Every exec-completion heartbeat produces a confusing "I don't see the output" reply. Users cannot rely on background exec completion notification via heartbeat.

extent analysis

TL;DR

Pass the exec event entries through to buildExecEventPrompt() and include compactOutput inline to fix the issue.

Guidance

  • The buildExecEventPrompt() function should be modified to accept and process the exec event entries, specifically the compactOutput.
  • The pendingEvents array should be filtered to include only exec completion events and passed to buildExecEventPrompt().
  • The buildExecEventPrompt() function should be updated to include the exec output in the prompt, as shown in the proposed fix.
  • Verify the fix by running a background exec command and checking the heartbeat prompt for the included exec output.

Example

function buildExecEventPrompt(opts: { deliverToUser?: boolean; execEvents?: string[] }) {
  const outputSection = opts.execEvents?.length
    ? `\n\nExec output:\n${opts.execEvents.join("\n")}`
    : "";
  // ...
}

// ...

hasExecCompletion ? buildExecEventPrompt({
  deliverToUser: params.canRelayToUser,
  execEvents: pendingEvents.filter(isExecCompletionEvent)
}) : ...

Notes

The proposed fix assumes that the compactOutput is available in the pendingEvents array. If this is not the case, additional modifications may be necessary to retrieve the exec output.

Recommendation

Apply the proposed workaround by modifying the buildExecEventPrompt() function and passing the exec event entries to it, as this directly addresses the root cause of the issue and provides a clear solution.

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

openclaw - 💡(How to fix) Fix Bug: heartbeat exec-completion prompt references phantom system messages — agent always replies "I don't see the output" [1 participants]