Skip to content

Fix streaming tool calls when reasoning parser is active#93

Open
janhilgard wants to merge 1 commit intowaybarrios:mainfrom
janhilgard:fix/streaming-tool-calls-with-reasoning
Open

Fix streaming tool calls when reasoning parser is active#93
janhilgard wants to merge 1 commit intowaybarrios:mainfrom
janhilgard:fix/streaming-tool-calls-with-reasoning

Conversation

@janhilgard
Copy link
Copy Markdown
Collaborator

Summary

  • Fix streaming tool calls being emitted as raw text when --reasoning-parser is enabled
  • The reasoning parser branch in stream_chat_completion() was skipping tool call parsing entirely, causing <tool_call> markup to leak into content instead of being parsed into structured tool_calls objects
  • Adds tool call parsing to the reasoning branch, mirroring the existing logic in the standard path

Problem

When both --reasoning-parser deepseek_r1 and --tool-call-parser hermes are enabled, streaming responses emit raw tool call markup as plain text:

{"delta": {"content": "<tool_call>\n<function=get_weather>\n<parameter=location>\nPrague\n</parameter>\n</function>\n</tool_call>", "tool_calls": null}, "finish_reason": "stop"}

Fix

After this change, tool calls are correctly parsed and emitted:

{"delta": {"tool_calls": [{"index": 0, "id": "call_4b99a63b", "type": "function", "function": {"name": "get_weather", "arguments": "{\"location\": \"Prague\"}"}}]}, "finish_reason": "tool_calls"}

Test plan

  • Streaming tool call with --reasoning-parser deepseek_r1 --tool-call-parser hermes returns structured tool_calls
  • finish_reason is "tool_calls" (not "stop")
  • Reasoning-only responses (no tool calls) still work correctly
  • Non-streaming tool calls unaffected
  • black formatting passes

🤖 Generated with Claude Code

The reasoning parser branch in stream_chat_completion() was missing
tool call parsing entirely. When both --reasoning-parser and
--tool-call-parser were enabled, streaming responses would emit raw
tool call markup (e.g. <tool_call><function=...>) as plain content
text instead of structured tool_calls objects.

This adds tool call parsing to the reasoning parser branch, mirroring
the existing logic in the standard (non-reasoning) path. Tool calls
are now correctly detected, buffered during accumulation, and emitted
as structured tool_calls with finish_reason="tool_calls".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant