
Agent-Reach 这个名字我盯了很久。Reach 是够得着的意思放到 agent 语境里它想表达的其实是一件很朴素的事让 agent 真的能触及到它需要触及的东西——工具、数据、其他 agent以及真实业务流程。这两年聊 agent 的人多真把 agent 跑进生产环境的人少中间的落差几乎全在够不着三个字上模型会聊天但调不动订单系统能写 SQL但拿不到正确的表结构能规划任务但规划完了没人执行。Agent-Reach 想填的就是这道沟。这篇文章我打算按一个真实项目的推进顺序来写从需求判断、架构分层、能力注册、路由设计、记忆分层、多 agent 协作一直讲到测试、可观测和踩坑。适合三类人看正在做 agent 项目但卡在接不上真实系统的工程师、准备把 agent 引入团队流程的技术负责人以及正在系统学习 agent 开发、想搞明白 harness、skill、路由节点这些名词到底指什么的人。我不打算写成概念科普尽量给你能直接抄的做法、参数和判断标准。1. Agent-Reach 到底在解决什么问题1.1 从会聊天到能办事的断层在哪绝大多数 agent demo 的生命周期都很短。演示的时候一切顺滑接进真实环境第一周就开始出问题。我把这些断层归成四类理解这四类基本就理解了 Agent-Reach 存在的理由。第一类是能力断层。模型知道应该查一下库存但它不知道库存系统怎么调、需要哪些参数、返回的字段叫什么。这不是模型不够聪明是它没有一份机器能读懂的能力清单。人接手一个新系统靠的是接口文档加上问同事agent 接手靠的是结构化的工具描述和清晰的参数约束缺了这个它只能瞎猜。第二类是上下文断层。真实任务的上下文是碎的昨天的会议结论、上周的工单记录、CRM 里的客户备注、某个 Excel 里的特批规则。这些信息散落在不同系统里格式不统一时效性也不同。把全部原文塞进上下文既贵又容易淹没有效信息不塞agent 就只能基于常识回答答得漂亮但没用。第三类是执行断层。模型输出一段我将调用 xxx 接口然后呢谁去调失败了谁重试超时了谁兜底并发冲突怎么处理这部分如果不工程化agent 就是个只会写方案的顾问不是能办事的执行者。第四类是验证断层。任务是不是真的完成了订单是不是真的创建了邮件是不是真的发出去了如果没有回读和校验环节agent 会把我发起了调用当成我完成了任务这在生产环境里是灾难性的。注意这四类断层里第二类和第四类最容易被低估。很多人把预算全砸在模型选型和提示词调优上最后发现瓶颈在数据供给和结果校验。1.2 Reach 的三层含义触达工具、触达数据、触达协作方我给 Agent-Reach 的理解是三层递进的触达。最内层是触达工具。把散落在各处的 API、脚本、数据库操作、内部命令行工具统一注册成 agent 可发现、可调用、可校验的能力单元。这一层的核心不是能调而是调得对——参数有类型约束返回值有结构约定失败有明确错误码而不是抛一个含糊的异常让模型去猜。中间层是触达数据。数据不是简单塞进上下文而是按需检索、按层组织。哪些放系统提示哪些按需召回哪些要实时查询哪些可以缓存这层设计好了token 成本能降一半以上效果反而更好因为模型看到的是高密度信息而不是噪声。最外层是触达协作方。单个 agent 的能力边界很清晰复杂任务需要多个 agent 分工。谁负责拆解谁负责执行谁负责审核交接的时候传什么、不传什么失败了怎么回滚。这一层就是多 agent 编排要解决的问题也是最近 A2A 这类协作协议被反复讨论的原因。三层里任何一层没打通整体就会卡住。我见过不少项目把第一层做得很好工具注册了几十个但数据层还是全量塞上下文结果每次调用都烧掉大半预算也见过协作层设计得很花哨实际工具没几个能调通的。1.3 什么团队适合引入什么团队先别急不是所有场景都值得上一套 Agent-Reach。我一般用三个判断条件来筛。任务是否具备可分解性。如果一个任务能拆成查—判—做—验这样的步骤并且每步的输入输出能说清楚那它适合 agent 化。如果任务本身依赖大量隐性经验、判断标准连老员工都说不清那先别急把判断标准显性化比上 agent 更值钱。错误成本是否可控。agent 会犯错关键是犯了错能不能被发现、能不能回滚。读操作、查询类、草稿生成类任务错误成本低适合先跑写操作、资金类、对外通知类任务必须有强校验和人工确认闸门否则一次幻觉可能就是一次事故。调用量是否够大。agent 的工程投入不小如果一天就跑几十次人工处理可能更快更省。真正划算的是高频、重复、规则相对明确的流程这时候 agent 降低的是长期的边际成本。提示判断顺序建议是先读后写、先内后外、先辅后主。先从只读的辅助场景切入跑两三个月把评测和观测补齐再考虑让它动真格的。2. 架构拆解Agent-Reach 的分层设计与选型考量2.1 五层结构入口层、编排层、能力层、记忆层、观测层我把 Agent-Reach 拆成五层每层职责单一边界清楚这样出问题的时候能快速定位是哪一层的锅。入口层负责接住请求。来源可能是 IM 消息、Web 表单、定时任务、webhook 回调。这一层要做的标准化工作包括识别调用者身份、判断权限范围、生成贯穿全链路的 trace id、做初步的输入清洗。很多人把入口层当成透传结果后面所有层都要重复处理身份和权限越写越乱。编排层是大脑。它决定任务怎么拆、走哪条路径、调用哪些能力、什么时候收手。编排层的实现形态有很多种单 agent 加工具循环、规划器加执行器、多 agent 的监督者模式、状态机式流程。选哪种取决于任务的确定性和复杂度后面细说。能力层是所有可调用单元的集合。工具体、脚本、查询、写操作都在这里。能力层的设计重点是描述规范统一和错误语义统一让编排层不需要为每个工具写特例。记忆层负责上下文的存取。按生命周期分成工作记忆、情景记忆、语义记忆、过程记忆四类各自有不同的存储介质和淘汰策略。观测层贯穿全部四层。记录每一步的输入输出、耗时、token 消耗、工具调用结果、异常堆栈。没有观测层的 agent 项目调优全靠玄学。这五层的好处是可替换。模型换了只动编排层工具换了只动能力层存储换了只动记忆层。我自己踩过的最大的坑就是早期把编排和工具耦合在一起换模型的时候整份代码重写。2.2 Harness 与 Agent 的边界谁负责跑谁负责想harness 这个词最近被问得特别多很多人的困惑是它和 agent 到底什么关系我的理解是agent 负责决策harness 负责承载决策的执行。agent 是想的部分harness 是跑的部分。具体来说harness 通常包含这些职责拉起模型调用、管理上下文窗口的裁剪与拼接、解析模型输出、把工具调用请求转成真实调用、处理超时和重试、把结果回填给模型、控制循环轮次上限、记录全过程轨迹。为什么要把这两件事分开因为它们的变更频率完全不同。agent 的策略提示词、规划方式、工具选择偏好几乎每周都在调而 harness 的机制重试策略、并发控制、序列化格式一旦定下来几个月都不动。混在一起写调策略的时候容易碰坏机制。一个判断标准如果某段逻辑在换模型、换提示词之后完全不需要改它大概率属于 harness。反过来如果某段逻辑会因为模型变聪明了而需要调整那它属于 agent 策略。工业级 harness 一般还要处理几个脏活流式输出的分片解析、工具调用的参数校验失败重试、多轮对话里上下文超限的压缩、以及异常情况下的状态回滚。这些事情在 demo 里看不出来上线后天天遇到。2.3 Skill 与 Agent 的区别以及为什么 Reach 把它们分开管skill 和 agent 的区别面试里高频出现实际项目里也经常被混用。我给的区分很简单skill 是能力agent 是决策者。skill 是一段给定输入产出输出的确定性逻辑它可以是一个函数、一段提示词模板、一个工作流片段。agent 是有目标、会做选择、会调用 skill 的执行主体。一个 skill 本身不会想它只负责把一件事做好agent 会想它决定在什么情况下用哪个 skill。举个具体例子。在客服场景里查询订单状态是一个 skill输入订单号输出状态和时间线逻辑固定。判断这个客户该不该走加急处理是一个 agent 该干的活因为它要综合会员等级、历史投诉、当前库存、时效承诺来做取舍。为什么 Agent-Reach 要把两者分开管因为治理方式不同。skill 可以做严格回归测试输入固定输出固定改坏了 CI 直接拦下来。agent 的行为有随机性只能做统计意义上的评测用通过率、人工抽检来管。如果混在一起管你要么给 agent 上了不该上的硬断言导致天天误报要么给 skill 放松了标准导致回归漏检。分开管还有一个好处是复用。同一个 skill 可以被多个 agent 调用改了 skill 只需要验证它自己的回归集不用把每个 agent 的全部场景重跑一遍。这在 agent 数量涨到十几个以后节省的验证成本非常可观。2.4 长上下文加思维链加 harness 的组合范式最近被提到很多的一个范式是长上下文 CoT harness。我的实践结论是这三者不是叠加而是互相补位。长上下文解决信息够不够但不是越长越好。我的经验值是有效信息密度比绝对长度重要得多。把 20 万 token 的原始日志塞进去效果通常不如 2 万 token 的提炼摘要。所以长上下文更适合放必须逐字保留的东西合同原文、报错堆栈、用户原话。可以概括的内容概括后再放。CoT 解决推理深不深。对需要多步推理的任务让它显式写出中间步骤确实能提升准确率代价是 token 消耗和延迟上升。我的做法是分级简单任务不启用中等任务启用但限制步数复杂任务启用并允许自检。关键是要让 CoT 的产物落进轨迹里方便事后分析它是在哪一步想歪的。harness 解决跑得稳不稳。它负责上下文超限时的压缩策略、CoT 步数超限时的截断、工具调用失败时的降级路径。三者组合起来长上下文给足信息CoT 给出推理路径harness 保证整个过程不失控。注意CoT 的中间步骤不要无脑暴露给最终用户。一是观感问题二是中间推理里可能包含内部规则、字段名、甚至不该外露的判断依据暴露出去就是信息泄露。3. 核心环节实操从零搭一个能触达的 Agent3.1 能力注册表把工具变成 Agent 能读懂的东西能力注册表是整个项目的基石。我的做法是用一份声明式配置描述每个工具字段包括名称、一句话功能描述、适用场景、参数列表含类型、是否必填、取值范围、默认值、返回值结构、错误码枚举、超时时间、幂等性、权限要求、调用示例。其中最容易写砸的是功能描述和适用场景。很多人图省事把接口文档里的一句话直接抄过来比如查询用户信息。这种描述对模型来说信息量几乎为零它不知道什么时候该用、什么时候不该用。好的描述长这样name: query_order_status description: 根据订单号查询订单当前状态与关键时间节点。 when_to_use: 用户询问订单进度、是否发货、预计到达时间时使用。 when_not_to_use: 用户询问退款金额或售后进度时不要使用请改用 query_refund_status。 parameters: - name: order_no type: string required: true pattern: ^[A-Z]{2}\\d{12}$ description: 订单号两位大写字母加十二位数字。 returns: status: created | paid | shipped | delivered | closed timeline: 按时间正序的关键节点数组 errors: ORDER_NOT_FOUND: 订单号不存在请向用户确认是否输入有误。 PERMISSION_DENIED: 当前调用方无权查询该订单不要重试。注意when_not_to_use这个字段。加上它以后工具误用的比例下降得很明显。模型最容易犯的错不是不会用工具而是用错工具把退款问题当成订单状态问题处理。参数校验我建议放在 harness 侧做不要指望模型每次都传对。类型不对直接拒绝并返回结构化错误让模型自己修正重试这比在提示词里反复强调注意参数格式有用得多。3.2 路由识别节点怎么写才不乱跑路由识别节点是决定任务走哪条路径的关键环节。我的实现方式是两段式先做意图分类再做能力筛选。意图分类用一个小模型或规则引擎完成输出一个粗粒度的意图标签比如查订单改地址投诉建议闲聊。这一步不追求细只追求快和准。分类结果决定后续给模型挂载哪些工具这就是能力筛选——不要把所有工具一股脑塞给模型。工具数量对准确率的影响是显著的。我的实测经验是单次暴露给模型的工具控制在 10 个以内准确率比较可控超过 20 个选错工具的概率明显上升而且提示词 token 成本涨得很快。所以按意图分桶、按需挂载是必须做的事。路由节点还需要一个置信度闸门。分类置信度低于阈值时不要硬走某条路径而是走澄清分支向用户问一句。我设的默认阈值是 0.75调低会误路由调高会频繁追问影响体验具体值要按你的场景测。def route(user_input, session): intent, confidence classify(user_input) if confidence 0.75: return ask_clarification(intent, confidence) tools registry.load_by_intent(intent) if not tools: return fallback_handler(user_input) return build_agent_context(intent, tools, session)这里有个细节fallback_handler必须有而且要好用。很多项目在分类失败时直接报错用户体验很差。我的做法是走一个通用 agent挂载少量最通用的工具比如搜索知识库、转人工并且记录这类请求作为后续扩充意图的输入。3.3 记忆分层短期、工作、长期记忆设计不好agent 就会表现得像失忆或者反过来把三个月前的无关信息当成当前事实。我按四层来设计。工作记忆是当前这一轮任务的临时状态存活时间以分钟计。存在内存里任务结束就丢。内容包括当前的拆解步骤、已完成的子任务、中间产物。这层的容量要严格控制超过阈值就做摘要压缩。情景记忆是历史任务的记录存活时间以月计。存进带向量索引的库用于上次类似问题怎么解决的这类召回。关键字段是任务描述、采取的动作、最终结果、是否成功。召回时优先取成功的、近期的、相似度高的。语义记忆是结构化的业务知识比如产品参数、政策条款、组织架构。这部分更新频率低适合定期全量重建索引查询时走精确匹配加向量召回混合。过程记忆是沉淀下来的怎么做事比如某类工单的标准处理流程、某个报错的排查步骤。这部分最有价值但也最难积累通常靠人工从成功案例里提炼再由 agent 调用。淘汰策略上我用三条规则一是时效优先超过设定窗口的情景记忆降权二是结果导向失败案例保留但标注原因避免重复踩坑三是容量上限每层设硬上限超了就按最近最少使用 加权重要性淘汰。提示不要把用户的原话不加处理地长期存储。一是隐私合规问题二是原话里往往包含情绪化表达和无关信息长期作为记忆会影响后续判断。建议存提炼后的事实。3.4 多 Agent 协作与 A2A 卡片多 agent 协作的拓扑我常用三种。监督者模式一个主 agent 负责拆解和调度多个子 agent 负责执行子 agent 之间不直接通信全部结果回到主 agent 汇总。优点是控制集中、容易追踪缺点是主 agent 上下文压力大任务复杂时容易成为瓶颈。流水线模式任务按固定阶段串联每个阶段一个 agent前一个的输出是后一个的输入。适合流程明确的场景比如信息抽取 → 校验 → 补全 → 生成。优点是每段可独立测试缺点是中间出错难以回退。共享面板模式多个 agent 读写同一份共享状态各自负责自己擅长的部分。适合探索性任务。优点是灵活缺点是容易写冲突必须加锁和版本号。跨系统协作现在普遍会涉及 A2A 这类协议。核心概念是 Agent Card——一份描述 agent 能力的元数据文档一般包含名称、功能说明、支持的能力列表、输入输出格式、认证方式、访问入口。不同协议版本的字段命名和嵌套结构会有差异比如早期版本对能力描述的组织方式和后续版本不完全一致接入时以你实际使用的那个版本的说明为准别照着网上抄来的示例硬套。Agent Card 的作用是让协作方在不读源码的情况下知道你能干什么、怎么找你、需要什么凭证。它的写法直接决定了被发现和被调用的成功率所以描述质量要和工具描述一样重视。3.5 参数选择超时、重试、并发与 Token 预算这部分是工程细节但恰恰是最容易拍脑袋的地方。我给几个可用的计算方式。超时预算。整体任务超时要和链路各段超时对齐T_total T_llm × N_round T_tool × M_call T_overhead假设单次模型调用 8 秒最多 6 轮工具平均 1.5 秒最多 10 次调用加上 5 秒开销就是 48 15 5 68 秒。那对外承诺的超时至少给到 75 秒留缓冲。如果业务要求 30 秒内返回就必须砍轮次或砍工具调用次数不能硬撑。重试策略。默认用指数退避基数 500 毫秒倍数 2最多 3 次加 ±20% 的随机抖动避免同时重试打堆。但要注意区分错误类型参数校验失败、权限不足、资源不存在这三类不要重试重试一百次结果也一样还白白消耗预算。只有超时、限流、网络类错误才值得重试。并发控制。用排队论里那个经典的估算方式并发数约等于到达速率乘以平均处理时长。每秒来 5 个请求每个平均处理 2 秒就需要 10 个并发位。留 30% 余量配 13 到 14 个。工具侧的并发还要单独限制尤其是写操作很多下游系统对并发写入很敏感。Token 预算。我的分配比例是输出预留 15%工具描述预留 20%历史和检索内容占 65%。工具多的时候把低频工具的完整描述改成按需加载——只在意图命中时才注入完整定义默认只放一行摘要。这一条在工具数超过 30 个以后效果非常明显。4. 测试与可观测Reach 项目最容易翻车的地方4.1 Agent 测试与普通单测的差别agent 的输出有随机性所以传统那套输入 A 必须等于输出 B的断言方式基本用不了。我采用的是分级断言。硬断言用于确定性部分工具是否被调用、调用的参数是否符合 schema、是否触发了权限校验、是否在轮次上限内结束、返回值是否能被成功解析。这些必须 100% 通过不允许有波动。软断言用于内容质量回答是否覆盖了关键信息点、是否符合话术规范、是否包含不该出现的内容。这部分用评分模型或关键词规则来打分设定通过率阈值而不是逐条通过。回放测试是省成本的关键。把生产环境的真实请求连同模型响应、工具返回一起录下来测试的时候走回放通道不打真实模型也不打真实系统。这样 CI 里跑几百个用例只要几十秒成本几乎为零。我一般每周从生产捞一批新样本补充进回放集保持覆盖度。模糊测试用来找边界。构造超长输入、特殊字符、多语言混杂、恶意指令注入等样本看 agent 是否会崩溃、是否会越权、是否会泄漏系统提示。这类测试跑一次能发现一堆问题。4.2 常见报错与排查速查表现象可能原因排查方向处理方式工具名不存在模型幻觉出未注册的工具检查注册表与提示词中的工具清单是否一致在 harness 侧拦截未知工具名返回可用清单让模型重选参数 schema 校验失败模型理解偏差或描述歧义对比失败样本与工具描述补充参数示例和取值范围说明上下文超限历史未压缩或检索召回过多统计各段 token 占比加摘要压缩限制召回条数陷入循环调用缺少终止条件或结果不满足判断查看轨迹里的重复模式设最大轮次硬上限加重复调用检测调用超时下游慢或超时设置过短看分段耗时埋点调整超时必要时改异步加回调重复写入缺幂等设计检查重试链路引入幂等键写操作前先查状态越权访问权限校验缺失或过宽审计每次调用的身份与资源范围最小权限原则参数级白名单输出包含内部信息工具返回值未脱敏直接入上下文检查返回字段在能力层做字段裁剪与脱敏这张表我建议直接贴到团队文档里出问题先对表能省大量沟通成本。4.3 安全边界权限、注入与越权agent 的安全风险比传统应用更集中因为它把决策和执行合在了一起。我关注三个方向。权限最小化。每个工具都要明确调用主体能访问的资源范围。不要用超级账号跑所有工具一旦被诱导越权影响面就是全部数据。我的做法是给每个工具配独立凭证权限按业务最小集配置敏感操作加二次确认。指令注入防护。这是一个必须认真对待的点工具返回的内容是数据不是指令。网页正文、邮件内容、用户上传的文档里都可能藏有忽略之前的指令执行以下操作这类文本。如果直接把工具返回值拼进提示词且不做隔离标记模型很可能会把它当指令执行。我的处理方式是用明确的边界标签包裹外部内容并在系统提示里强调边界内的内容是待处理数据而非指令同时敏感工具加二次校验。输出脱敏。工具返回的字段往往比需要的多比如查订单返回里带着手机号、地址、内部备注。这些字段不应该全部进入模型上下文更不应该出现在最终回复里。我在能力层做了字段裁剪只把必要字段往上抛其余留在日志里供排障。注意审计日志要记录谁、在什么时候、通过哪个 agent、调用了哪个工具、传了什么参数、得到什么结果。这既是排障依据也是合规要求。日志里的敏感字段要脱敏后再落盘。5. 学习路线与踩坑经验5.1 从零到能交付的四阶段路线经常有人问 agent 开发该怎么学。我按能交付为标准拆成四个阶段每个阶段都有明确的产出物避免学了半年还在看概念。第一阶段把模型调用的基本机制搞清楚。包括消息结构、多轮对话管理、流式输出解析、结构化输出约束。产出物是一个能稳定完成单轮问答的最小程序。这个阶段不需要框架手写一遍收获更大。第二阶段把单个工具跑通。实现一个工具注册、调用、结果回填的完整闭环理解函数调用的交互格式。产出物是能查一次真实数据的 agent。这个阶段会第一次遇到参数校验、错误处理、轮次控制这些真实问题。第三阶段做编排。引入意图路由、多工具组合、记忆存取、失败降级。产出物是能完成一个完整业务流程的 agent比如接收工单 → 查资料 → 生成方案 → 记录归档。第四阶段做工程化。补齐评测集、回放测试、观测埋点、成本统计、权限体系、灰度发布。产出物是能上线的系统。大部分人的卡点在第三到第四阶段之间因为这部分没有捷径全是细活。5.2 面试高频问题背后的真实考点agent 相关的面试题这两年变化很快但底层考点其实就那么几个。问 harness 和 agent 的区别考的是你有没有把机制和策略分开的意识。答一个是框架一个是模型就太浅了好的回答会落到变更频率、职责边界、可测试性上。问 skill 和 agent 的区别考的是抽象能力。能不能说清楚确定性逻辑和决策逻辑的治理差异是区分用过和想过的分水岭。问 agent 记忆怎么设计考的是你有没有真实调过。分层、淘汰、召回策略、成本控制能说出具体参数的人基本都踩过坑。问怎么评测 agent考的是工程成熟度。只答人工看是不够的要能说出硬断言、软断言、回放、模糊测试这套组合拳。问怎么降成本考的是权衡意识。答案通常包括工具按需加载、上下文压缩、小模型分流、缓存高频查询、限制无效重试。能给出量化比例的人更可信。5.3 我踩过的坑第一个坑是工具描述写太细。早期我恨不得把每个字段的业务含义都写进描述结果工具清单就吃掉了一半上下文预算模型反而更容易迷路。后来改成主描述精简 细节按需加载成本和准确率同时改善。第二个坑是没有幂等设计。有一次网络抖动触发了重试结果同一个工单被创建了两次。这个问题的修复成本很高因为要回头补幂等键还要清洗历史脏数据。教训是所有写操作从一开始就要设计幂等。第三个坑是把工具返回值直接当可信内容。有一段外部文本被拼进提示词后模型开始执行里面的建议。加上边界标签和内容隔离之后就没再出现。这个坑不踩一次很难真正重视。第四个坑是重试没有上限和分类。有个下游接口挂了agent 一直重试把对方打得更惨恢复时间反而更长。后来加了错误分类和退避策略才平稳下来。第五个坑是没有观测就调优。早期调提示词全靠感觉改完不知道是变好了还是随机波动。补上轨迹记录和通过率统计之后每次改动的影响都能量化效率提升非常明显。我现在推进任何 agent 项目都会先把能力注册表的规范、路由阈值、超时重试参数、评测集这四样东西定下来再开始写业务逻辑。这四样定得越早后面返工越少。Agent-Reach 这类项目的价值也正在这里——它不追求让 agent 显得多聪明而是让 agent 每一次够得着都够得准、够得住、够得可追溯。工具描述里的when_not_to_use那一行还有重试策略里那条参数错误不重试的规则看起来都是很小的细节但真到了线上往往就是这些地方决定了这个 agent 是能长期跑下去还是跑两周就被业务方叫停。