Skip to content

fix(agent): deduplicate ToolCall event in turn_streamed#5746

Merged
theonlyhennygod merged 1 commit intozeroclaw-labs:masterfrom
c98:fix/turn-streamed-duplicate-tool-call-event
Apr 15, 2026
Merged

fix(agent): deduplicate ToolCall event in turn_streamed#5746
theonlyhennygod merged 1 commit intozeroclaw-labs:masterfrom
c98:fix/turn-streamed-duplicate-tool-call-event

Conversation

@c98
Copy link
Copy Markdown
Contributor

@c98 c98 commented Apr 15, 2026

Summary

In turn_streamed, TurnEvent::ToolCall was being emitted twice for every tool call:

  1. Inside the StreamEvent::ToolCall match arm during stream processing
  2. Again in the post-parse_response loop before tool execution

This caused every tool_call SSE event to be sent to clients twice, as shown below:

tool_call_dup

Fix

Remove the event_tx.send(TurnEvent::ToolCall {...}) call from the StreamEvent::ToolCall match arm. The post-parse loop already covers both streaming and non-streaming paths, so it is the single, correct place to emit ToolCall events.

A brief comment is left at the match arm to explain why the send is intentionally absent there.

Risk

Low — runtime/agent only; no API boundary changes. Existing test turn_streamed_passes_tool_specs_to_provider passes.

Checklist

  • cargo fmt --all -- --check passes
  • cargo clippy --all-targets -- -D warnings passes
  • cargo test passes

In turn_streamed, StreamEvent::ToolCall was sending a TurnEvent::ToolCall
immediately during stream processing, and then the same event was sent
again in the post-parse loop before tool execution. This caused every
tool_call SSE event to be emitted twice to clients.

Fix: remove the send from the StreamEvent::ToolCall match arm and let
the unified post-parse loop (which covers both streaming and non-streaming
paths) be the single place where ToolCall events are emitted.
Copy link
Copy Markdown
Collaborator

@theonlyhennygod theonlyhennygod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@github-project-automation github-project-automation bot moved this from Backlog to Ready to Merge in ZeroClaw Project Board Apr 15, 2026
@theonlyhennygod theonlyhennygod merged commit 9f0de18 into zeroclaw-labs:master Apr 15, 2026
20 checks passed
@github-project-automation github-project-automation bot moved this from Ready to Merge to Shipped in ZeroClaw Project Board Apr 15, 2026
@singlerider
Copy link
Copy Markdown
Collaborator

I look forward to this resolving the streaming tool call duplications! You saved me some work, @c98 !

whtiehack added a commit to whtiehack/zeroclaw that referenced this pull request Apr 18, 2026
StreamEvent::ToolCall 分支发了一次 TurnEvent::ToolCall,post-parse loop
又发一次,客户端每个 tool_call 收两次。

删除 StreamEvent::ToolCall 分支的早发射,保留 streamed_tool_calls 收集,
让统一的 post-parse loop 成为唯一发射点。

Ports upstream 9f0de18 (zeroclaw-labs#5746) to master_wecom's
pre-workspace-split layout.

Co-authored-by: c98 <ichuan.me@outlook.com>
Co-authored-by: chuanzhi <ichuan.me@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Shipped

Development

Successfully merging this pull request may close these issues.

4 participants