模式矩阵 /模式白皮书/A1

ADPS Agent 设计模式白皮书

A1 · Tool Dispatch · 工具调度

Agent 在每一步行动前,由工程层依据工具元数据从工具集中挑出最合适的工具,而不是让模型自己临场决定。

版本
v0.3
状态
公开评审稿
发布日期
2026-07-13
分类
行动 Action × 路由 Route(选)
目录地位
核心模式
许可
CC BY 4.0

文档状态:本页为公开评审稿。模式定义与分类可供讨论和引用;未附来源链接的数字与应用示例只用于说明机制,不作为行业基准。

坐标 行动 Action × 路由 Route(选)
成本 低(与单次调用同量级,元数据开销可忽略)
模式组 行动模式
模式简介 Agent 在每一步行动前,由工程层依据工具元数据从工具集中挑出最合适的工具,而不是让模型自己临场决定。

问题

工具一多,agent 选错工具的概率就上来了。这里有一个反直觉的事实:LLM 擅长用工具(填参数、解读返回值),但不擅长选工具。一个接了 17 个工具的物流派单 agent,曾经把 80 单全部派给同一个堵在路上的司机——它每一步都"觉得"自己选对了,错误藏在"没刷新司机状态"和"没看路况"这些它注意不到的细节里。

Tool Dispatch 把"选哪个工具"这件事从模型手里收回到工程层。它的核心判断是:选工具是可靠性工程。靠的不是写一段更聪明的提示,而是给每个工具补足元数据,再配上配额、状态刷新、副作用追踪这一整套工程契约。

分类依据:行动 × 路由

  • 纵轴 · 行动:agent 要把决策变成对外影响,靠的就是工具调用。多工具场景下"调哪个"是行动端最前置、也最高频的决策,所以它属于行动模块而非推理模块。
  • 横轴 · 路由:它的工作方式是基于当前 intent 和 context,把这一次调用导向最合适的那个工具,是典型的路由结构,而不是链式串联或层级包装。同模块的最简工具集(A5)也落在路由这一侧,但分工不同——A1 解决"怎么挑",A5 解决"挑之前先砍"。

解决方案与机制

工业级 Tool Dispatch 的质量,主要由工具元数据的丰富度决定。OpenAI 早期 function calling 只有 name、description、parameters 三个字段,够 demo 用。Claude Code 的工具 schema 扩到了 14 个字段,按用途大致分成八类:标识、动态描述、双 schema、执行特性、UI 行为、来源标记、渐进披露、生命周期。

其中最关键的是执行特性五字段:isReadOnlyisConcurrencySafeisDestructiverequiresFreshStaterequiresApproval。它们的工程哲学是默认全部为 false,也就是"不知道就当不安全"——工具实现者忘了声明,系统也会保守处理,只有显式声明只读才进并行通道、跳过确认弹窗。每一个字段都对应一条资深工程师的工具操作直觉,把人靠多年经验积累的判断编码成机器可读的契约。

围绕元数据,还要配三件工程纪律:

机制 作用
Quota 配额 单 session 内同一工具(或同一参数)调用次数封顶,挡住"80 单派一个司机"这类副作用累积
State refresh 强制 写操作前必须先查询刷新状态,避免基于过期数据做写入
Saga 副作用追踪 每个 destructive 工具登记 inverse 动作,失败时反向回滚

适用条件

  • 工具数量多、副作用多、错调代价大三者叠加:物流派单、客服工单、运维操作。
  • 接入 MCP 等外部工具协议:外部工具来源不可信,必须靠元数据里的来源标记加额外安全审查。
  • 固定流程任务:可以更进一步走 Programmatic Tool Calling,由工程层显式编排调用序列,模型只负责填参数和解读结果,减少来回、容错更强、审计更清晰。

