“我们团队的大模型Demo跑得飞起,可一接真实业务就崩,你们这Agent到底怎么落地的?”这是我去年被业务方问得最多的一句话。后来我意识到,问题不在模型能力,而在“触达”——智能体的意图能不能准确到达正确的工具、正确的流程、正确的负责人手里。Agent-Reach这个项目,就是冲着这件事去的:把“Agent触达业务”从一句口号变成一套可配置、可观测、可重试的基础设施。这篇文章会讲清楚Agent-Reach的核心架构、路由设计、工具编排的实操细节,以及我在这套系统上踩过的三轮迭代坑。如果你是做Agent应用、RAG系统或者企业级AI中台的工程师,这篇文章应该能帮你少走不少弯路。
1. Agent-Reach要解决的问题:为什么Agent总是“看起来行,用起来废”
先说一个反直觉的观察:大部分Agent项目死掉,不是死在模型推理上,而是死在了“触达”这个看似简单的环节上。所谓触达,就是Agent在做完推理之后,能不能稳定、准确、可追溯地调用到外部系统——查库存、发工单、推送消息、更新数据库。这里面的坑比想象中多得多。
1.1 Agent项目失控的三种典型症状
我见过太多团队在Agent上线后的一到两周内陷入混乱,症状非常一致。
第一种是工具调用错位。模型明明想查A系统的订单状态,结果因为工具描述写得不清晰,调到了B系统的接口,返回了一堆语义相近但完全不是想要的数据。这个问题的根因不是模型笨,而是工具注册层的语义不够精确,缺少一层“调用前校验”。
第二种是超时和重试雪崩。Agent调外部接口,对方响应慢,Agent就傻等;等不起就重试;重试又叠加并发,直接把下游接口打挂。这个链路如果没有人盯着,往往要等到线上告警响了才发现。
第三种是状态丢失。Agent在对话过程中需要记住“刚才已经确认过客户姓名”“上一步已经扣过款”这类中间状态。很多团队把状态塞在提示词里,结果上下文一长就开始丢,用户问一句“我刚才那个申请到哪里了”,Agent完全答不上来。
这三种症状的共同点是什么?它们都不是模型能力问题,而是“触达链路”没有设计好。Agent-Reach要做的,就是给Agent装上一套可控的输入输出管道,让“推理”和“行动”之间有一层明确的、可管理的缓冲地带。
1.2 “触达”和“生成”的区别:Reach层是Agent落地的那道闸门
如果你把Agent比作一个人,模型是他的大脑,思考能力强不强决定他聪不聪明;但一个人想做成事,光有大脑不够,还得有手、有脚、有通讯工具。Agent-Reach这个名字里的“Reach”,强调的就是这双手和通讯工具——它决定一个智能体能不能真正把意图送达终点。
这层“Reach层”需要承担几件事:
- 意图路由:判断这个请求该交给哪个Agent、哪个技能包、还是直接走兜底流程。
- 工具准入:每次调用外部系统前做参数校验、权限校验、语义校验。
- 可靠性保障:超时、重试、熔断、降级、补偿。
- 状态同步:在多次调用和多次对话之间维护一致的会话上下文。
- 可观测性:每次触达的轨迹都能被记录下来,出了事能回溯到具体节点。
我们做Agent-Reach的第一课就是:把Reach层当成一个独立的中间件来设计,而不是把它揉进业务代码或者提示词里。揉进去的后果是,改动一次业务流程就要动一遍Agent代码,最后谁都不敢改。
2. 从零搭建Agent-Reach:一套可复用的核心架构
Agent-Reach第一版我们用了大概三周时间,在内部三个业务线试跑。整体架构并不复杂,但每个模块踩下来都有不少细节。
2.1 第一版架构长什么样
我们第一版的架构分为五个部分:
- 接入网关(Gateway):统一接收来自网页、IM、开放API的请求,做鉴权和流量控制。
- 语义路由器(Router):基于请求文本和会话上下文,决定把这条消息路由到哪个Agent或工具链。
- 连接器(Connector):封装所有外部系统调用,内部处理鉴权、参数映射、超时重试。
- 状态仓(State Store):存放会话快照与工具调用记录,支持断点恢复。
- 观测台(Observatory):记录每一次路由决策、每一次工具调用的耗时和结果,支持链路回放。
这套架构说白了一句话:Agent只负责“想清楚要做什么”,Reach层负责“把要做的事情安全地送到位”。模型可以随便换,业务系统可以随便换,但Reach层的接口和流程是稳定的。
当时选技术栈时也纠结过,是直接用现成的Agent编排框架,还是自己写Reach层。最后我们选择了自研核心路由和连接器,只在局部用了开源组件。原因很简单:编排框架给的是“Agent怎么想”的便利,但我们要深耕的是“Agent怎么触达”的可靠性,这个领域当时没有完全合适的现成方案。
2.2 路由器设计取舍:规则路由和语义路由怎么选
这是Agent-Reach里最值得展开讲的部分。路由器的任务,是把一条用户消息送到正确的处理单元。一开始我们纯用语义路由,也就是把用户消息做向量化,然后和每个技能包的描述算相似度。结果线上跑起来问题不少。
问题是:语义路由对“相近但不相同”的请求很容易误判。用户说“我要退订”,系统匹配到了“取消预约”技能,虽然两个动作确实很像,但业务上的处理流程完全不同。后来我们改成“规则优先、语义兜底”的混合路由:
- 第一步,先用业务规则强制匹配,比如消息里包含订单号就优先进订单查询链。
- 第二步,规则没命中时再做语义匹配,但会计算置信度。
- 第三步,置信度过低时,不走自动路由,直接转入人工澄清流程。
这个调整把路由准确率从82%提到了96%左右。置信度阈值我们设在0.7,低于阈值就澄清。阈值太高会导致太多消息转人工,太低又会导致误路由率上升,0.7是我们在实际业务语料上调出来的平衡点。
还有一点容易被忽略:路由器要能感知会话历史。用户上一句说“查一下上周的订单”,这一句说“再帮我看看物流”,如果你不结合上一轮上下文,单独看“再帮我看看物流”根本不知道要看什么。所以路由器的输入不只是当前消息,还要带上压缩后的会话摘要。
2.3 连接器层:触达能不能成功,全看这里
连接器是我们花时间最多的模块。每个外部系统都需要一个连接器,它负责把Agent的标准动作翻译成外部系统的具体调用。比如“创建工单”这个动作,在不同系统里可能需要不同的API、不同的字段名、不同的鉴权方式,连接器就是这一层的翻译官和快递员。
连接器设计里最核心的三个原则:
- 每个连接器必须有独立的超时和重试配置,不能全用一个全局值。查库存的接口通常很快,3秒超时没问题;但提交审批单的接口可能要5秒甚至更久,共用超时会导致大量假失败。
- 重试必须区分错误类型。网络抖动可以重试,鉴权失败重试一百次也没用,参数校验失败重试更是浪费。我们给每次调用打上错误类型标签,只有网络类错误走重试,业务类错误直接返回给Agent做修正。
- 每个连接器都要有“干跑模式”。上线前可以模拟调用,不真正修改上游数据,只验证参数结构是否匹配。这个模式帮我们拦下了大量低级错误。
我一向的主张是:连接器的数量一定要克制。不要让每个业务方都自己写连接器,而是提供一套标准化SDK,让业务方只声明接口信息,连接器的通用逻辑由Reach层统一管理。
3. 接入真实业务时的关键细节:工具编排与状态管理
架构搭起来只是第一步,真正让Agent-Reach稳定运行的是那些藏在细节里的工程决策。这一节我挑三个最容易被忽视的点来聊。
3.1 工具调用的“确认机制”与失败恢复
Agent调用工具,和人类下单买东西一样,最怕的是“重复扣款”和“做一半停了”。我们在连接器之上的编排层加了一层“动作确认”机制:
- 如果一个工具调用是只读的(查库存、查价格),不需要确认,直接执行。
- 如果一个工具调用是会改变状态的(下单、退款、改状态),Agent必须先把调用参数展示给用户或按策略确认一次,确认通过后才真正执行。
- 如果一次任务需要调用多个工具,我们会按依赖关系拆成“步骤”,每个步骤记录执行状态,任何一个步骤失败,后续步骤不执行,已执行的步骤进入补偿队列。
这套机制上线后,退款错单、重复下单这类事故基本清零。别嫌这一步麻烦,漏掉一个确认,后面擦屁股的成本高十倍。
失败恢复策略我们也调了好几版。一开始是所有失败都重试,后来发现有些失败重试也没用,反而耽误了用户时间。现在我们的策略是:
| 错误类型 | 处理策略 | 示例 |
|---|---|---|
| 网络超时 | 重试2次,间隔递增 | 连接池耗尽、DNS解析慢 |
| 上游返回5xx | 重试1次,若失败走熔断 | 上游服务暂时不可用 |
| 业务校验失败 | 不重试,返回Agent自行修正 | 参数类型错误、状态过期 |
| 鉴权失败 | 不重试,触发告警 | Token过期、权限变更 |
| 上游返回乱数据 | 不重试,走数据校验兜底 | 字段缺失、格式不符 |
这个表看着简单,但每一个策略都是被线上事故教训出来的。
3.2 上下文状态管理:别让Agent变成一个“健忘症患者”
Agent-Reach在状态管理上踩过的坑,我单拎出来讲一下,因为太典型了。第一版我们很天真,把整个会话上下文直接塞给大模型,靠模型自己记住状态。结果上下文一大,模型开始“忘事”,连用户刚说的订单号都能记混。
后来我们把状态管理从模型上下文里剥离出来,放到State Store里。所有工具调用的入参和出参、用户的确认动作、中间产生的业务实体ID,都结构化地存起来。大模型每次只需要看到一份“精简状态概要”,而不是所有历史消息。
具体做法是:
- 状态仓采用Redis存储,Key为会话ID,Value为状态快照,设置两小时过期。
- 每个工具调用的关键结果,比如生成的工单号、查询到的订单号,都会被提取出来写回状态仓。
- 大模型生成下一次调用时,会先通过接口拉取当前状态概要,替代传统的全量历史消息。
这个改动带来的效果非常明显:长对话场景下的状态错乱率大幅下降,用户问“刚才那个单子的状态”时,Agent能准确接上。如果你也在做Agent应用,我建议从一开始就把状态仓当成一等公民,别让模型裸奔着处理会话记忆。
3.3 外部接口不稳定时的兜底策略
再聊一个偏运维的细节。Agent-Reach所依赖的上游接口,质量参差不齐。有的接口文档写得很漂亮,生产环境却三天两头超时。我们的连接器层必须做好兜底。
兜底分三层:
- 单实例兜底:一次调用先走主实例,失败自动切换到备用地址。
- 静态缓存兜底:像商品类目、地区列表这类低频变化数据,本地缓存一份,上游挂了也能顶一会儿。
- 话术兜底:所有能力都不可用时,Agent必须输出一段预案话术,告诉用户“当前功能暂时不可用,建议稍后再试”,而不是干巴巴地报错。
有人可能会问:让Agent直接说“系统暂不可用”会不会显得很蠢?我的经验是,干脆利落地承认不可用,比让用户反复试错强得多。用户能接受偶尔的故障,但接受不了一直转圈和莫名其妙的错误。
4. Agent-Reach的三轮迭代:从跑通流程到平台化
说了这么多设计,再聊聊我们实际迭代的过程。这部分不按模块讲,按时间线讲,因为我踩的很多坑都和迭代节奏有关。
4.1 第一轮迭代:把“单场景触达”跑通
第一轮我们选了一个很窄的场景:“订单状态查询”。为什么选它?因为这个场景只涉及只读工具,链路短,风险低,适合验证Reach层的路由和连接器。
这一轮的核心动作:
- 写出第一个连接器,对接订单系统。
- 配置路由器,让“我的订单在哪”“发货没”这类话术全部路由到订单查询链。
- 搭好观测台,记录每一次查询的准确率和平均耗时。
这轮跑完我们心里有底了,确认Agent-Reach的基础链路是通的。第一轮我最大的收获是:从只读场景起步,不要让一个还没验证完基础设施的项目一上来就去碰资金、权限这类敏感操作。
4.2 第二轮迭代:从“一个Agent扛所有”到“多Agent分工”
第二轮我们开始增加复杂度,接入了订单修改和物流催办两个场景,结果马上发现问题:单一Agent处理所有能力,提示词越来越长,知识混在一起,开始出现行为冲突。比如同一个Agent,一会儿扮演订单客服,一会儿扮演售后处理,语气和流程边界都开始模糊。
解决办法是切换到多Agent结构:
- 每个Agent只负责一类问题域,比如订单Agent、物流Agent、售后Agent。
- Agent-Reach路由器根据用户意图做分发。
- Agent之间通过一个内部事件总线传递必要的业务上下文,但用户会话对用户来说仍然是连贯的。
我在这次迭代中最深的一个体会是:不要试图用一个Agent解决所有问题。让每个Agent职责单一、边界清晰,Reach层的路由压力反而小了,因为每个节点的行为都更可预期。
4.3 第三轮迭代:把Reach层做成业务方可自助接入的平台
第三轮是最难但价值最大的一轮:让业务方能自助接入Agent-Reach。原来每个新场景都要我们团队上手开发连接器,效率太低。这轮我们做了两件事:
- 提供可视化配置台:业务人员可以在界面上填写接口地址、参数映射、错误重试策略,自动生成标准连接器。
- 提供路由策略模板:比如“电商场景模板”“售后场景模板”,业务方只需要选择模板、填入自己的业务规则,路由器就能按模板工作。
说白了,就是把我们之前靠代码硬编码的东西变成配置项。这轮做完,一个新场景从提出需求到上线试运行,周期从两周压缩到了两天。
如果你也准备做平台化,我的建议是:第一轮别想着平台化,先跑通一个场景再说。平台化是基础设施稳定的结果,不是起点。
5. 实战排错清单:Agent-Reach上线后最容易翻车的五个问题
最后分享一份排错清单,这些都是我们上线后在业务方那边真实遇到过的问题,每一条背后都有一个加班的夜晚。
5.1 触达延迟的隐蔽原因
第一个隐蔽原因是连接池配置和下游服务不匹配。某个连接器每次调用都新建HTTP客户端,导致握手开销特别大,延迟从预期的200毫秒飙到1秒以上。改成复用连接池后,P95延迟直接降到300毫秒。
第二个隐蔽原因是语义路由的向量检索没有做索引切分。业务量大之后,把所有技能描述放在一个集合里检索,检索耗时会线性增长。后来按业务线做了索引分片,检索耗时才降下来。
第三个隐蔽原因是日志同步阻塞。观测台早期用同步方式写日志,一次触达的日志写入居然耗时近百毫秒。改成异步日志后,这部分开销基本消失了。
建议:排查延迟问题时,先看网络层和连接池,再看路由检索,最后看日志和监控本身的性能。这三个地方最容易被忽略。
5.2 Agent调用外部接口返回假数据
有一次业务方反馈,Agent查到的订单金额总是偏大。排查半天发现,某连接器在解析上游接口时,把“应收金额”和“定金金额”的字段映射反了。模型很听话,拿着映射错误的字段就去回答用户问题,数据自然是错的。
这个问题的根源在于:连接器层缺少字段级校验。后来我们给所有连接器加了一层Schema校验,上游返回的数据必须匹配预期格式,不匹配就当作失败处理。
这里也提醒我做Agent应用的朋友:模型判断“调用了什么工具”往往只看工具名和描述,对工具返回的数据质量没有分辨能力。数据正确性的责任必须压在Reach层,别指望Agent自己发现问题。
5.3 路由误判后的纠正路径
还有一个高频问题:路由误判之后,用户已经和错误Agent聊了好几句,怎么挽回?我们做了两层纠正:
- 会话内纠正:误判率高的请求会被观测台标记,路由器会自动降级该技能包的优先级。
- 人工切换:用户在对话界面可以强制切换技能,切走后系统会记录一次“路由纠偏样本”。
这部分的经验是:不要想着一次路由就百分百准确,一定要留出人工兜底和用户自助纠偏的路径。好的路由系统是一个持续学习的系统,而不是一锤子买卖。
5.4 高并发下的熔断与降级
上线初期我们吃过一次大亏。一次营销活动带来大量用户咨询,Agent-Reach的网关和连接器没有按业务线做隔离,一个慢接口的线程阻塞拖垮了整个集群,所有Agent都跟着不可用。
修复方案是我们把连接器池按业务线拆开,每个业务线独立分配线程数和限流阈值,同时给整个Reach层加了全局熔断器。某一个业务线下游出问题时,熔断只影响该业务线,其他业务线完全不受牵连。
做Agent中台的同学可以把这个经验直接抄走:一定要按业务隔离资源池,别让一个上游故障变成全局事故。
5.5 Agent-Reach的下一步:从配置化走向自适应
这套系统跑通之后,我们内部一直在讨论下一步的方向。目前路由器、连接器都靠人工配置,虽然比代码硬编码强很多,但本质还是“人写规则,机器执行”。下一代的Agent-Reach,我们希望它能够根据观测数据自动优化路由策略——比如某个技能包连续被用户纠正,系统自动调整它的匹配权重;某个连接器频繁超时,系统自动把流量切换到备选通道。
当然,这条路还很长,自动化的前提是规模化。规模不大、样本不够的时候,人工配置反而更靠谱。所以我的建议是:先把手里的链路做扎实,再考虑智能化。
最后再分享一个实际工作中的心得:做Agent-Reach这类基础设施项目,最难的不是技术,而是和业务方对齐“可靠”的标准。有的业务方觉得90%准确率已经很好,有的业务方盯着2%的误判不放。你一定要在一开始就约定好触达成功率、误判率、平均响应时间这些核心指标,并且让观测台每天把数据摆在所有人面前。有了数据,讨论才有依据;没有数据,一切都只是观点。
Agent-Reach距离一个完美的触达基础设施还很远,但它至少帮我解决了一个关键问题:让Agent不再是一个写完就忘的Demo,而是可以真正站在业务链路里,稳定地把事情推进下去的工程系统。