Tool Use
curl --request POST \
--url https://api.anthropic.com/v1/messages/tool-use \
--header 'Content-Type: application/json' \
--header 'anthropic-version: <anthropic-version>' \
--header 'x-api-key: <api-key>' \
--data '
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [
{
"name": "get_crypto_price",
"description": "Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.",
"input_schema": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "The cryptocurrency symbol, e.g. BTC, ETH, SOL"
}
},
"required": [
"symbol"
]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the current price of Bitcoin?"
}
]
}
'import requests
url = "https://api.anthropic.com/v1/messages/tool-use"
payload = {
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [
{
"name": "get_crypto_price",
"description": "Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.",
"input_schema": {
"type": "object",
"properties": { "symbol": {
"type": "string",
"description": "The cryptocurrency symbol, e.g. BTC, ETH, SOL"
} },
"required": ["symbol"]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the current price of Bitcoin?"
}
]
}
headers = {
"anthropic-version": "<anthropic-version>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'anthropic-version': '<anthropic-version>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
tools: [
{
name: 'get_crypto_price',
description: 'Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.',
input_schema: {
type: 'object',
properties: {
symbol: {type: 'string', description: 'The cryptocurrency symbol, e.g. BTC, ETH, SOL'}
},
required: ['symbol']
}
}
],
messages: [{role: 'user', content: 'What is the current price of Bitcoin?'}]
})
};
fetch('https://api.anthropic.com/v1/messages/tool-use', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.anthropic.com/v1/messages/tool-use",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'claude-sonnet-4-6',
'max_tokens' => 1024,
'tools' => [
[
'name' => 'get_crypto_price',
'description' => 'Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.',
'input_schema' => [
'type' => 'object',
'properties' => [
'symbol' => [
'type' => 'string',
'description' => 'The cryptocurrency symbol, e.g. BTC, ETH, SOL'
]
],
'required' => [
'symbol'
]
]
]
],
'messages' => [
[
'role' => 'user',
'content' => 'What is the current price of Bitcoin?'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"anthropic-version: <anthropic-version>",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.anthropic.com/v1/messages/tool-use"
payload := strings.NewReader("{\n \"model\": \"claude-sonnet-4-6\",\n \"max_tokens\": 1024,\n \"tools\": [\n {\n \"name\": \"get_crypto_price\",\n \"description\": \"Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.\",\n \"input_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"symbol\": {\n \"type\": \"string\",\n \"description\": \"The cryptocurrency symbol, e.g. BTC, ETH, SOL\"\n }\n },\n \"required\": [\n \"symbol\"\n ]\n }\n }\n ],\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"What is the current price of Bitcoin?\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("anthropic-version", "<anthropic-version>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.anthropic.com/v1/messages/tool-use")
.header("anthropic-version", "<anthropic-version>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"claude-sonnet-4-6\",\n \"max_tokens\": 1024,\n \"tools\": [\n {\n \"name\": \"get_crypto_price\",\n \"description\": \"Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.\",\n \"input_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"symbol\": {\n \"type\": \"string\",\n \"description\": \"The cryptocurrency symbol, e.g. BTC, ETH, SOL\"\n }\n },\n \"required\": [\n \"symbol\"\n ]\n }\n }\n ],\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"What is the current price of Bitcoin?\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.anthropic.com/v1/messages/tool-use")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["anthropic-version"] = '<anthropic-version>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"claude-sonnet-4-6\",\n \"max_tokens\": 1024,\n \"tools\": [\n {\n \"name\": \"get_crypto_price\",\n \"description\": \"Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.\",\n \"input_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"symbol\": {\n \"type\": \"string\",\n \"description\": \"The cryptocurrency symbol, e.g. BTC, ETH, SOL\"\n }\n },\n \"required\": [\n \"symbol\"\n ]\n }\n }\n ],\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"What is the current price of Bitcoin?\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello! How can I help you today?"
}
],
"model": "claude-sonnet-4-6",
"stop_reason": "end_turn",
"stop_details": {},
"usage": {
"input_tokens": 17,
"output_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"service_tier": "standard",
"inference_geo": "global"
}
}{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
},
"request_id": "req_011CdDNcA4MfikfhDdfNYDNj"
}{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
},
"request_id": "req_011CdDNcA4MfikfhDdfNYDNj"
}Endpoints
Tool Use
Define tools that Claude can call to access real-time data and external services.
POST
/
v1
/
messages
/
tool-use
Tool Use
curl --request POST \
--url https://api.anthropic.com/v1/messages/tool-use \
--header 'Content-Type: application/json' \
--header 'anthropic-version: <anthropic-version>' \
--header 'x-api-key: <api-key>' \
--data '
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [
{
"name": "get_crypto_price",
"description": "Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.",
"input_schema": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "The cryptocurrency symbol, e.g. BTC, ETH, SOL"
}
},
"required": [
"symbol"
]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the current price of Bitcoin?"
}
]
}
'import requests
url = "https://api.anthropic.com/v1/messages/tool-use"
payload = {
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [
{
"name": "get_crypto_price",
"description": "Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.",
"input_schema": {
"type": "object",
"properties": { "symbol": {
"type": "string",
"description": "The cryptocurrency symbol, e.g. BTC, ETH, SOL"
} },
"required": ["symbol"]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the current price of Bitcoin?"
}
]
}
headers = {
"anthropic-version": "<anthropic-version>",
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'anthropic-version': '<anthropic-version>',
'x-api-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
tools: [
{
name: 'get_crypto_price',
description: 'Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.',
input_schema: {
type: 'object',
properties: {
symbol: {type: 'string', description: 'The cryptocurrency symbol, e.g. BTC, ETH, SOL'}
},
required: ['symbol']
}
}
],
messages: [{role: 'user', content: 'What is the current price of Bitcoin?'}]
})
};
fetch('https://api.anthropic.com/v1/messages/tool-use', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.anthropic.com/v1/messages/tool-use",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'claude-sonnet-4-6',
'max_tokens' => 1024,
'tools' => [
[
'name' => 'get_crypto_price',
'description' => 'Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.',
'input_schema' => [
'type' => 'object',
'properties' => [
'symbol' => [
'type' => 'string',
'description' => 'The cryptocurrency symbol, e.g. BTC, ETH, SOL'
]
],
'required' => [
'symbol'
]
]
]
],
'messages' => [
[
'role' => 'user',
'content' => 'What is the current price of Bitcoin?'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"anthropic-version: <anthropic-version>",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.anthropic.com/v1/messages/tool-use"
payload := strings.NewReader("{\n \"model\": \"claude-sonnet-4-6\",\n \"max_tokens\": 1024,\n \"tools\": [\n {\n \"name\": \"get_crypto_price\",\n \"description\": \"Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.\",\n \"input_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"symbol\": {\n \"type\": \"string\",\n \"description\": \"The cryptocurrency symbol, e.g. BTC, ETH, SOL\"\n }\n },\n \"required\": [\n \"symbol\"\n ]\n }\n }\n ],\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"What is the current price of Bitcoin?\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("anthropic-version", "<anthropic-version>")
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.anthropic.com/v1/messages/tool-use")
.header("anthropic-version", "<anthropic-version>")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"claude-sonnet-4-6\",\n \"max_tokens\": 1024,\n \"tools\": [\n {\n \"name\": \"get_crypto_price\",\n \"description\": \"Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.\",\n \"input_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"symbol\": {\n \"type\": \"string\",\n \"description\": \"The cryptocurrency symbol, e.g. BTC, ETH, SOL\"\n }\n },\n \"required\": [\n \"symbol\"\n ]\n }\n }\n ],\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"What is the current price of Bitcoin?\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.anthropic.com/v1/messages/tool-use")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["anthropic-version"] = '<anthropic-version>'
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"claude-sonnet-4-6\",\n \"max_tokens\": 1024,\n \"tools\": [\n {\n \"name\": \"get_crypto_price\",\n \"description\": \"Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.\",\n \"input_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"symbol\": {\n \"type\": \"string\",\n \"description\": \"The cryptocurrency symbol, e.g. BTC, ETH, SOL\"\n }\n },\n \"required\": [\n \"symbol\"\n ]\n }\n }\n ],\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"What is the current price of Bitcoin?\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello! How can I help you today?"
}
],
"model": "claude-sonnet-4-6",
"stop_reason": "end_turn",
"stop_details": {},
"usage": {
"input_tokens": 17,
"output_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"service_tier": "standard",
"inference_geo": "global"
}
}{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
},
"request_id": "req_011CdDNcA4MfikfhDdfNYDNj"
}{
"type": "error",
"error": {
"type": "authentication_error",
"message": "invalid x-api-key"
},
"request_id": "req_011CdDNcA4MfikfhDdfNYDNj"
}Overview
Tool use lets developers define functions that Claude can call when it needs information it does not have or actions it cannot perform itself. Claude does not execute the function — it tells your application which function to run and with what arguments. Your application runs it, passes the result back, and Claude continues. This is how AI applications connect to the real world — payment systems, databases, live APIs, internal tools.The Tool Use Lifecycle
Tool use takes two requests to complete:Request 1: You define tools + send user message
↓
Claude decides a tool is needed
↓
Claude returns a tool_use block
↓
Request 2: You execute the function + pass result back
↓
Claude reads the result
↓
Claude returns a final text response
Request 1 — Define the Tool
Pass your tool definitions in thetools array alongside the user message:
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [
{
"name": "get_crypto_price",
"description": "Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.",
"input_schema": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "The cryptocurrency symbol, e.g. BTC, ETH, SOL"
}
},
"required": ["symbol"]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the current price of Bitcoin?"
}
]
}
Tool Definition Fields
Each tool in thetools array requires three fields:
| Field | Type | Description |
|---|---|---|
name | string | The function name. Use snake_case. Claude uses this to identify which tool to call. |
description | string | What the tool does and when to use it. Claude uses this to decide whether to call the tool. |
input_schema | object | JSON Schema definition of the tool’s parameters. |
The
description field is the most important part of your tool definition. Claude decides whether and how to call a tool based entirely on this description. A vague or incomplete description leads to missed or incorrect tool calls. Write it as if explaining the function to a junior developer.Response 1 — The Tool Use Block
When Claude decides a tool is needed it returns atool_use content block instead of a text response:
{
"id": "msg_011Cd8...",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01AXtTKvmkaPzQ75JP3o9R4X",
"name": "get_crypto_price",
"input": {
"symbol": "BTC"
}
}
],
"stop_reason": "tool_use",
"usage": {
"input_tokens": 407,
"output_tokens": 42
}
}
| Field | Value | What It Means |
|---|---|---|
content[0].type | tool_use | Claude is requesting a function call, not returning text |
stop_reason | tool_use | Generation stopped because a tool call is needed |
content[0].id | toolu_01... | Unique ID for this tool call — required in Request 2 |
content[0].input | {"symbol": "BTC"} | Arguments Claude extracted from the user’s message |
Copy the
content[0].id value from this response. You need it exactly in Request 2 — both in the assistant message and in the tool result. The IDs must match or the request will fail.Request 2 — Return the Tool Result
Pass the full conversation history including Claude’s tool call response and your tool result:{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [
{
"name": "get_crypto_price",
"description": "Get the current price of a cryptocurrency in USD. Use this when the user asks about current crypto prices.",
"input_schema": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "The cryptocurrency symbol, e.g. BTC, ETH, SOL"
}
},
"required": ["symbol"]
}
}
],
"messages": [
{
"role": "user",
"content": "What is the current price of Bitcoin?"
},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01AXtTKvmkaPzQ75JP3o9R4X",
"name": "get_crypto_price",
"input": {
"symbol": "BTC"
}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01AXtTKvmkaPzQ75JP3o9R4X",
"content": "The current price of BTC is $97,432.18 USD"
}
]
}
]
}
Response 2 — Final Text Response
Claude reads the tool result and generates a natural language response:{
"content": [
{
"type": "text",
"text": "The current price of Bitcoin (BTC) is $97,432.18 USD. Keep in mind that cryptocurrency prices are highly volatile and can change rapidly. Would you like to check the price of any other cryptocurrencies?"
}
],
"stop_reason": "end_turn"
}
stop_reason returns to end_turn — the tool use cycle is complete.
Token Cost of Tool Use
Tool definitions are included in input tokens on every request — whether Claude uses the tool or not:| Request | Input Tokens | Why |
|---|---|---|
| Basic message | 17 | Message only |
| Tool use Request 1 | 407 | Message + full tool definition |
| Tool use Request 2 | 687 | Full history + tool definition + tool result |
Multiple Tools
You can define multiple tools in a single request. Claude selects the right one based on the user’s message and each tool’s description:{
"tools": [
{
"name": "get_crypto_price",
"description": "Get the current price of a cryptocurrency in USD.",
"input_schema": {...}
},
{
"name": "get_weather",
"description": "Get the current weather for a city.",
"input_schema": {...}
},
{
"name": "search_news",
"description": "Search for recent news articles on a topic.",
"input_schema": {...}
}
]
}
tool_use blocks in a single response.
Controlling Tool Use Behavior
You can control when and how Claude uses tools with thetool_choice parameter:
| Value | Behavior |
|---|---|
auto | Claude decides whether to use a tool. Default behavior. |
any | Claude must use one of the provided tools. |
tool | Claude must use a specific named tool. |
{
"tool_choice": {"type": "auto"},
"tools": [...],
"messages": [...]
}
Further Reading
Messages
How tool results fit into the messages array structure
Tokens
Why tool definitions are the biggest driver of input token costs
Streaming
Combine streaming and tool use for real-time agent applications
Error Handling
Handle tool use errors and failed tool calls gracefully
Authorizations
Headers
Example:
"2023-06-01"
Body
application/json
The Claude model to use.
Available options:
claude-sonnet-4-6, claude-opus-4-6, claude-haiku-4-5 Example:
"claude-sonnet-4-6"
Maximum number of output tokens to generate.
Required range:
x >= 1Example:
1024
Show child attributes
Show child attributes
List of tools Claude can call during the response.
Show child attributes
Show child attributes
Response
Successful response — may contain tool_use content block
Example:
"msg_01XFDUDYJgAACzvnptvVoYEL"
Example:
"message"
Example:
"assistant"
Show child attributes
Show child attributes
Example:
"claude-sonnet-4-6"
Available options:
end_turn, max_tokens, stop_sequence, tool_use Example:
"end_turn"
Show child attributes
Show child attributes
⌘I