Tools and function calling: how a model gets things done
A model on its own can only write text. It can't read your files, query a database or send an email. Tools change that, and they're the foundation of every agent, MCP server and AI feature that does real work. The trick is simple once you see who does what.
1. The idea
Tool use, also called function calling, works in four steps:
- You describe the tools. Each has a name, a description (what it does and when to use it), and an input schema: the arguments it takes, written as JSON Schema.
- The model decides to call one. Instead of answering in prose, it replies with a structured request: the tool's name and the arguments, as JSON. That's the order ticket.
- Your code runs it. The model never executes anything. Your program calls the real function, API or database, with all the usual checks.
- You send the result back, and the model continues: it answers, or asks for another tool.
Some tools run on the vendor's side instead (server tools such as web search or code execution): you switch them on, and the vendor runs them for you. Either way, the model only ever asks; something else does.
2. How it works
Step through a real exchange with an order-status tool. The JSON uses the Claude API's field names; the other APIs use the same shape with different names (see the table below).
| API | Tool definition | The model asks | You answer with |
|---|---|---|---|
| Claude (Messages API) | name, description, input_schema | tool_use block (with stop_reason: "tool_use") | tool_result block with the matching tool_use_id |
| OpenAI (Responses API) | type: "function", name, description, parameters | function_call item with a call_id | function_call_output with the same call_id |
| Gemini API | Function declaration: name, description, parameters | A function call with name and arguments | A function result for that call |
All three can request several tools at once (parallel calls), let you force or forbid tool use (tool_choice or its equivalent), and offer a strict mode that guarantees the arguments match your schema.
3. Try it yourself: be the model
You're the model. The app gave you these four tools; for each request, choose what to do. Getting this right is exactly what the description text in a tool definition is for.
4. Why it matters at work
Whether you write tools for a product, build an MCP server (Module 16), or just choose which ones to connect, the same rules apply. Anthropic's engineers reported spending more time on their tools than on their prompts when building their coding agent.
- Write descriptions for the model. Say what the tool does, when to use it, and when not to: "Look up an order by its number. Use when the customer gives an order number; don't use for refunds."
- Few, sharp tools beat many vague ones. Every definition is sent with every request (it costs tokens) and every extra tool is another chance to pick the wrong one.
- Return small, structured results. Ten relevant rows, not the whole table. Paginate. Include a hint if the result is cut off.
- Return useful errors. "No order 4821; order numbers have 5 digits" lets the model recover; a stack trace doesn't.
- Enforce permissions in your code, never in the prompt. Check that this user may see this order inside the tool. The model can be talked into anything (Module 18).
- Mark irreversible tools and confirm them. "Creates a refund. Irreversible." Have your app ask a human before running it.
- Treat tool results as untrusted data. A web page or document a tool returns may contain text that tries to give the model new instructions. That's prompt injection, and it's why the rules above matter.
5. In your five tools
Coding agents are tool use in action: reading files, searching, editing and running commands are all tools. Every tool lets you see the calls and decide which ones need your approval. Checked October 2026.
| Tool | See its tools and calls | Control approvals |
|---|---|---|
| Claude Code | Each tool call appears in the session; /status lists the active tools; /mcp shows connected servers | /permissions: allow, ask or deny per tool or command |
| Antigravity CLI | Ctrl+O toggles the detailed trajectory of each step; /mcp, /skills | /permissions: request-review, always-proceed or strict |
| GitHub Copilot (VS Code) | Tool calls appear in the chat; the tools picker in the chat input shows and toggles available tools | Confirmation prompts per tool; auto-approve settings for trusted tools and terminal commands |
| Cursor | Tool calls appear in the agent chat | Run modes and an allowlist for commands that may run without asking |
| Codex CLI | Each command and edit appears in the session; /mcp for servers | /permissions: approval and sandbox settings |
6. Remember it
How this hook works: what “The model writes the order; your code cooks” means
What the slogan means, phrase by phrase
- “The model writes the order”
- A tool call is text: a name and JSON arguments, like an order ticket. Writing it changes nothing in the world.
- “your code cooks”
- Your program (or the vendor, for server tools) is the kitchen: it runs the real function, with real permissions, and decides whether to run it at all.
- Implied: the dish comes back to the table
- The result goes back into the conversation, and the model uses it to answer or to write the next order.
Why this picture fits: it makes the most important safety fact obvious. A waiter can write a silly order; a good kitchen refuses it. All the control (permissions, validation, confirmation) lives in the kitchen, never in the waiter's good intentions.
The story → the concept
| In the restaurant | In tool use |
|---|---|
| The menu | Tool definitions: names, descriptions, input schemas |
| The order ticket | The tool call: a name plus JSON arguments |
| A ticket the kitchen can't read | Arguments that don't match the schema (strict mode prevents these) |
| The kitchen | Your code (client tools) or the vendor (server tools) |
| "Sorry, we're out of that" | An error result the model can recover from |
| The manager approves a large order | Human confirmation for irreversible tools |
| Bringing the dish back | The tool result, sent back to the model |
Watch it on an example
A customer writes: "Refund order 48213, it arrived broken."
- The model writes an order:
get_order(order_id="48213"). Your code checks this customer owns that order, then looks it up. - The result comes back: delivered 2 days ago, £24.
- The model writes the next order:
create_refund(order_id="48213", reason="damaged"). - Your code sees a tool marked irreversible and asks a support agent to approve it. The model never had the power to refund anything on its own.
The trap it saves you from
Thinking "the AI did it", and putting the guard rails in the prompt ("never refund over £100"). Prompts can be argued with; the kitchen's rules can't. Put the check in the tool.
It still works when…
You meet MCP (Module 10): it's a standard menu format, so any app can read any kitchen's menu. And agents (Module 07) are simply many orders in a row: order, dish, order, dish, until the job is done.
7. Common mistakes
process(data) gives the model nothing to choose by. Name the action, say when to use it, and give an example input.8. Hands-on lab (30 minutes)
- Read a trajectory. Give a coding agent a small task and open its detailed view (expand the tool calls; Ctrl+O in Antigravity CLI). List every tool it called and why.
- Approvals. Open the permissions settings in two tools. Which tools run without asking, and which ask first? Would you change any?
- Write a tool definition. For one real action in your product, write the name, the description (when to use it, when not to) and the input schema. Run it through the "be the model" test: would a newcomer pick it correctly?
- Optional, with an API key: run the round trip yourself with the short example below, then add a second tool and ask a question that needs both.
import anthropic, json
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
tools = [{
"name": "get_order",
"description": "Look up one order by its 5-digit number. Use when the user gives an order number.",
"input_schema": {"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}]
messages = [{"role": "user", "content": "Where is order 48213?"}]
reply = client.messages.create(model="claude-sonnet-5-5", max_tokens=1024, tools=tools, messages=messages)
call = next(b for b in reply.content if b.type == "tool_use") # the order ticket
result = {"status": "shipped", "eta": "2026-10-15"} # your code cooks (a real lookup goes here)
messages += [{"role": "assistant", "content": reply.content},
{"role": "user", "content": [{"type": "tool_result", "tool_use_id": call.id,
"content": json.dumps(result)}]}]
final = client.messages.create(model="claude-sonnet-5-5", max_tokens=1024, tools=tools, messages=messages)
print(final.content[0].text) # "It shipped and should arrive on 15 October."
9. Self-check quiz
Who actually runs a client tool's function?
What does the model mainly use to decide which tool to call?
Where should "users may only see their own orders" be enforced?
Your tool keeps receiving arguments in the wrong shape. Which feature helps?
10. Go deeper
| Resource | Time | Why |
|---|---|---|
| Tool use with Claude (Anthropic) | 20 min | The round trip, client vs server tools, strict mode and pricing. |
| Function calling (OpenAI) | 20 min | The same ideas in the Responses API, plus built-in tools. |
| Function calling (Gemini) | 20 min | Parallel and compositional calling and calling modes. |
| Writing effective tools for agents (Anthropic) | 20 min | How to design, evaluate and improve tools an agent will use. |