Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openai/openai-cookbook/llms.txt

Use this file to discover all available pages before exploring further.

Function calling lets chat models interact with your code. You define one or more functions as tools using JSON schema, pass them to the model alongside a user message, and the model decides whether to call a function — and if so, with what arguments. Your application then executes the function and returns the result. The model incorporates that result into its final response. This round-trip between your code and the model is the fundamental building block of every agent.

Defining tools

Each tool is a JSON object with a type of "function" and a function description that includes a name, a description the model uses to decide when to call it, and a parameters schema in JSON Schema format.
from openai import OpenAI
import json

client = OpenAI()

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "City and state, e.g. 'San Francisco, CA'"
                    }
                },
                "required": ["location"]
            }
        }
    }
]
Write clear, specific descriptions. The model uses the description — not the function name — to decide when to call the tool. Be explicit about what the function does and what format the arguments should be in.

Calling the model with tools

Pass the tools array to chat.completions.create. The model will respond with either a normal message or a tool_calls object.
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What's the weather in SF?"}],
    tools=tools,
)

message = response.choices[0].message
print(message.tool_calls)
# [ChatCompletionMessageToolCall(
#     id='call_abc123',
#     function=Function(name='get_weather', arguments='{"location": "San Francisco, CA"}'),
#     type='function'
# )]
When finish_reason is "tool_calls", the model wants you to execute one or more functions and return the results.

Complete end-to-end example

This example shows the full loop: define a function, call the model, detect the tool call, execute the function, return the result, and get the final answer.
from openai import OpenAI
import json

client = OpenAI()

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

# Step 2: Your actual function implementation
def get_weather(location: str) -> str:
    # Replace with a real weather API call
    return f"Sunny, 68°F in {location}"

messages = [{"role": "user", "content": "What's the weather in Boston?"}]

# Step 3: Call the model
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
)

assistant_message = response.choices[0].message
messages.append(assistant_message)

# Step 4: Check if the model wants to call a function
if assistant_message.tool_calls:
    for tool_call in assistant_message.tool_calls:
        # Step 5: Execute the function
        args = json.loads(tool_call.function.arguments)
        result = get_weather(**args)

        # Step 6: Return the result to the model
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": result,
        })

    # Step 7: Get the final response
    final_response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
        tools=tools,
    )
    print(final_response.choices[0].message.content)
    # "The current weather in Boston is sunny and 68°F."

Multiple tools

You can define multiple tools and the model will choose the most appropriate one — or call several in a single turn.
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "Get the current weather",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "format": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The temperature unit. Infer from the location.",
                    },
                },
                "required": ["location", "format"],
            },
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_n_day_weather_forecast",
            "description": "Get an N-day weather forecast",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "format": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The temperature unit. Infer from the location.",
                    },
                    "num_days": {
                        "type": "integer",
                        "description": "The number of days to forecast",
                    }
                },
                "required": ["location", "format", "num_days"],
            },
        }
    },
]

Parallel function calls

When the model identifies multiple independent function calls it can make, it returns them all in a single response. You should execute all of them and return all results before the next model call.
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {
            "role": "user",
            "content": "What's the current weather in Glasgow and the 5-day forecast?"
        }
    ],
    tools=tools,
)

message = response.choices[0].message
# message.tool_calls may contain two entries:
# - get_current_weather(location="Glasgow, Scotland", format="celsius")
# - get_n_day_weather_forecast(location="Glasgow, Scotland", format="celsius", num_days=5)

messages.append(message)

if message.tool_calls:
    for tool_call in message.tool_calls:
        args = json.loads(tool_call.function.arguments)
        # Dispatch to the right function
        if tool_call.function.name == "get_current_weather":
            result = get_current_weather(**args)
        elif tool_call.function.name == "get_n_day_weather_forecast":
            result = get_n_day_weather_forecast(**args)

        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": str(result),
        })
Always return a tool result for every tool call ID in the response. If you skip one, the model will be confused about the missing result.

Controlling tool use

Use the tool_choice parameter to control whether and how the model uses tools.
# Default: model decides
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice="auto",       # model chooses (default)
)

# Force a specific function
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice={
        "type": "function",
        "function": {"name": "get_weather"}
    },
)

# Prevent any function calls
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice="none",
)
When tool_choice is set to a specific function, the model will always generate arguments for it even if the user’s question doesn’t require it. Use forced tool choice only when you are certain the function applies.

Required vs. optional parameters

Mark parameters as required when the function cannot run without them. Optional parameters can be omitted from the required array — the model will only include them in arguments when it has enough context to fill them in.
"parameters": {
    "type": "object",
    "properties": {
        "location": {
            "type": "string",
            "description": "City and state"
        },
        "units": {
            "type": "string",
            "enum": ["metric", "imperial"],
            "description": "Unit system. Defaults to metric if not specified."
        }
    },
    "required": ["location"]   # units is optional
}

Next steps

Agents overview

Use function calling inside an agent loop for multi-step reasoning.

OpenAI Agents SDK

The SDK wraps function calling with automatic schema generation and tool dispatch.

Build docs developers (and LLMs) love