已经是最新一篇文章了!
已经是最后一篇文章了!

agent runtime lab · 2026 · 技术研究笔记

04. 工具 Schema 怎样改变 Agent 的行为

模型不是直接操作系统,它只能从运行时提供的动作接口中选择

从工具名称、描述、参数约束和返回契约分析模型如何选择动作,以及为什么工具定义也是上下文的一部分

研究版 · 12 个章节 · 约 14 分钟 · 更新于 2026-07-27

版本 A · 中文 B · English
SCROLL

同一个只读任务,Codex 生成了一条复合 Shell 命令,Kimi 生成了两个并行 Bash 调用。这不能只解释为模型风格差异,因为模型看到的工具接口并不相同。

工具 Schema是工具名称、用途说明、参数类型、必填字段和取值范围组成的结构化契约。模型根据这份契约选择工具并生成参数,执行器再按同一契约校验输入。

工具定义同时影响能力与决策

Schema 部分对模型的影响对执行器的影响
名称建立动作概念映射到处理函数
描述判断何时使用不应作为权限依据
参数生成调用结构检查类型与范围
必填项避免缺失信息拒绝不完整调用
枚举与边界缩小选择空间阻止越界值
返回契约预期可获得的信息形成统一结果

若工具叫 run_anything,参数只有一个任意字符串,模型需要自行构造命令,执行器也很难在执行前判断影响。若拆成 read_file(path)list_directory(path, limit),动作意图在参数层就已经可见。

描述不是越长越好

描述要回答三个问题:工具做什么、什么时候使用、什么情况不能使用。过短会让相近工具难以区分;过长会增加每轮固定上下文,并把权限规则分散到自然语言中。

一个用于目录读取的接口至少应说明:

  • 只返回一层还是递归。
  • 是否包含隐藏文件。
  • 最大返回数量。
  • 路径必须位于哪个根目录。
  • 符号链接怎样处理。

其中最后两项不能只写在描述里。路径根目录和链接策略还要由执行器校验。

参数校验要发生两次

模型生成参数后,运行时先做结构校验,再做策略校验。

阶段检查内容失败示例
结构校验类型、必填项、格式limit 是字符串
策略校验权限、路径、配额路径逃出工作区

结构正确不等于操作被授权。{"path":"/etc/passwd"} 可能符合字符串类型,却不符合工作区读取策略。

我会怎样验证 Schema 的影响

保持模型、任务和文件目录不变,只修改工具定义:

组别变化
Aread_filelist_directory 分开
B合并成通用 filesystem 工具
C删除描述中的适用场景
Dlimit 增加 1 到 5 的范围

每组运行 30 次,记录工具选择正确率、参数校验失败率、模型轮次和输入 Token。单次轨迹只能展示机制,重复样本才能比较 Schema 是否稳定地改变行为。

工具返回也需要契约

返回值若只是一段文本,模型和日志系统无法可靠区分成功、空结果、截断和失败。至少要保留状态、耗时、错误类型、是否截断和结果正文。

Kimi 抓包中的两条工具消息使用 tool_call_id 对应 Bash_0Bash_1。这个标识让并行结果能够回到正确调用。工具名称告诉运行时调用谁,调用标识告诉运行时结果属于哪一次动作。

工具 Schema 因此不是 API 文档的附属内容。它是 Agent 的动作空间,也是权限检查和轨迹重放的入口。

Schema 版本必须进入轨迹

工具名称没有变化,不代表契约没有变化。新增必填字段、收紧枚举范围或修改路径解释方式,都可能让同一模型输出得到不同执行结果。每条 tool.requested 事件应记录 Schema 版本,失败日志也要指出调用按哪个版本校验。

兼容性测试至少覆盖三种变化:新增可选字段应继续接受旧调用;新增必填字段应产生明确的结构错误;收紧策略范围应产生权限或策略错误,而不是伪装成工具执行失败。

用负例检查描述与边界

正例只能证明模型在一个清晰任务中会使用工具。负例还要检查它是否在不该调用时保持不调用,例如用户只询问概念、路径位于工作区之外、limit 超过上限或任务要求递归而工具只支持一层。

评测结果应分开记录工具选择错误、参数结构错误和策略拒绝。三类错误分别对应描述、Schema 和权限配置,合并为一个“工具失败率”无法指导修改。

Schema 实际上在改变模型的动作空间

模型生成普通文本时,下一个 Token 可以来自整个词表;生成严格工具调用时,运行时或服务端可以用 JSON Schema 把合法输出限制在较小集合。这里的动作空间是模型在当前状态下能够表达的所有候选操作。

