OpenAI Function Calling Guide

OpenAI Function Calling and Tools: Complete Tutorial

Function calling (also known as tool use) allows GPT models to generate structured JSON arguments for functions you define, enabling the model to interact with external APIs, databases, and systems. This is one of the most powerful features of the OpenAI API, transforming language models from text generators into intelligent agents.

How Function Calling Works

  1. You define one or more tools (functions) with names, descriptions, and parameter schemas
  2. You send a user message along with the tool definitions
  3. The model decides whether to call a function and generates the arguments as JSON
  4. Your code executes the function with those arguments
  5. You send the function result back to the model
  6. The model generates a final response incorporating the function result

Basic Example: Weather Function

from openai import OpenAI
import json

client = OpenAI(base_url="https://claude4u.com/v1")

# Step 1: Define tools
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "City and state, e.g. San Francisco, CA"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "Temperature unit"
                }
            },
            "required": ["location"]
        }
    }
}]

# Step 2: Send message with tools
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=tools,
    tool_choice="auto"
)

message = response.choices[0].message

# Step 3: Check if the model wants to call a function
if message.tool_calls:
    tool_call = message.tool_calls[0]
    args = json.loads(tool_call.function.arguments)
    print(f"Function: {tool_call.function.name}")
    print(f"Arguments: {args}")

    # Step 4: Execute the function (your implementation)
    weather_result = {"temperature": 22, "condition": "Partly cloudy"}

    # Step 5: Send the result back
    followup = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "user", "content": "What's the weather in Tokyo?"},
            message,
            {
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(weather_result)
            }
        ],
        tools=tools
    )
    print(followup.choices[0].message.content)

Node.js Implementation

import OpenAI from 'openai';

const client = new OpenAI({ baseURL: 'https://claude4u.com/v1' });

const tools = [{
    type: 'function',
    function: {
        name: 'search_products',
        description: 'Search for products in the catalog',
        parameters: {
            type: 'object',
            properties: {
                query: { type: 'string', description: 'Search query' },
                category: { type: 'string', enum: ['electronics', 'clothing', 'books'] },
                max_price: { type: 'number', description: 'Maximum price in USD' }
            },
            required: ['query']
        }
    }
}];

const response = await client.chat.completions.create({
    model: 'gpt-4o',
    messages: [{ role: 'user', content: 'Find me a laptop under $1000' }],
    tools,
    tool_choice: 'auto'
});

const toolCall = response.choices[0].message.tool_calls?.[0];
if (toolCall) {
    const args = JSON.parse(toolCall.function.arguments);
    console.log('Function:', toolCall.function.name);
    console.log('Args:', args);
}

Multiple Functions

You can define multiple tools, and the model will choose the appropriate one:

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get current weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string"}
                },
                "required": ["location"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "search_web",
            "description": "Search the web for information",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string"}
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "send_email",
            "description": "Send an email to a recipient",
            "parameters": {
                "type": "object",
                "properties": {
                    "to": {"type": "string", "format": "email"},
                    "subject": {"type": "string"},
                    "body": {"type": "string"}
                },
                "required": ["to", "subject", "body"]
            }
        }
    }
]

Parallel Function Calls

GPT-4o can request multiple function calls in a single response. Handle them all before sending results back:

message = response.choices[0].message

if message.tool_calls:
    tool_results = []
    for tool_call in message.tool_calls:
        name = tool_call.function.name
        args = json.loads(tool_call.function.arguments)

        # Execute each function
        result = execute_function(name, args)

        tool_results.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result)
        })

    # Send all results back
    followup = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "user", "content": original_message},
            message,
            *tool_results
        ],
        tools=tools
    )

Controlling Tool Choice

Tip: Write detailed function descriptions. The model uses these descriptions to decide when and how to call each function. Vague descriptions lead to incorrect function calls.

Function Calling with Streaming

When streaming with function calls, you need to accumulate the tool call arguments across chunks:

stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What's the weather in Paris and London?"}],
    tools=tools,
    stream=True
)

tool_calls = {}
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.tool_calls:
        for tc in delta.tool_calls:
            idx = tc.index
            if idx not in tool_calls:
                tool_calls[idx] = {"id": tc.id, "name": tc.function.name, "arguments": ""}
            if tc.function.arguments:
                tool_calls[idx]["arguments"] += tc.function.arguments
Warning: Always validate function arguments before executing them. The model can generate invalid JSON or unexpected values. Use try/except around json.loads() and validate required fields.
Tip: claude4u.com supports function calling across all compatible models, including OpenAI and Claude. This means you can write your tool definitions once and use them with any supported model by simply changing the model parameter.

Get Started with 轻舟 AI

Stable, fast AI API relay — supports Claude, OpenAI, Gemini and more

Sign Up Free