尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI Agent Harness任务执行轨迹记录:用LangChain+LangSmith搭建可观测执行链路

AI Agent Harness任务执行轨迹记录:用LangChain+LangSmith搭建可观测执行链路 1. 从一次 Agent 执行断点说起AI Agent Harness 任务执行轨迹记录说白了就是给 Agent 装一个“行车记录仪”。LangChain 负责让 Agent 跑起来LangSmith 负责把 Agent 每一步想了什么、调了什么工具、返回了什么、在哪一步卡住全部按时间线串成一条可回放的链路。它适合正在用 LangChain 写 Agent、却经常遇到“任务跑一半没结果”“工具调用顺序诡异”“线上偶发失败无法复现”的开发者。我试过最典型的一个场景一个用 LangChain 搭的订单查询 Agent本地跑十次九次正常部署到测试环境后偶尔在“调用库存接口”这一步之后直接停住日志里只有一句Chain ended没有任何异常堆栈。没有轨迹记录时你只能靠猜有了 LangSmith 的 trace你能直接看到是 LLM 返回的 tool_calls 里参数少了一个字段导致下游工具抛错被吞掉。这篇就围绕这个场景给出 Harness 接入 LangSmith 的配置骨架、轨迹字段定义以及一次可复现的验证动作帮你把 Agent 执行断点定位到具体节点。核心检索词先摆清楚AI Agent Harness 是运行与观测 Agent 的骨架LangChain 是编排框架LangSmith 是链路追踪与调试平台任务执行轨迹记录是把三者串起来的那根线。下面从接入准备开始一步步落到可运行的代码。2. TaoToken 前置把模型调用统一到可追踪入口在接 LangSmith 之前先把模型调用入口固定下来。很多轨迹断点其实不是 LangChain 的问题而是模型侧返回格式不稳定导致的。我习惯用 TaoToken 作为统一的模型调用入口它的 API 兼容 OpenAI 风格LangChain 里可以直接用ChatOpenAI指向它省去为不同模型写适配层。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。注意 API 地址后面不加 UTM 参数直接作为base_url使用。你需要先在控制台创建一个 API Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到 Key 之后把它写进环境变量不要硬编码在代码里。export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api export LANGCHAIN_TRACING_V2true export LANGCHAIN_API_KEYlsv2_你的langsmith_key export LANGCHAIN_PROJECTagent-harness-trace-demo这里有个容易踩的坑LANGCHAIN_TRACING_V2必须显式设为true否则 LangChain 不会往 LangSmith 发数据。另外LANGCHAIN_PROJECT决定轨迹归到哪个项目下建议按环境区分比如agent-harness-trace-demo-dev和agent-harness-trace-demo-prod避免测试数据污染生产看板。如果你还没决定用哪个模型可以先在模型对话页试一下返回格式地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。对于 Agent 场景建议选支持 function calling 的模型否则 LangChain 的 tool 调用会退化成文本解析轨迹里会出现大量“解析失败”的噪声节点。3. 可复制配置LangChain LangSmith 轨迹骨架3.1 依赖安装与最小可运行 Agent先装依赖。LangChain 生态拆得比较细建议锁定版本避免 API 变动导致轨迹字段对不上。pip install langchain0.2.0 langchain-openai0.1.0 langsmith0.1.0 langchain-community0.2.0下面是一个最小可运行的 Agent包含两个工具一个查订单一个查库存。故意在库存工具里留一个参数校验用来制造可复现的断点。import os from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.tools import tool # 1. 模型入口统一指向 TaoToken llm ChatOpenAI( modelgpt-4o-mini, api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], temperature0, ) # 2. 定义工具注意参数 schema 要显式声明 tool def query_order(order_id: str) - dict: 根据订单号查询订单详情。order_id 必须是 8 位数字字符串。 if not order_id.isdigit() or len(order_id) ! 8: raise ValueError(forder_id 格式非法: {order_id}) return {order_id: order_id, status: paid, sku: FRIDGE-001} tool def query_stock(sku: str, warehouse: str) - dict: 查询指定仓库的库存。sku 和 warehouse 都不能为空。 if not sku or not warehouse: raise ValueError(sku 和 warehouse 均为必填) return {sku: sku, warehouse: warehouse, available: 12} tools [query_order, query_stock] # 3. 构造 prompt保留 agent_scratchpad 让 LangChain 自动注入中间步骤 prompt ChatPromptTemplate.from_messages([ (system, 你是一个订单助手先查订单再查库存最后给出结论。), (human, {input}), MessagesPlaceholder(variable_nameagent_scratchpad), ]) agent create_openai_tools_agent(llm, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue, return_intermediate_stepsTrue) if __name__ __main__: result executor.invoke({input: 帮我查一下订单 12345678 的库存情况仓库选上海仓}) print(result[output])这段代码跑起来后LangSmith 会自动生成一条 trace包含 LLM 节点、tool 节点、以及 AgentExecutor 的根节点。你不需要手动埋点LangChain 的回调机制已经帮你把轨迹发过去了。3.2 轨迹字段定义Trace / Span / Event 三层LangSmith 的轨迹模型和 OpenTelemetry 类似分三层Run对应 Trace、Child Run对应 Span、Event对应节点内事件。在 Agent 场景里我建议按下面的字段约定来理解方便排查时快速定位。层级LangSmith 字段对应 Agent 语义排查用途Runid/name一次完整任务定位是哪次执行出问题Runrun_typechain/llm/tool区分节点类型Runinputs/outputs节点输入输出看参数是否缺失Runerror异常信息直接定位报错节点Runstart_time/end_time节点耗时找超时节点Child Runparent_run_id父子关系还原调用树Eventeventstoken 流、工具重试看流式与重试细节在 LangSmith 控制台里一条 Agent 执行的轨迹会呈现为树形结构根节点是AgentExecutor下面挂ChatOpenAI的 LLM 节点和query_order、query_stock的 tool 节点。每个节点都能点开看 inputs 和 outputs。当query_stock抛错时tool 节点的error字段会直接显示sku 和 warehouse 均为必填而不是像以前那样被 AgentExecutor 吞掉。3.3 给轨迹加自定义元数据默认轨迹只记录 LangChain 能拿到的信息。如果你想在轨迹里标记业务上下文比如用户 ID、会话 ID、环境可以用config传metadata和tags。result executor.invoke( {input: 帮我查一下订单 12345678 的库存情况仓库选上海仓}, config{ metadata: { user_id: u_10086, session_id: sess_20240520_001, env: dev, }, tags: [order-agent, stock-check], run_name: order_stock_agent_run, }, )这样在 LangSmith 里就能按user_id或session_id过滤轨迹。当线上出现某个用户反复失败时直接搜user_id就能把该用户所有执行链路拉出来对比比翻日志快得多。4. 验证请求一次可复现的断点定位4.1 制造断点把上面的代码跑起来输入一个会让query_stock报错的请求。比如让模型只传sku不传warehouse或者传一个空的warehouse。由于我们在工具里做了显式校验这个错误会以异常形式抛出。python agent_demo.py终端里你会看到verboseTrue打印的中间步骤最后可能是一个ValueError。但关键不在这里关键是打开 LangSmith 控制台找到这次 run。4.2 在 LangSmith 里读轨迹进入项目agent-harness-trace-demo你会看到刚才那条 run。点进去之后按下面的顺序看第一步看根节点AgentExecutor的inputs确认用户原始输入是什么。第二步展开子节点找到query_stock这个 tool run点开它的inputs你会看到模型实际传进来的参数。如果warehouse是空字符串或者缺失问题就定位到了模型侧的工具参数生成。第三步看这个 tool run 的error字段确认异常信息。第四步回到 LLM 节点看它的outputs里tool_calls的完整结构对比工具 schema就能判断是模型没按 schema 填还是 schema 本身描述不清。这个过程在以前可能要加一堆 print 才能还原现在在 LangSmith 里点几下就能看到完整链路。如果你需要更细的 token 级事件可以在 LangSmith 的 run 详情里看events标签页流式返回的每个 chunk 都有记录。4.3 用 API 拉取轨迹做自动化断言除了在控制台看你还可以用 LangSmith 的 SDK 把轨迹拉下来做自动化回归。比如每次 CI 跑完 Agent 测试后断言轨迹里不能出现error节点。from langsmith import Client client Client() runs client.list_runs( project_nameagent-harness-trace-demo, filtereq(status, error), limit10, ) for run in runs: print(run.name, run.error, run.inputs)这段代码能帮你把“轨迹记录”从人工排查升级成自动化监控。当 Agent 在测试环境出现断点时CI 直接失败并打印出错节点不用等到上线才发现。5. 本篇常见错排查5.1 LangSmith 里没有轨迹最常见的原因是环境变量没生效。检查LANGCHAIN_TRACING_V2是否为trueLANGCHAIN_API_KEY是否以lsv2_开头。另外如果你在代码里手动设置了os.environ要确保在 import LangChain 之前设置否则回调不会注册。还有一个隐蔽情况某些 LangChain 版本需要显式传callbacks可以试试在invoke时加config{callbacks: [LangChainTracer()]}。5.2 轨迹里只有根节点没有子节点这通常是 Agent 没有真正走到工具调用。检查模型是否支持 function calling以及create_openai_tools_agent的 prompt 里是否包含agent_scratchpad。如果模型返回的是纯文本而不是 tool_callsLangChain 不会生成 tool 子节点轨迹里自然看不到工具调用。可以在模型对话页换一个支持 function calling 的模型再试。5.3 工具节点报错但 Agent 仍然返回成功这是 AgentExecutor 的默认行为工具抛错后错误信息会作为 observation 回传给 LLMLLM 可能选择忽略并给出一个“看起来正常”的回复。要避免这种情况可以在工具里返回结构化错误而不是抛异常或者在 AgentExecutor 里设置handle_parsing_errorsFalse并配合max_iterations限制。更彻底的做法是在轨迹里对error节点做告警一旦出现就人工介入。5.4 轨迹数据太大控制台加载慢Agent 跑长任务时轨迹里会包含大量 LLM 输入输出。可以在 LangSmith 项目设置里开启采样或者用metadata标记关键 run只对关键 run 做完整记录。另外把verbose关掉能减少终端输出但不影响 LangSmith 的轨迹记录。5.5 本地能追踪部署后追踪不到检查部署环境是否设置了LANGCHAIN_TRACING_V2和LANGCHAIN_API_KEY。容器化部署时环境变量容易漏配。另外如果部署环境访问 LangSmith 需要网络策略放行确认出站规则允许。对于长期编码和 Agent 项目可以考虑用 Coding Plan 统一管理模型与追踪配置入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。6. 把轨迹记录变成 Agent 的常规能力接入 LangSmith 之后我最大的感受是Agent 的调试方式从“猜”变成了“看”。以前遇到断点第一反应是加 print现在第一反应是打开 LangSmith按时间线走一遍。轨迹记录不是上线后才补的监控而是开发阶段就该有的基础设施。如果你还在用裸 LangChain 跑 Agent建议先把LANGCHAIN_TRACING_V2打开跑一次最简单的任务看看轨迹长什么样。然后把你最常出问题的那个工具在轨迹里找到它的 inputs 和 outputs对比模型实际传参和你的 schema 期望大概率能发现一两个之前忽略的字段问题。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite API Keys 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 需要看模型返回格式就去模型对话页 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。把轨迹记录跑通一次后面每次 Agent 出问题你都能少熬一个凌晨。
返回列表