Agent 开发跑通容易,跑稳很难。接触过的团队基本都卡在同一个环节:Agent 在测试环境里表现得像模像样,一上真实业务就原形毕露——工具调用链莫名其妙断掉、多轮对话后上下文漂移、模型自作主张绕过设定好的流程。问题复现不了,日志又是一团乱麻,根本定位不到是哪一步出了岔子。
这也是我花精力做 Agent-Reach 的原因。它是我给 Agent 应用搭的一套可观测与评估平台,核心解决三件事:完整记录 Agent 从接收指令到最终输出之间的每一步决策、工具调用和中间结果;把任何一次运行都变成一个可回溯、可对比、可评估的完整轨迹;在此基础上做回归测试和质量评估,让 Agent 的每一次改动都有数据兜底。
如果你现在正在开发基于大模型的 Agent 应用,每天被"偶现问题"和"C端用户反馈不一致"折磨,或者你的团队已经进入 Agent 效果调优阶段却苦于没有量化手段,这篇文章应该能给你一些参考。
1. 设计初衷与定位:Agent-Reach 到底解决什么问题
做一个 Agent 观测平台,听起来是个工程活,实际上第一步是梳理清楚痛点到底在哪。我做 Agent-Reach 之前,团队内部的 Agent 项目已经在线上跑了两个月,功能是能用的,但问题不少:
Agent 的执行过程像黑盒。大模型是概率系统,同样的输入,两次运行的思考链条可能完全不同。用户反馈"刚才还能查到的数据现在查不到了",你连它中间调了哪个工具、传了什么参数、模型是怎么做决策的,全都无从查起。
多轮对话的上下文状态难以追踪。Agent 不是单次问答,它需要维护持久化的记忆和状态。某个变量在第三轮被错误地覆盖,到了第五轮才引发故障,这种问题靠看代码很难定位,因为你根本不知道模型在每一轮到底往上下文里写了什么。
效果评估缺乏标准。传统软件有明确的输入输出断言,Agent 没有。同一个问题换个问法,可能有十种合理的回答路径,也可能有十种错误路径。这个"合理"和"错误"怎么定义,需要一套可量化的评估体系。
我把这三个月踩坑得到的需求,汇总成了 Agent-Reach 的核心定位:它不是日志系统,也不是 APM,而是专门为 Agent 的认知过程设计的"行车记录仪 + 赛道分析系统"。传统日志记录的是"发生了什么",Agent-Reach 记录的是"Agent 为什么这么想、为什么这么选、结果怎么样"。
这个定位决定了 Agent-Reach 的几个核心设计原则:
第一,追踪的粒度必须到"推理步骤"级别。不仅仅是记录调用了一个工具,还要记录调用前的模型思考、调用后的结果摘要、以及 Agent 基于这个结果做出的下一步决策。
第二,保留完整的决策上下文。任何一个步骤的观测数据,都要能还原当时的完整上下文状态,包括系统提示词、历史消息、当前可用的工具列表、以及关键变量值。
第三,评估能力要内置。观测数据如果不能直接转化为"好/坏"的判断,那它的价值就打了折扣。Agent-Reach 把评估器设计为第一等公民,让每个轨迹都可以一键跑评估。
2. 核心细节解析:三个关键设计的选择逻辑
2.1 链路追踪:从"稀疏日志"到"密集语义轨迹"
Agent 的链路追踪,技术上比传统的微服务追踪复杂一个量级。普通的 RPC 追踪,每个 span 的语义是明确的——"这是一个 HTTP 调用""这是一个数据库查询",但 Agent 的 span 里,核心内容是大模型的自然语言输出,甚至是多个候选决策路径。这就带来一个问题:采集什么、丢弃什么,直接决定了平台的价值。
我在 Agent-Reach 里定义了四种核心 span 类型:
- Plan span:记录 Agent 的规划决策,包括当前目标、候选方案、最终选中的路径。这一层解决"它为什么这么干"的问题。
- Tool span:记录每一次工具调用的输入、输出、耗时和错误信息。这一层解决"它干了什么"的问题。
- Context span:记录每次模型调用时,系统上下文里实际注入了什么内容。这一层解决"它看到了什么"的问题。
- Reflection span:记录 Agent 对自身输出的校验和修正过程。这一层解决"它有没有发现自己错了"的问题,很多复杂 Agent 都有自我纠错机制,这个环节恰恰是最容易被忽略的。
这里是 Agent-Reach 与普通日志系统的分水岭:普通日志把工具入参和出参打出来就算完成,Agent-Reach 还会记录模型每一步的完整思考文案。这个"思考链"数据是后面做评估、做回归、做调试的关键素材,也是排查那些"工具调用完全正确但最终答案错误"的疑难杂症的唯一线索。
2.2 会话存储设计:既要可查询,也要可重放
链路追踪数据存下来只是第一步,怎么组织这些数据,决定了你后面查问题时顺不顺畅。我一开始用的是最朴素的方案——一条一条地存 JSON,查询靠全文检索。结果就是:查到了"它调用了一个天气查询工具",但看不到这个调用发生在整个任务推进的哪个阶段,也看不到前后几个步骤的因果关联。
后来我引入了Trajectory(轨迹)这个层级概念,作为 Organisation Unit 的核心数据模型。每个 Agent 任务生成一条轨迹,一条轨迹包含若干个节点,每个节点对应一次"思考-调用-观察"的循环。节点之间通过 parent_id 关联,支持分支结构,因为有些 Agent 会并行探索多条路径。
存储引擎选型上,我对比了 PostgreSQL、MongoDB 和 ClickHouse,最后选择了PostgreSQL + JSONB的组合。原因很简单:Agent 的轨迹数据虽然有结构化的一面(时间戳、耗时、工具名),但核心尽量是形态不固定的文本语义(思考内容、结果摘要),JSONB 对这种混合形态支持得最顺手。再加上 PG 的分区能力,按天分表,数据量在千万级以内不会有什么压力。如果你的团队 Agent 调用量很大,再考虑接 ClickHouse 或 Elasticsearch 做分析型查询也不迟。
2.3 评估体系:不靠人工打分,用"规则 + 模型"双引擎
这是 Agent-Reach 最核心的部分,也是我做的最费劲的部分。Agent 的评估不能像传统软件那样做断言,需要考虑多种维度。我最后落地的评估层分两级。
第一级是确定性规则引擎,跑得最快,适合做硬性检查:
- 工具错误率:一次轨迹中,工具报错的占比。
- 关键步骤缺失率:必须调用的工具有没有被调用。
- 响应延迟:超过阈值直接告警。
- 上下文超限次数:上下文窗口被撑爆的次数。
第二级是模型辅助评估,適合做语义判断。我会用两个独立的评估模型,一个按照既定标准打分,另一个模拟用户视角回评"最终答案是否解决了问题",两者互相校验。实测下来,这种双模型交叉评估比单模型稳靠谱不少,单模型打分的时候容易产生系统性偏好,两个模型互相纠缠可以把这个噪声消除掉一部分。
评估结果不是产出"好"或"坏",而是产出一个多维度的评估报告,包括任务完成度、工具使用合理性、推理链条完整性、以及扣分理由。这些报告会沉淀为回归测试集,每次 Agent 配置或者提示词改动后,自动跑一遍历史样本,看哪些原有能力的评分下降了。
3. 实操过程:四个小时内跑通完整链路
讲了这么多设计,下面直接上实操。我按照从零到一的顺序,把搭建 Agent-Reach 的完整流程走一遍。
3.1 环境准备与部署
Agent-Reach 主体是 Python 写的,后端用的是 FastAPI,前端是 React 加 D3。部署方式我推荐 Docker Compose,一键拉起。最低配置要求:4 核 CPU、8G 内存、50G 磁盘。这个配置对早期的团队足够用了。
git clone https://github.com/yourorg/agent-reach cd agent-reach cp .env.example .env docker compose up -d启动完成后,默认会起四个服务:API 网关(8000 端口)、PostgreSQL(5432)、Redis(6379)、以及前端静态站点(3000 端口)。初始化时,.env 里要设置两个关键参数:
REACH_TRACE_LEVEL=detailed REACH_CONTEXT_STORAGE=fullREACH_TRACE_LEVEL控制采集粒度,detailed会保留完整的思考链文案,生产环境如果对存储成本敏感可以改成summary,只保留工具调用摘要。REACH_CONTEXT_STORAGE=full则代表每次都记录完整的上下文快照,这个对后期排查上下文漂移问题极为关键,建议不要随便改。
3.2 接入你的 Agent:两个方法,适配不同场景
Agent-Reach 的接入方式有两种,按侵入程度区分。
方法一:SDK 埋点(推荐)
Agent-Reach 提供了 Python 和 TypeScript 两个版本的 SDK,核心暴露了@reach.trace这个装饰器。你只要在 Agent 的编排函数上加上装饰器,然后在函数内部需要记录的核心节点上调用reach.record()就行:
from agent_reach import trace, record @trace(agent_id="customer_service_v3") async def agent_run(user_input: str): record("stage", "intent_parsing", input=user_input) # 你的 agent 编排逻辑 result = await dispatch_tools(user_input) record("stage", "response_generation", tool_result=result) return result这种接入方式对 Agent 本体代码的侵入非常小,大概改动几十行就可以完成核心节点埋点。人力的优势是灵活,你可以根据自己的业务需求在任何位置插入标记。
方法二:OpenTelemetry 协议接入
如果你的 Agent 项目已经用了 OTel 做链路追踪,Agent-Reach 可以直接复用 OTel 的 span 数据。我们做了一个协议转换层,可以把 OTel 的 span 语义自动映射到 Agent-Reach 的轨迹模型上。
实操提醒:OTel 的 span 语义是围绕"服务调用"设计的,并不直接对应"推理步骤",所以映射后的轨迹会丢失思考链信息。除非你的团队已经深度绑定 OTel,否则我更推荐直接使用 SDK 埋点,数据质量会高一个档次。
3.3 配置首个评估任务
接入完成后,就可以配置自动评估了。在 Agent-Reach 的管理界面上,创建一个新的评估任务,指定评估数据集(就是历史轨迹或人工标注样本),然后选择评估器。
我这里以"客服场景故障恢复能力"为例,配置了三个核心指标:
evaluators: - name: tool_error_rate target: <=0.05 severity: high - name: task_success model: gpt-4o criteria: "用户的问题是否在3轮对话内解决" - name: context_limit_exceeded target: =0 severity: critical配置完成后,Agent-Reach 会每隔一段时间自动抽取新的轨迹样本跑一轮评估,并把结果推送到钉钉或者 Slack。我在团队里设了每日上午十点的自动评估任务,每天到点就能看到前一天的 Agent 运行质量报告,哪个工具经常报错、哪类问题经常回答不好,一目了然。
4. 实战案例:从"偶现错误"到"定位根因"的一次完整排查
这里我分享一个真实的排查案例。团队当时做的是一个内部知识库问答 Agent,用户会问一些包含多种条件组合的筛选问题,Agent 需要调用几个不同的工具来完成筛选,最后汇总答案。
某天开始,产品反馈 "QA 同学说查不到数据了",但是不是每次都复现,大概三五次里有一次会出错。传统排查方式基本没用:日志看了,代码审查了,工具接口测了,全都没问题。最后 Agent-Reach 派上了用场。
通过轨迹检索,我把出错的那几次运行全部捞出来,直接对比成功和失败轨迹的结构差异。结果发现,失败的运行都有一个共同特征:在第二次工具调用后,Context span 里的某个关键筛选条件字段被覆盖成空字符串了。
继续往下查,这个字段的上一轮赋值来自于一个"意图解析"节点。我打开那次运行的 Plan span 和思考链,发现模型在解析用户问题时,因为提问里同时包含了两个筛选条件,它做了一个错误的合并判断,把其中一个条件解析为了空值。这个解析结果回填到上下文,导致后续工具调用直接缺参。
问题根因找到后,修复方案也很简单——在提示词里加上一句话,要求意图解析节点必须输出完整的条件列表,如果条件不完整,需要向用户确认而不是自行推断。改动上线后,同类问题的发生率直接降到了零。这个问题的根因,如果靠传统日志,大概率要排查好几个工作日,而这些 Agent-Reach 配合轨迹对比,一上午就能定位。
5. 常见问题速查表与避坑建议
在搭建和维护 Agent-Reach 的过程中,还有几个高频问题值得单独说。整理成速查表,方便直接对照:
| 常见问题 | 根因分析 | 解决方案 |
|---|---|---|
| 轨迹查询很慢 | 没有给时间范围加索引,或者是历史数据堆积过多 | 在开始时间字段上建立索引,按天分区,超过 30 天的数据可以考虑冷存储 |
| 接入 SDK 后发现思考链没有被记录 | 忘记把日志级别设为detailed,或者提示词里被链式跳过了 | 检查.env配置,确认REACH_TRACE_LEVEL=detailed,再看代码里record()的位置是否在模型调用之后 |
| 模型评估结果不稳定 | 评估模型本身存在偏好,或者样本量不够 | 启用双模型交叉校验,确保单个评估任务的轨迹样本不低于 50 条 |
| 自定义工具的输入输出过大 | 文档内容整段塞进工具结果,导致 span 存储膨胀 | 在record()前对工具输出做裁剪,只保留摘要和结构化字段 |
| 线上环境发现某类 Agent 从未产生轨迹 | 可能是 Agent 进程没有加载 SDK 初始化函数 | 检查 Agent 启动时是否调用reach.init(),常见于多进程部署时初始化代码被跳过 |
再补充几个我踩过的坑:
评估样本不要只用成功案例。做回归测试时,我一开始习惯挑那些成功完成的轨迹当样本,结果 Agent 改动后明明能力衰退了,评估分数却还挺高。后来想明白了,成功案例只能验证"没退步",你要同时把历史上出过错、被用户投诉过的失败样本也放进去,才能确认 Agent 没有把之前修好的 bug 又犯了。
上下文存储全开要算成本。开了REACH_CONTEXT_STORAGE=full之后,一天跑几千次调用,光上下文快照的存储就能吃掉好几个 GB。后来我的方案是:对高价值场景(生产环境、高客诉风险场景)保持全量记录,对一些低风险的内部场景降级为summary模式,平衡了存储成本和调试的能力。
可视化界面要有,但依赖别太重。我最早给 Agent-Reach 接了一套非常炫酷的前端图可视化,但真正排查问题的时候发现,同事用得最多的还是"轨迹列表 + 关键节点详情"这种平淡但直接的视图。图上链路确实直观,可一旦轨迹长了,还是列表展示最方便逐节点排查。这个经验后面做类似项目也通用:好看不是第一诉求,能快速定位才是。
6. Agent-Reach 在团队中的实际落地效果
在持续使用的这几个月里,Agent-Reach 带来了几个比较直观的变化,供你评估这类平台的投资回报。
首先是问题响应速度。以前反馈一个 Agent 相关的线上问题,开发同学通常是先看日志、再尝试复现、再读代码,前后得花半天。现在可以直接从 Agent-Reach 里把轨迹拉出来,每一步看过来,问题原因基本半小时内就能有个结论,开发效率的提升是非常明确的。
其次是评估体系的沉淀。我们的评估数据集从最初的 30 条交通工具,积累到了现在的两百多条,覆盖了各个业务方向和大量的失败案例。这些数据变成了一套闭环的资产:Agent 每次改动都要跑回归,不过关不上线。这个机制在团队里建立之后,Agent 质量不再依赖某个人的"感觉",而是有数据说了算。
最后是团队协作的改善。算法工程师和业务运营在讨论 Agent 效果时,终于有了共同语言。业务运营不需要懂代码,直接看评估报告就行;算法也不用语焉不详地解释"模型可能有点抽风",直接指出轨迹里哪一步不对就行。这种沟通成本的降低,在协作频繁的 Agent 项目里价值很大。
回归到最开始的问题——Agent 开发跑通容易,跑稳很难。难就难在它的决策链路过长、状态空间过大、行为又具有概率性,用传统的手段根本看不透。Agent-Reach 这种思路的核心价值在于,它把不可见的认知过程变成了可见、可回放、可评估的数据资产。你只有先看见 Agent 在想什么、做什么,才能有效地约束它、引导它、改进它,这也是 Agent 工程化绕不开的一环。
我个人在实际使用中的体会是,这类平台不要等到线上出了问题才想起来搭。Agent 项目一旦开始规模化,跑数据、攒评估样本、建回归基线,这些事情越早开始做越好,因为评估集的积累本身就需要时间和数据。真等到"事故驱动"再去建设,损失的就不只是几个工作日的排查时间了。