快速结论:该问题出现在 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、显卡或节点版本文档,无需按这些项排查。
解决步骤
- 先确认当前 LiteLLM 版本与修复状态。Issue 说明该问题由 #47445 修复,修复后的行为是:流式
/v1/responsesMCP 自动执行会在一条 spend row 中计费每一轮模型调用,并记录每次工具调用。若版本尚未包含该修复,可优先尝试升级到包含 #47445 的版本;Issue 未给出具体版本号,升级前请核对发布说明。 - 若暂时无法升级,可评估评论中复现者使用的临时规避方式:将
require_approval设为"always",并让应用自行发起后续调用。这属于绕过自动执行链路的临时方案,不是官方修复,Issue 也未说明其长期适用性。 - 检查日志中链式调用是否仍复用父请求的
litellm_logging_obj和litellm_call_id。修复目标是让每一轮 LLM 调用拥有独立的成功回调,而不是被has_dispatched_final_stream_success或has_logged_async_success拦截。 - 检查 MCP 工具调用写入的
request_id是否重复。若仍回退到父级litellm_call_id,需确认修复是否已为每个工具调用生成独立标识,避免被create_many(skip_duplicates=True)丢弃。 - 对使用
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 且未入账,修复后这部分应被计入。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![[Bug]: Bedrock count_tokens returns 400 for cross-region inference-profile models — prefix stripped before request](https://www.chat-gpts.plus/wp-content/uploads/2026/10/32683-e728913d-768x403.jpg)

