AI — Claude API Development
Anthropic Claude Tool Use in Agent Workflows
Direct answer
Claude tool use works by declaring tools in the request — each with a name, description, and JSON Schema input_schema — and letting the model return a tool_use block when it decides to call one. Your code executes the tool, sends the result back as a tool_result block, and loops until Claude stops requesting tools. That request-execute-respond loop is the backbone of every Claude agent workflow I ship.
Tool use is where the Claude API stops being a text generator and becomes an agent runtime. This is the exact loop, schema design, and guardrail pattern I use when I build tool-calling agents for production.
Key facts, with sources
- Anthropic's published API pricing lists Claude Sonnet 4.6 at $3 per million input tokens and $15 per million output tokens, with Claude Haiku 4.5 at $1 and $5 for lighter workloads. (Claude Platform Docs)
- The Claude API offers a 50 percent discount on both input and output tokens via the Batch API and up to 90 percent savings on repeated input through prompt caching. (Claude Platform Docs)
- Current Claude Opus and Sonnet models support a 1 million token context window at flat per-token rates with no long-context surcharge. (CloudZero)
- Anthropic raised a $30 billion Series G at a $380 billion post-money valuation in 2026. (Anthropic)
- Anthropic said it hit a $30 billion revenue run rate after roughly 80x growth in about two years, driven primarily by enterprise and developer API consumption. (VentureBeat)
How the tool-use contract works
The contract has three parts. You pass a tools array where each tool declares a name, a description, and an input_schema in JSON Schema. When Claude decides a tool is needed, the response comes back with stop_reason set to tool_use and one or more tool_use content blocks, each carrying an id and a parsed input object matching your schema. You execute the tool yourself — the API never runs your code — then send a user message containing tool_result blocks that reference each tool_use_id.
Two details trip people up in code audits I run. First, tool inputs should be treated as parsed objects, never string-matched against serialized JSON, because escaping can vary. Second, the assistant message containing the tool_use blocks must be appended to history verbatim before you send results, or the API rejects the turn.
import anthropic
MODEL = "claude-..." # use the latest Claude model id
client = anthropic.Anthropic()
tools = [
{
"name": "get_order_status",
"description": (
"Look up the current status of a customer order. "
"Call this whenever the user asks where an order is "
"or references an order number."
),
"input_schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order identifier, e.g. ORD-1042",
}
},
"required": ["order_id"],
},
}
]
response = client.messages.create(
model=MODEL,
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "Where is order ORD-1042?"}],
)Tool descriptions decide whether your agent works
The single highest-leverage line in an agent is the tool description. Claude uses it to decide when to call the tool, so I write descriptions that are prescriptive about the trigger condition, not just the mechanics: call this when the user asks about current prices beats returns price data. I use enum constraints for parameters with fixed values, describe every property, and keep truly optional parameters out of the required list.
When an agent under-calls a tool, the fix is almost always the description, not the prompt. When it over-calls, the description is usually too aggressive — phrases like always use this tool cause exactly the overtriggering they sound like they would. I keep the total tool count focused; a dozen sharply described tools beat forty vague ones every time.
The agent loop in production
The runtime loop is simple: call the API, check stop_reason, execute any requested tools, return all results in a single user message, repeat until the model answers in plain text. Claude can request multiple tools in one turn — execute them concurrently when they are independent, but always return every tool_result together in one message. Splitting results across messages quietly teaches the model to stop parallelizing.
Failures go back through the same channel: a tool_result with is_error set to true and a readable error message lets Claude adapt — retry with different arguments, try another tool, or ask the user. Swallowing tool errors is the most common bug I find in agent codebases; the model cannot recover from a failure it never sees. I also cap loop iterations so a confused agent burns a bounded number of calls, never an unbounded one.
messages = [{"role": "user", "content": user_input}]
for _ in range(MAX_TURNS):
response = client.messages.create(
model=MODEL,
max_tokens=2048,
tools=tools,
messages=messages,
)
if response.stop_reason != "tool_use":
break
# Append the assistant turn verbatim, tool_use blocks included
messages.append({"role": "assistant", "content": response.content})
results = []
for block in response.content:
if block.type == "tool_use":
try:
output = execute_tool(block.name, block.input)
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
})
except ToolError as e:
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(e),
"is_error": True,
})
# Every result goes back in ONE user message
messages.append({"role": "user", "content": results})Gate the tools that can hurt you
Not all tools deserve equal trust. Read-only lookups can execute automatically; anything hard to reverse — sending email, mutating records, moving money — gets a gate between the model's request and execution. The pattern I use: the loop inspects the tool name before executing, and side-effect tools route through an approval step, a dry-run mode, or a policy check. The model experiences a slow tool; the business gets a safety boundary.
This is also why I promote dangerous actions to dedicated tools instead of hiding them behind a generic execute-anything tool. A dedicated send_invoice tool with typed arguments is auditable and gateable; an arbitrary shell command is neither. Design the tool surface around what your harness needs to intercept, not just what the model needs to do.
Choosing tool_choice deliberately
The tool_choice parameter controls agency. The default auto lets Claude decide, which is right for genuine agents. Forcing a specific tool guarantees structured extraction into that tool's schema — useful when the tool call is really a formatting trick. Setting it to any requires at least one call, and none disables tools for a turn without removing definitions from the request.
I use forced tool choice for deterministic pipeline stages and auto for interactive workflows. One caution from audits: teams sometimes force a tool as a workaround for a weak description, which masks the real problem and breaks the moment they add a second tool. Fix the description first; reach for forcing only when the workflow genuinely has exactly one correct next step.
When to hire senior help
Senior help matters most when you go beyond simple completions into agentic systems on the Claude API, where tool design, caching architecture, and eval harnesses decide reliability and cost. A few days of experienced review typically cuts token bills materially and prevents expensive rewrites later. If your stack includes React Native + Python + AI, a senior engineer who owns the full product beats coordinating multiple juniors.
Bottom line
Dhairya Senjaliya ships AI — Claude API Development projects worldwide — book a scoping call to discuss your specific situation.
Common pitfalls to avoid
- ✕Skipping prompt caching in agent loops that resend the same system prompt and tool definitions every turn, paying full input price for tokens that could cost 90 percent less
- ✕Running latency-insensitive workloads like evals, backfills, and bulk classification through the live API instead of the Batch API's 50 percent discount
- ✕Migrating model versions by swapping the ID string without checking for removed parameters like temperature or thinking budgets, which now return 400 errors on newer Claude models
- ✕Treating refusal and max-token stop reasons as generic errors instead of branching on stop_reason, which surfaces as silent empty responses in production
Frequently asked questions
How does tool use work in the Claude API?
You declare tools with a name, description, and JSON Schema input_schema in the request. When Claude wants to call one, the response has stop_reason tool_use and structured input. Your code executes the tool and returns a tool_result block referencing the tool_use_id, then calls the API again. The loop continues until Claude responds without requesting tools.
Can Claude call multiple tools in one response?
Yes. A single assistant turn can contain several tool_use blocks. Execute independent calls concurrently, then return all tool_result blocks together in a single user message. Splitting results across multiple messages degrades the model's willingness to parallelize in later turns, so always batch them.
How do I stop an AI agent from calling dangerous tools?
Gate side-effect tools in your execution layer, not in the prompt. The model only requests a call; your code decides whether to run it. Route irreversible actions — emails, payments, deletions — through approval steps or dry-run checks, and give risky operations dedicated, typed tools so they can be intercepted and audited individually.
Is Claude cheaper or more expensive than GPT for production workloads?
List prices are comparable tier for tier, so real cost differences come from token efficiency, caching hit rates, and how many loop iterations each model needs to finish a task. The only reliable answer is to run both on your own eval set and compare cost per completed task, not per token.
When do we actually need the 1 million token context window?
Most applications work fine well under 200K tokens, and input cost scales with everything you send. The 1M window matters for whole-codebase analysis, large document sets, and long-running agent sessions, and pairing it with prompt caching keeps repeated long contexts affordable.
How do we keep Claude API costs under control?
The three biggest levers are prompt caching (up to 90 percent off repeated input), the Batch API (50 percent off asynchronous work), and routing simple tasks to Haiku-class models. Instrument the usage fields on every response so you can see cache hit rates and catch cost regressions early.
Bottom line: Dhairya Senjaliya ships AI — Claude API Development projects worldwide. Book a scoping call at https://dhairyasenjaliya.com/#book-call.