Tool Calling / Function Calling
Module 06 — Tool Calling / Function Calling
Goal: Understand how to let a model use tools — calculators, search, databases, APIs, code — so it can do things it can’t do from memory alone. This is the foundation of useful AI applications and agents.
6.1 The problem tools solve
From Module 01 you know the model:
- Can’t reliably do exact math.
- Doesn’t know today’s data, prices, or your private records.
- Can’t take real actions (send an email, query a database, book a flight).
- Can hallucinate facts it “remembers.”
Tool calling (a.k.a. function calling) fixes this by giving the model a set of tools it can ask to use. Instead of guessing, the model says “call the get_weather tool with city=Paris,” your code runs the real function, and the result is handed back to the model to use in its answer.
Analogy: The model is a smart manager who can’t personally run to the warehouse. You give it a phone with labeled buttons (tools). It decides which button to press and what to say; your staff (your code) does the physical work and reports back.
6.2 How tool calling actually works (the loop)
Crucially: the model does not run the tool itself. It only requests a call by emitting structured data (the tool name + arguments, as JSON — this is why Module 05 matters). Your application code executes the tool and returns the result. The cycle:
1. You define tools (name, description, parameter schema) and send them with the prompt.
2. User asks something. The model decides: answer directly, or call a tool.
3. If it calls a tool, it outputs: tool name + arguments (structured JSON).
4. YOUR CODE runs that tool with those arguments and gets a real result.
5. You send the result back to the model (as a "tool result" message).
6. The model uses the result to produce its final answer — or calls another tool.
7. Repeat 3–6 until the model is done, then it replies to the user.
This back-and-forth is a loop, and it can run multiple times (call search → call calculator → answer). Managing this loop well is core to agents (Module 08).
6.3 Defining a tool
You describe each tool to the model with three things:
- Name — e.g.,
get_weather. - Description — what it does and when to use it. This is prompt engineering! A clear description is how the model knows to pick the right tool.
- Parameters — a JSON Schema (Module 05) of the inputs: names, types, which are required, allowed values.
Example tool definition (provider formats vary slightly, but all carry this info):
{
"name": "get_weather",
"description": "Get the current weather for a city. Use when the user asks about current weather or temperature.",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "City name, e.g. 'Paris'" },
"units": { "type": "string", "enum": ["celsius", "fahrenheit"], "default": "celsius" }
},
"required": ["city"]
}
}
You typically pass a list of such tools. The model reads the descriptions and schemas to decide which (if any) to call and how to fill the arguments.
6.4 A walkthrough example
You send: the user message + the get_weather tool definition.
User: “What should I wear in Paris today?”
Model responds with a tool call (not text):
{ "tool": "get_weather", "arguments": { "city": "Paris", "units": "celsius" } }
Your code runs get_weather("Paris"), gets { "temp_c": 8, "condition": "rainy" }, and sends that back as a tool-result message.
Model then replies to the user:
It’s about 8°C and rainy in Paris right now. Wear a warm waterproof jacket and bring an umbrella.
The model combined a real fact (from your tool) with its language ability. No hallucinated weather.
6.5 Minimal code sketch (Python-style pseudocode)
Don’t worry about exact API syntax (it differs by provider and changes over time — always check current docs). Focus on the shape:
tools = [ get_weather_tool_definition ] # the JSON from 6.3
# 1. First call: send user message + tools
response = model.chat(messages=[user("What should I wear in Paris today?")],
tools=tools)
# 2. Did the model ask for a tool?
if response.tool_call:
name = response.tool_call.name # "get_weather"
args = response.tool_call.arguments # {"city": "Paris", "units": "celsius"}
# 3. YOUR code executes the real function
result = run_function(name, args) # {"temp_c": 8, "condition": "rainy"}
# 4. Send the result back so the model can finish
final = model.chat(messages=[
user("What should I wear in Paris today?"),
assistant_tool_call(response.tool_call),
tool_result(name, result),
], tools=tools)
print(final.text) # the natural-language answer
else:
print(response.text) # model answered without a tool
The key insight: you wire up an execute-and-return-result loop. The model orchestrates; your code does the doing.
6.6 Writing tool definitions well (this is prompt engineering)
The model’s ability to use tools correctly depends almost entirely on how you describe them. Treat tool descriptions like mini-prompts:
- Name things clearly and consistently.
search_ordersbeatsdo_thing. - In the description, say what it does AND when to use it (and when NOT to). e.g., “Use to look up an order by ID. Do not use for general product questions.”
- Describe every parameter: meaning, format, examples, allowed values. Ambiguous params → wrong arguments.
- Mark required vs. optional and give defaults where sensible.
- Keep the tool set focused. Too many overlapping tools confuses the model about which to pick. Group or trim.
- Make tools do one clear thing. Narrow, well-named tools are chosen more accurately than giant do-everything tools.
- Return clean, structured results from your code (JSON the model can read), including error info (“no order found”) so the model can recover gracefully.
6.7 Guiding when and how the model uses tools
You shape tool behavior with system-prompt instructions too:
You have access to tools. Follow these rules:
- For any question about current data (weather, prices, inventory, user records),
ALWAYS use the relevant tool instead of answering from memory.
- Do the math with the calculator tool; never compute large arithmetic yourself.
- If a tool returns an error or no result, tell the user plainly; do not invent data.
- Only call tools that are necessary. Don't call a tool if you can answer directly.
- After getting tool results, summarize them clearly for the user.
Many APIs also expose a tool-choice setting: auto (model decides), required/any (must call some tool), none (don’t call), or force a specific tool. Use forcing when you know a tool must run (e.g., always classify via your function).
6.8 Common kinds of tools
- Information retrieval: web search, documentation lookup, database queries, vector search over your documents (leads into RAG, Module 08).
- Computation: calculator, code execution / sandbox, data analysis.
- Actions: send email, create a ticket, post a message, schedule an event, call another API.
- Structured extraction: a “function” whose only purpose is to receive structured arguments (a clean way to get structured output, Module 05).
Safety note: Tools that take actions or spend money or delete data are high-stakes. Add confirmation steps, permission checks, and limits in your code — never let the model trigger irreversible actions unguarded. More in Module 10.
6.9 Multi-tool and multi-step usage
Real tasks often need several calls:
“Email me a summary of yesterday’s sales vs. our target.”
The model might: call get_sales(date=yesterday) → call get_target(...) → reason about the comparison → call send_email(...). Each step uses the previous result. This chained tool use is exactly what agents do (Module 08), often combined with reasoning (ReAct: reason, then act, then observe, repeat).
Practical tips for multi-step tool use:
- Cap the number of tool calls to avoid runaway loops.
- Handle tool errors so one failure doesn’t crash the whole flow — return the error to the model and let it adapt or stop.
- Log every tool call and result for debugging and evals (Module 09).
6.10 MCP and tool ecosystems (brief, for awareness)
You’ll encounter standardized ways to connect tools to models, such as the Model Context Protocol (MCP) — a common interface so tools/data sources (“servers”) can be plugged into AI apps (“clients”) without custom glue each time. You don’t need it to learn tool calling, but know that the industry is converging on standards so the same tool can be reused across apps. The underlying concept is identical to what you learned here: described tools, the model requests calls, your side executes them.
6.11 Common pitfalls
| Pitfall | Fix |
|---|---|
| Vague tool descriptions | Spell out purpose, when-to-use, and every parameter |
| Model answers from memory instead of calling the tool | System rule: “always use tool X for current data”; consider forcing tool choice |
| Wrong arguments | Tighten parameter schema/descriptions; add examples; validate args in code |
| Model invents data when a tool errors | Return clear error results; instruct “never fabricate; report the error” |
| Infinite tool-call loops | Cap iterations; detect repeats; add a stop condition |
| Dangerous actions executed blindly | Require confirmation/permissions in code for any write/spend/delete |
| Too many similar tools | Reduce/merge; make each tool distinct and well-named |
Exercises
- Design tools (no code). For a pizza-ordering assistant, write JSON tool definitions for
get_menu,add_to_cart(item, size, quantity), andplace_order(payment_method). Write crisp descriptions and parameter schemas with enums where useful. - Trace the loop. For the message “Order me a large pepperoni,” write out the sequence of tool calls, the (made-up) results, and the model’s final reply — step by step as in 6.4.
- Guardrail prompt. Write system-prompt rules so the assistant always confirms with the user before calling
place_order, and never invents menu items. - (If you code.) Using your provider’s SDK, implement the weather example end-to-end with a fake
get_weatherthat returns hard-coded data. Make the full request→tool-call→result→answer loop work. - Failure handling. Decide what
get_menushould return if the menu service is down, and how you’d instruct the model to respond to the user in that case.
Key takeaways
- Tool/function calling lets the model do things it can’t from memory: real math, live data, actions.
- The model only requests calls (as structured JSON); YOUR code executes them and returns results in a loop.
- Tool definitions (name, description, parameter schema) are prompt engineering — clarity here drives correctness.
- Use system rules and tool-choice settings to control when tools are used; always handle errors and never fabricate.
- Guard high-stakes/irreversible actions with confirmations and permissions. Multi-step tool use is the basis of agents.