openclaw - 💡(How to fix) Fix [Bug]: Block streaming: same-channel text blocks not delivered before tool execution on WhatsApp [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#71664Fetched 2026-04-26 05:10:03
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×1labeled ×1

When an agent emits text and then makes tool calls in the same turn, the text is not delivered to WhatsApp until all tool calls complete and the entire turn finishes. This means a simple "Checking now..." acknowledgment can be delayed by minutes if the subsequent tool calls take time.

Root Cause

This appears to be the same underlying issue as #32868 (reported 2026-02-24, still present in 2026.4.23). The analysis there identified that dispatcher.sendBlockReply() in the same-channel path is fire-and-forget — it enqueues the block but doesn't await actual delivery. The onBlockReplyFlush() resolves after the pipeline chain (instant), not after the dispatcher chain (actual channel send).

Cross-channel delivery works correctly because it uses await sendPayloadAsync(). Same-channel (the common WhatsApp DM case) does not.

Fix Action

Fix / Workaround

This appears to be the same underlying issue as #32868 (reported 2026-02-24, still present in 2026.4.23). The analysis there identified that dispatcher.sendBlockReply() in the same-channel path is fire-and-forget — it enqueues the block but doesn't await actual delivery. The onBlockReplyFlush() resolves after the pipeline chain (instant), not after the dispatcher chain (actual channel send).

Why the existing workaround is insufficient

Same as #32868's suggestion: make dispatcher.sendBlockReply() return a Promise that resolves when options.deliver() completes, OR await dispatcher.waitForIdle() in the onBlockReply callback for the same-channel path. This would make blockStreamingBreak: "text_end" actually deliver blocks between tool calls as intended.

Code Example

## Proposed fix

Same as #32868's suggestion: make `dispatcher.sendBlockReply()` return a Promise that resolves when `options.deliver()` completes, OR await `dispatcher.waitForIdle()` in the `onBlockReply` callback for the same-channel path. This would make `blockStreamingBreak: "text_end"` actually deliver blocks between tool calls as intended.
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When an agent emits text and then makes tool calls in the same turn, the text is not delivered to WhatsApp until all tool calls complete and the entire turn finishes. This means a simple "Checking now..." acknowledgment can be delayed by minutes if the subsequent tool calls take time.

Steps to reproduce

  1. Configure OpenClaw with WhatsApp channel
  2. Send a message that triggers the agent to write a brief text response followed by multiple tool calls
  3. Observe: nothing appears in WhatsApp until ALL tool calls complete
  4. The "typing..." indicator shows (so the user knows something is happening), but no text arrives until the turn ends

Expected behavior

When an agent writes text (e.g. "Let me verify that...") and then calls tools, the text should be delivered to the WhatsApp chat before the tool calls execute. The user should see progressive output — the acknowledgment first, then the results after tool calls complete.

Actual behavior

The entire response (text + tool call results + final text) is delivered as a single atomic message only after all tool calls finish. A 3-second acknowledgment gets delayed by a 3-minute tool chain.

Real-world example

User asked "Did the upgrade complete successfully?" at 7:36 AM. Agent wrote "Gateway came back and WhatsApp reconnected. Let me verify everything..." then ran 8+ tool calls (exec, process poll, config validate, etc.). User didn't see ANY response until 7:39 AM — a 3-minute wait for what should have been an instant acknowledgment.

OpenClaw version

2026.4.23

Operating system

Ubunutu 24.04

Install method

npm global

Model

ollama.com -> GLM5.1

Provider / routing chain

openclaw -> ollama.com -> GLM5.1

Additional provider/model setup details

Root cause

This appears to be the same underlying issue as #32868 (reported 2026-02-24, still present in 2026.4.23). The analysis there identified that dispatcher.sendBlockReply() in the same-channel path is fire-and-forget — it enqueues the block but doesn't await actual delivery. The onBlockReplyFlush() resolves after the pipeline chain (instant), not after the dispatcher chain (actual channel send).

Cross-channel delivery works correctly because it uses await sendPayloadAsync(). Same-channel (the common WhatsApp DM case) does not.

Why the existing workaround is insufficient

#32868 suggests using message tool for real-time updates. This works but has drawbacks:

  1. Two-message pattern is awkward — user gets "Checking now..." then a separate results message, rather than a single coherent reply that streams in
  2. Requires agent-side discipline — every agent must remember to send an ack first, which is fragile and inconsistent
  3. Doesn't fix the root cause — block streaming with text_end should work as documented

Logs, screenshots, and evidence

## Proposed fix

Same as #32868's suggestion: make `dispatcher.sendBlockReply()` return a Promise that resolves when `options.deliver()` completes, OR await `dispatcher.waitForIdle()` in the `onBlockReply` callback for the same-channel path. This would make `blockStreamingBreak: "text_end"` actually deliver blocks between tool calls as intended.

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

To fix the issue, modify dispatcher.sendBlockReply() to return a Promise that resolves when options.deliver() completes, or await dispatcher.waitForIdle() in the onBlockReply callback for the same-channel path.

Guidance

  • Review the analysis in #32868 and verify that the issue is indeed caused by the fire-and-forget behavior of dispatcher.sendBlockReply().
  • Consider implementing the proposed fix by modifying dispatcher.sendBlockReply() to return a Promise that resolves when options.deliver() completes.
  • Alternatively, await dispatcher.waitForIdle() in the onBlockReply callback for the same-channel path to ensure that the block is delivered before proceeding.
  • Test the fix with the provided steps to reproduce and verify that the text is delivered to WhatsApp before the tool calls complete.

Example

// Proposed fix: modify dispatcher.sendBlockReply() to return a Promise
dispatcher.sendBlockReply = function(block) {
  return new Promise((resolve, reject) => {
    // ...
    options.deliver(block, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve();
      }
    });
  });
};

Notes

The proposed fix assumes that the issue is caused by the fire-and-forget behavior of dispatcher.sendBlockReply(). If this is not the case, further investigation may be necessary.

Recommendation

Apply the proposed workaround by modifying dispatcher.sendBlockReply() to return a Promise that resolves when options.deliver() completes. This should fix the root cause of the issue and provide the expected behavior.

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…

FAQ

Expected behavior

When an agent writes text (e.g. "Let me verify that...") and then calls tools, the text should be delivered to the WhatsApp chat before the tool calls execute. The user should see progressive output — the acknowledgment first, then the results after tool calls complete.

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]: Block streaming: same-channel text blocks not delivered before tool execution on WhatsApp [1 participants]