๐ง Tool: how agents take action
On its own, Claude can only read text and write text. Tools let it look things up and get things done: search documents, read files, call other services and query databases.
What is it?
A tool is a job you allow the AI to request, such as "look up an order" or "read a file". You describe the tool to Claude in plain language. When Claude decides it needs the tool, it doesn't run anything itself. It sends back a structured request saying which tool to use and what details to use it with. Your program does the work and returns the result to Claude.
- AI model
- The trained system that understands and writes text. Claude is an AI model.
- Agent
- A program in which the model works towards a goal: it decides which steps to take, uses tools and checks results, in a loop, until the job is done.
- Tool
- A named capability with a description and a list of inputs that the agent can ask to use.
- Parameter (input)
- A piece of information the tool needs, such as an
order_id. - Tool call
- Claude's request to use a tool. In the Claude API this is a
tool_useblock. - Tool result
- What your code sends back after running the tool. In the API this is a
tool_resultblock. - API
- "Application Programming Interface": a way for one program to ask another program to do something.
- JSON
- A common text format for structured data, such as
{"order_id": "A1001"}. - Schema
- A description of what shape the data must have: which fields exist, their types, and which ones are required.
Model, agent and tool: what's the difference?
๐ง Model
The brain. It understands the request and decides what to do, but it can't touch anything outside the conversation.
๐ค Agent
The worker. The model plus your code running in a loop: think, act, look at the result, repeat.
๐งฐ Tool
The hands. Specific actions the agent may use, such as search, read, calculate or send.
Without tools, an agent can only talk. Without a model, tools are just functions that nobody chooses when to call. An agent needs both.
Why is it important?
- Up-to-date information: a model only knows what it learned during training. It doesn't know today's stock levels or your customer's order.
- Private information: your files, databases and company systems were never part of its training.
- Taking action: creating a ticket, booking a meeting or saving a file all happen in other systems.
- Accuracy: a calculator or database lookup gives an exact answer where a guess might be wrong.
Real-world analogy
Imagine a very knowledgeable assistant who can't leave their desk. On the desk is a pile of forms: "Order lookup form", "File request form", "Database search form". Each form has a title (the tool name), a short note explaining when to use it (the description) and blank boxes to fill in (the parameters).
When a customer asks "Where's my parcel?", the assistant fills in an order lookup form with the order number and hands it to a runner. The runner is your code. It goes to the warehouse system, comes back with the answer and hands it over. The assistant then replies to the customer. The assistant never walks into the warehouse, and that's what keeps the system safe.
How does it work?
- You describe the tools. Each tool has a
name, adescriptionand aninput_schemathat lists its parameters. - The user asks something. You send the question and the list of tools to Claude.
- Claude decides. If a tool would help, Claude replies with a
tool_useblock (for exampleget_order_statuswith{"order_id": "A1001"}) and the response'sstop_reasonis"tool_use". If no tool is needed, it simply answers. - Your code checks and runs the tool. Confirm the tool is allowed and the inputs make sense, then run it.
- You send back the result in a
tool_resultblock linked to the call by itstool_use_id. If something went wrong, send the error withis_error: true. - Claude continues. It may call another tool or write the final answer using the result.
Client tools are tools you define and run in your own code, like everything on this page. Server tools are tools Anthropic runs for you, such as web search and code execution. You switch a server tool on in your request and its results come back automatically. See the tool use overview.
Workflow diagram
Simple overview
Detailed workflow
Try it: simulated tool call
Available tools: get_order_status, read_file, delete_records (admin only)
Common kinds of tools
๐ Search documents
search_docs(query) finds matching passages in your help centre or policies, so Claude answers from your content.
๐ Call an API
get_weather(city) or create_ticket(title, body) call another service over the internet.
๐ Read files
read_file(path) returns a file's text. Restrict it to one safe folder.
๐๏ธ Query a database
find_customer(email) runs a fixed, safe query. Never let the model write raw database commands.
Practical example: order-status assistant
A shop wants its chat assistant to answer "Where's my order?" Here is what travels back and forth:
- The customer writes: "Hi! Where is my order a1001?"
- Claude replies with a tool call:
get_order_statuswith{"order_id": "A1001"}. Notice that it tidied up the lowercase "a1001". - Your code looks up the order and sends back
{"status": "shipped", "carrier": "DHL", "eta": "2026-10-20"}. - Claude writes: "Good news, order A1001 has shipped with DHL and should arrive around 20 October."
If the customer types an ID that doesn't exist, the tool returns an error. Claude then asks the customer to double-check the number instead of making up an answer.
Code example
A complete, runnable Python program. It needs the official anthropic package (pip install anthropic) and an API key stored in the ANTHROPIC_API_KEY environment variable on your computer or server. Never put an API key in a web page.
# tool_agent.py: a tiny agent with one tool.
# Setup: pip install anthropic, then set the ANTHROPIC_API_KEY environment variable.
import json
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from the environment
# 1. A pretend database. In a real app this would be your order system.
ORDERS = {
"A1001": {"status": "shipped", "carrier": "DHL", "eta": "2026-10-20"},
"A1002": {"status": "processing", "carrier": None, "eta": None},
}
# 2. Describe the tool so Claude knows WHEN and HOW to use it.
TOOLS = [{
"name": "get_order_status",
"description": "Look up the shipping status of a customer order by its order ID. "
"Use this whenever the user asks where an order is. IDs look like A1001.",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "The order ID, e.g. A1001"}
},
"required": ["order_id"],
},
}]
# 3. The real Python function that does the work.
def get_order_status(order_id: str) -> dict:
order_id = order_id.strip().upper()
if not (order_id.startswith("A") and order_id[1:].isdigit()):
raise ValueError(f"'{order_id}' is not a valid order ID")
if order_id not in ORDERS:
raise LookupError(f"No order found with ID {order_id}")
return {"order_id": order_id, **ORDERS[order_id]}
def run_tool(name: str, tool_input: dict) -> dict:
# Allowlist: only run tools we have explicitly approved.
if name == "get_order_status":
return get_order_status(**tool_input)
raise PermissionError(f"Tool '{name}' is not allowed")
def ask(question: str) -> str:
messages = [{"role": "user", "content": question}]
for _ in range(5): # safety limit so the loop can never run forever
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
tools=TOOLS,
messages=messages,
)
# No tool requested: this is the final answer.
if response.stop_reason != "tool_use":
return "".join(b.text for b in response.content if b.type == "text")
# Keep Claude's turn (including its tool_use blocks) in the history.
messages.append({"role": "assistant", "content": response.content})
results = []
for block in response.content:
if block.type != "tool_use":
continue
print(f"[tool call] {block.name}({block.input})")
try:
output = run_tool(block.name, block.input)
results.append({"type": "tool_result", "tool_use_id": block.id,
"content": json.dumps(output)})
except Exception as err: # report the problem to Claude instead of crashing
results.append({"type": "tool_result", "tool_use_id": block.id,
"content": f"Error: {err}", "is_error": True})
# All results go back together in ONE user message.
messages.append({"role": "user", "content": results})
return "Stopped: too many tool calls."
if __name__ == "__main__":
print(ask("Hi! Where is my order a1001?"))
Expected output (Claude's exact wording will vary):
[tool call] get_order_status({'order_id': 'A1001'})
Good news! Order A1001 has shipped with DHL and is expected to arrive on 20 October 2026.
The Python SDK also has a beta Tool Runner (client.beta.messages.tool_runner with the @beta_tool decorator). It writes the loop above for you. We wrote the loop by hand here so you can see every step. See How to implement tool use.
Step-by-step explanation
anthropic.Anthropic()creates a client. It reads your API key from the environment, so the key never appears in your code.ORDERSstands in for a real database so the example runs anywhere.TOOLSis the list of tool descriptions sent to Claude. Thedescriptionmatters most because Claude reads it to decide when to use the tool.input_schemais a JSON Schema that saysorder_idmust be text and is required.get_order_statusis ordinary Python. It validates the input (is it shaped like an order ID?) before using it, and raises a clear error otherwise.run_toolis an allowlist: if Claude ever asks for a tool you didn't approve, it is refused.- Inside
ask,client.messages.create(...)sends the conversation and the tools to the modelclaude-opus-5-5. - If
stop_reasonisn't"tool_use", Claude has finished, so we join its text blocks and return them. - Otherwise we save Claude's turn in
messages, run each requested tool, and build atool_resultfor each one, matched bytool_use_id. - Errors become
tool_resultblocks with"is_error": True, so Claude can explain the problem or try again instead of the program crashing. - The
for _ in range(5)limit stops a confused agent from looping forever and running up costs.
Inputs, execution, results and errors
| Stage | What happens | What can go wrong | What to do |
|---|---|---|---|
| Input parameters | Claude fills in the inputs your schema describes | Missing, badly formatted or unexpected values | Validate everything in your code. Adding "strict": true to a tool definition makes Claude's inputs match the schema exactly. |
| Execution | Your function runs | Timeouts, the service is down, not found | Catch the error, set a timeout, retry only when it's safe to do so |
| Returned result | You send text or JSON back | Huge results waste tokens and money | Return only the fields Claude needs |
| Error handling | You send an error result | Crashing, or hiding the error so Claude guesses | Send is_error: true with a clear, helpful message |
Permissions, validation and security
Claude can make mistakes, and text it reads (a web page, an email, a file) can contain hidden instructions trying to trick it. This is called prompt injection. Your code is the final gatekeeper.
- Least privilege: give the agent only the tools it needs. A read-only tool can't delete anything.
- Allowlists: run only tools you have listed, and limit file tools to one safe folder.
- Validate inputs: check types, formats and ranges before using them. Never pass model output straight into a database query or shell command.
- Check the user's rights: the person asking must be allowed to see or change that data.
- Ask a human first for anything that spends money, sends messages or deletes things. See Human in the Loop.
- Keep secrets on the server: API keys belong in environment variables on a backend, never in browser code.
- Log every call (tool, inputs, result, who asked) so you can investigate problems later.
Use cases
- Customer support bots that check orders, bookings or account status
- Research assistants that search the web or internal documents
- Coding assistants that read files and run tests (Claude Code works this way)
- Data helpers that run safe, predefined database queries and explain the results
- Office assistants that create calendar events or tickets, with approval
Advantages and limitations
โ Advantages
- Answers based on real, current data
- Can take real actions
- Exact results from calculators and databases
- You decide exactly what is possible
โ ๏ธ Limitations
- Each tool call adds time and cost
- Vague descriptions lead to the wrong tool being picked
- Tools bring security risks if they aren't guarded
- Too many similar tools confuse the model
๐ซ Common mistakes
- One-line descriptions like "gets data"
- Trusting tool inputs without checking them
- Returning huge raw results
- No limit on how many times the loop can run
Best practices
- Write descriptions as you would for a new colleague: what the tool does, when to use it, and what the inputs look like.
- Use clear, specific names such as
get_order_status, nottool1. - Keep each tool focused on one job, and keep the tool list small.
- Return compact, well-labelled results.
- Make error messages tell Claude how to recover ("Order IDs look like A1001").
- Test with confusing, wrong and malicious requests, not just the easy ones.
Knowledge check
1. When you define a client tool, who actually runs it?
Claude only requests the tool with a tool_use block. Your program runs it and sends back a tool_result. (Server tools such as web search are the exception: Anthropic runs those.)
2. What does Claude mainly use to decide which tool to call?
Clear names and detailed descriptions are the most important part of tool design.
3. Your tool fails because the order ID doesn't exist. What should your code do?
An error result lets Claude explain the problem or try again, instead of guessing or crashing.
4. Which statement best describes an agent?
The model is the brain, the tools are the hands, and the agent is the whole worker repeating think, act, check.
5. Why should an API key never be placed in website (frontend) code?
Everything sent to a browser can be read by visitors. Real API calls belong on a secure backend.
Mini project
Build an FAQ helper tool.
- Copy
tool_agent.py. Add a second tool,search_faq(question), that looks up answers in a small Python dictionary (for example shipping times, returns and opening hours). - Write a careful description that says when Claude should use
search_faqrather thanget_order_status. - If no FAQ entry matches, return an error result.
- Test it with: "How long do returns take?", "Where is order A1002?" and "What's your favourite colour?"
Success: the first question uses search_faq, the second uses get_order_status, and the third uses no tool at all.
Key takeaways
- Tools give an agent access to live data and real actions.
- Claude requests a tool, and your code decides whether and how to run it.
- Good names and descriptions are what make Claude choose the right tool.
- Always validate inputs, handle errors, limit the loop, and guard risky actions.
- Keep API keys on a server, never in the browser.
Further learning
- Tool use with Claude: overview (official docs)
- How to implement tool use (official docs)
- Anthropic Python SDK (official GitHub repository)
- Building effective agents, including its appendix on designing tools (Anthropic engineering blog)