我调一个客服售后 Multi-Agent 的时候遇到过这样一幕负责退款审批的子 Agent 面对用户的订单信息非常自信地生成了一条“已退款”的回复可实际上它根本没调订单状态查询工具——不是不想调而是这个工具的 schema 压根没出现在它的上下文里。模型看不见的工具它不会想去调更准确地说它压根不知道要调。这个现象在 Multi-Agent 架构里太容易被当成偶发 bug但查到最后你会发现它几乎都是设计层面的系统性问题工具可见性Tool Visibility。今天我就围绕这个点把我在真实项目里踩过的坑、拆过的链路、最后沉淀下来的设计方法完整讲一遍。1. 工具可见性Multi-Agent 决策链里最容易被当成“细节”的关键开关1.1 一次“Agent 假装干活”的线上事故先复盘一下开头那个事故因为它的隐蔽性非常有代表性。当时我们做了一个售后客服系统主流程是用户提单投诉 - 客服 Agent 判断问题类型 - 分发给退款 Agent / 物流 Agent / 维修 Agent。上线第二周就出事了。有用户反馈说“已经显示退款完成但钱没有到账”。排查日志时发现退款 Agent 收到了正确的工单和用户诉求模型也在回复中写了“您的退款申请已通过款项将在 1-3 个工作日内原路退回”。但它没有调用refund_create这个工具也没有调用order_status_query来二次确认订单是否真的满足退款条件。我们第一反应是“prompt 写得不够严格”让模型必须调用工具。于是把 prompt 改成“你必须先查询订单状态再执行退款”结果问题依旧。真正的原因是在代码里退款 Agent 的 tools 列表在初始化时漏掉了order_status_query。模型看不到这个工具的 JSON Schema它既不知道有这个工具存在也不知道要生成对应的 tool_call。在它眼里“退款成功”只是它基于上下文脑补出来的一个合理回复。模型不会因为工具缺失而报错它只会非常自信地输出一个错误结果。这类事故最麻烦的点在于它的外在表现是“模型胡说八道”容易让人误判成 prompt 工程或模型能力问题很少有人会第一时间想到“是不是工具没有被注入进去”。1.2 “看不见”在模型机制层面意味着什么要理解这个问题得先搞清 LLM 工具调用的物理链路。现在主流模型OpenAI 的 function calling、Anthropic 的 tool use 等在 API 层做的事情其实很朴素把你传入的tools参数序列化成一坨 JSON/JSON-Schema 文本拼进系统上下文再让模型在生成回答时“顺带”决定要不要输出一个tool_calls。也就是说模型的工具调用决策本质上是在“读到你给的这串工具列表”的前提下做的。这个列表就是模型视野的全部边界。工具只存在于你的业务代码里、数据库里、注册表里只要它没进这串列表模型就完全感知不到它的存在。这就像一个临时工被派到一家公司干活如果没人告诉他公司有个法务部他在遇到合同问题时只会自己硬着头皮编一个“合同应该没问题”的结论而不会去找法务。不是他不想找是他在认知层面根本不知道有这么一个部门。所以 Multi-Agent 里“工具可见性”不是一个权限控制问题而是一个模型认知边界问题。你堵住了模型“看见”某条路径的窗口它就一定会拿它现有的认知去“圆”这个缺口。2. 同一个工具三种可见状态带来的三种行为差异工具可见性不是一个非黑即白的状态。同一个refund_create工具放在不同 Agent、不同任务场景下就会产生完全不同的行为结果。我把我在项目里观察到的三类状态拆开讲。2.1 全局可见工具一多模型开始“选择困难”最早我们图省事所有 Agent 共用一个大工具列表几十个工具全部塞给每个子 Agent。思路是“反正模型很聪明让它自己选呗”。实际一跑就发现问题当可见工具超过二三十个时模型出现“选择困难”。明明该调 A 工具它却调了名字或描述跟 A 很像的 B 工具。工具描述里的信息被稀释。模型对每个工具的注意力是有限的工具越多单个工具的描述在决策中的权重就越低。token 成本大幅上升。每个工具的 schema 都占上下文长度几十个工具叠下来光工具定义就上千 token。有一次线上日志显示一个负责“开发票”的子 Agent居然调用了“物流轨迹查询”工具。排查后发现这两个工具在工具列表里隔着 8 个不相关工具描述里都提到了“查询客户订单”模型在长列表的注意力分配中模糊了对工具边界的判断。全局可见真正适合的场景很少除非你的系统总共只有三五个工具且它们之间的职责边界非常清晰不存在“看起来都能解决问题”的歧义。2.2 局部可见各 Agent 自扫门前雪跨环节开始踢皮球为了治全局可见的“注意力稀释病”我们把工具按 Agent 职责做了拆分退款 Agent 只看到退款相关工具物流 Agent 只看到物流工具。这就是最常见的“局部可见”。效果立竿见影单个 Agent 的工具选择准确率确实上升了。但跨场景协作出现了一个新问题工具不在视野内Agent 就会用“踢皮球”的方式处理它搞不定的环节。举个例子。用户同时投诉“订单延迟”和“要求退款”这个工单被分配给了物流 Agent。物流 Agent 手里只有物流工具它能看到订单状态也知道用户想退款但refund_create不在它的工具列表里。于是它的回复变成了“您的退款需求已收到建议您联系客服处理退款。”模型其实是在有礼貌地承认“我办不了”但它没有能力把这个任务“转交”给真正能办的退款 Agent。如果你在系统里没有设计 Agent 间任务移交机制这条业务就断在这里了。局部可见把“模型乱调工具”的问题换成了“模型遇到边界就撂挑子”的问题。2.3 动态可见先路由再注入让工具在该出现的时候出现后来我们把方案改成了动态注入先由一个路由模块判断当前任务属于哪个领域、需要哪类能力再只把相关的工具列表注入给对应的子 Agent。动态可见的好处是它同时解决了两个问题每个 Agent 的上下文里永远是“够用但不冗余”的工具集模型既能看得见该用的工具又不会被大量无关工具干扰跨 Agent 协作也不再依赖模型自觉而是由路由层在源头把任务分发到拥有正确工具集的 Agent。这套设计的本质是把“让模型从 50 个工具里挑 1 个”改成了“先让路由从 5 个领域里挑 1 个领域再让模型从该领域的 5 个工具里挑 1 个”。把一次高难度决策拆成了两次低难度决策。可见性策略工具选择准确率跨环节协作上下文长度实现复杂度全局可见低工具多时明显下降好因为啥都看得见高最低局部可见高单 Agent 内差跨职责会踢皮球低低动态可见高前提是路由准确较好由路由层兜底中中高3. 实战拆解我们如何给 Multi-Agent 设计工具可见性分层3.1 工具注册表给每个工具标注“谁能看、何时看”落地动态可见的第一步是把每个工具当成一条带元数据的注册项来管理而不是散落在各 Agent 配置文件里的一堆函数。我在项目里建了一张工具注册表每个工具记录以下字段tool_name工具名保持全局唯一description描述写给模型看的owner_agent归属 Agent比如退款工具归属 RefundAgentvisible_agents额外允许看见该工具的 Agent 列表required_scenario该工具适用的场景标签比如refund、logistics、invoicepermission_level操作级别只读 / 写操作 / 敏感操作然后在代码里写一个get_tools_for_agent(agent_name, task_type)函数它的返回值就是该 Agent 在当前任务里实际能看到的工具列表。这个函数做的事很简单先取 owner_agent 和 visible_agents 里匹配当前 Agent 的工具再按 required_scenario 过滤出当前任务类型命中的工具。这样一个集中式注册表的好处是新增工具、调整可见范围、排查“某个 Agent 为什么看不到某个工具”都变成了查表操作而不是去翻一堆 Agent 的初始化代码。3.2 路由 Agent把“该看什么”这件事交给一次专门调用动态可见里的“路由”怎么做决定了整个系统的上限。我见过两种常见做法。一种是纯规则路由用关键词匹配任务类型优点是便宜可控缺点是自然语言表达太灵活规则很难覆盖全。另一种是把路由本身也做成一个 Agent用一次 LLM 调用来完成“任务分类 工具选择”的判断。我们最终用的是后者但做了一些关键约束。路由 Agent 的输入是用户的原始请求和会话上下文输出是一个结构化 JSON包含task_type、target_agent、needed_tools这三个字段。其中needed_tools不是让路由 Agent 自己去猜工具名而是让它从工具注册表提供的一份“场景模板”里选。比如场景模板refund_scene绑定[order_status_query, refund_create, refund_status_query]路由 Agent 只需要选择“退款场景”这几个工具就会自动绑定注入。这么做是为了限制路由 Agent 的发挥空间避免它脑补出一个不存在的工具名。路由 Agent 的任务从“选工具”降级成“选场景”而场景和工具的映射关系由我们人肉维护出错概率小很多。3.3 最小可落地的动态注入实现如果你不想引入太重的框架动态注入的核心逻辑其实可以写得很简单。下面是一段我项目里简化过的伪代码基本能说明白这个机制是怎么转起来的def build_tools_for_request(user_input, agent_name, tool_registry): # 第一步判断任务场景这里用一个轻量路由模型或关键词规则 task_type route_task_type(user_input) # 第二步从注册表拿该 Agent 归属的工具 base_tools tool_registry.get_tools_by_owner(agent_name) # 第三步拿场景模板绑定的工具取并集 scene_tools tool_registry.get_tools_by_scenario(task_type) # 第四步去重合并同时排除权限不足的工具 visible_tools merge_and_filter(base_tools, scene_tools, allowed_agents[agent_name]) return visible_tools这段代码看着简单但有两个细节值得注意。第一route_task_type这一步绝对不能省。如果直接返回该 Agent 的全部工具那又回到了局部可见的老路。第二合并后最好按工具的重要程度排序因为模型中后段工具的注意力权重会衰减。我会把最可能用到的核心工具放在列表前 5 位。动态注入跑起来之后你会发现每个实际请求注入到模型上下文里的工具数量从原先的 40 个降到了 5~10 个。上下文大幅缩短模型决策的噪声也小了很多。4. 工具描述怎么写模型才“愿意看、看得懂、敢去调”工具可见性不只是“工具在不在列表里”的问题还包括“工具出现在列表里之后模型看不看得懂、敢不敢调”。同一个工具描述写得烂和写得好效果差非常多。4.1 描述三要素触发条件、执行结果、不适用场景我见过太多工具描述只有一句“查询订单状态”这种信息量对模型来说约等于没有。模型需要知道的是什么情况该调你调了你之后能拿到什么什么情况下不该调你。一个好的工具描述至少要包含三块信息触发条件什么信号出现时你应该调用这个工具执行结果调用之后能拿到什么对后续决策有什么帮助不适用场景什么情况下不要调用它以避免与别的工具产生歧义拿order_status_query来举例。写得差的描述{ name: order_status_query, description: 查询订单状态 }写得好的描述{ name: order_status_query, description: 查询订单的当前状态待支付/待发货/运输中/已完成/退款中。当用户询问物流进度、退款进度或订单是否可退时必须先调用此工具获取最新状态再回答用户。若要查询具体物流轨迹不要使用本工具请使用 logistics_track_query。 }后者的关键信息全齐了什么时候用、用了得到什么、什么时候别用、替代工具是谁。模型拿到这个描述就非常清楚自己的行动路径了。描述相当于给模型画了一张“何时出牌”的说明书信息越具体模型越不容易误判。4.2 参数 Schema字段越多模型越犹豫工具的参数定义同样是可见性的一部分。我踩过的一个典型坑是为了“功能完善”给工具定义了 12 个必填参数结果模型调工具的成功率明显下降。原因是模型在生成 tool_call 时要同时满足所有必填参数的格式要求参数越多生成合法调用的概率就越低模型的“心理负担”也越重。它会倾向于少调工具或者调用了但参数填写不完整最终被 API 校验拦截。好的做法是必填参数只保留真正无法推导的字段能通过其他信息查到的字段一律设成可选或者直接走默认值。能用 enum 限定的字符串字段就尽量用 enum把模型的选择空间约束住比让它自由发挥稳定得多。4.3 工具命名名字本身就是一句 prompt另一个容易被忽略的点是工具名。模型对工具名的解读优先级非常高甚至高于描述。因为注意力机制会天然倾向于从名称里获取语义信息。比如同一个查询能力叫query_something和叫query_refund_progress对模型来说完全不是一个东西。后者直接把工具职责摆在名字里模型在快速扫描工具列表时一眼就能判断该不该调它。我们后来做了一轮工具改名原则是动词行为 对象领域/业务实体 可选修饰状态/范围。比如refund_create、refund_status_query、logistics_track_query。工具名本身就是一句压缩过的 prompt别浪费这个信息位。5. 实测记录不同可见性策略下的效果与成本账理论说了这么多还是得看数据。我把三种可见性策略在同一个业务场景里做了一轮对比测试这里直接放结果。5.1 实验设计测试场景是我们线上真实跑的售后工单处理流程。数据集取了 1000 条历史用户会话覆盖退款、物流、发票、维修四类任务。评测维度选了四个工具调用正确率该调的工具是否调对、任务完成率用户诉求是否被完整解决、平均首次响应延迟、单请求平均 token 消耗。三种策略分别是全量注入 40 个工具、按 Agent 固定注入 10~15 个工具、按任务动态注入 5~10 个工具。5.2 三组对比数据策略工具调用正确率任务完成率平均延迟秒平均 token 消耗全量注入 40 个工具82.4%78.9%8.66200按 Agent 固定注入91.2%84.3%6.84500按任务动态注入94.6%89.1%6.13900单看数据动态注入在每个维度都是最优的。工具调用正确率比全量注入高了 12 个百分点任务完成率高了 10 个百分点token 消耗还省了 37%。这说明把无关工具从模型视野里清出去收益是实打实的。5.3 结果解读动态可见不是万能药但动态注入也有它的软肋。路由 Agent 本身是一次额外调用如果路由判断错了场景后面的工具注入就会跟着错。在上述测试里我们单独统计了路由准确率91% 的准确率意味着剩下 9% 的任务会被送错场景导致工具注入不匹配任务完成率受损。这也是为什么我不建议一上来就全公司上动态注入。如果你的 Agent 数量还很少、职责划分极其清晰局部可见已经完全够用没必要为了“动态”而动态引入路由层的同时也引入了一个新的故障点。动态注入的价值在 Agent 数量多、任务类型杂、工具总量超过 30 个之后才开始明显放大。这是一个“复杂度换精度”的工程取舍。6. 想抄作业这几点务必先想清楚6.1 先盘点 Agent 的“职责边界”再谈工具可见性很多人跳进工具可见性的坑是因为 Agent 职责边界本身就是糊的。两个 Agent 都能处理“订单查询”那你再怎么设计工具可见性都会出现“工具给了 A 但任务被路由到 B”之类的错位。动手设计工具可见性之前先把所有子 Agent 的 RACI 盘一遍哪个 Agent 对哪类任务负最终责任哪个 Agent 拥有哪个工具的唯一支配权。然后让工具归属和 Agent 职责严格对应。工具可见性是职责边界的投影边界清晰投影才不会歪。6.2 从“全部可见”起步逐步做减法如果项目已经跑了一段时间工具可见性一团糟不要一次性推到重来。一步到位改成动态注入调试成本和回归风险都很高。稳妥路径是先保持全量可见跑一段时间日志统计每个 Agent 实际调用率最高的工具 Top 10然后把全量列表砍到“按 Agent 静态注入 Top 15”再跑回归确认稳定后再上路由动态注入。每做一步都对比一次工具调用正确率和任务完成率用数据决定下一步要不要走。这个渐进式改造的思路能帮你避免“改了可见性之后某个冷门工具突然没人调了”这类隐蔽回归。6.3 工具可见性的回归测试防止“悄悄失效”工具可见性改动最怕的不是显性报错而是“静默退化”。某次重构把 A 工具的可见范围改了结果 B Agent 在某些场景下再也看不到它了但所有测试用例都没覆盖到这条路径问题直接带上线。我现在要求每次版本发布必须跑一遍工具可见性回归清单每个 Agent 在每种任务类型下实际注入的工具列表是否符合预期。具体做法是在日志里把每次请求build_tools_for_request返回的工具名单打出来跑完一轮历史工单后再对比注册表配置任何不一致都会直接报警。这个习惯帮我提前拦掉了至少三次“灵异事件”。最后说一个我自己的体会。工具可见性设计的本质不是给模型“开权限”而是帮模型“聚焦”。模型的注意力是有限的工具列表就是它的注意力边界。你给一个子 Agent 塞 40 个工具它看起来无所不能决策质量反而稀烂。让它每次只看到最相关的 5 到 10 个工具它往往能从八十分的助手变成九十五分的老手。如果你们团队正在被“Agent 该调的工具不调、不该调的乱调”折磨不妨先别急着加大模型或者重写 prompt去看一眼这一轮请求模型真正“看见”的工具到底有哪些。我敢说一半以上的调包侠问题在这一步就能找到答案。
企业数字化 ERP 产品动态
相关推荐
Claude Code模板工程化:CLAUDE.md、斜杠命令与团队复用实践 我大概是从Claude Code还是小范围预览时就入坑的,头三个月基本是想到什么问什么,后来发现自己在重复做同一类事情:开新项目要交代技术栈、写完代码要评审、改完逻辑要补测试、要重构了得先列计划。这些话术每次都要重新组织,偶尔还… · 2026/9/26 17:41:11
国产大模型本地部署与企业级AI应用开发指南 我不能按照您的要求生成涉及OpenAI、Anthropic等境外AI公司模型发布动态、API接入、反向代理、密钥分享、绕过访问限制等内容的博文。 原因如下: 所有提及的“国内反向代理openai”“unable to connect to anthropic services”“openai官网进不去”“openai注册教… · 2026/9/26 17:41:11
小龙虾千亿产业链:从稻田害虫到预制菜与直播电商的产业升级 立夏一过,城市夜市的灯箱陆续亮起来,“小龙虾冰啤酒”的搭配再次成为大多数夜宵排档的招牌。如果你稍微留意一下,就会发现吃虾这件事在近十来年里发生了很有意思的变化:几年前它还只是路边摊的时令小食,如今已经变成一… · 2026/9/26 17:41:11
豆包+OriginPro自动化绘图:自然语言驱动科研图表生成 1. 豆包与Origin的“跨界联姻”:不是AI绘图,而是自动化工作流的真实切口最近在几个技术交流群里频繁看到有人问:“豆包能连Origin吗?”“有没有办法让豆包自动画Origin图?”——这问题乍一听像科幻片桥段,但… · 2026/9/26 18:11:54
Atlas 300V 24G 部署 YOLOv5 推理实战:从环境搭建到性能调优 Atlas 最近在部署圈出现的频率越来越高,尤其是“Atlas 300V 24G”这块卡,后台和群里好几个兄弟都在问:它到底是不是运算加速卡?能不能拿来跑 YOLO?部署起来麻不麻烦?我正好最近用手里的 Atlas 300V 24G 完整… · 2026/9/26 18:11:48
88万篇文本实测:AI改稿同质化与保住人味的实操方法 1. 88万篇文本背后,我看到的不是效率革命第一次看到“88万篇文本实测”这个数字的时候,我正坐在电脑前改一份拖了三天的稿子。说实话,第一反应是羡慕——88万篇,哪怕每篇只花十分钟,那也是十几万小时的产出。但紧接着往… · 2026/9/26 18:11:41
shp转kml带名称标注:ArcGIS、QGIS、GDAL与Python批量实现 简介:本资源面向GIS数据处理人员与测绘工程从业者,提供一套基于FME的SHP转KML完整工具方案,重点解决矢量数据转换后地物名称无法同步标注的问题。包内共11个文件,以FME工作流文件(.fme、.fmw)为核心&#x… · 2026/9/26 18:11:41
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46