Skip to main content

7.2 Tool Calling & Function Use

AI-Generated Content

AI-generated content may contain errors. Always verify against official sources.

7.2 Tool Calling & Function Use

Key Concepts: OpenAI function calling · Anthropic tool use · Schema definition

Official Docs: OpenAI Function Calling · Anthropic Tool Use


How Tool Calling Works

  1. Define tools as JSON schemas (name, description, parameters)
  2. The LLM decides if and which tool to call
  3. Your code executes the tool and returns the result
  4. The LLM incorporates the result and generates the final answer
User: "What is 123 × 456?"

LLM decides: call multiply(a=123, b=456)
Your code: returns 56088
LLM answer: "123 × 456 = 56,088"

OpenAI Tool Calling

from openai import OpenAI
import json

client = OpenAI()

tools = [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "Get the current stock price for a ticker symbol.",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "Stock ticker, e.g. AAPL"
}
},
"required": ["symbol"],
},
},
}
]

def get_stock_price(symbol: str) -> dict:
prices = {"AAPL": 189.50, "GOOG": 175.20, "MSFT": 415.80}
return {"symbol": symbol, "price": prices.get(symbol, 0), "currency": "USD"}

messages = [{"role": "user", "content": "What is the price of Apple stock?"}]

while True:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools,
tool_choice="auto",
)
msg = resp.choices[0].message
messages.append(msg)

if msg.tool_calls:
for tc in msg.tool_calls:
result = get_stock_price(**json.loads(tc.function.arguments))
messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": json.dumps(result),
})
else:
print(msg.content)
break

Anthropic Tool Use

import anthropic, json

client = anthropic.Anthropic()

tools = [
{
"name": "get_stock_price",
"description": "Get the current stock price for a ticker symbol.",
"input_schema": {
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "Stock ticker"}
},
"required": ["symbol"],
},
}
]

messages = [{"role": "user", "content": "What is Apple's stock price?"}]

while True:
resp = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=1024,
tools=tools,
messages=messages,
)

if resp.stop_reason == "tool_use":
messages.append({"role": "assistant", "content": resp.content})
tool_results = []
for block in resp.content:
if block.type == "tool_use":
result = get_stock_price(**block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result),
})
messages.append({"role": "user", "content": tool_results})
else:
print(resp.content[0].text)
break

Common Mistakes

Common Mistakes
  1. Trusting json.loads without validation — always validate tool arguments before executing. The model may pass wrong types or out-of-range values.
  2. Not looping on tool calls — the model may call multiple tools before giving a final answer. Always loop until finish_reason == "stop".
  3. Vague tool descriptions — the description is what the model reads to decide when to call a tool. Be precise: "Get the current EUR/USD exchange rate" not "Get a rate".
  4. No fallback when a tool fails — if the API your tool calls is down, return a descriptive error string so the model can tell the user what went wrong.

Quick Quiz

Test Your Understanding

Q1. What are the three steps in a tool-calling loop?
A1. (1) Model decides to call a tool and returns its name + arguments. (2) Your code executes the tool. (3) Result is injected back into messages. Loop until finish_reason == "stop".

Q2. In Anthropic’s API, what stop_reason indicates the model wants to call a tool?
A2. "tool_use".

Q3. Why should you validate tool arguments before execution?
A3. The model generates arguments as strings; it can produce values of the wrong type or outside valid ranges. Validation prevents downstream errors.


Student Exercise

Exercise 7.2 — Multi-tool agent
Build an agent with three tools: web_search(query) (mock), calculate(expression), and get_date() (returns today’s date). Test: "What day of the week is 60 days from today?" Observe the multi-step tool-calling loop.


Further Reading

Next → 7.3 Agent Frameworks