Artificial Intelligence (AI) October 18, 2026 0

Function Calling and Tool Use in AI Models

By Admin 5 min read

Language models on their own can only produce text. Function calling, also known as tool use, lets them ask your program to do something: look up an order, fetch the weather, query a database or create a calendar event. The model never runs your code directly. It returns a structured request, your code executes it, and you send the result back so the model can continue.

Why it matters

Without tools, a model must guess or rely on outdated knowledge. With tools it can:

  • Retrieve live, accurate data instead of hallucinating
  • Perform exact calculations instead of estimating
  • Take actions in your systems, such as creating a record or sending a message
  • Produce structured output that software can process reliably

The flow

  1. You describe available tools to the model: a name, a description and a JSON schema for the inputs.
  2. The user asks something, for example "Is order 4521 delivered yet?"
  3. The model decides it needs a tool and replies with a tool call, including a name and arguments such as {"order_id": 4521}.
  4. Your code validates the arguments and runs the real function.
  5. You send the result back to the model.
  6. The model uses the result to write a final answer for the user.

Several tool calls can happen in sequence or even in parallel.

Describing a tool

A tool definition has three important parts.

  • Name: short and clear, like get_order_status.
  • Description: explains when to use it and what it returns. This is the model's main clue, so write it carefully.
  • Input schema: JSON Schema describing parameters, types, allowed values and which are required.
tools = [
    {
        "name": "get_order_status",
        "description": "Get the current delivery status of a customer order by its numeric ID.",
        "input_schema": {
            "type": "object",
            "properties": {
                "order_id": {"type": "integer", "description": "The order number, e.g. 4521"}
            },
            "required": ["order_id"],
        },
    }
]

A complete example

import json
import anthropic

client = anthropic.Anthropic()

ORDERS = {4521: {"status": "out for delivery", "eta": "today before 6 pm"}}

def get_order_status(order_id: int) -> dict:
    return ORDERS.get(order_id, {"error": "order not found"})

tools = [{
    "name": "get_order_status",
    "description": "Get the delivery status of an order by its numeric ID.",
    "input_schema": {"type": "object",
                     "properties": {"order_id": {"type": "integer"}},
                     "required": ["order_id"]},
}]

messages = [{"role": "user", "content": "Where is my order 4521?"}]
first = client.messages.create(model="claude-sonnet-5-5", max_tokens=300,
                               tools=tools, messages=messages)

if first.stop_reason == "tool_use":
    call = next(b for b in first.content if b.type == "tool_use")
    result = get_order_status(**call.input)                       # your code runs it

    messages.append({"role": "assistant", "content": first.content})
    messages.append({"role": "user", "content": [{
        "type": "tool_result",
        "tool_use_id": call.id,
        "content": json.dumps(result),
    }]})
    final = client.messages.create(model="claude-sonnet-5-5", max_tokens=300,
                                   tools=tools, messages=messages)
    print(final.content[0].text)

The same idea works across providers, with slightly different field names.

Using tools for structured data extraction

You can define a tool whose only purpose is to receive structured data. Ask the model to "call save_contact" with name, phone and email extracted from a message, and then store the arguments directly. Because the output follows a schema, parsing is far more reliable than free text.

Best practices

  1. Write precise descriptions and keep the number of tools small. Too many similar tools confuse the model.
  2. Validate every argument in code. Treat model output as untrusted input, just like form data from a browser.
  3. Apply permissions. The tool should check that the current user may access that order or record.
  4. Return concise results. Large outputs waste tokens; return only what the model needs.
  5. Handle errors gracefully. Send back a clear error message so the model can recover or apologise.
  6. Set limits on the number of tool calls per request to prevent loops.
  7. Make risky actions two-step. For anything irreversible, require confirmation from a human.
  8. Log calls with arguments and results for debugging and audits.

Common mistakes

  • Trusting the model's arguments without checking types and ranges
  • Exposing powerful tools such as raw SQL or shell commands
  • Vague descriptions, causing wrong tool choices
  • Forgetting to send tool results back, leaving the conversation incomplete
  • Ignoring that tool outputs can contain malicious instructions (prompt injection)

Frequently Asked Questions

Does the model run my function?

No. It only outputs the name and arguments. Your program decides whether and how to run the function.

Can the model call several tools at once?

Many APIs allow parallel calls when the requests are independent. Your code should run each and return all results.

What if the model picks the wrong tool?

Improve the tool descriptions, reduce overlapping tools and add examples in the system prompt.

Is function calling the same as an agent?

It is a building block. An agent repeats tool calls in a loop to reach a goal; a single function call is just one step.

Conclusion

Function calling turns a language model into an interface for your software: it chooses the action, your code performs it safely, and the model explains the result. Define clear tools, validate everything and keep humans in charge of risky steps.