工具契约:输入、结果与错误语义
在能力路由之后补齐工具接口工程,用输入、结果、错误、权限和幂等契约,让执行层保留真实业务语义。
最近修订:2026.09.07
阅读导航 · 第 1 / 4 篇
能力路由架构解决了从大量能力中寻找可执行方案的问题。以资料核验为例,目标是为指定资料创建一张核验工单。选中 create_review_ticket 之后,系统仍然需要回答:参数从哪里来,出错能否重试,返回的编号是否可以查证?
工具的名称、参数和文字说明是模型看到的接口;服务端的校验、授权、去重和查询能力决定真实行为。两边需要表达同一份契约。
一个工具应围绕明确的业务动作
比较两个名称:operate(data) 和 create_review_ticket(source_id, title)。前者把意图、数据类型和读写边界都藏起来;后者至少说明会创建什么资源、需要哪些输入。
不过,拆得越细也未必越好。如果一个查询需要连续读取三种内部表才能返回有意义的结果,可以在服务端组合为一次业务查询。关键是组合后仍能说明权限、部分失败和副作用,而不是机械地把每个底层 API 暴露给模型。
Anthropic 的工具设计指南强调清楚的功能边界、高信号返回内容和可行动的错误提示。这些原则应通过真实任务评测验证,不能只凭工具描述读起来是否顺畅。官方指南
输入分成候选参数与可信执行上下文
下面是这里推荐的逻辑分工,不是 MCP 标准字段:
| 输入 | 来源 | 校验位置 |
|---|---|---|
| 资料编号、标题 | 模型候选或用户输入 | Schema、资源存在性与业务规则 |
| 用户、团队身份 | 已认证的服务端上下文 | 授权层 |
| 操作键 | 持久运行控制 | 去重服务 |
| 审批依据 | 可信审批记录 | 执行前策略检查 |
| 当前策略版本 | 策略服务 | 恢复和派发边界 |
Schema 能拒绝缺失字段或类型错误,却不能证明用户有权操作这份资料。即使模型填入了合法的团队编号,也不能用它替代服务端确定的身份作用域。
资料正文也不应直接成为工具指令。正文可能包含链接、代码或命令,这些内容需要继续按数据处理;是否调用相应能力由任务与策略共同决定。
结果必须让下一步可判断
下面的 JSON 是建议的业务结果封装,并非 MCP 原生响应格式:
{
"status": "succeeded",
"operation_id": "review-001:ticket",
"resource_id": "ticket-42",
"source_id": "source-001",
"deduplicated": false,
"next_action": "read_and_verify"
}
模型需要高信号信息,运行时还需要稳定编号与状态。本例返回的 succeeded 仅表示创建接口成功,后续仍要查询 ticket-42,与原任务的资料编号和标题要求比较。
对于大结果,返回是否截断、下一页游标、总量口径和原文引用。只保留“最相关的十条”却不说明省略,会让模型把局部结果当全集,进而对“不存在”作出错误判断。
错误类型决定恢复策略
| 错误 | 推荐处理 | 不应发生的行为 |
|---|---|---|
| 参数错误 | 返回具体字段与修正线索 | 原样反复调用 |
| 无权访问 | 拒绝并说明授权缺口 | 自动换高权限凭证 |
| 限流或暂时不可用 | 按服务契约限次退避 | 多层无限叠加重试 |
| 同键不同参数 | 拒绝并核对原操作 | 静默复用旧结果 |
| 请求超时、效果未知 | 按操作键查询或对账 | 换新键再创建 |
| 工具成功、业务验收失败 | 保留实际资源并进入修复决策 | 报告任务成功 |
“可重试”不是一个脱离操作语义的布尔值。只读查询和创建工单,即使遇到相同网络错误,也应采用不同策略。重试还应有一个明确负责的层,避免网关重试三次、SDK 再重试三次、Agent 又重试三轮。
开源实现怎样保留执行事实
Kimi Code 的批次适配器按调用编号把结果交还给等待者。源码模块实验中,执行器只返回两个调用中的一个,适配层给另一项返回明确的缺失结果错误。这能结束本地等待,却不能证明对应外部操作没有发生。调用编号首先用于消息配对;若没有额外协议,它不是业务服务的幂等键。
OpenCode 的工具处理器记录 pending、running、completed 和 error,并保留失败前的进度元数据。取消信号发出后,工具仍可能赶在清理前返回可记录的结果;未能收尾的调用随后被标记中断。这里至少有三个不同时间点:提出取消、工具返回、本地状态收尾。它们不一定同时发生,外部写入更不必跟随本地取消回滚。
因此工具契约需要分别回答:调用是否被派发、是否收到了结果、业务效果是否已确认。对于只读任务,重新读取通常容易处理;对于创建工单,结果未知时应查询原操作,不能因为本地返回 error 就再次创建。实验及版本边界见两篇项目文章,完整外部写入恢复尚未实测。
MCP、CLI 与代码执行保留各自边界
MCP 可以标准化工具发现与调用方式,但业务幂等、审批是否匹配当前动作、外部结果如何验收,仍然需要具体实现。工具的只读或破坏性提示也不等于执行层强制权限。
CLI 适合已有命令和本地环境;直接 API 适合精确业务接口;代码执行适合在一次程序中组合计算。选择哪条路径,应核对身份如何传递、参数怎样校验、输出如何解析,以及失败后是否保留足够证据。已有执行语义篇可以作为路线比较入口。
一张工具契约卡
为每个可写工具记录六件事:业务动作、可信身份、候选参数、结果结构、错误分类、幂等与对账机制。再准备三个反例:缺参数、无权限、写入后丢响应。
如果工具说明只写了“创建核验工单”,这张卡会暴露尚未被表达的工程责任。它也为后续协议适配提供稳定对象:更换 MCP 或 API 客户端时,保留业务契约,再验证传输差异。