跳转到主要内容

工具接口是 Schema 问题:先有类型化参数,再谈聪明的提示词

大多数 agent 工具调用失败源于 schema 定义不充分,而非推理能力不足。把工具接口当作可靠性的首要杠杆。

Vibrant backlit buttons on an electronic music controller for audio production.

失败通常发生在边界上

当 agent 调用工具而出错时,本能反应是怪模型。提示词不够清晰、推理太浅、上下文太嘈杂。但在实践中,这类失败中有很大一部分在模型开始推理之前就已经注定了:问题出在工具 schema 上。schema 是模型与系统之间的契约。如果这份契约含糊不清,模型就会用看似合理的猜测去填补空白,而工具会照单执行。

本文主张,接口设计应当被视为 agent 系统可靠性的首要杠杆,优先于提示词工程。提示词以概率方式塑造行为,schema 则以结构方式强制行为。

工具调用究竟在哪里失败

有三种模式造成了不成比例的错误工具调用。

参数名含糊。 一个叫 target、value 或 options 的字段,会诱使模型从上下文中推断含义。模型产出一个语法上合法、语义上错误的参数。工具接受了它。错误在之后才浮现,往往表现为下游数据问题,而不是一次失败的调用。像 target_user_id 和 retention_days 这样的命名并不啰嗦,它们是在消除歧义。

可选字段却没有默认值。 如果 schema 把某个字段标为可选,但工具既没有默认值也没有 null 处理路径,模型就必须编造一个值来完成调用。它一定会编。编出来的值看起来合理,但错得很难被发现。可选性是关于工具行为的声明,不是给模型的提示。

自由文本参数。 没有结构的字符串参数把意图压缩成了散文。工具无法校验散文。模型也无法被散文纠正。一个接受 "send the report to the team tomorrow morning" 的字段,等于把调度逻辑塞进了模型脑子里,在那里它既不可检视也不可测试。

这些不是推理失败,而是以推理失败的形式呈现出来的规格失败。

工具 schema 的设计规则

Interior view of a warehouse in Dar es Salaam with a shrink film machine and industrial equipment.

工具 schema 应当以对待公开 API 的同等严谨度来对待,因为它本来就是。

每个参数都要有类型、有边界,并在边界处校验。 类型是必要的,但不充分。一个必须取自固定集合的字符串应当是 enum。一个必须落在某个范围内的数字应当携带该范围,边界应当在执行前拒绝范围外的值。在边界处校验意味着工具永远不会看到它无法处理的参数,而模型在产出这样的参数时会收到确定性的信号。

前置条件写在描述里,而不是从上下文假定。 如果某个工具要求某个资源存在,或要求先前的调用已成功,这应当写进描述。模型并不能可靠地从对话历史中推断前置条件,也不应该要求它这么做。一句写着“需要从 open_session 获取的有效 session id”的描述是规格。一句写着“做那件事”的描述是许愿。

错误以类型化代码返回,并附带修复提示。 当调用未通过校验时,响应应当是机器可读的:一个 agent 可以据此分支的代码,外加一条关于怎样才能满足契约的简短提示。堆栈跟踪和自由文本错误消息把解析工作又推回给了模型,而这恰恰是 schema 本应消除的工作。

一个具体的机制:两阶段调用路径。模型依据 schema 产出参数。校验器检查类型、边界、enum 和前置条件,返回一个规范化后的参数对象,或一个类型化的拒绝。只有规范化后的对象才会到达工具实现。工具实现于是可以假定其输入是良构的,这消除了执行路径中的防御性分支,并使失败可归因于两处之一:模型的参数,或工具的行为。

为什么提示词无法补偿

人们很容易想写一段更长的系统提示词来解释工具的怪癖。这不可扩展,原因有三。

指令遵循会随上下文长度和工具数量而退化。 随着可用工具增多,模型对任何单条指令的注意力都会变薄。在长提示词中只陈述一次的规则,要与窗口中的其他一切竞争。而 schema 在每次调用时都被强制执行,无论存在多少工具。

schema 是被强制执行的,提示词是被遵守的。 这是核心的不对称性。校验确定性地运行。提示词遵循是一个随措辞、顺序和上下文而变的概率。当可靠性重要时,应当投资于那个每次都运行的机制。

schema 变更是可审查的产物。 对工具 schema 的 diff 就是对契约的 diff。它可以被审查、版本化、测试和回滚。

Detailed view of a retro arcade machine control panel with colorful buttons and joystick.

诚实的权衡:更严格的 schema 会牺牲灵活性。一个严格类型化的工具无法吸收一个规格松散的请求,一些合法的用例会在边界处被拒绝,而不是被优雅地处理。替代方案是一个接受一切、却以不可预测的方式失败的工具。对大多数生产系统而言,一次类型化的拒绝比一个静默的错误结果更便宜。在确实需要灵活性的地方,应当显式地建模,例如建模为类型化请求变体的可辨识联合,而不是一个无类型的字符串。

迁移与版本化

工具就是 API。它们需要弃用窗口、版本化命名,以及一段新旧 schema 都能解析的时期。一个通过描述习得了工具形态的 agent 不会瞬间适应破坏性变更,围绕它构建的评估也不会。

有两个指标应当与延迟和成本一起,进入一等公民的仪表盘:

  • 单工具调用成功率。 按工具细分,而不是聚合。系统级的成功率会掩盖那个正在失败的工具。
  • 参数拒绝率。 执行前被校验器拒绝的调用比例。拒绝率上升是一个早期信号,说明某个 schema 含糊、某个描述有误导,或者模型被要求给出一个它不可能知道的值。

这两个指标把 schema 问题与推理问题区分开来。一个拒绝率高、且拒绝代码清晰的工具,是在告诉你它的契约不清楚。一个调用成功率高、但之后产生错误结果的工具,是在告诉你它的校验过于宽松。这两种信号在提示词里都看不见。

这在实践中改变了什么

把工具接口当作 schema 问题,会改变工程投入的方向。schema 设计成为一项可审查的活动,有自己的测试。描述成为带有前置条件和后置条件的规格。错误成为接口的一部分,而不是事后补丁。提示词仍然重要,但它们在做自己擅长的事:塑造语气、策略和分解。它们不再承担强制执行契约的重担。

更宏观的一点是,agent 的可靠性主要是一种接口纪律。一个面对含糊接口也能推理得很好的模型,仍然会产出含糊的调用。一个面对精确接口推理得还算够用的模型,会产出可被检查、拒绝和纠正的调用。第二种系统才是可以被运维的系统。

封面照片:Jakub Pabis / Pexels。

分享XLinkedIn永久链接6 分钟阅读

相关阅读

这能回答的问题

Why do agent tool calls fail even when the model reasons correctly?

Because the failure is often at the schema boundary, not in reasoning. Ambiguous parameter names, optional fields with no default, and free-text arguments all let the model produce plausible but wrong arguments that the tool accepts. The schema, not the prompt, decides whether those arguments can be validated.

Can a longer system prompt fix an unclear tool schema?

Not reliably. Instruction following degrades as context length and tool count grow, and prompt adherence is probabilistic. A schema is enforced on every call regardless of context, which makes it the more dependable place to encode the contract.

What metrics should track tool schema health?

Per-tool call success rate and argument-rejection rate, both broken down by tool rather than aggregated. A rising rejection rate points to an ambiguous schema or misleading description; a high success rate on calls that later produce wrong results points to validation that is too permissive.

How should tool schemas be versioned?

Like any API. Use versioned names, deprecation windows, and a period where old and new schemas both resolve, so agents and the evaluations built around them can migrate without breaking.