Page history
strict-tool-use
agents-and-tools/tool-use/strict-tool-use
History
agents-and-tools/tool-use/strict-tool-use Changed · +2 / -0 lines
from line 380
</Step> </Steps> +The [computer use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool) and [browser use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/browser-use-tool) toolset entries (`computer_toolset_20260801` and `browser_toolset_20260801`) don't accept `strict: true`; a request that sets it on either entry is rejected. + ## Common use cases <AccordionGroup>
agents-and-tools/tool-use/strict-tool-use Changed · +2 / -2 lines
from line 577
if err != nil { log.Fatal(err) } - fmt.Println(response) + fmt.Println(response.RawJSON()) ``` ```java Java
from line 962
if err != nil { log.Fatal(err) } - fmt.Println(response) + fmt.Println(response.RawJSON()) ``` ```java Java
agents-and-tools/tool-use/strict-tool-use First recorded · 1142 lines, first recorded
## Why strict tool use matters for agents ## Quick start ## How it works ## Common use cases ## Data retention ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Strict tool use
url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use
description: Enforce JSON Schema compliance on Claude's tool inputs with grammar-constrained sampling.
---
Setting `strict: true` on a tool definition guarantees Claude's tool inputs match your JSON Schema by constraining the model's token sampling to schema-valid outputs (a technique called grammar-constrained sampling). This page covers why strict mode matters for agents, how to enable it, and common use cases. For the supported JSON Schema subset, see [JSON Schema limitations](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#json-schema-limitations). For non-strict schema guidance, see [Define tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools).
Strict tool use validates tool parameters, ensuring Claude calls your functions with correctly-typed arguments. Use strict tool use when you need to:
* Validate tool parameters
* Build agentic workflows
* Ensure type-safe function calls
* Handle complex tools with nested properties
## Why strict tool use matters for agents
Building reliable agentic systems requires guaranteed schema conformance. Without strict mode, Claude might return incompatible types (`"2"` instead of `2`) or omit required fields, breaking your functions and causing runtime errors.
Strict tool use guarantees type-safe parameters:
* Functions receive correctly-typed arguments every time
* No need to validate and retry tool calls
* Production-ready agents that work consistently at scale
For example, suppose a booking system needs `passengers: int`. Without strict mode, Claude might provide `passengers: "two"` or `passengers: "2"`. With `strict: true`, the response always contains `passengers: 2`.
## Quick start
<CodeGroup>
```bash cURL
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-5",
"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
}
}]
}'
```
```bash CLI
ant messages create --transform content <<'YAML'
model: claude-opus-5
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
```
```python Python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
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, # Enable strict mode
"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)
```
```typescript TypeScript
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
const response = await client.messages.create({
model: "claude-opus-5",
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, // Enable strict mode
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);
```
```csharp C#
using System.Text.Json;
using Anthropic;
using Anthropic.Models.Messages;
AnthropicClient client = new();
var parameters = new MessageCreateParams
{
Model = Model.ClaudeOpus5,
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);
```
```go Go
client := anthropic.NewClient()
response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
Model: anthropic.ModelClaudeOpus5,
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)
```
```java Java
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_5)
.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 PHP
$client = new Client();
$message = $client->messages->create(
maxTokens: 1024,
messages: [
['role' => 'user', 'content' => "What's the weather like in San Francisco?"]
],
model: 'claude-opus-5',
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',
Cut at 300 lines.