引言为什么 Agent 一复杂日志就开始不够用了在前一篇《LangGraph 与 ReAct Agent 调试技巧》中我们已经讲过printloggingstream_mode[updates, values, debug]interrupt_before/interrupt_aftertime-travel 回放这些方法已经足够帮你排掉 80% 的问题。但当你的 Agent 开始变复杂以后你很快会发现单靠日志已经不够了。例如一个 Agent 里有 10 个节点、5 个 Tool一个用户问题会产生几十次模型调用同一个问题不同时间运行结果不一样线上用户反馈“Agent 卡住了”但你根本拿不到当时现场Tool 调了但你不知道到底是哪一步开始偏Token 花得很快但你不知道浪费在哪这时候普通日志会遇到三个根本问题日志太碎无法把一次完整执行串起来无法比较不同运行之间的差异于是你会进入一种非常痛苦的状态日志很多 但还是不知道问题在哪这也是为什么Agent 项目一旦进入真实开发阶段就几乎一定会用到LangSmithLangSmith 是 LangChain / LangGraph 官方提供的 AI 应用调试、Tracing、评估平台。它最大的价值不是“再多打一层日志”而是把一次 Agent 执行从黑盒变成一条完整、可追踪、可回放、可比较的轨迹。简单理解你可以把它看成AI Agent 版的 APMAI Agent 版的链路追踪AI Agent 版的 Jaeger / Zipkin / SkyWalking只不过它追踪的不是 HTTP 请求而是Prompt → 模型调用 → Tool 调用 → State 更新 → 最终输出这篇文章我们就来完整讲清楚LangSmith 到底是什么为什么单靠日志不够如何一行代码开启 Tracing如何用 LangSmith UI 看 Trace、Token、Latency、Tool如何用 Polly 聊天式排查 Agent 问题如何定位“工具没返回”“State 没更新”“死循环”等顽固 bug一、LangSmith 是什么一句话总结LangSmith 是专门给 AI Agent / LLM 应用做调试和评估的平台。如果你熟悉传统后端你可以这样类比传统系统AI Agent 系统Jaeger / ZipkinLangSmith日志平台Trace Run TreeAPMToken / Latency / Cost单元测试Dataset EvaluationLangSmith 最核心的概念是把一次 Agent 执行拆成一棵树。例如一个 ReAct Agent用户问题 └─ LLM 推理 └─ Tool: get_weather └─ Tool 返回 Observation └─ LLM 再推理 └─ Tool: calculator └─ 最终答案在日志里这可能只是几十行混乱输出。但在 LangSmith 里它会变成一棵可以展开、点击、查看每一步细节的 Trace Tree。这也是它最大的价值它让你知道Agent 到底是怎么一步一步走到这个结果的。二、为什么单靠日志不够很多工程师第一次接触 LangSmith都会想我已经有 print 和 logging 了还需要这个吗答案通常是当你的 Agent 超过 3 个节点以后就非常需要。因为日志天生有三个问题。1. 日志是线性的但 Agent 是树状的日志通常长这样[tool_node] input... [tool_node] output... [llm_node] input... [llm_node] output...你很难看出谁是谁的父节点哪一次 Tool 调用属于哪一次模型推理当前调用到底在第几轮循环里而 LangSmith 会自动把它组织成Agent ├─ LLM Call #1 ├─ Tool Call #1 ├─ LLM Call #2 └─ Final Output这对于 ReAct、LangGraph、多 Agent 特别重要。2. 日志不能方便地比较两次运行很多 Agent 问题不是“永远错”而是同一个输入这次对下次错。这时候你最想做的是把两次运行放在一起看看到底哪一步开始不一样普通日志很难做到。而 LangSmith 支持直接比较两个 Trace。3. 日志通常没有 Token、Latency、Cost你可能会发现为什么这个 Agent 这么慢为什么 token 花得特别多是不是某一步循环太多次这些问题普通日志几乎回答不了。而 LangSmith 会自动展示每一步 latency每一步 token 数模型花费Tool 执行耗时所以你不仅能排“对不对”还能排“慢不慢”“贵不贵”。三、一行代码开启 TracingLangGraph 自动支持LangSmith 最爽的一点是接入特别简单。尤其是 LangGraph / LangChain 项目很多情况下只需要环境变量。1. 安装pipinstall-Ulangsmith2. 配置环境变量exportLANGCHAIN_TRACING_V2trueexportLANGCHAIN_API_KEY你的_langsmith_keyexportLANGCHAIN_PROJECTmy-agent-project如果你用.envLANGCHAIN_TRACING_V2true LANGCHAIN_API_KEY你的_langsmith_key LANGCHAIN_PROJECTmy-agent-project然后在代码里fromdotenvimportload_dotenv load_dotenv()就可以了。对于 LangChain / LangGraph大多数调用都会自动被 Trace。例如graph.invoke(input_data)执行完以后你去 LangSmith UI就会看到完整 Trace。3. 为什么说“LangGraph 自动支持”因为 LangGraph 的节点、边、State本身就很适合被记录成一棵 Trace Tree。所以你不需要手工埋点每个节点。LangSmith 会自动记录当前执行了哪个 nodenode 输入是什么node 输出是什么下一个 node 是谁这也是它比纯日志方便很多的原因。四、LangSmith UI 实战你真正应该看什么很多人第一次打开 LangSmith会被一堆字段吓到。实际上真正最值得看的只有四类东西Trace TreeToken 与 CostLatencyTool 调用详情1. Trace Tree先看执行路径进入一次 Run 后最先看的永远是左边的 Trace Tree。它会像这样AgentExecutor ├─ ChatOpenAI ├─ get_weather ├─ ChatOpenAI ├─ calculator └─ ChatOpenAI你首先要回答的问题是它有没有按我预期的顺序执行例如有没有调 ToolTool 调的是不是正确的有没有多走了一轮有没有进入死循环如果执行路径已经不对那后面不用再看 Prompt 了。2. Token 使用为什么 Agent 这么贵很多人第一次做 Agent都会发现明明只问了一句话怎么花了这么多 tokenLangSmith 会帮你直接展示Prompt tokensCompletion tokensTotal tokens你会很容易发现某个节点 Prompt 太长Memory 把太多历史带进去了Agent 在循环里重复调用同一个模型例如LLM Call #1: 1200 tokens LLM Call #2: 1500 tokens LLM Call #3: 1700 tokens那大概率说明State / messages 在不断膨胀。这也是定位 Memory 失控最有效的方法之一。3. LatencyAgent 为什么这么慢很多时候用户觉得 Agent “不好用”其实不是因为结果错而是因为太慢。LangSmith 会告诉你哪一步最慢是模型慢还是 Tool 慢是某个节点卡住了还是循环太多次例如get_weather: 50ms calculator: 5ms ChatOpenAI: 8s那你立刻就知道问题不在 Tool而在模型。如果你看到同一个节点重复执行了 6 次那说明Agent 很可能陷入循环。4. Tool 调用详情最容易藏 bug 的地方很多 Agent 问题其实最后都会落到 Tool 上。例如Tool 名字不清参数没提取对Tool 返回值没写对Tool 返回了但下一步没读在 LangSmith 里你可以直接点开某个 Tool Run看到Tool Name: get_weather Input: {city: 北京} Output: 北京今天晴天25度如果参数不对、返回为空、或者输出字段错了这里会非常明显。五、Polly直接问“这个 Agent 为什么错了”这是 LangSmith 里 2026 年非常值得写的一部分。LangSmith 现在内置了一个 AI 调试助手Polly你可以把它理解成一个会帮你读 Trace 的 AI 工程师。你不需要自己一层一层点。你可以直接问为什么这个 Agent 没有调用 get_weather或者为什么它一直循环甚至这个 Trace 里最可能的问题在哪Polly 会自动分析整条 Trace并给你类似该 Agent 没有调用 get_weather因为 system prompt 没有明确要求必须使用工具。 模型直接根据常识回答。或者Agent 在 tool_node 和 llm_node 之间循环了 5 次。 因为 state[done] 从未被设置为 True。这对于复杂 Agent 来说非常有价值。因为很多时候问题并不是“看不到”而是Trace 太长人已经看不过来了。而 Polly 相当于帮你先读一遍。六、案例定位“工具结果没返回”这是最常见的一类问题。现象Tool 已经执行了 但最终答案还是瞎猜你打开 LangSmith Trace会看到Tool: get_weather Output: 北京今天晴天25度说明 Tool 本身没问题。接着你再看下一轮 LLM 输入。结果发现messages 里没有 ToolMessage这说明Tool 虽然执行了但 Observation 没被写回上下文。最终模型等于“没看到工具结果”。问题就定位到了 Tool Node。七、案例定位“State 没更新”例如Graph 里 weather_node 已经跑完 但下一步 answer_node 却拿不到 weather在 LangSmith Trace 里你会看到weather_node output: { result: 北京25度 }而 answer_node 期待的是state[weather]于是问题就很明显字段名写错了。日志里你可能很难第一时间发现。但在 LangSmith 的输入 / 输出面板里一眼就能看出来。八、案例定位“无限循环”无限循环是 Agent 最痛苦的问题之一。例如 Trace 看起来像llm_node → tool_node → llm_node → tool_node → llm_node → tool_node一直重复。这时候你可以直接看 Trace Tree。如果发现相同节点重复出现很多次每次输入几乎一样每次输出也几乎一样那大概率就是停止条件没有触发。你再去看对应节点输出。通常会发现state[done]False永远没变。或者模型每次都在说我还需要继续查询。这说明 Prompt 没明确告诉模型什么时候应该停止。九、为什么 LangSmith 特别适合复杂 Agent如果你的 Agent 只是Prompt → 模型 → 输出那 print 和 logging 可能已经够了。但如果你开始做ReAct多 ToolLangGraph多 Agent 协作Memory长时间运行你会发现问题已经不是“有没有日志”而是“有没有办法把整个执行过程组织起来”。而 LangSmith 最强的地方就在这里它能自动记录每一步能自动关联上下游能直接比较两次运行能统计 Token、Latency、Cost能帮你找到真正的问题开始于哪里一句话说LangSmith 不是为了让你“看更多日志”而是为了让你“终于能看懂日志”。十、给工程师的实战建议最后给你几条特别实用的经验。1. 不要等 Agent 出问题了才接 LangSmith最好的做法是项目一开始就接。因为很多问题只有在第一次出错时Trace 才最完整。2. 每个重要版本都保留一个固定测试集例如天气问题工具调用问题Memory 问题多轮对话问题每次改 Prompt、改 Tool、改 Graph 后都重新跑一遍。这样你才能知道是不是修了一个 bug又引入了另一个 bug。3. 调试时先看 Trace Tree再看 Prompt很多人一上来就怀疑 Prompt。但真正的问题经常更简单Tool 没调参数错了State 没写边连错了所以一定先看执行路径。4. Polly 适合快速定位但不要完全依赖Polly 非常适合快速读长 Trace给出第一层怀疑但最后还是建议你自己打开关键节点确认。因为真正的复杂 bug最终还是要落到PromptToolStateGraph这些具体实现上。结语一句话总结当 Agent 进入真实项目后最难的不是“写”而是“知道它为什么错”。而 LangSmith 真正提供的不只是日志而是一整套Tracing可视化Token / Cost / Latency 分析多次运行比较AI 辅助排障它会让你第一次真正看见Agent 到底是如何一步一步走向错误或者走向正确。当你能看见它的轨迹时复杂 Agent 才真正开始变得可维护。 相关资源j-langchain GitHubhttps://github.com/flower-trees/j-langchain