Tool use examples
Here are a few code examples demonstrating various tool use patterns and techniques. For brevity's sake, the tools are simple tools, and the tool descriptions are shorter than would be ideal to ensure best performance. See specifying tools for more information.
Single tool
This example shows a basic single-tool situation, using a get_weather
tool.
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "anthropic-beta: tools-2024-04-04" \
--header "content-type: application/json" \
--data \
'{
"model": "claude-3-opus-20240229",
"max_tokens": 1024,
"tools": [{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
}],
"messages": [{"role": "user", "content": "What is the weather like in San Francisco?"}]
}'
import anthropic
client = anthropic.Anthropic()
response = client.beta.tools.messages.create(
model="claude-3-opus-20240229",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
}
],
messages=[{"role": "user", "content": "What is the weather like in San Francisco?"}]
)
print(response)
Claude will return a response similar to:
{
"id": "msg_01Aq9w938a90dw8q",
"model": "claude-3-opus-20240229",
"stop_reason": "tool_use",
"role": "assistant",
"content": [
{
"type": "text",
"text": "<thinking>I need to call the get_weather function, and the user wants SF, which is likely San Francisco, CA.</thinking>"
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {"location": "San Francisco, CA", "unit": "celsius"}
}
]
}
You would then need to execute the get_weather
function with the provided input, and return the result in a new user
message:
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "anthropic-beta: tools-2024-04-04" \
--header "content-type: application/json" \
--data \
'{
"model": "claude-3-opus-20240229",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the weather like in San Francisco?"
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "<thinking>I need to use get_weather, and the user wants SF, which is likely San Francisco, CA.</thinking>"
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {
"location": "San Francisco, CA",
"unit": "celsius"
}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "15 degrees"
}
]
}
]
}'
response = client.beta.tools.messages.create(
model="claude-3-opus-20240229",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
}
],
messages=[
{
"role": "user",
"content": "What's the weather like in San Francisco?"
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "<thinking>I need to use get_weather, and the user wants SF, which is likely San Francisco, CA.</thinking>"
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {"location": "San Francisco, CA", "unit": "celsius"}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9", # from the API response
"content": "65 degrees" # from running your tool
}
]
}
]
)
print(response)
This will print Claude's final response, incorporating the weather data:
{
"id": "msg_01Aq9w938a90dw8q",
"model": "claude-3-opus-20240229",
"stop_reason": "stop_sequence",
"role": "assistant",
"content": [
{
"type": "text",
"text": "The current weather in San Francisco is 15 degrees Celsius (59 degrees Fahrenheit). It's a cool day in the city by the bay!"
}
]
}
Missing information
If the user's prompt doesn't include enough information to fill all the required parameters for a tool, Claude 3 Opus is much more likely to recognize that a parameter is missing and ask for it. Claude 3 Sonnet may ask, especially when prompted to think before outputting a tool request. But it may also do its best to infer a reasonable value.
For example, using the get_weather
tool above, if you ask Claude "What's the weather?" without specifying a location, Claude, particularly Claude 3 Sonnet, may make a guess about tools inputs:
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {"location": "New York, NY", "unit": "fahrenheit"}
}
This behavior is not guaranteed, especially for more ambiguous prompts and for models less intelligent than Claude 3 Opus. If Claude 3 Opus doesn't have enough context to fill in the required parameters, it is far more likely respond with a clarifying question instead of making a tool call.
Multiple tools
You can provide Claude with multiple tools to choose from in a single request. Here's an example with both a get_weather
and a get_time
tool, along with a user query that asks for both.
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "anthropic-beta: tools-2024-04-04" \
--header "content-type: application/json" \
--data \
'{
"model": "claude-3-opus-20240229",
"max_tokens": 1024,
"tools": [{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
},
{
"name": "get_time",
"description": "Get the current time in a given time zone",
"input_schema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "The IANA time zone name, e.g. America/Los_Angeles"
}
},
"required": ["timezone"]
}
}],
"messages": [{
"role": "user",
"content": "What is the weather like right now in New York? Also what time is it there?"
}]
}'
import anthropic
client = anthropic.Anthropic()
response = client.beta.tools.messages.create(
model="claude-3-opus-20240229",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
},
{
"name": "get_time",
"description": "Get the current time in a given time zone",
"input_schema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "The IANA time zone name, e.g. America/Los_Angeles"
}
},
"required": ["timezone"]
}
}
],
messages=[
{
"role": "user",
"content": "What is the weather like right now in New York? Also what time is it there?"
}
]
)
print(response)
In this case, Claude will most likely try to use two separate tools, one at a time — get_weather
and then get_time
— in order to fully answer the user's question. However, it will also occasionally output two tool_use
blocks at once, particularly if they are not dependent on each other. You would need to execute each tool and return their results in separate tool_result
blocks within a single user
message.
Sequential tools
Some tasks may require calling multiple tools in sequence, using the output of one tool as the input to another. In such a case, Claude will call one tool at a time. If prompted to call the tools all at once, Claude is likely to guess parameters for tools further downstream if they are dependent on tool results for tools further upstream.
Here's an example of using a get_location
tool to get the user's location, then passing that location to the get_weather
tool:
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "anthropic-beta: tools-2024-04-04" \
--header "content-type: application/json" \
--data \
'{
"model": "claude-3-opus-20240229",
"max_tokens": 1024,
"tools": [
{
"name": "get_location",
"description": "Get the current user location based on their IP address. This tool has no parameters or arguments.",
"input_schema": {
"type": "object",
"properties": {}
}
},
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
}
],
"messages": [{
"role": "user",
"content": "What is the weather like where I am?"
}]
}'
response = client.beta.tools.messages.create(
model="claude-3-opus-20240229",
max_tokens=1024,
tools=[
{
"name": "get_location",
"description": "Get the current user location based on their IP address. This tool has no parameters or arguments.",
"input_schema": {
"type": "object",
"properties": {}
}
},
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"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"]
}
}
],
messages=[{
"role": "user",
"content": "What's the weather like where I am?"
}]
)
In this case, Claude would first call the get_location
tool to get the user's location. After you return the location in a tool_result
, Claude would then call get_weather
with that location to get the final answer.
The full conversation might look like:
Role | Content |
---|---|
User | What's the weather like where I am? |
Assistant | <thinking> To answer this, I first need to determine the user's location using the get_location tool. Then I can pass that location to the get_weather tool to find the current weather there. </thinking> [Tool use for get_location ] |
User | [Tool result for get_location with matching id and result of San Francisco, CA ] |
Assistant | [Tool use for get_weather with the following input ]{ "location": "San Francisco, CA", "unit": "fahrenheit" } |
User | [Tool result for get_weather with matching id and result of "59°F (15°C), mostly cloudy" ] |
Assistant | Based on your current location in San Francisco, CA, the weather right now is 59°F (15°C) and mostly cloudy. It's a fairly cool and overcast day in the city. You may want to bring a light jacket if you're heading outside. |
This example demonstrates how Claude can chain together multiple tool calls to answer a question that requires gathering data from different sources. The key steps are:
-
Claude first realizes it needs the user's location to answer the weather question, so it calls the
get_location
tool. -
The user (i.e. the client code) executes the actual
get_location
function and returns the result "San Francisco, CA" in atool_result
block. -
With the location now known, Claude proceeds to call the
get_weather
tool, passing in "San Francisco, CA" as thelocation
parameter (as well as a guessedunit
parameter, asunit
is not a required parameter). -
The user again executes the actual
get_weather
function with the provided arguments and returns the weather data in anothertool_result
block. -
Finally, Claude incorporates the weather data into a natural language response to the original question.
Chain of thought tool use
By default, Claude 3 Opus is prompted to think before it answers a tool use query to best determine whether a tool is necessary, which tool to use, and the appropriate parameters. Claude 3 Sonnet and Claude 3 Haiku are prompted to try to use tools as much as possible and are more likely to call an unnecessary tool or infer missing parameters. To prompt Sonnet or Haiku to better assess the user query before making tool calls, the following prompt can be used:
Answer the user's request using relevant tools (if they are available). Before calling a tool, do some analysis within <thinking></thinking> tags. First, think about which of the provided tools is the relevant tool to answer the user's request. Second, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool call. BUT, if one of the values for a required parameter is missing, DO NOT invoke the function (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters. DO NOT ask for more information on optional parameters if it is not provided.
JSON mode
You can use tools to get Claude produce JSON output that follows a schema, even if you don't have any intention of running that output through a tool or function.
When using tools in this way:
- You usually want to provide a single tool
- You should instruct the model explicitly to use that tool.
- Remember that the model will pass the
input
to the tool, so the name of the tool and description should be from the model's perspective.
The following uses a record_summary
tool to describe an image following a particular format.
#!/bin/bash
IMAGE_URL="https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg"
IMAGE_MEDIA_TYPE="image/jpeg"
IMAGE_BASE64=$(curl "$IMAGE_URL" | base64)
curl https://api.anthropic.com/v1/messages \
--header "content-type: application/json" \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "anthropic-beta: tools-2024-04-04" \
--data \
'{
"model": "claude-3-sonnet-20240229",
"max_tokens": 1024,
"tools": [{
"name": "record_summary",
"description": "Record summary of an image into well-structured JSON.",
"input_schema": {
"type": "object",
"properties": {
"key_colors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"r": { "type": "number", "description": "red value [0.0, 1.0]" },
"g": { "type": "number", "description": "green value [0.0, 1.0]" },
"b": { "type": "number", "description": "blue value [0.0, 1.0]" },
"name": { "type": "string", "description": "Human-readable color name in snake_case, e.g. \"olive_green\" or \"turquoise\"" }
},
"required": [ "r", "g", "b", "name" ]
},
"description": "Key colors in the image. Limit to less then four."
},
"description": {
"type": "string",
"description": "Image description. One to two sentences max."
},
"estimated_year": {
"type": "integer",
"description": "Estimated year that the images was taken, if is it a photo. Only set this if the image appears to be non-fictional. Rough estimates are okay!"
}
},
"required": [ "key_colors", "description" ]
}
}],
"messages": [
{"role": "user", "content": [
{"type": "image", "source": {
"type": "base64",
"media_type": "'$IMAGE_MEDIA_TYPE'",
"data": "'$IMAGE_BASE64'"
}},
{"type": "text", "text": "Use `record_summary` to describe this image."}
]}
]
}'
import base64
import anthropic
import httpx
image_url = "https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg"
image_media_type = "image/jpeg"
image_data = base64.b64encode(httpx.get(image_url).content).decode("utf-8")
message = anthropic.Anthropic().beta.tools.messages.create(
model="claude-3-sonnet-20240229",
max_tokens=1024,
tools=[
{
"name": "record_summary",
"description": "Record summary an image into well-structured JSON.",
"input_schema": {
"type": "object",
"properties": {
"key_colors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"r": {
"type": "number",
"description": "red value [0.0, 1.0]",
},
"g": {
"type": "number",
"description": "green value [0.0, 1.0]",
},
"b": {
"type": "number",
"description": "blue value [0.0, 1.0]",
},
"name": {
"type": "string",
"description": "Human-readable color name in snake_case, e.g. \"olive_green\" or \"turquoise\""
},
},
"required": ["r", "g", "b", "name"],
},
"description": "Key colors in the image. Limit to less then four.",
},
"description": {
"type": "string",
"description": "Image description. One to two sentences max.",
},
"estimated_year": {
"type": "integer",
"description": "Estimated year that the images was taken, if it a photo. Only set this if the image appears to be non-fictional. Rough estimates are okay!",
},
},
"required": ["key_colors", "description"],
},
}
],
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": image_media_type,
"data": image_data,
},
},
{"type": "text", "text": "Use `record_summary` to describe this image."},
],
}
],
)
print(message)
Updated 30 days ago