[Bug]: Spend logs only record the first tool call and first LLM round for chained MCP calls on streaming /responses (require_approval=”never

该问题出现在 LiteLLM 代理使用流式 /v1/responses (以及 /chat/completions )并启用 MCP 工具自动执行( require_approval="never" )时:模型链式多次调用工具、网关自动执行并多轮回调模型,但 spend logs 和日志页只记录第一

快速结论:该问题出现在 LiteLLM 代理使用流式 /v1/responses(以及 /chat/completions)并启用 MCP 工具自动执行(require_approval="never")时:模型链式多次调用工具、网关自动执行并多轮回调模型,但 spend logs 和日志页只记录第一轮 LLM 调用和第一个工具调用,导致后续轮次无记录、费用被少计。优先排查 LiteLLM 版本是否已包含修复,以及是否仍在使用共享 logging 对象和重复 request_id 的旧链路。

适用环境:已确认的工具为 LiteLLM(proxy);已确认存在问题的版本为 v1.97.0(非流式 /chat/completions 路径复现)。Issue 中未提供操作系统、Python、CUDA、显卡等信息。

最快修复方案:暂无确认的一步修复方案。Issue 记录该问题已由 #47445 修复:流式 /v1/responses 的 MCP 自动执行现在会在一条 spend row 中计费每一轮模型调用,并记录每次工具调用。具体可升级到包含该修复的 LiteLLM 版本,但 Issue 未给出对应版本号。

注意事项:该问题不仅影响日志可见性,还会导致费用少计;评论指出预算执行读取同样的计数器,因此设置了 max_budget 的 key/team 在 MCP 流量下可能花费接近上限的两倍。复现者使用的临时缓解方式是改用 require_approval: "always",由应用自行发起后续调用,这不是官方修复,只应作为临时规避。

问题场景

用户在 LiteLLM Proxy 上发送流式 POST /v1/responses 请求,请求中携带 MCP 工具:

"tools": [{"type": "mcp", "server_url": "litellm_proxy", "require_approval": "never"}]

模型先调用工具 A,网关自动执行后再调用模型,模型又调用工具 B,最后再回调模型输出答案,整个链路以 response.completed 结束。客户端通过 SSE 能收到完整链路和正确回答,但打开 /ui/?page=logs 或 spend logs 表时,只看到第一轮模型调用和工具 A 的记录;工具 B 及后续两轮模型调用均无独立日志行。该 key 的报告费用也只包含第一轮模型的 token。

评论补充在 v1.97.0 的非流式 /chat/completions 路径上同样复现:一次请求中模型调用一个工具、网关执行后再次调用模型,最终 spend logs 只有 list_mcp_tools、acompletion、call_mcp_tool 三行,后续模型轮次没有记录。客户端收到的响应有自己的 id 和 usage.total_tokens = 964,且响应头带有 x-litellm-response-cost: 0.0014520,说明代理已计算该轮成本但没有写入 spend logs。该 key 的 spend 为 0.0012067,仅第一轮。

报错原文

[Bug]: Spend logs only record the first tool call and first LLM round for chained MCP calls on streaming /responses (require_approval="never")

日志表现上并没有抛出异常,主要异常是:

follow-up LLM calls and every tool call after the first never get their own log entries
spend is undercounted
has_dispatched_final_stream_success
has_logged_async_success
request_id is the primary key
create_many(skip_duplicates=True)

原因分析

Issue 作者定位到两个问题叠加:

  • 链式 LLM 调用复用父请求的 logging 对象。后续调用在 litellm/responses/mcp/mcp_streaming_iterator.py 的 _create_follow_up_iterator 中复制原始请求参数,而原始参数包含 litellm_logging_obj 和 litellm_call_id,因此所有轮次共享同一个 Logging 对象。litellm/litellm_core_utils/litellm_logging.py 的 dispatch_success_handlers 存在一次性保护 has_dispatched_final_stream_success,只有第一轮的 response.completed 能到达成功回调;非流式路径通过 has_logged_async_success 遇到同样限制。评论中的非流式复现与此一致。
  • 每次 MCP 工具调用写入相同的 request_id。在 litellm/responses/mcp/litellm_proxy_mcp_handler.py 的 _execute_tool_calls 中,tool_logging_call_id 对每轮每个工具调用都回退到父级 litellm_call_id;由于 CallToolResult 没有 id,所有工具调用的 spend row 的 request_id 完全相同。request_id 是主键,插入使用 create_many(skip_duplicates=True),所以只有第一条工具调用记录保留下来。

Issue 指出同样两个问题也存在于 chat completions 的 MCP 路径 litellm/responses/mcp/chat_completions_handler.py。

环境排查

  • 确认 LiteLLM Proxy 版本:评论中 v1.97.0 可复现;需确认是否已包含 #47445 的修复。
  • 确认请求路径:流式 /v1/responses 或非流式/流式 /v1/chat/completions。
  • 确认 MCP 工具配置:tools 中是否设置 "type": "mcp"、"require_approval": "never",以及 server_url 是否指向代理 MCP。
  • 确认是否发生链式多轮调用:日志中是否应出现多次模型调用和多次工具调用。
  • 确认日志侧配置:spend logs 是否写入成功,request_id 是否重复,是否存在 skip_duplicates=True 导致后写记录被丢弃。
  • 确认预算影响:使用带 max_budget 的独立 key 对比请求前后 spend 增量,判断是否只计入首轮费用。
  • Issue 未提供 Python、CUDA、PyTorch、显卡或节点版本文档,无需按这些项排查。

解决步骤

  1. 先确认当前 LiteLLM 版本与修复状态。Issue 说明该问题由 #47445 修复,修复后的行为是:流式 /v1/responses MCP 自动执行会在一条 spend row 中计费每一轮模型调用,并记录每次工具调用。若版本尚未包含该修复,可优先尝试升级到包含 #47445 的版本;Issue 未给出具体版本号,升级前请核对发布说明。
  2. 若暂时无法升级,可评估评论中复现者使用的临时规避方式:将 require_approval 设为 "always",并让应用自行发起后续调用。这属于绕过自动执行链路的临时方案,不是官方修复,Issue 也未说明其长期适用性。
  3. 检查日志中链式调用是否仍复用父请求的 litellm_logging_obj 和 litellm_call_id。修复目标是让每一轮 LLM 调用拥有独立的成功回调,而不是被 has_dispatched_final_stream_success 或 has_logged_async_success 拦截。
  4. 检查 MCP 工具调用写入的 request_id 是否重复。若仍回退到父级 litellm_call_id,需确认修复是否已为每个工具调用生成独立标识,避免被 create_many(skip_duplicates=True) 丢弃。
  5. 对使用 max_budget 的 key 和 team 做费用核对,确认预算执行是否读取到所有轮次的 token 计数。评论指出该问题会让 MCP 流量可能花费接近上限两倍,修复后应复查预算计数。

验证方法

发起一次带 MCP 自动执行且发生链式调用的请求,然后检查 /ui/?page=logs 或 GET /spend/logs:理想结果是每次模型调用有一行独立记录(各自有 response id),每次工具调用也有一行(工具 A 和工具 B 都存在)。同时用带 max_budget 的独立 key 对比请求前后 spend 增量,确认后续模型轮次的 token 成本被写入,而不是只计首轮。评论中的复现示例可作为核对基准:首轮 acompletion 记录 845 tokens、0.0012067,但响应头成本为 0.0014520 且未入账,修复后这部分应被计入。

参考来源

BerriAI/litellm #37358

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 29574

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注