Function calling lets a large language model decide when to invoke a tool you've defined—fetching live weather, querying a database, sending an email—and output a structured request naming the function and its arguments, which your code then executes. It's the mechanism that turns a text generator into something that can take actions and reach real data. This function calling in LLMs tutorial walks through exactly how the loop works, a concrete code example, how to write tool definitions the model uses reliably, and the pitfalls—especially security—that trip up first-time builders.
What function calling actually is
The most important thing to understand up front is what the model does and doesn't do. The LLM never executes anything itself. You give it a set of tool definitions—each with a name, a description, and a list of parameters—and based on the user's request, the model decides whether to call a tool, which one, and what arguments to pass. It then outputs a structured request (typically JSON) describing that call. Your own code parses that request, runs the actual function, and hands the result back to the model.
So the division of labor is clean: the model reasons and formats, your code executes. The model is essentially saying "I'd like you to run get_weather with location: 'Tokyo'"—it can't run anything, reach the internet, or touch your database on its own. This is why function calling is safe by design in principle: nothing happens unless your code chooses to make it happen.
This capability is the underlying engine behind the broader concept of tool use in LLMs. "Tool use" describes the general ability of a model to work with external tools; "function calling" (also called "tool calling") is the specific mechanism—the structured request-and-response protocol—that makes it work. Understand function calling and you understand how nearly every LLM-powered application connects a model to the real world.
How the function calling loop works
Function calling follows a predictable cycle. For a single tool call, the flow is:
- Define your tools. Describe each available function with a schema: its name, what it does, and its parameters.
- Send the request. Pass the user's message and the tool definitions to the model.
- The model responds with either a normal text answer or a tool call—the name of a function and the arguments to pass it, as structured JSON.
- Your code executes. Parse the tool call, run the corresponding real function, and capture its result.
- Return the result to the model as a tool-result message, appended to the conversation.
- The model answers. It uses the result to produce its final response to the user.
The crucial point is that this is a loop, not a one-shot. After receiving a tool result, the model might decide it needs to call another tool—so steps 3 through 5 repeat: call, result, call, result, until the model has everything it needs and produces a final answer. That repeating loop, driven toward a goal, is precisely what an AI agent is. A weather bot might make one call; an agent booking travel might chain a dozen.
A concrete example
Here's the full cycle for a weather query. First, the tool definition you send to the model, using the JSON Schema format that's standard across providers:
{
"name": "get_weather",
"description": "Get the current weather for a city. Use when the user asks about weather.",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City name, e.g. 'Tokyo'" },
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location"]
}
}
The user asks, "What's the weather in Tokyo?" The model doesn't know the weather, but it recognizes the tool fits and responds with a tool call:
{ "name": "get_weather", "arguments": { "location": "Tokyo", "unit": "celsius" } }
Your code parses that, runs your real get_weather("Tokyo", "celsius") function—hitting a weather API—and gets back, say, { "temp": 18, "condition": "cloudy" }. You return that result to the model as a tool-result message. Finally, the model uses it to answer: "It's currently 18°C and cloudy in Tokyo."
The exact wire format varies slightly by provider—OpenAI uses a tools array and returns tool_calls, with results sent back as role: "tool" messages, while Anthropic uses tool_use and tool_result content blocks—but the concept and flow are identical everywhere.
Writing good tool definitions
Here's what separates reliable function calling from flaky function calling: the model decides which tool to call, and with what arguments, based almost entirely on your descriptions. Writing tool definitions is really a form of prompt engineering, and vague definitions produce wrong calls.
A few principles make definitions reliable:
- Use clear, specific names.
search_ordersbeatshandler2. - Describe what the tool does and when to use it. "Get the current weather for a city. Use when the user asks about weather" tells the model both the function and the trigger. The "when" is what guides its decision.
- Specify parameters precisely. Give each parameter a type, mark required ones, use
enumto constrain choices, and add a short description. Tight schemas produce well-formed arguments. - Keep the tool set focused. Too many tools—especially overlapping ones—cause decision paralysis and wrong choices. A handful of well-defined tools outperforms dozens of fuzzy ones.
Because the model must reason about which tool fits an ambiguous request, techniques that improve its reasoning help here too—prompting it to think step by step, as in chain-of-thought prompting, can improve tool-selection accuracy on complex, multi-step tasks. The clearer your definitions and the better the model's reasoning, the more reliably it calls the right tool at the right time.
Patterns, pitfalls, and building toward agents
A few patterns and dangers are worth knowing before you ship.
Useful patterns. Models can request parallel tool calls—several functions at once—when a task needs multiple independent lookups. You can also constrain behavior with a tool_choice setting to require, forbid, or auto-select tool use. And function calling doubles as a way to get structured output: defining a "tool" whose parameters are your desired data shape forces the model to return clean, validated JSON instead of free text. Increasingly, the Model Context Protocol (MCP)—an open standard introduced by Anthropic—standardizes how tools connect to models, so you can expose a tool once and use it across different applications instead of rewriting integrations.
The pitfalls that matter most:
- Never trust the model's arguments blindly. This is the big one. The model can hallucinate arguments, produce malformed values, or be manipulated by a prompt-injection attack in its input. Treat every tool call as untrusted input: validate arguments against your schema, check ranges and permissions, and never pass model output straight into a shell command, SQL query, or file path without sanitizing it. Sandbox anything dangerous.
- Handle errors by returning them to the model. If a tool fails, send the error back as the tool result rather than crashing. The model can often recover—retrying with corrected arguments or explaining the problem to the user.
- Remember it's probabilistic. The model won't call tools correctly 100% of the time; it may skip a needed call or invoke the wrong tool. Build for that reality, and measure it—systematically testing behavior is the subject of evaluating AI agent reliability.
- Watch cost and latency. Every turn of the loop is another model call, so a long tool-calling chain multiplies both. Keep loops as short as the task allows.
From function calling to agents. Once you're comfortable with the loop, you have the foundation of agents: an agent is essentially this loop running autonomously toward a goal, deciding tool after tool until the task is done. You rarely write this loop by hand in production—agent frameworks manage the orchestration, retries, and state for you, and multi-agent systems coordinate several such loops working together. Function calling is the primitive they're all built on.
Frequently asked questions
What is function calling in LLMs? It's a capability that lets a language model request the execution of predefined functions. You provide the model with tool definitions, and based on the user's request it outputs a structured JSON call naming a function and its arguments. Your code runs the actual function and returns the result, which the model uses to respond. The model decides and formats the call but never executes anything itself.
Does the LLM run the function itself? No—and this is the key point. The model only outputs a structured request describing which function to call and with what arguments. Your application code parses that request, executes the real function, and passes the result back. The model has no ability to run code, access the internet, or touch your systems on its own, which is why you control (and must secure) what actually gets executed.
What's the difference between function calling and tool use? Tool use is the broad concept of an LLM working with external tools to accomplish tasks. Function calling is the specific mechanism that enables it: the structured protocol by which the model requests a function and receives its result. In short, function calling is how tool use is implemented—the terms are often used interchangeably, but function calling refers to the underlying request-and-response cycle.
How do I make an LLM call the right function? Write clear tool definitions. The model chooses based on your descriptions, so give each tool a specific name, describe both what it does and when to use it, and define parameters precisely with types and constraints. Keep the tool set small and non-overlapping. Well-written definitions are the single biggest factor in reliable tool selection, since the model is essentially reading your descriptions to decide.
Is function calling secure? The mechanism is safe in principle because the model can't execute anything—your code does. But that makes your code responsible for security. The model's arguments are untrusted input that can be hallucinated or manipulated via prompt injection, so always validate them, enforce permissions, sanitize anything passed to shells, queries, or file systems, and sandbox risky operations. Never execute a model's tool call blindly.
The takeaway
This function calling in LLMs tutorial comes down to one mental model: the model decides and formats a structured call, and your code executes it, in a loop that repeats until the task is done—which is exactly the foundation every AI agent is built on. Get the fundamentals right by writing clear, focused tool definitions and, above all, treating the model's arguments as untrusted input you validate before executing. Your next step is to implement the full loop once by hand with a single simple tool—define it, send it, parse the call, run it, return the result—because building that cycle yourself is what makes everything about agents click into place.