快速结论:该报错通常出现在通过 OpenInference Claude Agent SDK 插桩 + @langfuse/otel 上报追踪、且使用 Anthropic prompt caching 的多轮 Agent 场景中。优先级排查:确认 span 上是否携带 llm.cost.total,但 Langfuse 实际展示的是按 llm.token_count.* × 定价表推算的成本。核心报错:Span processor ignores OpenInference’s llm.cost.total attribute; recomputes from partial llm.token_count.* instead
适用环境:Langfuse(OTel 接入);@langfuse/otel 5.3.0;@langfuse/tracing 5.3.0;@arizeai/openinference-instrumentation-claude-agent-sdk;@anthropic-ai/claude-agent-sdk(Node.js / TypeScript,依据 Issue 中的复现代码)。Issue 未提供操作系统、Python、CUDA、显卡信息。
最快修复方案:暂无确认的一步修复方案。Issue 讨论给出的可行绕过方式是:让插桩侧同时输出 Langfuse 能识别的成本属性——优先 langfuse.observation.cost_details(JSON,如 {"total": 0.52231845}),其次 gen_ai.usage.cost;二者会被 Langfuse 用作 totalCost。可优先尝试。
注意事项:该绕过方案依赖你能修改或包装插桩输出,属于讨论中提出的做法,并非 Issue 中已验证的上游修复;llm.cost.total 的原生支持在关闭时仍未确认已合入。另一相关 PR #13572 只补充了 llm.token_count.prompt_details.cache_read / cache_write 的 token 统计,不解决成本属性映射问题。
问题场景
用户在 Node.js 中通过 NodeSDK 注册 LangfuseSpanProcessor,并挂载 ClaudeAgentSDKInstrumentation 来追踪 Anthropic Claude Agent SDK(ClaudeAgentSDK.query,如 claude-sonnet-4-6)的多轮 Agent 运行,且请求带 system prompt、工具和 prompt caching。OpenInference 插桩在 AGENT span 上正确写出了 attributes.llm.cost.total(源自 Anthropic 返回的 result.total_cost_usd),但 Langfuse 中 observation.totalCost 为 null,calculatedTotalCost(tokens × 定价)显著偏低,最终 trace.totalCost 只有真实花费的约 46%。
报错原文
Span processor ignores OpenInference's `llm.cost.total` attribute; recomputes from partial `llm.token_count.*` instead
observation.totalCost: null
observation.calculatedTotalCost: 0.237606
trace.totalCost (UI): 0.237606
attributes.llm.cost.total: 0.52231845
原因分析
根据 Issue 讨论,Langfuse 的 OTel 摄取处理器(OtelIngestionProcessor)在提取成本时只识别两类属性:
langfuse.observation.cost_details(Langfuse 自有 JSON 属性,最高优先级);gen_ai.usage.cost(OpenTelemetry GenAI 语义约定,映射为{ total: <value> })。
两者都不存在时,成本留空,Langfuse 改用 token 数 × 定价表推算。OpenInference 使用的 llm.cost.total 不在已识别键集合内,因此被静默丢弃。
同时,OpenInference 插桩只上报最后一轮的输入 token 加总输出 token,不输出 llm.token_count.prompt_cache_read 与 llm.token_count.prompt_cache_creation,而 Anthropic prompt caching 的输入用量主要由这两项构成,导致按 token 推算的成本被大幅低估(Issue 观测约 40%–46%)。PR #13572 已为 OpenInference 补充 cache_read / cache_write 的 token 解析,但未加入 llm.cost.total 作为成本来源。另一个可能原因是你使用的 @langfuse/otel 版本尚未包含对上述属性的支持。
环境排查
- 确认
@langfuse/otel与@langfuse/tracing版本;Issue 中为 5.3.0。 - 确认
@arizeai/openinference-instrumentation-claude-agent-sdk是否处于会写出llm.cost.total的版本。 - 确认
LangfuseSpanProcessor的shouldExportSpan已放行该插桩的 span(Issue 中使用instrumentationScope.name判断)。 - 确认模型与场景:是否为 Claude Sonnet 4.x + system prompt + 工具 + prompt caching 的多轮调用。
- 查看 Langfuse UI 中 span 的 attributes 面板,核对
llm.cost.total、llm.token_count.total是否与实际相符。 - 检查是否已有
langfuse.observation.cost_details或gen_ai.usage.cost属性被覆盖或遗漏。
解决步骤
- 先核实问题:在 Langfuse UI 打开该 AGENT span 的 attributes 面板,确认
attributes.llm.cost.total已写入(Issue 中为 0.52231845),同时 API 返回的totalCost为null、calculatedTotalCost明显偏低。 - 调用
/api/public/observations?traceId=<id>对比usage字段,确认input是否缺少 cache read / cache write 的 token。 - 可优先尝试:在应用侧或插桩包装层,把已知的权威成本额外写成
gen_ai.usage.cost(数值型),或写成langfuse.observation.cost_details的 JSON(如{"total": 0.52231845})。前者映射为{ total },后者优先级最高。 - 升级到包含 PR #13572 的 Langfuse 版本,以缓解 cache token 未被统计导致的 token 低估问题;但这不替代成本属性映射。
- 如果确实无法改造插桩输出,Issue 中提到的兜底方式是:在应用侧用 Anthropic 返回的
result.total_cost_usd为 trace 打自定义 score,用作成本观测。 - 跟踪上游修复:在
extractCostDetails()中把llm.cost.total加入gen_ai.usage.cost同级 fallback,是讨论中提到的直接改法。
验证方法
重新运行同样的多轮 Agent 请求后,查看 API observations 返回:totalCost 不再为 null,且与 Anthropic 返回的 result.total_cost_usd 一致;UI 中 trace 的 totalCost 与真实花费吻合,不再出现仅约一半的偏差。同时确认 usage.input 已体现 cache 相关 token(若已升级到含 PR #13572 的版本)。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


