严格工具使用

通过语法约束采样强制 Claude 的工具输入符合 JSON Schema。


在工具定义上设置 strict: true 可以保证 Claude 的工具输入与你的 JSON Schema 匹配,方法是将模型的 token 采样约束为 schema 有效输出(一种称为语法约束采样的技术)。本页介绍严格模式对 agent 的重要性、如何启用它以及常见用例。有关支持的 JSON Schema 子集,请参阅 JSON Schema 限制。有关非严格 schema 指导,请参阅定义工具

严格工具使用验证工具参数,确保 Claude 使用正确类型的参数调用你的函数。在以下情况下使用严格工具使用:

  • 验证工具参数
  • 构建 agentic 工作流
  • 确保类型安全的函数调用
  • 处理具有嵌套属性的复杂工具

为什么严格工具使用对 agent 很重要

构建可靠的 agentic 系统需要保证 schema 一致性。没有严格模式,Claude 可能返回不兼容的类型("2" 而不是 2)或缺少必需字段,破坏你的函数并导致运行时错误。

严格工具使用保证类型安全的参数:

  • 函数每次都接收正确类型的参数
  • 无需验证和重试工具调用
  • 生产就绪的 agent 在大规模下一致工作

例如,假设一个预订系统需要 passengers: int。没有严格模式,Claude 可能提供 passengers: "two"passengers: "2"。使用 strict: true,响应始终包含 passengers: 2

快速开始

curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-opus-4-7",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "What is the weather in San Francisco?"}
    ],
    "tools": [{
      "name": "get_weather",
      "description": "Get the current weather in a given location",
      "strict": true,
      "input_schema": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "The city and state, e.g. San Francisco, CA"
          },
          "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"]
          }
        },
        "required": ["location"],
        "additionalProperties": false
      }
    }]
  }'
ant messages create --transform content <<'YAML'
model: claude-opus-4-7
max_tokens: 1024
messages:
  - role: user
    content: What is the weather in San Francisco?
tools:
  - name: get_weather
    description: Get the current weather in a given location
    strict: true
    input_schema:
      type: object
      properties:
        location:
          type: string
          description: The city and state, e.g. San Francisco, CA
        unit:
          type: string
          enum: [celsius, fahrenheit]
      required: [location]
      additionalProperties: false
YAML
import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
    tools=[
        {
            "name": "get_weather",
            "description": "Get the current weather in a given location",
            "strict": True,  # 启用严格模式
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The unit of temperature, either 'celsius' or 'fahrenheit'",
                    },
                },
                "required": ["location"],
                "additionalProperties": False,
            },
        }
    ],
)
print(response.content)
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY
});

const response = await client.messages.create({
  model: "claude-opus-4-7",
  max_tokens: 1024,
  messages: [
    {
      role: "user",
      content: "What's the weather like in San Francisco?"
    }
  ],
  tools: [
    {
      name: "get_weather",
      description: "Get the current weather in a given location",
      strict: true, // 启用严格模式
      input_schema: {
        type: "object",
        properties: {
          location: {
            type: "string",
            description: "The city and state, e.g. San Francisco, CA"
          },
          unit: {
            type: "string",
            enum: ["celsius", "fahrenheit"]
          }
        },
        required: ["location"],
        additionalProperties: false
      }
    }
  ]
});
console.log(response.content);
using System.Text.Json;
using Anthropic;
using Anthropic.Models.Messages;

AnthropicClient client = new();

var parameters = new MessageCreateParams
{
    Model = Model.ClaudeOpus4_7,
    MaxTokens = 1024,
    Messages = [new() { Role = Role.User, Content = "What's the weather like in San Francisco?" }],
    Tools = [
        new ToolUnion(new Tool()
        {
            Name = "get_weather",
            Description = "Get the current weather in a given location",
            Strict = true,
            InputSchema = new InputSchema(new Dictionary<string, JsonElement>
            {
                ["properties"] = JsonSerializer.SerializeToElement(new Dictionary<string, object>
                {
                    ["location"] = new { type = "string", description = "The city and state, e.g. San Francisco, CA" },
                    ["unit"] = new { type = "string", @enum = new[] { "celsius", "fahrenheit" } },
                }),
                ["required"] = JsonSerializer.SerializeToElement(new[] { "location" }),
                ["additionalProperties"] = JsonSerializer.SerializeToElement(false),
            }),
        }),
    ]
};

