All posts
AI & ML

Function Calling and Tool Use: Getting Reliable Actions From an LLM

A model that can only talk is a chatbot. A model that can call your functions is an agent. Function calling is the bridge — and getting it reliable is mostly about tool design, validation, and not trusting the model blindly. Here is how it works.

Dhileep Kumar7 min read
Function Calling and Tool Use: Getting Reliable Actions From an LLM

On its own, a language model can only produce text. It cannot check your calendar, query a database, or send an email. Function calling — also called tool use — is the mechanism that lets it do all of those things: instead of answering, the model can ask your code to run a specific function with specific arguments, see the result, and keep going.

This one capability is what turns a chatbot into an agent. Every coding assistant, research agent, and customer-support bot that actually does things rather than just describing them runs on tool calling underneath. The idea is simple; the reliability is where the real engineering lives.

How the loop actually works

You never let the model run code directly. You describe the tools it is allowed to use, the model decides which to call and with what arguments, and your code does the actual running. It is a conversation with a strict handoff at each step.

  • You provide tools: each one is a name, a plain-language description, and a JSON schema for its arguments. The description is how the model knows when to reach for it.
  • The model decides. Given the conversation, it either answers in text or emits a structured request — this tool, these arguments — without running anything.
  • Your code executes. You parse the arguments, validate them, run the real function, and capture the result.
  • You feed the result back into the conversation and call the model again. It reads the result and either calls another tool or writes the final answer.

It is structured output, but for actions

Function calling is a cousin of structured output. Structured output forces the model's final answer into a fixed shape, like JSON. Tool calling uses the same machinery to produce something different: a request to act, which your system fulfills before the model continues. One shapes the answer; the other shapes a step.

That distinction matters because a tool call is not the end of the turn — it is the middle of one. The model emits a call, waits for the result you return, and only then keeps reasoning. A single user question can trigger a whole chain of calls before any text comes back.

Defining and handling a tool

In code, a tool is a schema you pass in and a function you run when the model asks for it. The round-trip looks like this:

python
# Give the model a tool, run the call it requests, then feed the result back.
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a city. Use it for any weather question.",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]

resp = client.chat.completions.create(model="gpt-4o", messages=messages, tools=tools)
for call in resp.choices[0].message.tool_calls or []:
    args = json.loads(call.function.arguments)        # validate these before trusting them
    result = TOOLS[call.function.name](**args)        # run the real function
    messages.append({"role": "tool", "tool_call_id": call.id, "content": str(result)})
# call the model again with the tool results appended; now it writes the final answer

Everything past this — parallel calls, retries, multi-step plans — is just more turns around the same loop: describe tools, let the model ask, run it yourself, return the result.

The model does not call your functions; it requests that you call them. That gap is your safety margin — every argument it produces is a suggestion to validate, not a command to obey.

Where reliability is won or lost

  • Descriptions are prompts. The tool name and description are the only things the model uses to decide when and how to call it — vague ones cause wrong or missing calls. Write them like instructions.
  • Validate every argument. Models hallucinate arguments and occasionally invent tool names. Check the arguments against the schema before you execute anything.
  • Return errors as results, not exceptions. When a call fails, hand the model a clear error message as the tool result; it can usually correct itself and retry.
  • Guard side effects. Never auto-run anything destructive or costly on the model's say-so — require confirmation for those, and treat tool outputs themselves as untrusted input.
  • Cap the loop. An agent can call tools forever; set a maximum number of steps so a confused model cannot spin in circles or run up a bill.

The bottom line

Function calling is the difference between a model that talks about a task and one that completes it. The protocol is small — describe tools, let the model request a call, run it yourself, feed back the result — but the quality lives in the details: sharp descriptions, strict validation, graceful errors, and hard limits on what the model can trigger.

Treat the model as a smart planner that proposes actions and your code as the adult that checks and executes them. Get that division of labor right and tool use is reliable; blur it — let the model's output run unchecked — and you have built something that works in the demo and fails in production.

Share

Enjoyed this?

Get the next deep dive in your inbox. No spam — just the stories worth reading.

Subscribe to the newsletter

Comments