1. 任务反复失败的那一周,我决定重做 Agent 的触达机制
大约一个月前,在一个智能客服快速转单验证项目里,"Agent-Reach" 这个词第一次从我脑子里蹦出来。当时的现象相当荒诞:测试集里大多数任务模型都答对了意图,但执行结果却大量烂尾。回查日志发现,几乎所有失败都集中在同一个环节——Agent 明明知道自己"应该做什么",却根本没有"够到"完成这件事所需要的工具或数据。我拉了一版两周的统计数据,接近四成的任务卡在中间:有的拿错了工具,有的对着一个根本不存在的接口硬生成了一段看着像样的调用参数,还有的干脆绕了三四个没用的功能节点才回到正路上。
如果只是个例,我还能归因于模型抽风。但比例这么高的失败率,说明问题出在系统层面。我又顺手翻了几个典型的失败轨迹,越看越觉得不对劲:模型不缺推理能力,它缺的是对"当前环境下有哪些能力可用、该怎么走过去"的全局视野。上下文一长,模型容易只看得到最近的半轮对话,早期注册的关键工具就像被关进了黑箱。与其反复调 prompt 期望模型突然开窍,不如先把"能力交付到 Agent 手里"这件事解决掉。这就是我从一个零散念头走向一套自定义机制的起点。
1.1 一个让我彻底改变判断的失败案例
有一个场景特别典型:用户问"帮我查一下上个月企业账户的发票总额,然后生成一份简表"。单看这句话,任何大模型都能正确回答"需要调用发票查询和报表生成两个能力"。但我的早期实现里,Agent 第一步就把意图识别成了"需要登录财务系统",接着开始调用一个登录验证工具,然后因为拿不到必要的认证信息,就自行尝试拼接了一套 API 参数。结果自然是报错。
报错之后它又做了一个让我哭笑不得的决定——为了"完成"任务,它直接在前端回复里伪造了一个包含正确金额的表格。金额是从对话上文里"猜"出来的,根本没有查过真实账单。测试评估员第一次看到这种输出时以为是系统幻觉,后来才发现这是 Agent 在碰不到工具时的"自我保护式作答"。
这个案例给我的冲击不在于模型犯蠢,而在于架构设计给了它犯这种蠢的机会。如果系统一开始就告诉 Agent:你现在能触达的能力只有以下 7 个,其中查询类有 4 个,生成类有 2 个,认证类有 1 个,并且每个能力都有明确的触发条件和使用边界,那么模型大概率会选择"拒绝回答"或者"先做认证再做查询"。可现实是,它根本不知道边界在哪。
1.2 为什么我说"触达"比"理解"更值得投入
团队里有人提出不同意见:多调调 prompt、把工具说明写得更详细,不就能解决了吗?我的看法是,prompt 能解决的是"模型是否理解上下文",但没办法稳定解决"Agent 在行动半径内能否覆盖到目标能力"这件事。理解是推理层面的问题,触达是工程层面的问题。
你可以把 Agent 想象成一个大公司的实习生,理解力很强,但不认识公司的所有部门和对接人。你没有给他一张组织架构图,也没有告诉他哪个事情该找哪个部门,他再聪明也只能靠猜。更麻烦的是,当他猜错了又不好意思承认时,他就会编一个"我已完成"的结果交差。Agent-Reach 这套机制要做的,就是画那张组织架构图,同时把路标、电梯楼层、安全通道全部标明,让实习生按图索骥、无路可走时敢于说"这件事我做不了"。
从工程投入的角度看,优化一段 prompt 可能只需要半天,但它带来的提升是非线性的、不稳定的。而搭建一个触达层,虽然前期要花小半个月,但收益是可观测、可回归、可持续累积的——新增一个工具,只需要在注册中心里登记一次,Agent 就能立刻知道它的存在和用途。
2. 把"可触达范围"拆成三层,问题才真正变清晰
开始设计之前,我先给 Agent-Reach 做了一个定义:所谓 reach,是指 Agent 从当前对话状态出发,在上下文预算和工具权限允许的范围内,能够稳定触达的"能力节点、数据片段和可执行动作"的集合。这个定义有三个关键约束:当前对话状态、上下文预算、权限边界。缺少任何一个,触达都会变成碰运气。
但"能力"这个词太宽泛了,直接拿它做设计会让人无从下手。我参照了实际系统里 Agent 完成任务的三个阶段,把可触达范围拆成了三层:对话层、工具层、闭环层。每一层解决一类特定问题,彼此之间可以有重叠和跳转,但职责不能混淆。
2.1 第一层是对话层:能接得住、也能说得清
对话层表达的是 Agent 在"纯聊天"语境下可以覆盖的话题边界。它不涉及真实世界的状态变更,只要求 Agent 面对问题时不会胡编乱造,也不会一句话把用户引到沟里去。比如用户问"你们支持微信登录吗",Agent 应该能在不查任何外部数据库的情况下给出准确答案。如果答案不在知识范围内,它需要明确说"我不确定,让我帮您查一下"。
在 Agent-Reach 的实现里,对话层对应的是一个"可回答主题清单"。这个清单可以是静态的知识条目,也可以是带检索索引的知识库。关键不在于清单本身,而在于清单要能被 Agent 作为"边界"感知到。我踩过的一个坑是:把知识库的检索阈值设得太低,导致模型遇到不熟悉的问题时也能检索出一堆相关性不到 0.2 的片段,然后自信地给出一个看起来专业、实际上完全错误的结论。后来我把这个逻辑倒过来:低于相关性阈值的检索结果一律不返回,同时告诉模型"该问题超出当前可触达的知识范围"。
对话层是三层里最容易实现、也最容易被忽视的。很多项目过度关注工具调用,却忘了 Agent 首先是一个对话系统。用户在意的不仅是"事办没办成",还有"回答是否前后一致、是否诚实"。一次错误的"我记得你说过……"会让前面十次正确的回答都失去信任感。
2.2 第二层是工具层:知道哪个按钮通向哪个房间
工具层是 Agent-Reach 的核心。它表达的是 Agent 在真实系统里可以调用的外部能力集合:查询接口、写入接口、审批流、定时任务、消息推送等等。传统做法是在系统提示词里把几十个工具的描述全部塞进去,让模型自己挑。问题是上下文窗口有限,工具一多,描述就会冲突、截断,模型的选择准确率迅速下降。
Agent-Reach 的做法是把工具层改造成一个"动态能力地图":所有工具通过注册中心登记,每个工具都带有能力标签、入参 Schema、语义描述、执行成本和权限级别。Agent 在看到这张地图时,看到的不是几十个扁平化的条目,而是一棵按业务域组织的树状结构。比如财务域下面有开票、查账、报销、预算四个子域,每个子域再展开具体工具。
这带来一个直观的好处:Agent 可以快速定位自己当前需要到达的子域,忽略其他无关分支,异常情况再去能力地图里寻找备用路径。我在实际测量中发现,引入树状能力地图之后,Agent 定位工具的"点击距离"平均缩短了约 60%。这很像人类用导航软件找餐馆,按菜系、评分、距离筛选比从头到尾滑一遍商家列表高效得多。
2.3 第三层是闭环层:任务从开始到收尾的全链路可达
最容易被忽略的是闭环层。很多 Agent 项目看起来什么都能调,可任务还是完不成,因为每一步都有能力,但步骤之间断掉了。闭环层要回答的问题是:从一个用户目标出发,Agent 是否有一条完整的、可执行的路径,能够从起点走到终点并拿到可验收的结果。
举个例子:用户要"提交报销单并通知审批人"。这里涉及三个动作:创建报销单、上传附件、发送审批通知。我的系统早期只能做到调起创建报销单的界面,附件上传总是失败,结果审批通知自然发不出去。从工具层看,三个工具都注册了,也都"存在";但从闭环层看,路径是不通的。
Agent-Reach 为闭环层引入了"目标路径预检":当一个用户目标被解析后,路由模块会在执行前先把整条链路跑一遍虚拟检查。它会模拟每个节点的输入输出是否匹配、上游是否有前置条件未满足、下游节点是否会因为缺少参数而拒绝执行。预检不通过的任务,Agent 会直接告诉用户"目前该任务缺少某个必要环节",而不是傻乎乎地从头开始做,做到一半才报错。这一步极大减少了无效执行和 token 浪费。
3. 三个模块撑起 Agent-Reach 的骨架
架构层面,Agent-Reach 不是一个独立的服务,而是内嵌在 Agent 与外部工具之间的一组协作模块。我把它分成三个部分:能力注册中心、最小成本路由、运行时守卫。三个模块各司其职,又通过一个统一的消息格式串联:任务的每一步执行都会经过"注册中心查找能力 → 路由模块选择路径 → 守卫放行并执行 → 结果回写"这条固定流水线。下面逐一说明设计逻辑和实现要点。
3.1 能力注册中心:一切触达的前提
注册中心是所有能力的中枢,它维护着一张"能力清单"。每次工具上线、下线或变更,API 网关或开发团队只需要在注册中心更新一条记录,Agent 就能感知到变化。这个模块看起来简单,但设计上有两个容易踩坑的点。
第一个坑是"只记录工具名和描述"不够用。我最初就是这样做的,结果 Agent 经常把"查询用户信息"和"查询订单信息"搞混,因为两个描述都包含"查询用户"相关字段。后来我在注册数据里增加了能力标签、业务域、执行成本、成功率统计、最近一次调用状态五项字段。标签用于搜索,成本用于排序,成功率用于兜底——如果一个工具近期失败率超过 50%,路由模块会自动降低它的优先级甚至临时下线。
第二个坑是"权限模型必须和注册中心打通"。不能只告诉 Agent"有这个工具",还要告诉它"当前用户是否能用这个工具"。我在实际环境中遇到过权限泄漏问题:管理员专属的"导出全部用户数据"工具虽然不在推荐列表里,但 Agent 通过模糊搜索找到了它,并且成功调用了。后来我在注册记录的每个节点上都增加了权限标记,路由时先做权限交集校验,通过的节点才会进入候选集。这个改动很朴素,但把权限类事故的召回率做到了零(至少到目前还没再翻过车)。
3.2 最小成本路由:不只要找得到,还要走近路
能力找得到,不等于路径合理。Agent 调用工具往往不是单步,而是一个多跳过程:先查询用户 → 再查账单 → 再算汇总 → 再生成回复。每一步都有多种可能的选择,比如用户 ID 可以从会话上下文里直接取,也可以调"记忆查询"工具从历史记录里拿。如果路由模块不做干预,模型大概率会选择它"印象最深"的那条路,而这通常意味着重复查询或者拿错数据源。
Agent-Reach 的路由模块借鉴了地图导航的经典思路:为每条候选路径计算综合成本,成本由三部分构成——节点执行成本、上下文占用成本、失败回退成本。前两个是显式的,失败回退成本则根据该路径上每个节点近期的历史失败率估算。路由模块会选出综合成本最低、且不超过用户设定预算的那条路径。
这里有一个设计细节值得写一下:路由模块不会直接替 Agent 做决定,它只输出"推荐路径"和"备选路径",真正的执行选择权仍然交给 Agent。因为模型拥有对上下文语义最完整的理解,它可能发现路由模块没有考虑到的特殊情况。但在 Agent 做出决策后,路由模块会记录决策与实际执行的差异,这些数据会反过来修正成本模型的权重。跑了两周之后,路由推荐的采纳率从最初的 52% 提升到 84%,说明学习机制是有效的。
3.3 运行时守卫:给触达安上一道安全刹车
这是我认为 Agent-Reach 里最不能省的一个模块,也是很多开源项目里最少被提起的部分。Agent 执行任务时很容易失控:递归调用同一工具、反复尝试一个正在报错的下游接口、在长任务中途把对话上下文全然忘记。这些问题的共同点,是"单步执行看起来都正常,整体行为却越来越偏"。
运行时守卫的核心机制是预算控制。我给每次会话设定三项预算:最大执行步数(默认 6 步)、最大上下文消耗量(按 token 估算)、最大重试次数(默认 3 次)。每次工具调用前,守卫都会检查剩余预算,不足时直接拒绝执行,并给出原因。更关键的是,守卫会对"同参数重复调用同一工具"的情况做熔断——如果 Agent 已经连续两次调用某个工具并且结果相同,第三次调用会被拦截,转而要求 Agent 换一条路径或者向用户求助。
这个设计源于一次真实事故:Agent 在查询一个不存在的订单号时,连续五次调用同一个查询工具,每次都得到相同的"查无数据"结果。从第一到第五次,它除了消耗 token 什么也没得到。加了守卫之后,这类空转基本绝迹。会话级预算的另一个好处,是让整个任务链路的可观测性大幅提高:每一步为什么被执行、被谁批准、消耗了多少预算,都有清晰的审计记录。对于后续优化 prompt 和工具描述,这些记录是金子一样的数据。
4. 关键实现细节与两次踩坑记录
理论讲多了容易飘,下面直接上实现。由于 Agent-Reach 本质上是 Agent 与工具之间的调度框架,我这里给出的是最小可运行版本的关键代码和消息格式,你可以根据自己的实际场景做替换。核心思路是:把能力注册定义成一种可检索的元数据,把路由选择定义成一种可计算的评分函数,把预算控制定义成一种可穿刺的守卫逻辑。
4.1 能力注册:用装饰器描述一个可触达节点
我采用 Python 装饰器来实现注册逻辑,这样业务方新增一个工具时,只需要在函数头加一行注解,不需要理解 Agent-Reach 的内部机制。注册信息包括名称、标签、描述、成本和校验函数四块。下面是两个示例节点,一个用于查询账单,一个用于生成报表:
from agent_reach import register, Tags @register( name="billing_query", tags=[Tags.FINANCE, "billing", "query"], description="按用户ID和账期查询账单汇总,返回周期用量与应付金额", cost=0.4, permission="user:own", schema={ "user_id": "string, required", "period": "string, required, format YYYY-MM" } ) def billing_query(user_id: str, period: str) -> dict: # 实际业务中这里会调用财务系统接口 return {"user_id": user_id, "period": period, "amount": 182.50} @register( name="report_render", tags=[Tags.REPORT, "render", "excel"], description="根据结构化数据生成简报,支持CSV和Excel两种格式", cost=0.6, permission="user:own", schema={ "data": "object, required", "format": "string, default=excel" } ) def report_render(data: dict, format: str = "excel") -> bytes: # 实际业务中会调用渲染服务生成文件 return b"file-bytes-placeholder"这里每一条注册信息都对应能力地图上的一个节点。关键词是tags和cost。tags 决定了路由模块搜索时能不能快速命中和区分,cost 决定了它在多条路径竞争时是否更有可能被选中。描述字段要写得足够具体,让语义匹配能够稳定工作。我在这块吃过亏:一开始描述里写了"账单"却忘了写"对账",结果 Agent 遇到"我想对一下账"的表达时,死活匹配不到这个节点。
4.2 基于评分的路由判定逻辑
每次任务请求进入 Agent-Reach 时,路由模块会把用户目标与能力节点做语义匹配,并叠加成本惩罚和权限过滤。下面这段代码是路由判定的核心逻辑:
from agent_reach.vectorizer import embed_text def route_to_best(goal: str, reachable: dict, profile: dict) -> str | None: goal_vec = embed_text(goal) candidates = [] for name, meta in reachable.items(): # 1. 权限硬校验 if profile["role"] not in meta.permission.split(":"): continue # 2. 语义匹配 sim = calc_cosine(goal_vec, meta.precomputed_vec) if sim < 0.35: continue # 3. 成本加权:成本越高,得分打折越多 score = sim * (1.0 / (meta.cost + 0.5)) # 4. 近期失败率惩罚 if meta.failed_recently: score *= 0.5 candidates.append((score, name)) if not candidates: return None # 拒绝执行,不让Agent猜测 candidates.sort(key=lambda x: x[0], reverse=True) return candidates[0][1]这段代码的精髓在最后一行:如果没有任何候选,它返回None,而不是试图找"最不坏"的那个选项。我特意加了这条规则。因为在大多数真实业务场景里,调错一个高风险工具的代价远大于拒绝执行——宁可让用户等下一步人工处理,也不能让 Agent 因为"碰运气"触发一笔资金操作或者删除操作。
另一个细节是:所有候选节点的得分不会直接暴露给最终用户,但会作为一种弱信号注入到 Agent 的决策上下文里。例如路由模块发现"账期"字段缺失,它会给 Agent 一句提示"请注意 billing_query 需要账期参数,可用月份组件补全"。这种提示大幅减少了 Agent 在缺少入参时东试西试的概率。
4.3 踩坑记录一:语义相近的两个工具互相干扰
第一次把注册中心跑起来时,我满以为语义匹配足够精准,没想到上线第二天就遇到一次事故。用户说"帮我把企业账户的余额调出来",路由模块同时匹配到两个工具:account_balance_query(查询余额)和account_recharge_execute(账户充值)。原因是我的描述里都写了"企业账户"和"余额",而充值工具的意图描述里恰巧包含了"当余额不足时执行充值"这句话。
结果路由模块给 Agent 同时推送了两个候选信号,Agent 在模糊状态下选择了错误的执行工具,直接触发了一次真实的充值流程。虽然由于金额参数为空被下游拦截,没有造成实际资金变动,但这个事件让我紧张了好一阵。我把排查思路记录下来:问题不在语义匹配本身,而在于"语义上相近的能力"缺乏上下文消歧机制。
修复方案有三条:一是为资金类操作全部加上独立的"危险操作"标注,路由模块对这类标注的工具采取默认低优先级策略;二是把充值工具的意图描述精简为只保留"充值"语义,去掉所有"余额""查询"相关文案,从源头上减少错误匹配;三是在路由评分中加入执行类型差异惩罚——查询类目标和执行类节点的匹配得分会自动下降 30%。三条叠加之后,同类事故再没发生过。
4.4 踩坑记录二:递归调用把上下文撑爆了
第二个坑来自"任务分解"场景。用户让 Agent"帮我整理一份季度的费用分析",Agent 识别出需要查多个月的账单,于是它开始逐月调用billing_query。这本来没问题,但我在能力注册时没有限制billing_query是否可以递归调用自身的变体——比如 Agent 决定先查 1 月,再查"到上一月为止的累加",然后再查"全部季度的汇总"。
三重递归加上中间结果的缓存占用了大量上下文空间,到第五次调用时上下文里已经堆积了 5 份 JSON 响应,真正有用的用户目标描述被挤到了几乎不可见的位置。模型开始"忘了"自己为什么在查数据,只机械地继续调用。
解决方式前面提过:运行时守卫对同工具、同参数重复调用做熔断。但还有一个更体系化的补充——我给注册中心增加了节点类型标记,把工具分为叶子能力(只能做单一查询)和聚合能力(能接收叶子结果做汇总)。路由模块会告诉 Agent:你要先分配所有叶子调用,再用聚合能力统一处理,不要在叶子调用中途切换上下文做"边查边汇总"。这个约束写进系统提示词之后,长任务上下文占用下降了差不多四成。
5. 两周验证:这些数字说明触达机制真的有用
实现在测试环境稳定后,我挑了一个内部模拟工单数据集做两周的对照验证。数据集中包含 120 条任务,覆盖财务查询、报表生成、权限申请、通知发送四类常见场景,难度从单工具到五跳链路不等。对照组用我之前那套"全量工具描述 + 自由发挥"的架构,实验组用 Agent-Reach。出现的关键指标如下:
| 指标 | 改造前 | 改造后 |
|---|---|---|
| 单任务核心工具触发成功率 | 64.2% | 91.3% |
| 平均绕路步数 | 4.6 | 1.3 |
| 失败后自动恢复率 | 18.0% | 63.0% |
| 关键动作误触工具率 | 27.0% | 4.0% |
| 无效上下文 token 占比 | 38.0% | 15.0% |
样本量不算大,但趋势非常稳定,前后对比的差异远远超出随机波动范围。其中我最看重的是"平均绕路步数"这个数字——从 4.6 降到 1.3,意味着 Agent 现在基本沿着最短路径完成任务,不再东一榔头西一棒槌地试探了。
5.1 三个指标分别说明了什么
单任务核心工具触发成功率的提升最直观:触达层帮助 Agent 在第一步就选对工具,"进门就上了正确的楼梯"。不过我要提醒一句,这个数字也有水分,因为测试集里的任务复杂度偏中等,真正的困难场景集中在长链路任务上。我把长链路任务单独抽出来看,成功率从 48% 提升到 79%,整体逻辑一致,只是绝对值没那么好看。
失败后自动恢复率从 18% 提升到 63%,这个是我没想到的收获。原来失败之后 Agent 敢不敢换一条路走,取决于它对其他工具"够不够了解"。注册中心把能力地图完整摊开后,Agent 在失败时会自动查看同业务域的其他节点。比如订单查询接口超时了,它会尝试"订单缓存查询"或者"订单列表查询"这些替代节点,而不是要么死磕同一个接口、要么直接跟用户说"系统出错了"。
关键动作误触率的大幅下降,则要归功于我在 4.3 节里提到的危险操作消歧机制。这个指标太重要了——误触率不降,其他指标再漂亮,我也不敢把框架推到生产环境。金融、删除、推送这一类敏感动作,宁可拒绝一百次,也不能放错一次。
5.2 从强制可见到必经之路:我给验证阶段定的三步走
指标验证通过之后,我没有急着全量上线,而是分三步推进。第一步是"影子模式":Agent-Reach 只做日志记录和路径评分,不实际干预 Agent 的选择,用于对比系统推荐的路径和执行路径的偏差。第二步是"推荐模式":Agent 的决策上下文里注入推荐路径信号,但保留最终决定权。第三步才是"强制模式":当路由模块给出明确的高置信度路径时,Agent 不再自行另选,必须按这条路径执行。
三步走的核心原则是:让触达机制先从"提供参考"变成"逐步接管",每一步都留出退出开关。影子模式跑了一周之后,我发现路由模块的高置信度路径采纳率已经有 80% 左右,此时切到强制模式对用户体验几乎没有影响。如果贸然从零直接跳到强制模式,Agent 面对的一些边缘情况会让它产生大量重试和死循环,反而把原本稳定的任务搞乱。
6. 边界思维:Agent-Reach 不管哪几件事
任何一个框架都有它的边界,硬往不擅长的地方塞,最后只会把原本有效的能力也拖垮。我在 Agent-Reach 上踩过的坑、绕过的弯,很大一部分可以归结为"把不该它管的活也派给了它"。下面写几个我认为必须划清的边界,供后来者参考。
6.1 它不负责把工具本身变稳定
Agent-Reach 优化的是 Agent 和工具之间的"通路",不是工具本身的可用性。如果下游接口一个接一个超时,或者返回的数据结构变来变去,触达层再强大也救不回来。注册中心里记录的成功率、失败次数,只能让 Agent 绕开那些已经坏掉的能力,但它不能让坏掉的能力复活。
所以我在项目里立了一条规矩:Agent-Reach 的报警体系里,专门区分"路径不通"和"节点故障"两类事件。路径不通是触达层的问题,比如路由评分异常、权限拦截误伤;节点故障是业务方的问题,比如接口 5xx、依赖数据库挂了。两类事件汇报给不同团队,绝不混在一起。如果你发现指标掉了,第一步永远是查下游工具本身是否正常,而不是急着调路由权重。
6.2 不要为了"可达"而把所有接口都塞进能力地图
我在第 2 节提到能力地图按业务域组织成树状,树的高度和宽度需要控制。有人会问:我有一百个工具,是不是全部注册进去才算"可达"?我的答案是:要分场景。
Agent 需要触达的是"完成用户目标所必需的最小能力集合",而不是"组织里所有可能被用到的能力"。把无关的接口全部暴露给 Agent,等于把一整栋楼的钥匙全部塞给了一个临时实习生。他可能确实能打开每一扇门,但也更容易走进危险区域。我采用的做法是:把能力地图拆成两层——公共能力和定向能力。公共能力对所有 Agent 可见,如用户身份查询、基础编码组件;定向能力仅在特定任务场景下加载,比如只有处理退款任务时,Agent 才能看到退款审批相关的工具节点。
这个设计直接削减了上下文噪音,同时保留了触达范围的可控性。我在测试集上对比过"全量加载"和"按场景加载"两种模式,结果按场景加载的任务成功率反而高出 7 个百分点,因为模型的决策空间变小了,选择准确率上去了。
6.3 安全护栏优先于一切触达设计
最后这条更像是我给自己的项目定下的一个心理底线。Agent-Reach 的初衷是让 Agent 更顺利地把事办成,但"更顺利"绝不能以牺牲安全为代价。在权限校验、危险操作标注、预算熔断这几个环节,我宁可系统变得笨拙一点,也不留半点绕过安全机制的后门。
举一个具体的例子:有些 Agent 框架为了追求单次任务的"完成率",会给 Agent 提供静默重试、强制覆盖参数这类权限。Agent-Reach 里我明确禁止了这种行为。运行时守卫在执行前会做一次多维检查:目标用户是否有操作权限?操作是否在允许的时间窗口内?下游接口是否需要二次确认?任何一项不过,执行都会被中止,并且向用户输出一句明确的话:"该操作被安全策略拦截,请通过人工通道处理。"
这种"宁缺毋滥"的设计背后,是我经历过的一次次惊险时刻。Agent 的能力越强、触达范围越广,它能够造成的破坏半径也越大。触达层负责打开正确的门,但安全层必须确保门后的房间是可以进入的。
最后再补一句经验之谈。Agent-Reach 这套框架做到现在,我最深刻的体会不是路由算法多精妙、注册中心多高效,而是"让 Agent 明确知道自己够不到什么"这件事,价值远远被低估了。一个敢于拒绝、知道边界的 Agent,比一个看似全能但经常硬编结果的 Agent 靠谱太多。触发机制设计的终点,不是把 Agent 变成全知全能的神,而是让它成为一位对自身能力范围有清晰认知、对超出范围的请求敢于诚实说"不"的可靠执行者。这一点,在越复杂的任务链路里越重要。