快速结论:当你在 LiteLLM 中同时对 Anthropic Claude 使用 stream=True、response_format(走 json_tool_call 路径)和 tools 时,如果模型在同一轮里既调用了内部 JSON 工具又调用了用户工具,流式响应会错误地把 finish_reason 报成 "stop"。优先排查是否是流式迭代器覆盖 finish_reason 导致,并升级到包含修复 PR #46331 的版本。
适用环境:Issue 中确认的环境为 LiteLLM v1.106.0(main at 2b8e53b5ca),涉及 Anthropic Claude 流式调用,以及复用同一迭代器的 Bedrock invoke Claude 和 Vertex AI Claude 流式路径。Issue 未提供操作系统、Python、CUDA、显卡或具体依赖版本信息。
最快修复方案:升级到已包含 PR #46331 的 LiteLLM 版本。该 PR 修复后,当流式请求同时带 response_format 并调用了用户工具时,finish_reason 会保持 "tool_calls"。
注意事项:该修复针对的是 response_format 经由 json_tool_call 工具、而非 Anthropic 原生结构化输出的路径;如果你的调用走的是原生 structured outputs,则不属于本 Issue 覆盖范围。在你自行修改源码打补丁前,请注意 Issue 中的离线复现和修复仅针对流式迭代器路径,非流式路径本就正常。若无法立即升级,需确认 PR #46331 是否已进入你所用的分支或发行版本。
问题场景
用户在 LiteLLM 中调用 litellm.completion(),使用 Anthropic Claude 模型(如 anthropic/claude-sonnet-4-5),同时传入 stream=True、tools 和 JSON Schema 形式的 response_format。当这一轮里模型既调用了内部用于结构化输出的 json_tool_call 工具,又调用了用户定义的工具(例如 get_weather),流式返回的最后一个 chunk 的 finish_reason 变成了 "stop" 而不是 "tool_calls"。用户工具调用的内容本身是正常流出的,但依赖 finish_reason == "tool_calls" 判断是否执行工具的 agent 循环(如 OpenAI Agents SDK、LangChain 等)会误认为本轮已结束,从而不执行工具。
报错原文
[Bug]: Anthropic streaming with response_format and tools reports finish_reason "stop" when a user tool is called
Expected: finish_reason="tool_calls" when any user tool call was streamed, and "stop" only when the json_tool_call tool was the only tool, matching the non-streaming result
原因分析
原因定位在 litellm/llms/anthropic/chat/handler.py 中的 ModelResponseIterator._handle_message_delta。每当 converted_response_format_tool 被设置时,它会无条件把 finish_reason 覆盖为 "stop",而没有检查这一轮是否还流出了用户工具调用。该路径用于 response_format 经由 json_tool_call 工具而非原生结构化输出的场景,同一迭代器也被 Bedrock invoke Claude 和 Vertex AI Claude 流式调用复用。非流式路径本来已正确处理:_resolve_json_mode_non_streaming 会保留用户工具调用、把 JSON 合并进 content,并保持 finish_reason="tool_calls",因此问题只出现在流式路径的一致性上。
环境排查
- 确认 LiteLLM 版本;Issue 复现于 v1.106.0(main at 2b8e53b5ca),若低于包含 PR #46331 的版本则可能受影响。
- 确认调用方是否为 Anthropic 流式路径;若使用 Bedrock invoke Claude 或 Vertex AI Claude 流式,注意它们复用同一迭代器,可能同样受影响。
- 确认是否同时使用了
stream=True、response_format(JSON Schema 形式)和tools三个条件。 - 确认
response_format是否经由json_tool_call路径(而非原生 structured outputs);只有前者是本 Issue 描述的场景。 - Issue 未提供操作系统、Python、CUDA、显卡或依赖版本信息,如需进一步排查请自行记录这些环境项。
解决步骤
- 先确认当前触发的报错是否符合本 Issue 特征:流式请求同时带
response_format和tools,且最终finish_reason为"stop"而实际已流出用户工具调用。 - 检查你使用的 LiteLLM 版本是否已包含 PR #46331 的修复;Issue 已确认由 #46331 修复并关闭。
- 升级到包含该 PR 的 LiteLLM 版本,或让运维确认 PR #46331 已合并进你使用的分支/发行版。
- 如无法立即升级,可参考 Issue 正文中的离线复现脚本,用同一组 Anthropic 流事件对比流式与
AnthropicConfig().transform_parsed_response的非流式结果,确认差异确实来自_handle_message_delta对finish_reason的覆盖,再评估是否临时打补丁。 - 若你走的是 Bedrock invoke Claude 或 Vertex AI Claude 流式路径,升级时同样需要验证对应的复用迭代器行为,因为 Issue 指出它们共用同一代码路径。
验证方法
用与本 Issue 相同的调用方式发起一次流式请求:stream=True + response_format(JSON Schema)+ 同时会触发用户工具的 tools。检查流式返回的最后一个 chunk,确认 finish_reason == "tool_calls" 而不是 "stop";同时确认用户工具调用内容仍正常流出。也可用 Issue 正文中的离线复现脚本,对比流式结果与非流式 transform_parsed_response 的结果是否一致。若依赖该字段的 agent 循环(OpenAI Agents SDK、LangChain 等)能正常执行工具,则说明问题已解决。
参考来源
Issue 中提及的修复 PR:#46331(Issue 评论区确认 Fixed by #46331,Closing as completed)。
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


