← Back to PRs

#19518: fix: await block reply flush before tool execution

by katalabut open 2026-02-17 22:27 View on GitHub →
agents size: XS
## Summary - **Problem:** Block reply flush (`onBlockReplyFlush`) was called with `void` (fire-and-forget) in `handleToolExecutionStart`, causing narration text to arrive **after** message tool sends due to a race condition between the flush HTTP delivery and the tool's own HTTP call. - **Why it matters:** Users see messages out of order — tool-sent messages appear before the narration text that should precede them. Affects all channels with `blockStreaming` enabled. - **What changed:** Changed `void ctx.params.onBlockReplyFlush()` to `await ctx.params.onBlockReplyFlush()` in `handleToolExecutionStart`, so the pipeline flush completes before the handler returns. Updated comment in the event dispatcher to document the ordering guarantee. - **What did NOT change:** The SDK subscribe callback signature (`void` return type) is unchanged. The `await` operates within the async handler — the SDK still fire-and-forgets the handler, but the flush now completes before any subsequent handler logic. ## Change Type - [x] Bug fix ## Scope - [x] Gateway / orchestration ## Linked Issue - Closes #15968 - Related #11044, #13944 ## User-visible / Behavior Changes Block reply narration text (e.g., "Let me check...") now arrives before message tool sends in the same turn, when `blockStreaming` is enabled. Previously, the ordering was non-deterministic. ## Security Impact - New permissions/capabilities? No - Secrets/tokens handling changed? No - New/changed network calls? No - Command/tool execution surface changed? No - Data access scope changed? No ## Repro + Verification ### Environment - OS: Linux (tested), originally reported on macOS - Runtime: Node 22 - Model/provider: Any - Integration/channel: BlueBubbles, Telegram, any channel with blockStreaming ### Steps 1. Enable `blockStreaming: true` on a channel 2. Send a prompt that causes the agent to write narration text, then call the `message` tool 3. Observe message ordering in the channel ### Expected Narration text arrives before message tool send. ### Actual (before fix) Message tool send arrives first, narration arrives second (race condition). ## Evidence - [x] Failing test before + passing after: `handleToolExecutionStart block reply flush ordering (#15968)` test verifies flush completes before handler returns. Test fails with `void` (fire-and-forget), passes with `await`. ## Human Verification - Verified: Test confirms ordering invariant (flush_complete before handler_returned) - Edge cases: Handler rejection is still caught by `.catch()` in the event dispatcher - Not verified: Live channel testing (no BlueBubbles setup available) ## Compatibility / Migration - Backward compatible? Yes - Config/env changes? No - Migration needed? No ## Failure Recovery - Revert this single commit - Watch for: slower tool execution start (flush adds latency before handler returns, but this is intentional — flush was always meant to complete before tool execution) ## Risks and Mitigations - Risk: Flush timeout could delay tool execution start notification - Mitigation: `onBlockReplyFlush` already has its own timeout via the block reply pipeline; the handler `.catch()` prevents unhandled rejections ## AI Disclosure - AI-assisted: Yes (OpenClaw agent) - Testing level: Unit test verifying ordering invariant - Understanding: Confirmed — traced full event flow from SDK agent-loop through subscribe handlers to pipeline delivery ### Limitation Note This fix reduces but does not fully eliminate the race condition. The SDK's `subscribe` callback is fire-and-forget (`(e: AgentEvent) => void`), so the agent loop proceeds to `tool.execute()` without waiting for the handler. The `await` ensures the flush HTTP call completes within the handler, but tool execution may still start concurrently via the SDK. A complete fix would require either SDK-level pre-tool hooks or serializing all outbound messages (block replies + message tool sends) through a single delivery queue.

Most Similar PRs