Schema 同时产生三种约束:

约束例子能排除什么
语法约束输出必须是 JSON 对象缺括号、混入说明文字
类型约束limit 必须是整数"five"
业务约束limit 取值为 1 至 5100000

即使服务端提供严格结构化输出,Schema 也不能证明参数语义正确。{"path":"README.md","limit":5} 可以通过全部结构检查,却仍可能选择了错误文件。结构正确率与任务正确率必须分开统计。

工具名称和描述还会改变模型对动作的可辨识程度。两个工具都叫“search”,但一个查询本地代码、另一个访问互联网,模型需要从较长描述中推断差异;若名称直接表达作用域,选择所需的语义推断更少。这个影响不是执行器的类型系统能够修复的。

工具粒度存在两种相反成本

把文件操作拆成 read_filelist_directorysearch_text,每次调用的意图清晰,权限也容易匹配;拆成数百个相近工具后,工具定义会占用更多上下文,模型还要在相近名称之间选择。

反过来,一个通用 Shell 工具只需要很短的 Schema,却把路径解析、引号、管道、副作用和错误处理全部交给模型。工具越通用,执行前越难判断真实影响。

因此工具粒度不是越细越好,而是在三项成本之间取平衡:

总成本 = 工具选择成本 + 参数构造成本 + 执行风险

工具过细会提高选择成本,工具过粗会提高参数构造成本和执行风险。合适的边界通常对应一个可以独立授权、独立重试并返回明确结果的业务动作。

Anthropic 当前工具文档把这层关系称为模型与应用之间的契约:模型只产生结构化请求,真正执行发生在客户端或服务端工具中。Anthropic:How tool use works MCP 的工具规范则要求每个工具具有名称、描述、输入 Schema,并可提供输出 Schema;客户端仍要在调用前验证结果来自哪个服务器以及是否获得授权。MCP Tools specification

Schema 消融实验怎样排除模型波动

前面的 A 至 D 四组每组运行 30 次,还需要随机化运行顺序。若先运行完 A 再运行 B,服务端版本、缓存状态或限流变化可能与 Schema 变化重合。更稳妥的顺序是每轮随机选择 A、B、C、D,并把模型版本、温度、任务和目录快照写入轨迹。

每次结果按四层判定:

  1. 是否选择了完成任务所需的工具。
  2. 是否生成结构有效的参数。
  3. 参数是否引用正确资源并表达正确语义。
  4. 执行后是否得到任务需要的证据。

一个结果可能在第二层通过、第三层失败。比如模型正确调用 read_file,参数也符合 Schema,却读取了相邻文件。若只统计工具调用解析成功率,这类错误会被计为成功。

还应加入无工具基线:允许模型直接回答相同问题,但不给文件工具。若模型凭已有知识猜测目录内容,最终文字可能偶然正确;文件系统快照可以证明它没有取得当前证据。这个对照用于区分“选择了正确答案”和“执行了能够支持答案的动作”。

动态加载工具改变了实验变量

当工具数量达到数十个时,一次性发送全部 Schema 会占用固定上下文。当前 Anthropic 文档建议在大型工具集里使用 Tool Search:模型先搜索工具目录,再把命中的定义追加到轨迹。这样降低了初始上下文,却增加一次发现步骤,并使“模型当时看见哪些工具”成为轨迹的一部分。Anthropic:Manage tool context

动态加载后的评测要区分两个失败:

失败阶段现象可能原因
工具发现没有加载所需工具索引、名称或发现描述不清
工具使用已加载但调用错误参数 Schema 或任务理解有误

如果日志只保存最终工具列表,就无法判断模型一开始没有工具,还是看见工具后没有选择。可重放轨迹需要保存工具目录版本、搜索查询、命中结果和实际加载的 Schema 版本。

Schema 不能承载全部安全语义

JSON Schema 适合表达类型、枚举、格式和局部条件,不适合独自回答“当前用户能否读取这个路径”或“这个目标域名是否允许接收这类数据”。后两项依赖会话身份、资源状态和数据来源,属于运行时策略。

最终可以把工具调用看成三份契约叠加:

契约负责的问题
模型契约应当在什么任务中选择这个工具
数据契约参数与结果采用什么结构
授权契约当前主体在当前条件下是否可以执行

只完善其中一份,仍然会留下不同类型的失败。工具设计的目标不是让 Schema 描述所有规则,而是让三份契约在日志里能够分别验证。

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:04. 工具 Schema 怎样改变 Agent 的行为

本文链接:https://www.sshipanoo.com/blog/ai/agent-runtime-lab/04-工具Schema怎样改变行为/