
1. 多工具调用下LLM 调用链为什么总是断的如果你同时用 Claude Code、Cursor、自己写的 Python 脚本还有几个跑在服务器上的 Agent大概率会遇到一个很具体的问题出错了不知道去哪查。用户反馈「回答不对」你打开日志只看到一行200 OK模型返回了什么、用了哪个 Prompt 版本、消耗多少 Token、中间调了几次工具全是黑的。这不是你代码写得差而是 LLM 应用天生比传统后端难观测。传统接口的输入输出是确定的LLM 的输入是 Prompt 拼装结果输出是流式的中间还可能嵌套工具调用和多轮对话。没有调用链追踪你只能靠print大法而print在并发场景下基本等于没有。Langfuse 解决的就是这件事。它是一个开源的 LLM 可观测性平台核心能力是把每一次 LLM 请求变成一条可检索的 TraceTrace 里包含完整的输入输出、Token 消耗、延迟、嵌套的 Span以及你绑定的 Prompt 版本。你可以把它理解成 LLM 应用的「监控摄像头」——不是看服务器 CPU而是看模型到底收到了什么、吐出了什么。但这里有个前置问题容易被忽略当你的多个工具各自持有不同的 API Key 时Trace 的归属和成本统计会散落在不同账号下调用链追踪就变成了「每个工具各追各的」。所以这篇的重点不是单纯讲 Langfuse 怎么装而是用 TaoToken 统一 Key 之后让所有工具的调用都汇聚到同一条可观测链路上。适合已经用上多个 AI 工具、想让调用链和成本口径统一的开发者。2. 前置准备TaoToken 统一 Key 与 Langfuse 项目初始化先说清楚分工。TaoToken 在这里承担的是「统一入口」的角色你不再给每个工具单独配一套 Key而是用同一个 Key 走同一个 API 地址这样所有请求的来源、模型、消耗都能在一个口径下对齐。Langfuse 承担的是「记录与展示」它通过 SDK 或 OTel 接收你的调用数据生成 Trace 和 Prompt 版本视图。你需要准备两样东西。第一样是 TaoToken 的 API Key。登录官网后进入控制台在 API Keys 页面创建一个 Key复制保存。注意这个 Key 只在创建时完整显示一次丢了就重新建。API 地址统一用https://taotoken.net/api不要带任何多余路径。第二样是 Langfuse 的项目凭证。如果你用 Langfuse Cloud创建项目后能在 Settings 里拿到Public Key和Secret Key如果自托管部署完成后同样在项目设置里生成。这两个 Key 加上Host地址就是后面环境变量的三件套。环境变量建议统一写在一个.env文件里不要散落在各个工具的配置中。这样做的直接好处是换 Key 只改一处所有工具同步生效。# .env TAOTOKEN_API_KEYsk-你的taotoken密钥 TAOTOKEN_BASE_URLhttps://taotoken.net/api LANGFUSE_PUBLIC_KEYpk-lf-你的公钥 LANGFUSE_SECRET_KEYsk-lf-你的私钥 LANGFUSE_HOSThttps://cloud.langfuse.com注意LANGFUSE_HOST如果你用的是自托管换成自己的域名不要照抄 Cloud 地址。自托管场景下这个值写错SDK 会静默失败Trace 不会报错但也不会出现。这里有个我踩过的坑很多人把TAOTOKEN_BASE_URL写成带/v1的地址结果 OpenAI SDK 又自动拼了一次/v1变成/v1/v1/chat/completions直接 404。统一用https://taotoken.net/api让 SDK 自己处理版本路径。3. 可复制配置settings.json 与 config.toml 片段不同工具的配置入口不一样这里给两个最常见的骨架Claude Code 类的settings.json以及通用 CLI 工具的config.toml。核心思路都是把 base URL 指向 TaoToken把 Key 从环境变量读取同时把 Langfuse 的追踪开关打开。先看settings.json。这个文件通常放在用户目录下的工具配置文件夹里比如~/.claude/settings.json。关键字段是env把 API 地址和 Key 注入进去。{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的taotoken密钥, LANGFUSE_PUBLIC_KEY: pk-lf-你的公钥, LANGFUSE_SECRET_KEY: sk-lf-你的私钥, LANGFUSE_HOST: https://cloud.langfuse.com }, telemetry: { enabled: true, exporter: langfuse } }再看config.toml。很多 CLI 工具用 TOML 管理配置结构更清晰。下面这个片段把模型提供方和可观测性分开写方便你对照自己的工具改。[provider] name taotoken base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY [observability] enabled true provider langfuse public_key_env LANGFUSE_PUBLIC_KEY secret_key_env LANGFUSE_SECRET_KEY host_env LANGFUSE_HOST [trace] capture_input true capture_output true sample_rate 1.0sample_rate 1.0表示全量采集。调试阶段建议全采生产环境如果量很大可以降到0.1或更低避免 Langfuse 侧写入压力过大。capture_input和capture_output打开后Prompt 和模型返回会完整进 Trace这也是后面核对 Prompt 版本的前提。如果你用的是 Python 脚本而不是现成工具直接在代码里初始化更直接。Langfuse 的 SDK 支持装饰器方式包住你的 LLM 调用函数即可。import os from langfuse.decorators import observe from openai import OpenAI client OpenAI( api_keyos.getenv(TAOTOKEN_API_KEY), base_urlos.getenv(TAOTOKEN_BASE_URL), ) observe() def ask_model(prompt: str): response client.chat.completions.create( modelclaude-sonnet-4-20250514, messages[{role: user, content: prompt}], ) return response.choices[0].message.content if __name__ __main__: print(ask_model(用一句话解释什么是可观测性))observe()会自动创建一个 Trace把函数的输入输出、耗时、异常都记录下来。如果你在函数里还调了别的工具用observe(as_typespan)嵌套就能在 Langfuse 面板里看到树状调用链。4. 验证请求一次调用后 Trace 与 Prompt 版本核对配置写完不算完必须跑一次真实调用然后去 Langfuse 面板核对三件事Trace 是否出现、Span 层级是否正确、Prompt 版本是否绑定。先跑上面那段 Python。运行后终端会打印模型回答同时 Langfuse SDK 在后台把数据发出去。注意 SDK 是异步发送的程序结束太快可能来不及 flush。稳妥做法是在脚本末尾加一行langfuse.flush()或者用with上下文管理。from langfuse import Langfuse langfuse Langfuse() # ... 你的调用逻辑 ... langfuse.flush()跑完之后打开 Langfuse 面板进入 Traces 页面。你应该能看到一条新的 Trace名字默认是函数名ask_model。点进去核对以下几点。第一Trace 的 Input 里应该有你传的 prompt 原文Output 里是模型返回。如果 Input 是空的说明capture_input没开或者 SDK 版本不支持自动捕获需要手动langfuse.update_current_trace(input...)。第二看 Token 消耗和延迟。Langfuse 会从 OpenAI 兼容的返回体里解析usage字段。因为走的是 TaoToken 统一入口这里的模型名和消耗口径是一致的不会出现同一个模型在不同工具里统计对不上的情况。第三Prompt 版本。如果你在 Langfuse 里创建了 Prompt 并指定了版本需要在调用时显式关联。SDK 支持这样写from langfuse import Langfuse langfuse Langfuse() prompt langfuse.get_prompt(my-prompt, version2) observe() def ask_with_prompt(user_input: str): compiled prompt.compile(queryuser_input) response client.chat.completions.create( modelclaude-sonnet-4-20250514, messages[{role: user, content: compiled}], ) return response.choices[0].message.content这样在 Trace 详情页的 Prompt 区域会显示my-prompt的version2你就能清楚知道这次回答用的是哪个版本的提示词。做 A/B 测试时这个绑定关系是刚需。验证成功的标志很明确Traces 列表出现新记录点进去能看到完整的 Input/Output、Token 数、延迟以及 Prompt 名称和版本号。如果这四项都齐了说明统一 Key 加调用链追踪的链路已经通了。5. 本篇常见错排查接入过程中最容易卡住的几个点我按出现频率排一下。Trace 完全不出现。先检查LANGFUSE_HOST是否写对自托管用户特别容易把 Cloud 地址抄进去。其次确认LANGFUSE_PUBLIC_KEY和LANGFUSE_SECRET_KEY没有前后空格环境变量读取失败时 SDK 通常不报错只是静默不发。最后确认程序退出前调用了flush()异步队列没发完就退出数据会丢。Trace 出现了但 Input/Output 为空。这是capture_input/capture_output没开或者你用的 SDK 版本较老不支持自动捕获。升级 SDK 到最新版或者在代码里手动补langfuse.update_current_trace( input{prompt: prompt}, output{response: result}, )Token 消耗显示为 0。说明返回体里没有usage字段或者 SDK 没解析到。走 TaoToken 统一入口时OpenAI 兼容格式的返回体是带usage的如果还是 0检查你的 SDK 是不是把streamTrue的流式响应直接透传了——流式场景下 usage 需要额外开启stream_options{include_usage: True}。Prompt 版本不显示。只有通过langfuse.get_prompt()获取的 Prompt 才会自动绑定版本。如果你直接把字符串塞进 messagesLangfuse 不知道它对应哪个版本自然不显示。想追踪版本就必须走 Prompt 管理接口。多个工具 Trace 分散在不同项目。这是统一 Key 没做到位。检查每个工具的配置确认它们用的是同一个TAOTOKEN_API_KEY和同一个 Langfuse 项目凭证。只要有一个工具漏配它的调用就不会进同一条链路。6. 把统一 Key 和调用链固定下来走到这一步你手上应该有一套能跑通的配置TaoToken 统一 Key 负责所有工具的出口Langfuse 负责把每次调用变成可检索的 Trace。接下来要做的不是继续加工具而是把这两个凭证的管理固定成习惯。具体来说环境变量集中在一个.env里所有工具从环境变量读不硬编码。新增工具时先确认它的 base URL 指向https://taotoken.net/api再确认 Langfuse 的追踪开关打开最后跑一次验证调用去面板核对 Trace 和 Prompt 版本。这个流程走顺了后面接多少个工具都不会乱。如果你还在选型阶段想先验证模型对话效果可以直接用模型对话页面试如果是要长期跑编码和 Agent 任务建议把 Coding Plan 配好让统一 Key 的额度管理更清晰接入过程中遇到 Key 或权限问题去 API Keys 页面和接入文档对照排查比在代码里猜要快得多。