ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent触达层设计:Agent-Reach如何打通模型与外部系统的最后一公里

Agent触达层设计:Agent-Reach如何打通模型与外部系统的最后一公里 1. 为什么我会在Agent能力“看起来够用”时反而去写一个叫Agent-Reach的中间层先交代一下背景。我最近半年一直在做AI Agent相关的落地项目主要方向是把大模型接进企业内部的工具链让Agent能自己去调用API、读写数据、触发流程。项目做到中期模型本身的表现已经不差了——该多轮推理有多轮推理该引用上下文也会引用——但真正卡住进度的根本不是模型能力而是“让Agent真正触达到它该触达的那个东西”。具体点说Agent要查一个订单状态背后是订单系统的接口Agent要发一条审批通知背后是IM机器人的WebhookAgent要修正一份报表背后是一个老得令人发指的内部系统只支持XML over HTTP。模型的规划能力再强到了“发出请求、拿回结果、再决定下一步”这一步就全看底层这层触达做得够不够糙。大部分Agent项目就是死在“规划很丰满触达很骨感”这件事上。决定动手做Agent-Reach并不是想再封装一个“API网关”而是想把“Agent怎么触达外部世界”这件事单独拆出来做成一条完整可观测、可控制、可恢复的链路。这篇文章就把这套东西的核心设计、踩坑过程、以及几个让我反复返工的真实场景完整讲一遍。如果你也在做Agent类的项目尤其是涉及多系统、多工具、长流程调用的这篇应该能帮你少走不少弯路。2. Agent-Reach到底解决什么问题模型手里的“工具清单”和真实的“系统边界”之间存在断层在写任何代码之前先把问题定义清楚这一点最重要。2.1 模型中描述的工具和真实系统之间隔着三层认知差异用大模型做Agent时通常的做法是给模型一份工具清单JSON Schema或者Function Calling的定义告诉它“你有这些工具可以用”。模型负责决定“我应该用哪个工具”然后框架负责“把参数填好、把请求发出去、把结果喂回来”。这套流程说起来顺实际跑起来全是断层。第一个断层是参数层面的。模型从用户的话里抽取参数它以为“用户ID”是一个字符串但真实订单系统的接口要求的是Base64编码的用户标识带着系统前缀。模型并不知道这件事它只会按自己理解的东西填参数。如果你不在中间层做转换第一次真实调用必炸。第二个断层是语义层面的。模型以为“查询订单”这个工具永远返回一个标准JSON但真实系统可能返回200却带一个业务错误码也可能直接返回一段HTML错误页甚至可能接口本身是好的但依赖的下游服务超时了。模型看到的工具是一片平坦的“黑箱接口”而真实系统是一个有状态、有失败模式、有级联依赖的复杂体系。第三个断层是行为层面的。模型做规划时是“逐轮”的它调用一个工具拿到结果再决定下一步。但真实业务往往需要“一组动作必须整体成功或者整体失败”或者是“某个调用发了出去但回调结果要等两分钟后才回来”。这些行为语义单纯靠在模型提示词里写“你调用工具的时候要注意”根本解决不了。2.2 Agent-Reach的定位不是网关是Agent的“触达层”我最初也想过直接用现成的API网关把Agent的请求转发出去就完事。但很快发现网关解决的是“流量管理”问题不是“触达一致性”问题。Agent需要的不是简单的转发而是把模型的意图翻译成真实系统能理解的请求把真实系统的响应翻译回模型能理解的结果在触达失败时替模型决定是重试、降级还是终止把每一次触达的过程全部记录下来让开发者能复盘“模型到底做了什么、系统到底回了什么”Agent-Reach做的是这件事。它可以理解为模型与外部系统之间的一个适配层模型只跟Agent-Reach暴露出来的“语义工具”打交道至于这个语义工具背后连的是REST接口、SOAP服务、消息队列还是数据库由Agent-Reach去消化。设计上我参考了企业集成中经典的“网关适配器”模式但做了大幅简化只保留Agent场景真正需要的几个能力工具语义注册、参数双向转换、调用策略控制、全链路追踪。听上去不复杂做起来全是大大小小的坑下面逐个说。3. Agent-Reach的架构拆解一次工具调用的完整生命周期和它背后的设计取舍整个系统我分成三层接入层、语义层、执行层。每一层都有自己独立的职责和独立的配置体系这样在排查问题时能快速定位。3.1 接入层让Agent用“人类可读的工具描述”发起调用而不是直接面对HTTP细节接入层是Agent直接对话的部分。它对外暴露的是一组“语义工具”每个工具有一个名字、一段用途描述、一份参数Schema、一份返回Schema。模型根据这些信息决定要不要调用、传什么参数、怎么解读结果。这里的核心设计决策是Agent-Reach要求工具定义里必须包含“最优调用姿势”和“退化调用姿势”。比如说查订单最优调用是传完整订单号走主查询接口退化调用是只传用户ID那就走按用户检索的接口返回结果里多一个“候选订单列表”。为什么必须要求这个因为真实场景里模型经常拿不到完整参数如果中间层不提供退化路径模型就只能硬编一个假参数去撞运气Agent一次调用就脏了。为了降低模型误用概率我在接入层做了参数预校验。Schema里声明“order_id”是必填时不是简单判空而是判断这个ID是否符合真实系统中ID的形态规则。模型有时候会把“订单备注”里的一串数字当成订单号传进来预校验能拦下一部分明显不合理的调用。这个预校验规则不是写在模型代码里的而是写在Agent-Reach每个工具的配置文件里线上可以直接改不用发布。3.2 语义层参数转换和结果归一化是Agent-Reach说“我能少写一半胶水代码”的底气语义层是整个项目最核心的部分做两件事把Agent传来的统一参数转换为各个系统独有的真实参数把各个系统返回的千奇百怪的结果转换为一套统一结构。参数转换这部分我在实践中总结了一套规则模板的思路。每个工具接入时需要映射三组关系字段名映射、值域映射、格式映射。举例来说真实系统的参数叫“user_identify_code”Agent这边叫“user_id”这是一条字段映射“order_state”的真实取值是0、1、2Agent这边希望看到的是“pending、paid、shipped”这是一条值域映射日期字段真实系统要“yyyy/MM/dd HH:mm”Agent统一传ISO8601这是一条格式映射。结果归一化听起来简单其实是最容易翻车的地方。真实接口返回的JSON结构千变万化有的系统把业务数据包在“data”里有的包在“result.list”里有的直接就是数组有的错误码叫“code”有的叫“status”有的甚至只在HTTP Header里放一个“X-Error-Code”。每个工具都要配一份“结果提取规则”告诉Agent-Reach“从响应的哪个位置拿真正的业务数据、从哪个位置判断调用是否成功”。做完这一步模型侧看到的工具返回就永远是统一的一个“success”字段加一个“payload”字段模型不用理解每个系统的特殊结构。3.3 执行层连接真实系统的部分也是我在超时和重试上掉坑最多的地方执行层负责把语义层翻译好的请求真正发出去。它支持几种连接方式HTTP/HTTPS、WebSocket、消息队列、以及最简单的“直接执行本地命令”。大部分内部系统的连接方式无外乎这几种。执行层有一个其他网关不常做的设计调用策略可编程。每个工具可以绑定一段策略脚本描述“什么时候允许重试、什么时候必须熔断、什么时候可以降级”。这不是让开发者在代码里写到死的逻辑而是可以在Agent-Reach的配置中心动态调整的规则。比如订单查询接口策略是“超时重试一次如果第二次也超时就降级为查询缓存快照同时记录一条警告日志”再比如发送审批通知的工具策略是“不允许重试因为重复发送会产生两条重复审批宁可直接标记失败并让Agent向用户说明”。为什么要把策略设计成动态可配置的因为Agent场景下同一个工具在不同任务里的失败容忍度完全不同。发通知这个动作在“提醒用户补材料”这个场景里重复一次可能无所谓但在“审批通过”这个动作里重复一次就是事故。把策略游离出代码才能在线上灵活调整。3.4 一次完整调用长什么样从模型决策到系统响应全链路可追踪我习惯用一个具体流程来讲解这个架构这样比我空谈设计直观得多。假设Agent收到用户指令“帮我把上个季度华东区的销售报表归档并发一份摘要到项目群。”第一步模型根据Agent-Reach暴露的工具清单决定依次调用“查询销售报表”“归档文件”“发送群消息”三个工具。它发出的请求是标准化的语义参数比如“query_sales_report({region: east_china, quarter: 2024Q3})”。Agent-Reach接入层收到这个请求先做参数预校验检查area_code是否合法。然后语义层开始转换把“east_china”映射成真实系统里表示华东区的编号把“2024Q3”转换成系统要求的“start_time/end_time”两个字段再按照报表系统的接口格式组装好。执行层发出真实请求。结果返回后语义层做归一化把报表系统的字段名逐个映射回来并且把计算好的汇总数字转成模型易于引用的结构。Agent拿到结果后生成归档指令再触发下一个工具。每一次调用产生的请求日志、耗时、重试记录、返回摘要都会写入追踪系统形成一条完整的调用链。4. 核心实现难点拆解API适配、动态工具注册、状态补偿这三个问题决定了Agent-Reach能不能用在真实业务里架构画出来只是纸面功夫真正动手写的时候有三个问题最磨人我逐个讲清楚当时的思考和最终的实现。4.1 动态工具注册让新系统接入时“不写代码”这件事做到了什么程度一开始我按常规思路把每个工具定义成一个Python类写SDK式的代码。结果接入到第八个系统时代码量开始爆炸因为每个系统的差异性导致每个类里都有大量无法复用的适配逻辑。后来我意识到工具接入应该走“描述驱动”的路线一个工具接入系统不是写一个类而是写一份YAML配置描述清楚这个工具的语义定义、参数映射规则、结果提取规则、调用策略。Agent-Reach通过一个注册中心加载这些配置运行时按配置动态组装适配逻辑。这样说可能太空了我贴一个简化的配置结构tool: name: query_sales_report description: 查询指定区域、指定时间段的销售报表返回汇总数据和明细文件索引 params: - name: region type: string required: true enum: [east_china, north_china, south_china] - name: quarter type: string required: true mapping: region: east_china: 010 north_china: 020 south_china: 030 quarter: type: date_range_transformer request: method: POST url: https://report.internal.example/api/sales/query headers: Content-Type: application/json body_template: | { area: $region, start_date: $quarter.start, end_date: $quarter.end, source: agent } response: success_when: - jsonpath: $.status equals: OK extract: summary: $.data.summary files: $.data.files[].url strategy: retry: 1 retry_interval_ms: 500 on_failure: fallback_to_cache这份配置解决了一个很实际的问题新系统接入时不需要改Java/Python代码只需要把接口文档翻译成这份YAML放在注册目录里Agent-Reach热加载后模型下一次对话就能使用这个新工具。动态工具注册的另一个好处是可以做到“按Agent实例隔离工具集”。同一个Agent-Reach集群上可能跑着多个Agent项目每个项目需要触达的工具完全不同。通过注册中心给每个Agent分配可用的工具列表避免了所有Agent都直面所有系统也防止一个项目的错误调用把另一个项目的资源挤爆。4.2 参数转换的边界情况我踩过的最怪的坑是一次订单号首尾空格引发的连锁事故参数转换看起来是纯字符串处理但真实情况恶心得多。我记得最清楚的一次事故是订单查询工具上线后线上隔三差五报“订单不存在”查日志又发现模型明明传了一个看起来存在的订单号。后来手工请求真实系统依然返回不存在但用Python直接在代码里拼接请求体再发一次就成功了。排查到最后发现问题出在模型返回的JSON参数里订单号字符串带有首尾空格。这个空格在日志里肉眼完全看不出来但真实系统的查询逻辑是拿整个字符串去精确匹配的于是每次都匹配失败。更麻烦的是这个空格不是每次都有只有某些句式下模型才会在参数值前后残留空白。这个案例给我提了个醒参数转换规则里除了字段映射还必须包含“清洗规则”。对所有字符串类型的参数默认做trim对日期类型做格式统一校验对金额类型做精度规整对那些ID型参数还要去掉可能误入的字面量前缀比如用户说“订单号20240098号”的时候模型可能把“号”字也带进去。所以我在Agent-Reach的参数Schema里增加了一个sanitize字段可以声明这个参数该应用哪些清洗动作。清洗发生在参数预校验之前也就是模型参数进门第一件事就是清理不给脏数据继续扩散的机会。4.3 状态与补偿Agent-Raach做完一件事之后谁来负责“这件事的后果”这是整个项目里想法上最难的一环也是很多人做Agent集成时会忽略的。传统API调用讲“一次请求一次响应”Agent调用工具在大多数情况下也遵循这个模型但真实业务不是。比如“发送审批通知”这个动作调用IM接口成功后状态变成“已通知”这个状态在IM系统里存在但如果Agent接下来要执行的“归档文件”失败了整个流程回滚时这条已发送的通知怎么办Agent-Reach在设计上引入了一个简单的补偿模型。每个工具在注册时可以选择声明自己是“可补偿动作”还是“纯查询动作”。纯查询动作失败就失败了不影响其他步骤可补偿动作则要求配置一个“反向操作”工具。比如“发送审批通知”的反向操作就是“撤回消息”如果IM系统支持撤回的话。在编排Agent的多步调用时Agent-Reach会记录每个已成功执行的补偿操作一旦后续步骤发生不可恢复的错误就按“后进先出”的顺序依次执行补偿。这套机制不是要让Agent的每一步都完美无缺而是确保在长流程中途失败时系统不会留下“半完成状态”的脏数据。说实话这个补偿机制在第一个版本里我是做漏的当时觉得“Agent自己会把失败处理好”。直到有一次生产环境出了事故Agent已经发了通知但后续归档操作因为权限问题反复失败Agent在没收到明确错误反馈的情况下又发了一次通知重复消息直接把群机器人干封号了。从那以后补偿逻辑成了Agent-Reach的标配。5. 稳定性优先的实战细节重试、限流、熔断以及一套专门给Agent场景设计的“故障语义”如果把功能比作Agent-Reach的上限那稳定性就是它的下限。没有下限再强的功能也白搭。这一章聊聊我实际测出来的各种故障形态和各种应对手段。5.1 重试策略里最容易被忽视的不是重试几次而是重试后模型/用户感知到了什么做重试策略时大多数人第一反应是“超时了就重试”。但如果只是简单重试会遇到一个典型恶心问题Agent已经告诉用户“正在发送通知”然后重试机制在后台静默重试了三次最后用户看到的是Agent在十几秒后才回应而且回应内容还是“发送失败”。这种体验让用户对Agent能力产生严重不信任。后来我在Agent-Reach中引入了一个机制叫“感知原子性”。它的含义是一次工具调用无论底层重试了多少次对上层模型或用户而言应该感知为“一次尝试”。也就是说如果系统决定重试它会先缓存当前的进度状态在模型侧保持沉默等最终成功后统一返回结果如果最终失败返回的失败信息里要包含“已经尝试了几次、每次失败的原因分别是什么”的汇总摘要。这样模型在向用户汇报时能给出准确信息“我已经重试了两次第一次是网络超时第二次是接口限流请稍后再试。”而不是含糊的“失败了”。对用户来说这个信息质量完全不一样。5.2 限流不只看QPS还要看Agent的“并发规划”传统的API限流按每秒请求数计算就行但Agent触达真实系统时有一个特性一个Agent流程可能会在短时间内连续调用同一个工具多次比如“批量查询100个订单的状态”。这种情况下如果按简单的QPS限流Agent-Reach要么直接拒掉后面的请求要么全部放过去把下游打爆。我给Agent-Reach设计了一个“语义限流”机制。它不再只按时间窗口算而是同时考虑两个维度单请求的QPS限制、单个Agent实例的并发计算单元限制。拿批量查询订单举例工具注册时可以声明“单个调用最多允许传入50个订单号”这样Agent-Reach拿到一个50个订单号的批量请求时会在内部拆成多个子请求以一个固定速率发往真实系统而不是一股脑全打过去。这个机制还解决了一个隐蔽问题模型有时会“贪心”把本该分多轮的调用合并成一次超大参数的调用。如果没有语义限流下游系统会被这种畸形请求冲垮。5.3 熔断不是“断掉”是“切换路径”我对熔断的理解在做Agent-Reach的过程中发生了变化。传统微服务里熔断是当某个依赖频繁出错时直接拒绝新请求保护依赖不再被继续压垮。但Agent场景下直接拒绝会直接导致Agent流程中断用户看到的就是“这个功能不可用”。所以Agent-Reach的熔断做了增强一个工具进入熔断状态后并不会简单返回“失败”而是返回一个“可用性降级”的信号同时附带上可替代方案的提示。举一个例订单查询接口连续五次超时熔断器合上Agent-Reach会返回一个特殊结构给模型内容是“订单查询接口暂不可用但缓存服务还可用已自动切换为缓存数据数据可能延迟5分钟”。模型看到这个后可以在提醒用户时说明数据可能不是最新的。本质上这是把“让模型接管异常处理”变成现实——Agent-Reach负责侦测故障、切换路径、提供可理解的降级结果模型负责跟用户沟通这个降级结果。分工明确稳定性自然提升。5.4 全链路观测把一次Agent任务的所有工具调用拼成一张可回溯的“调用图谱”这个环节前期容易被忽略到排查问题时才后知后觉它的重要性。Agent-Reach每处理一次调用会生成一条包含以下字段的追踪记录工具名称、请求来源Agent实例、模型生成的原始参数、经过清洗和转换后的最终请求参数真实系统返回的原始响应、归一化后的结构、策略执行情况是否重试、是否降级、是否熔断整个调用的耗时分解等待模型决策时间、参数处理时间、网络请求时间、响应解析时间关联上下文这次调用属于哪个用户任务、它前后调用了哪些工具这些追踪记录拼起来就是一次Agent任务从开始到结束所经历的所有触达路径。排查问题时价值巨大。比如用户说“Agent乱发消息”打开追踪图谱能直接看到模型是先调用了哪一个工具拿到了什么返回然后才决定发消息的而不是对着聊天记录瞎猜。6. 几个真实案例复盘每个“看起来是模型的问题”最后都查到了Agent-Reach头上做这种中间层项目最大的感受是模型常常背锅。我复盘三个真实案例都很有代表性。6.1 订单查询“老是说查不到”不是模型理解错了是真实系统有多个订单库有段时间Agent在处理“查订单”请求时经常告诉用户“没有找到该订单”。当时第一反应是模型参数抽取不对于是我花了很多时间调提示词。但真正原因特别隐蔽真实订单系统分了主库和归档库新订单在主库超过一年历史的订单在归档库。Agent-Reach注册的“查询订单”工具默认打的是主库接口用户问的偏偏是去年的一笔老订单所以永远查不到。这个问题的解法不是让模型去判断“这笔订单在哪个库”因为模型无从得知。正确做法是在Agent-Reach的工具策略里配置“双库查询”主库查不到时自动再查一次归档库两边汇总结果后统一返回。这正好印证了我前面说的——模型对“系统边界”毫无感知只有触达层才看得到这种边界。6.2 审批流程“重复提交”Agent把“表单已提交”误判为“提交失败”还有个案例Agent在帮用户提交一个审批表单用户执行完操作后审批工具返回的是“已受理审批流程已启动”的提示但Agent-Reach的结果提取规则是按“HTTP 200就是成功”来写的偏偏这个审批系统的接口在正常情况下返回的是HTTP 202Accepted200反而是一种业务端异常。因为规则写得太粗糙Agent-Reach把这个成功的响应误判成了失败触发重试导致同一张表单被提交了两次。当时没有补偿机制两张重复表单流向了审批人。这个案例让我把“结果判断规则”提升为每个工具接入时最优先校验的项目。后续每一个新工具上线的验收条件里都有一条必须能区分“成功但非HTTP200”和“失败但HTTP200”两种情况。6.3 群机器人被封Agent在不知道“消息内容违规”的情况下拼命重发这也是前面提到过我印象最深的一次事故。群机器人收到一条带有外部链接的消息被平台风控拦截返回了“发送失败”。Agent-Reach配置的重试策略是“失败重试一次”其实本来重试一次也不会太严重但问题是模型收到失败反馈后又自己主动重试了两次。也就是说Agent参与到重试循环中形成一个“模型重试叠加中间层重试”的放大效应。后来我用了一个很简单的机制来治理Agent-Reach的返回结构里增加一个标志位告诉模型“这个错误不建议自行重试因为会触发风控或幂等冲突”。模型在决策时读取这个标志位就会停止重试转向其他策略比如换一种表达方式重发或者直接让用户介入。这件事让我意识到触达层不仅要控制自己的行为也要有能力引导模型的行为。7. 如果你也想搭一套Agent触达层我的建议顺序和几个可以直接抄的配置项目做到这个阶段我把整个过程中踩过的坑和沉淀下来的经验整理成一套执行顺序如果你也在做类似项目可以直接按这个顺序推进能少走不少弯路。这不是标准的“Roadmap”而是我亲自验证过的一条路径。7.1 起步阶段先接三个“足够不同”的工具而不是接一堆同类型的我的建议是先不要贪多而是选三个形态差异足够大的工具来验证Agent-Reach的设计。我当年选的三个是一个标准REST接口订单查询、一个老旧的XML-over-HTTP服务报表导出、一个带回调的异步任务接口批量文件转换。这三个工具覆盖了三种完全不同的调用形态和返回模式能逼着Agent-Reach把参数转换、结果提取、异步任务状态查询这几条核心路径都走通。如果一上来只接REST接口后面遇到其他形态时会发现自己设计的架构根本撑不住又得返工。7.2 每个工具上线必须过“四关”缺一不可我在项目里定了一个工具上线的验收流程每条都来自实际事故的教训第一关能区分“业务成功”和“HTTP成功”。接口返回200但有业务错误码的必须能识别出来。第二关失败注入测试。人为把下游接口改错、改超时、改返回结构Agent-Reach必须能稳定降级或报错不能死循环。第三关参数边界测试。所有字符串参数都需要测试带空格、带特殊字符、带Unicode的情况确认清洗规则能兜住。第四关重复调用幂等性。连续调用同一个工具两次观察是否会产生重复副作用如果会产生必须有去重或补偿机制。这四关看着很基础但一旦漏掉任何一关线上大概率会出问题。7.3 几个配置文件模板可以直接抄进项目里我把两个最常用的工具配置模板贴出来你在接新工具时可以照着改。第一个是“查询型工具”的配置适合大多数GET请求tool: name: get_user_profile description: 查询用户的公开资料信息包括昵称、头像、部门 params: - name: user_id type: string required: true sanitize: [trim, strip_prefix_id] request: method: GET url: https://user.internal.example/api/v1/users/$user_id headers: Accept: application/json response: success_when: - jsonpath: $.success equals: true extract: profile: $.data strategy: retry: 2 retry_interval_ms: 200 on_failure: return_error第二是“写操作型工具”的配置重点在声明幂等键和补偿动作tool: name: send_approval_notice description: 向指定的审批人发送一条审批提醒同一次审批流程内不可重复发送 params: - name: approval_id type: string required: true - name: approver_id type: string required: true idempotency: key_template: approval:$approval_id:$approver_id request: method: POST url: https://im.internal.example/webhook/send body_template: | { receiver: $approver_id, message_type: approval, message_id: $idempotency_key } response: success_when: - jsonpath: $.code equals: 0 extract: msg_id: $.data.message_id compensation: tool: revoke_approval_notice parameters: message_id: $msg_id strategy: retry: 0 on_failure: inform_user“inform_user”这种策略可能很多人一开始没概念它实际做的事情是工具调用失败后Agent-Reach把失败原因整理成用户能懂的一句话同时告诉模型“这个动作没有被执行用户可以手动去操作或者稍后再试”。这样就避免了模型盲目重试。8. 几点最终的体会和技术选择上的复盘技术细节说了很多最后聊聊我做完Agent-Reach这个项目之后对Agent工程化这件事的几点整体感受。第一Agent的能力边界很大程度就是触达层的边界。模型负责思考但思考之后所有动作的落地都依赖触达层。一个Agent项目如果表现不稳定很可能不是模型本身的推理能力不行而是模型接触到的工具接口太粗糙、反馈太模糊、失败处理太生硬。把触达层做好往往比换一个大模型更有效果。第二做Agent-Reach这类中间层最难的不是技术是“语义对齐”。技术上的HTTP、JSON解析、重试限流都有成熟方案。真正需要反复打磨的是你怎么把真实系统的语言、模型的语言、用户的语言这三者对齐。参数命名、结果结构、错误信息的表达每一个地方都要做一次翻译而这种翻译质量直接决定了Agent是“聪明”还是“智障”。第三这类项目一定要坚持可观测优先。如果不能在问题发生时完整回溯Agent的每一次触达你就会被“模型是不是又乱说话了”这种判断困住而错过真正的问题所在。我甚至建议做Agent触达层时把日志系统放在比缓存系统更早的位置去建设。第四“失败”本身要设计成可交互的。传统系统对接失败就是失败返回一个错误码就完事。但Agent场景里失败是一个对话事件——模型还需要基于失败继续和用户交互。所以Agent-Reach的失败返回不是冰冷的错误而是带着“发生了什么、系统做了什么尝试、用户现在能做什么”三个信息点的结构化反馈。这可能是Agent中间件与传统中间件最大的不同。我到现在还在持续迭代Agent-Reach最近在补的方向是“工具间依赖关系的自动发现”让Agent-Reach能根据调用记录自动推断出哪些工具经常一起出现、哪些工具的前置条件是什么。如果你也在做Agent工程化尤其是触达层的设计欢迎看完这篇之后按自己的场景去调整架构也希望能听到你的不同解法。
返回列表