Tool Use and Function Calling
Tool use and function calling is the capability that allows large language models (LLMs) to invoke external functions, APIs, and services during inference — bridging the gap between static text generation and dynamic interaction with the real world. It matters because it transforms LLMs from read-only knowledge retrieval systems into active agents that can fetch live data, run computations, and trigger side effects. The counterintuitive fact: the model never actually executes any code itself — it only outputs a structured description of what it wants to call, and an external orchestrator does the real work.
An LLM with tool use doesn't run your Python functions — it decides which function to call and what arguments to pass, then hands that decision back to your application as structured data (usually JSON). Your code reads that JSON, actually calls the function, and feeds the result back into the conversation. The "aha moment" is realizing the LLM is acting like a very smart dispatcher: it reads a menu of available tools, figures out which tool fits the user's request, fills in the order form, and waits for the kitchen to cook the meal.
How It Works
Function calling works through a structured conversation loop. The model is given a list of tool schemas — descriptions of what each function does, what parameters it takes, and what types those parameters are. When the model decides a tool is needed, it emits a special response instead of plain prose. The decision loop can be described simply. At each step, the model scores whether to answer directly or invoke a tool:
Explanation: The model picks the action â (either "respond in text" or "call tool T with args") that has the highest probability given the user input x and the set of available tools 𝒯. Here, is the set of all possible actions (one per tool plus the "just talk" option), is the conversation so far, and is the tool schema list injected into the system prompt or a dedicated API field. After a tool is called and the result is returned, the model computes its next response conditioning on the augmented context:
Explanation: The final reply y is generated using not just the original input x, but also the tool call that was made and the result that came back. Here is the tool invocation (function name + arguments) and is the tool's return value, both appended as new messages before the model generates its answer. Here is the fundamental orchestration loop in Python: ```python import json import openai client = openai.OpenAI()
# 1. Define the tool schema tools = [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current temperature for a city.", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "The city name, e.g. 'London'" } }, "required": ["city"] } } } ]
# 2. The actual Python function the model wants to call def get_weather(city: str) -> dict:
# In a real app this would call a weather API return {"city": city, "temperature_c": 18, "condition": "Cloudy"}
# 3. First model call — model may request a tool messages = [{"role": "user", "content": "What's the weather in Paris?"}] response = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, tool_choice="auto" # model decides whether to call a tool ) msg = response.choices[0].message
# 4. Check if the model wants to call a tool if msg.tool_calls: tool_call = msg.tool_calls[0] func_name = tool_call.function.name # "get_weather" func_args = json.loads(tool_call.function.arguments) # {"city": "Paris"}
# 5. WE run the function — not the model result = get_weather(**func_args)
# 6. Feed the result back as a new message messages.append(msg) # assistant's tool-call request messages.append({ "role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result) })
# 7. Second model call — now model has the data and writes a response final = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools ) print(final.choices[0].message.content)
# → "It's currently 18°C and cloudy in Paris." ``` A key structural piece is the tool schema — a JSON Schema object telling the model exactly what shape the arguments must take: ```python
# Richer schema example with multiple parameters and types weather_schema = { "name": "get_forecast", "description": "Get a multi-day weather forecast for a location.", "parameters": { "type": "object", "properties": { "city": {"type": "string"}, "days": {"type": "integer", "minimum": 1, "maximum": 7}, "units": {"type": "string", "enum": ["celsius", "fahrenheit"]} }, "required": ["city", "days"] } } ``` When multiple tools are available, the model can call them sequentially (one at a time, waiting for results) or — in systems that support it — in parallel, batching several tool calls in one response: ```python
# Parallel tool calls — model returns a list of tool_calls for tool_call in msg.tool_calls: # iterate over all requested calls name = tool_call.function.name args = json.loads(tool_call.function.arguments) result = dispatch(name, args) # your router function messages.append({ "role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result) }) ```
Jason Wei is a researcher at OpenAI (formerly Google Brain) who co-authored the landmark chain-of-thought prompting paper (2022) and the seminal "Emergent Abilities of Large Language Models" paper. His work on reasoning traces laid conceptual groundwork for understanding why large models can plan multi-step tool use sequences rather than just single calls. Surprisingly, Wei started his PhD program but left before completing it to join Google Brain as a full-time researcher — one of the most consequential early-career pivots in recent AI history.
Intuition
Imagine you're a brilliant analyst who has never left the office and can only communicate by reading and writing memos. A colleague asks you: "What flights are available from New York to Tokyo next Friday?" You can't browse the internet yourself, but you can write a perfectly structured request slip and slide it under the door: `{"tool": "flight_search", "origin": "JFK", "destination": "NRT", "date": "2025-08-01"}`. Someone outside your office runs the search, writes the results on a new memo, and slides it back. You then read that memo and write a beautiful, conversational answer for your colleague. That's exactly what an LLM does with tool use — it writes the request slip (JSON), you run the search, and it writes the final answer. The model's entire contribution is deciding what to ask for and how to present the answer — the actual work of fetching information happens entirely outside it.
Historical Development
Origins · 1 minhow this was discovered
Why It Matters
Prerequisites
What This Leads To
See Also
AI Agents and Agentic Loops · Retrieval-Augmented Generation · Prompt Engineering · Chain-of-Thought Prompting · Multi-Agent Frameworks