var message = await client.Messages.Create(parameters);
Console.WriteLine(message);
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()

	response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
		Model:     anthropic.ModelClaudeOpus4_7,
		MaxTokens: 1024,
		Messages: []anthropic.MessageParam{
			anthropic.NewUserMessage(anthropic.NewTextBlock("What's the weather like in San Francisco?")),
		},
		Tools: []anthropic.ToolUnionParam{
			{OfTool: &anthropic.ToolParam{
				Name:        "get_weather",
				Description: anthropic.String("Get the current weather in a given location"),
				Strict:      anthropic.Bool(true),
				InputSchema: anthropic.ToolInputSchemaParam{
					Properties: map[string]any{
						"location": map[string]any{
							"type":        "string",
							"description": "The city and state, e.g. San Francisco, CA",
						},
						"unit": map[string]any{
							"type": "string",
							"enum": []string{"celsius", "fahrenheit"},
						},
					},
					Required: []string{"location"},
					ExtraFields: map[string]any{
						"additionalProperties": false,
					},
				}}},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(response.Content)
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.Tool;
import com.anthropic.models.messages.Tool.InputSchema;
import java.util.List;
import java.util.Map;

void main() {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    InputSchema schema = InputSchema.builder()
        .properties(
            JsonValue.from(
                Map.of(
                    "location", Map.of(
                        "type", "string",
                        "description", "The city and state, e.g. San Francisco, CA"
                    ),
                    "unit", Map.of(
                        "type", "string",
                        "enum", List.of("celsius", "fahrenheit")
                    )
                )
            )
        )
        .putAdditionalProperty("required", JsonValue.from(List.of("location")))
        .putAdditionalProperty("additionalProperties", JsonValue.from(false))
        .build();

    MessageCreateParams params = MessageCreateParams.builder()
        .model(Model.CLAUDE_OPUS_4_7)
        .maxTokens(1024L)
        .addUserMessage("What's the weather like in San Francisco?")
        .addTool(
            Tool.builder()
                .name("get_weather")
                .description("Get the current weather in a given location")
                .strict(true)
                .inputSchema(schema)
                .build()
        )
        .build();

    Message response = client.messages().create(params);
    IO.println(response.content());
}
<?php

use Anthropic\Client;

$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));

$message = $client->messages->create(
    maxTokens: 1024,
    messages: [
        ['role' => 'user', 'content' => "What's the weather like in San Francisco?"]
    ],
    model: 'claude-opus-4-7',
    tools: [
        [
            'name' => 'get_weather',
            'description' => 'Get the current weather in a given location',
            'strict' => true,
            'input_schema' => [
                'type' => 'object',
                'properties' => [
                    'location' => [
                        'type' => 'string',
                        'description' => 'The city and state, e.g. San Francisco, CA'
                    ],
                    'unit' => [
                        'type' => 'string',
                        'enum' => ['celsius', 'fahrenheit']
                    ]
                ],
                'required' => ['location'],
                'additionalProperties' => false
            ]
        ]
    ],
);

echo $message;
require "anthropic"

client = Anthropic::Client.new

message = client.messages.create(
  model: "claude-opus-4-7",
  max_tokens: 1024,
  messages: [
    { role: "user", content: "What's the weather like in San Francisco?" }
  ],
  tools: [
    {
      name: "get_weather",
      description: "Get the current weather in a given location",
      strict: true,
      input_schema: {
        type: "object",
        properties: {
          location: {
            type: "string",
            description: "The city and state, e.g. San Francisco, CA"
          },
          unit: {
            type: "string",
            enum: ["celsius", "fahrenheit"]
          }
        },
        required: ["location"],
        additionalProperties: false
      }
    }
  ]
)
puts message.content

响应格式: 工具使用块在 response.content[x].input 中包含经过验证的输入

{
  "type": "tool_use",
  "name": "get_weather",
  "input": {
    "location": "San Francisco, CA"
  }
}

保证:

  • 工具 input 严格遵循 input_schema
  • 工具 name 始终有效(来自提供的工具或服务器端工具)

工作原理

  1. 定义你的工具 schema

    为你的工具的 input_schema 创建一个 JSON schema。该 schema 使用标准 JSON Schema 格式,有一些限制(参见 JSON Schema 限制)。

  2. 添加 strict: true

    在工具定义中将 "strict": true 设置为顶级属性,与 namedescriptioninput_schema 并列。

  3. 处理工具调用

    当 Claude 使用工具时,tool_use 块中的 input 字段严格遵循你的 input_schemaname 始终有效。

常见用例

经过验证的工具输入

确保工具参数完全匹配你的 schema:

(代码示例省略,保留原文代码块不变)

具有多个经过验证工具的 agentic 工作流

使用保证的工具参数构建可靠的多步骤 agent:

(代码示例省略,保留原文代码块不变)

数据保留

严格工具使用使用与结构化输出相同的管道将工具 input_schema 定义编译为语法。工具 schema 自上次使用后最多临时缓存 24 小时。提示和响应在 API 响应之后不会被保留。

严格工具使用符合 HIPAA 要求,但 PHI 不得包含在工具 schema 定义中。API 将编译后的 schema 与消息内容分开缓存,这些缓存的 schema 不会获得与提示和响应相同的 PHI 保护。不要在 input_schema 属性名称、enum 值、const 值或 pattern 正则表达式中包含 PHI。PHI 应仅出现在消息内容(提示和响应)中,在那里它受到 HIPAA 安全保护。

有关所有功能的 ZDR 和 HIPAA 资格,请参阅 API 和数据保留