加载中

严格工具使用:停止拒绝自己的调用

第 2 课10 分钟
加载中

严格工具使用:停止拒绝自己的调用

摘要文字记录

当您的后端拒绝了 Claude 自己生成的工具调用时,严格工具使用就是解决方案。视频中在 Meridian(一家虚构的工程咨询公司)为一个工具启用了该功能,并在启用前后各运行了相同的 100 个请求。

本视频中的演示录制于 2026 年 9 月。它在 Claude Haiku 4.5(claude-haiku-4-5)上运行。在较新的模型上结果可能有所不同。

Claude 通常会遵循工具的 input_schema,但默认情况下没有任何机制强制执行这一点。因此,有时您的后端会拒绝 Claude 发出的工具调用,因为该调用的输入存在以下情况之一:

  • 字符串 "2" 而不是整数 2
  • 缺少必填字段

严格工具使用可以解决这个问题。只需一个标志 strict: true,就能让 Claude 写入的输入与您的模式(schema)匹配。

在 Meridian,一个助手使用 queue_stamp_request 工具为持证工程师的图章排队处理图纸集。Meridian 的验证器是检查每个工具调用的代码。在关闭严格模式的情况下,它会拒绝 100 个请求中的 79 个。在开启严格模式且模式(schema)是从验证器生成的情况下,它不会拒绝任何请求。

严格工具使用的工作原理

当设置 strict: true 时,API 首先会将您的 JSON Schema 编译成一个语法(grammar)。语法是一组规则,规定了在输入的每一点上接下来可以出现哪些令牌(token)。 然后,每当 Claude 选取工具调用的下一个令牌时,它只能选取该语法所允许的令牌。这被称为语法约束采样(grammar-constrained sampling)。

schema 规定 revision 是整数,Claude 已写到 "revision":。不启用 strict 时,下一个 token 有五种可选:3、"3"、three、3.0 和 null。使用 strict: true 时,只能选 3,其余四个都被划掉。

在设置 strict: true 时,只能选取您的模式(schema)所允许的令牌,因此整数字段只能得到一个整数。

这是 Meridian 的工具定义,经过精简。严格模式需要其中两行:该标志,以及该标志所要求的一项设置。

json
{
  "name": "queue_stamp_request",
  "description": "Queues a drawing set for a professional engineer's stamp.",
  "strict": true,
  "input_schema": {
    "type": "object",
    "properties": {
      "drawing_set_id": {"type": "string"},
      "revision": {"type": "integer"}
    },
    "required": ["drawing_set_id", "revision"],
    "additionalProperties": false
  }
}
  • "strict": true 是该标志。它位于顶层,与 name、description 和 input_schema 并列,在模式(schema)之外。
  • "additionalProperties": false 是该设置。它意味着输入不能携带模式(schema)未指明的字段,而严格模式要求每个对象上都必须有这一设置。

从您的验证器构建模式(schema)

严格工具使用会让 Claude 写入的输入与您的模式(schema)匹配,因此模式(schema)必须与您的验证器所说的一致。当您手写模式(schema)时,两者会逐渐产生分歧。这样一来,一个工具调用可能与模式(schema)匹配,却仍然被拒绝。 在 Meridian,一份手写的模式(schema)将执照编号定义为不带任何模式(pattern)限制的普通字符串。因此 "PE 46196" 通过了模式(schema)检验,却未通过验证器检验,而验证器要求的格式是 PE- 加五位数字。

只在您的验证器中编写一次规则,再由它生成模式(schema)。在 Python 中,验证器通常是一个 Pydantic 类。在 TypeScript 中,通常使用 Zod 编写。

下面是 Meridian 的 Pydantic 类 StampRequest,以及使用它的代码,再之后是 StampRequest.model_json_schema() 返回的模式(schema)。每个 # ... 代表未展示的代码,该模式(schema)仅展示了执照编号部分。

python
class StampRequest(BaseModel):
    model_config = {"extra": "forbid"}
    # ...
    pe_license_number: str | None = Field(pattern=r"^PE-\d{5}$")
    # ...
stamp_tool = {
    # ...
    "input_schema": StampRequest.model_json_schema(),
    "strict": True,
}
stamp_request = StampRequest.model_validate(call.input)
json
{
  "additionalProperties": false,
  "properties": {
    "pe_license_number": {
      "anyOf": [
        {"pattern": "^PE-\\d{5}$", "type": "string"},
        {"type": "null"}
      ],
      "title": "Pe License Number"
    }
  }
}
  • "extra": "forbid" 会变成 "additionalProperties": false,即严格模式所要求的设置。
  • str | None 会变成 anyOf,因此执照编号是一个带有该 pattern 的字符串,或为 null。
  • model_validate() 会用同一个类来检查 call.input,即 Claude 写入的输入。

比较关闭和开启严格模式的运行结果

Meridian 的测试向 Claude Haiku 4.5 发送 100 个使用 queue_stamp_request 工具的日常语言图章请求,并由 StampRequest 验证每一次工具调用。同样的 100 个请求运行两次:第一次使用手写模式(schema)且关闭严格模式,第二次使用生成的模式(schema)且开启严格模式。

请在下方重放这两次运行。

加载中

模式(schema)中的 pattern 规定了允许的格式,而严格模式会让 Claude 遵守它。

严格模式控制的是输入的结构,但无法补充请求中从未给出的事实。在这 100 个请求中,有 28 个从未提到执照信息。生成的模式(schema)允许执照编号为 null,而这 28 个请求返回的结果也确实全部是 null。

严格工具使用的局限性

截至 2026 年 10 月,有六点需要了解:

  1. 请勿包含受保护的健康信息(PHI)。 编译后的模式(schema)不具备与提示和响应相同的 PHI 保护措施,因此请不要在属性名、enum 值、const 值和 pattern 表达式中包含 PHI。
  2. 不支持边界限制。 如果请求的模式(schema)中使用了 minimum、maximum、minLength 或 maxLength,将返回 400 错误。请改用验证函数(例如 Pydantic 的 @field_validator)来检查边界,并在字段的描述中说明这些边界。
  3. 限制会在各工具之间累加。 一个请求最多可以包含 20 个严格工具。在这些工具之间,最多可以包含 24 个可选参数。它还最多可以包含 16 个使用 anyOf 或类型数组的参数,而像 str | None 这样的可空字段正是生成此类参数的方式。
  4. 输入仍可能无法匹配模式(schema)。 这种情况会发生在拒绝回答之后、响应因达到 max_tokens 而被截断时,或者当 enum 或 const 字符串以不同大小写形式返回时。
  5. 部分模型会拒绝强制工具调用。 将 tool_choice 设置为 any 或 tool 会强制进行工具调用。这会在 Claude Opus 5.5、Claude Sonnet 5.5、Claude Fable 5.1 和 Claude Mythos 5.1 上返回 400 错误。在这些模型上,请将 tool_choice 保留为其默认值 auto。
  6. 程序化工具调用无法使用严格工具。 在程序化工具调用中,Claude 编写调用您工具的代码。第 8 课将对此进行讲解。

关键要点

  • strict: true 会让工具输入与您的模式(schema)匹配,但在拒绝回答、响应被截断,或 enum/const 字符串大小写发生变化等情况下除外。
  • 从您的验证器(例如 Pydantic 类)生成模式(schema)。
  • 不要在模式(schema)中设置边界限制,并在整个请求范围内统计工具数量、可选参数数量和可空参数数量。