ptrnsai

Function Calling

Basic🔧 Tool Use PatternsOpenAI / Anthropic

Intent

Enable LLMs to invoke external functions with structured parameters, bridging the gap between language and action.

Problem

LLMs can reason and generate text but can't directly interact with the world. They can't query databases, call APIs, or perform calculations. You need a reliable way for the model to specify which action to take with what parameters, in a format that can be programmatically executed.

Solution

Define a set of functions with typed parameters and descriptions. The LLM generates structured function calls (typically JSON) specifying which function to invoke and with what arguments. Your system executes the function and returns the result to the LLM for further reasoning. The key is treating tool definitions like API documentation for the model — the better your descriptions and parameter schemas, the more accurately the model will use them.

Diagram

User: "What's the weather in Tokyo?"
    ↓
LLM → { function: "get_weather", args: { city: "Tokyo" } }
    ↓
[System executes get_weather("Tokyo")]
    ↓
Result: { temp: 22, condition: "sunny" }
    ↓
LLM → "It's 22°C and sunny in Tokyo!"

When to Use

  • Any task requiring interaction with external systems
  • Database queries, API calls, calculations
  • When you need structured, reliable tool invocation
  • Building the 'hands' of an agent that can act in the world

When NOT to Use

  • Pure text generation tasks with no need for external data
  • When the model's training data is sufficient

Pros & Cons

Pros

  • Reliable, structured interaction with external systems
  • Model chooses the right tool and parameters based on context
  • Easy to add new tools by defining new function schemas
  • Works across all major LLM providers

Cons

  • Model may call wrong functions or pass wrong parameters
  • Tool descriptions need careful engineering
  • Each tool call adds latency
  • Security: model-directed actions need guardrails

Implementation Steps

  1. 1Define functions with clear names, descriptions, and typed parameter schemas
  2. 2Write descriptions as if documenting APIs for a junior developer
  3. 3Implement function execution and error handling
  4. 4Return results in a format the LLM can easily interpret
  5. 5Test with varied inputs to catch common misuse patterns
  6. 6Add parameter validation before executing any function

Real-World Example

E-commerce Agent

Agent has tools: search_products(query, filters), get_product_details(id), add_to_cart(product_id, quantity), check_inventory(product_id). User says 'Find me a blue jacket under $100.' Agent calls search_products with appropriate filters, presents results, and adds the user's choice to cart.

PythonOpenAI Function Calling
from openai import OpenAI
import json

client = OpenAI()

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name"},
                "units": {"type": "string", "enum": ["celsius", "fahrenheit"]},
            },
            "required": ["city"],
        },
    },
}]

def get_weather(city: str, units: str = "celsius") -> dict:
    return {"city": city, "temp": 22, "condition": "sunny", "units": units}

TOOL_MAP = {"get_weather": get_weather}

def chat(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]
    response = client.chat.completions.create(model="gpt-4o", messages=messages, tools=tools)
    msg = response.choices[0].message

    if msg.tool_calls:
        messages.append(msg)
        for call in msg.tool_calls:
            fn = TOOL_MAP[call.function.name]
            result = fn(**json.loads(call.function.arguments))
            messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
        response = client.chat.completions.create(model="gpt-4o", messages=messages)

    return response.choices[0].message.content

References