How to Use Claude Tool Calling: A Developer Guide
"Using a Claude tool" almost always means one of two things: giving Claude access to functions it can call (tool use / function calling), or connecting a third-party tool that talks to Claude through an API. This guide covers the first and most common case — how to actually wire up tool calling in your own application, from your first request to handling the response Claude sends back.
The short version: you describe your tools (name, description, input schema) in your API request, Claude decides whether to call one, you execute the actual function on your side, and you send the result back so Claude can finish its answer. Nothing runs on Anthropic's servers — Claude only tells you what to run and with what arguments.
What you need before starting
- An API key (from Anthropic directly, or a proxy like SubToAPI if you're already paying for Claude access and want a standard HTTPS API instead of managing raw API billing).
- A clear idea of the actions you want Claude to trigger: look up a database record, call a weather API, run a calculation, search your docs, etc.
- A way to execute code server-side in response to Claude's request — tool use is a two-way conversation, not a one-shot call.
Step 1: Define your tool
Every tool needs a name, a description, and a JSON schema for its inputs. The description matters more than people expect — it's how the model decides when to call the tool, not just how.
{
"name": "get_weather",
"description": "Get the current weather for a given city",
"input_schema": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "City name, e.g. Paris" },
"unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
},
"required": ["city"]
}
}
Keep schemas minimal. Extra optional fields the model doesn't need just add ambiguity and increase the chance of malformed calls.
Step 2: Send the request with the tool attached
You pass the tool definition alongside your normal messages request. The model reads the conversation and decides on its own whether a tool call is needed.
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-3-5-sonnet",
"max_tokens": 1024,
"tools": [{
"name": "get_weather",
"description": "Get the current weather for a given city",
"input_schema": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}],
"messages": [
{ "role": "user", "content": "What is the weather like in Lisbon?" }
]
}'
Step 3: Read the tool_use block
If Claude decides a tool is needed, the response contains a content block with type: "tool_use", the tool name, and structured input arguments — not free text.
{
"content": [
{
"type": "tool_use",
"id": "toolu_01Xyz",
"name": "get_weather",
"input": { "city": "Lisbon" }
}
],
"stop_reason": "tool_use"
}
Your code checks stop_reason. If it's tool_use, you extract the name and input, run the matching function yourself, and capture the output.
Step 4: Send the result back
You append the tool call to the conversation as an assistant message, then add a tool_result block as a user message with the same id. Claude uses that result to write its final answer.
const toolResult = await getWeather(input.city); // your actual function
const followUp = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "claude-3-5-sonnet",
max_tokens: 1024,
tools: [ /* same tool definitions */ ],
messages: [
{ role: "user", content: "What is the weather like in Lisbon?" },
{ role: "assistant", content: previousToolUseBlocks },
{
role: "user",
content: [{
type: "tool_result",
tool_use_id: "toolu_01Xyz",
content: JSON.stringify(toolResult)
}]
}
]
})
});
Claude then returns a normal text response, now informed by real data instead of a guess.
Common mistakes when using Claude tool calling
- Vague descriptions. "Handles user requests" tells the model nothing. Describe exactly what the tool does and when to use it.
- Forgetting the loop is stateful. You must resend the full conversation, including the tool_use and tool_result blocks, on every follow-up call.
- Mismatched tool_use_id. The result block has to reference the exact id Claude generated, or the request will fail validation.
- Over-tooling. Giving Claude ten similar tools with overlapping purposes increases the odds it picks the wrong one. Fewer, well-scoped tools work better than many broad ones.
- Ignoring
stop_reason. If you only check for text content, you'll silently miss tool calls and return empty responses to users.
Where SubToAPI fits in
If you're paying for a Claude subscription and don't want to separately manage Anthropic API billing, SubToAPI turns that access into a standard HTTPS endpoint with application API keys (sub_live_...), streaming, and full tool-use support — so the same request format shown above works without changes. It also gives you per-key usage metadata, which is useful once you have several tools and want to see which ones actually get called in production.
Start with the quickstart guide, then check the tool use docs for the full request/response schema and the messages reference for everything else the endpoint supports. Plans start with a free trial at signup — pricing is on the pricing page.
questions
Do I need a special API plan to use Claude's tools? No — tool use is part of the standard Messages API, available on any plan that supports the model you're calling. You just include a tools array in your request.
Can Claude call the tool for me automatically? No. Claude only returns the tool name and arguments; your application has to execute the actual function and send the result back in a follow-up request.
Why isn't Claude calling my tool even though I defined it? Usually the description is too vague, the user's message doesn't clearly need that action, or the tool schema has a required field the model can't reasonably infer — tighten the description and required parameters first.