已知失效方式

  • 元数据太薄:只有 name 加 description,agent 凭一句话选工具,相当于让实习生凭一行 job description 上手。这是错调的首要根因。
  • 副作用工具没配套:写数据库、发消息、扣款这类工具没有 quota、没有 state refresh、没有 saga,一次错调就是生产事故。
  • 工具堆砌(Tool Stuffing):50 多个工具全发给模型,schema 吃掉大段 context,准确率不升反降。应对是渐进披露——核心工具常驻,其余按需检索加载。
  • 工具中毒(Tool Poisoning):这是 OWASP Agentic 头号威胁,攻击者在 MCP 工具的 description 里嵌入隐藏指令,所有用这个工具的 session 都中招,持久且范围广。它不是普通 prompt injection,必须靠白名单、描述扫描、描述沙箱、行为监控、最小权限这五层防护,缺一层都是开放的攻击面。

验证指标

  • 工具选择准确率(健康区 >90%):回放历史 query,用 reviewer 模型判断每步选对没。低于 80% 多半是 description 不够好或工具太多。
  • 副作用可控率(健康区 100%):定期做 chaos test,故意让模型错调某个 destructive 工具,看能否在一分钟内被 quota 拦下并被 saga 回滚干净。任何错调都该能 rollback。
  • 工具幻觉率(健康区 <5%):调用不存在的工具或填错参数的比例。靠 registry 严格校验加调用前 schema 检查压制。
  • 平均每任务工具数(健康区 3-7):少了说明 agent 没干活,多了是 over-tooling。

参考实现

dispatch(tool_name, args, session):
    工具不存在        → 拒绝(tool_hallucination)
    配额已用满        → 拒绝(quota_exceeded)
    需新鲜状态但已过期 → 拒绝(stale_state_must_refresh)
    需人工审批        → 挂起(awaiting_approval)
    执行 handler:
        成功且 destructive → 登记 saga inverse + 累加 quota + 刷新 state 时间戳
        失败              → 记 trace,交由上层 saga 回滚
    返回 DispatchTrace(工具/参数/触发方/状态/拒因/耗时)

工程落地要点:元数据默认按不安全处理;quota 按主参数计(如派单按司机 id 计);MCP 工具加来源标记走额外的描述校验和行为监控。

应用示例

梁博团队的执行型 agent 把工具、技能、知识库分成三种角色:工具是"手",技能是"套路",知识库是"地图加手册"。agent 通过 retrieve 看地图、use_skill 读套路、call_tool 出手——出手前先看图读套路,正是 Tool Dispatch 在工程层做选择的体现。落到那个城配派单 agent 上,团队重写 dispatch 层时加了五件事:工具元数据扩展、selection guidance、写操作前强制状态刷新、单 session 内同一司机派单配额、saga 副作用追踪。准确率从 60% 升到 96%,代价是 dispatch 层多了约 800 行代码。多出来的每一行,本质都是把工程师踩过的坑固化成了机器执行的规则。

相关模式

  • 最简工具集(A5):同格互补。A1 在给定工具集里挑得准,A5 先把工具集砍到合理规模让 A1 挑得动。
  • 规划-执行(A2):A1 是单步决策的优化,A2 是多步任务的整体编排。Programmatic Tool Calling 是两者的交汇——工程层定调用序列,每步内部仍是一次 dispatch。
  • 护栏三明治(A4):A4 在 dispatch 的前后套 pre-check 和 post-check,与 A1 的 quota、state refresh 是嵌套关系——A1 选对工具,A4 保证选错时也兜得住。
  • 复杂度路由(R2):思路同源,都是基于 context 做路由,区别在 R2 路由的是推理档位,A1 路由的是工具。

设计结论

Tool Dispatch 的本质不是"写一段挑工具的提示",而是把工程师群体多年积累的工具操作纪律,编码成元数据和工程契约交给 agent 用——demo 级 agent 的工具元数据是 3 字段,生产级是 14 字段,这道字段差就是玩具和系统之间的距离。

企业证据

以下现场记录说明该模式在具体业务约束下如何实现。案例结论只在文中声明的系统边界内成立。

案例收录要求说明业务约束、实现结构、已知失败和迁移边界。参见 贡献与评审规则

引用建议:ADPS,《A1 工具调度》,Agent 设计模式白皮书 v0.3,2026-07-13。

模式目录 · 参考实现 · CC BY 4.0