Function Calling & Tool Integration

Medium 25 min read

Function Calling Overview

Why Function Calling Matters

The Problem: Early tool use required fragile text parsing to extract tool names and arguments from LLM output, leading to frequent failures.

The Solution: Native function calling lets the LLM output structured tool invocations directly, with the API handling parameter validation and formatting.

Real Impact: Function calling reduced tool invocation errors by over 90% and is now the standard way to build tool-using agents.

Real-World Analogy

Think of function calling like a voice-activated smart home:

  • Function Schema = The list of devices and their controls
  • Function Call = "Turn on living room lights to 80%"
  • Execution = Smart hub sends the command to the device
  • Result = "Living room lights set to 80%"
  • Parallel Calls = "Turn on lights AND set thermostat to 72"

Function Calling Flow

Schema Definition

Define function name, description, and parameters using JSON Schema. The LLM uses this to decide when and how to call.

Model Decision

The LLM decides whether to call a function and which one, based on the request and available functions.

Structured Output

Instead of free text, the model outputs a structured function call with typed arguments.

Result Integration

Your code executes the function, and the result is sent back to the model to generate a final response.

Defining Functions

Function Calling Flow
User Message + tool schemas LLM Decides call function? Function Call {name, args} Your Code executes function LLM + Result final response
function_calling.py
from openai import OpenAI
client = OpenAI()

tools = [{
    "type": "function",
    "function": {
        "name": "search_database",
        "description": "Search the product database",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {"type": "string"},
                "limit": {"type": "integer", "default": 10}
            },
            "required": ["query"]
        }
    }
}]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Find laptops under $1000"}],
    tools=tools
)

# Model returns structured function call
tool_call = response.choices[0].message.tool_calls[0]
# tool_call.function.name = "search_database"
# tool_call.function.arguments = '{"query":"laptops under $1000"}'

Parallel Function Calls

Parallel Execution

  • OpenAI: Model can return multiple tool_calls in one response
  • Claude: Supports multiple tool_use blocks in a single response
  • Execute concurrently: Run all tool calls in parallel for speed
  • Return all results: Send all results back in subsequent messages

Error Handling

Error TypeCauseSolution
Invalid JSONMalformed argumentsReturn parse error, model self-corrects
Missing paramsRequired field omittedReturn validation error with details
Tool not foundHallucinated function nameReturn list of available tools
Execution errorTool throws exceptionReturn error message as tool result

Provider Comparison

ProviderAPI FieldParallel CallsForced Calling
OpenAItools + tool_choiceYestool_choice: {type: "function"}
Anthropictools + tool_choiceYestool_choice: {type: "tool"}
Googletools + tool_configYestool_config: {mode: "any"}
Mistraltools + tool_choiceYestool_choice: "any"

Quick Reference

ConceptDescriptionKey Point
Function SchemaJSON Schema definition of toolGood descriptions improve accuracy
tool_choiceControls when model calls toolsauto, none, required, specific
Parallel CallsMultiple tools in one responseExecute concurrently for speed
StreamingStream function call argumentsShow progress during long calls
ValidationCheck args before executionPrevent injection and errors