Skip to content

fix(sight): guard tool_call name against empty-string overwrite in SSE delta merge#1303

Open
jfeng18 wants to merge 2 commits into
alibaba:mainfrom
jfeng18:fix/openai-tool-call-name-overwrite
Open

fix(sight): guard tool_call name against empty-string overwrite in SSE delta merge#1303
jfeng18 wants to merge 2 commits into
alibaba:mainfrom
jfeng18:fix/openai-tool-call-name-overwrite

Conversation

@jfeng18

@jfeng18 jfeng18 commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Mirror the existing id empty-string guard onto name in extract_parts_from_sse_body SSE tool_call delta merging
  • Add a discriminating regression test reproducing the DashScope/Qwen continuation-chunk pattern

Problem

DashScope/Qwen-compatible gateways resend function.name as an explicit empty string ("") on continuation SSE chunks, rather than omitting the key. The id field already had an !is_empty() guard (added in #1133), but name did not — so a later chunk's name:"" clobbers the real tool name captured on the first chunk.

This causes is_bash_tool("") to return false for every Bash tool_call arriving via an OpenAI-compatible streaming backend, silently hiding it from the correlator and downstream ToolUse consumers.

Evidence

  • Raw SSE capture from DashScope qwen3-30b-a3b-instruct-2507 (Spring AI issue #4790) shows explicit "name":"" on every continuation chunk
  • Independent fix for the same DashScope quirk in tinyhumansai/openhuman PR #3610
  • Reproduced locally: ECS cosh session via DashScope produced name:"" in genai_events for all tool_calls

Test plan

  • New test test_extract_parts_from_sse_body_tool_calls_empty_name_does_not_overwrite — fails without fix, passes with fix
  • Existing test_extract_parts_from_sse_body_tool_calls (name-omitted pattern) unaffected
  • cargo +1.89.0 test --lib — 973 passed
  • cargo +1.89.0 fmt --check — clean
  • cargo +1.89.0 clippy --all-targets -- -D warnings — clean
  • ECS E2E: run agentsight trace + cosh via DashScope, verify tool_call name is no longer empty in genai_events

🤖 Generated with Claude Code

…E delta merge

DashScope/Qwen-compatible gateways resend function.name as an explicit
empty string on continuation chunks rather than omitting the key. The
existing id field already had an !is_empty() guard (added in alibaba#1133);
mirror it onto name so a later empty-string chunk no longer clobbers
the real tool name captured on the first chunk.

Without this fix any Bash tool_call arriving via an OpenAI-compatible
streaming backend is stored with name="" which makes is_bash_tool()
return false, silently hiding it from the correlator and downstream
ToolUse consumers.
@jfeng18 jfeng18 requested a review from chengshuyi as a code owner July 3, 2026 06:55
DashScope/Qwen gateways sometimes omit function.name from ALL SSE delta
chunks for a tool_call (not just later chunks). The previous commit's
empty-string guard handles the "overwrite" case but cannot help when no
chunk ever carries the name.

Add a post-merge recovery step in build_llm_call: after assembling the
response, scan output_messages for empty-name ToolCalls and back-fill
from the request's tools array — single tool defined → unconditional,
multiple tools → match by comparing argument keys against each tool's
parameters.properties.
@github-actions github-actions Bot added the component:sight src/agentsight/ label Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:sight src/agentsight/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant