#22886: fix: await onBlockReplyFlush before tool execution to preserve message ordering
agents
size: XS
Cluster:
Tool Result Handling Improvements
## Problem
When `shouldRouteToOriginating` is true (e.g., agent routing from webchat → telegram), block replies bypass the dispatcher's `sendChain` and go directly through `routeReply` → `sendMessageTelegram`.
In `handleToolExecutionStart`, `onBlockReplyFlush()` was called with `void` (fire-and-forget). This meant tool-initiated sends (e.g., message tool sending a PDF) could race block replies through the async chain and reach the per-chat serializer first, causing **out-of-order delivery** on Telegram.
Example: agent streams reasoning text, then sends a PDF via message tool → PDF arrives before the reasoning text.
## Fix
`void` → `await` on `ctx.params.onBlockReplyFlush()` in `handleToolExecutionStart`. This ensures all pending block reply deliveries complete before tool execution proceeds.
One-line change, the function is already `async`.
## Testing
- Verified build compiles cleanly
- Existing e2e test (`calls-onblockreplyflush-before-tool-execution-start-preserve`) still passes (mock returns void, `await undefined` is a no-op)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Changes `void` to `await` on `ctx.params.onBlockReplyFlush()` call in `handleToolExecutionStart` (line 141). This ensures pending block replies complete delivery before tool execution proceeds, preventing race conditions where tool-initiated sends could arrive before streamed reasoning text when routing through Telegram.
- The function signature already returns `void | Promise<void>`, so awaiting is safe
- Existing test passes (mock returns void, `await undefined` is a no-op)
- Fixes out-of-order message delivery in agent routing scenarios (webchat → telegram)
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The change is minimal (one keyword change from `void` to `await`), the function is already async, the type signature supports both sync and async returns, and existing tests verify the behavior. The fix addresses a real race condition without introducing new complexity or breaking changes.
- No files require special attention
<sub>Last reviewed commit: e1cf374</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#15920: fix: await coalescer flush before tool execution
by Bridgerz · 2026-02-14
88.0%
#15996: fix(agents): messages arrive out of order — tool output beats narra...
by yinghaosang · 2026-02-14
87.6%
#9171: Fix: Route tool result deliveries through BlockReplyPipeline for pr...
by vishaltandale00 · 2026-02-04
82.7%
#2805: fix: wire onToolResult to dispatcher for verbose tool summaries
by LinghaoZhuang · 2026-01-27
79.6%
#19518: fix: await block reply flush before tool execution
by katalabut · 2026-02-17
79.3%
#18187: fix: tool summaries silently dropped when reasoningLevel is stream
by ayanesakura · 2026-02-16
77.5%
#19632: fix: suppressToolErrors now suppresses exec tool failure notifications
by Gitjay11 · 2026-02-18
76.9%
#19235: fix(telegram): tool error warnings no longer overwrite streamed rep...
by gatewaybuddy · 2026-02-17
76.9%
#19141: fix(telegram): serialize per-chat sends and await block reply flush...
by botverse · 2026-02-17
76.5%
#18678: fix(telegram): preserve draft message when all final payloads are e...
by julianubico · 2026-02-16
76.4%