Skip to main content
Article
openaifunction-callingtool-usestructured-outputpythonapiagent-developmentgpt-4o

Use OpenAI Function Calling for Reliable Tool Use

Enable OpenAI models to reliably call external tools and APIs. Define your functions, let the model generate the arguments as structured JSON, and execute them in your code to build more capable applications.

beginner15 min4 steps
The play
  1. Define Your Tools
    Describe your local or external functions to the model using a specific JSON schema. This schema tells the model the function's name, purpose, and the parameters it accepts. This is the most critical step for successful OpenAI Function Calling.
  2. Make the Initial API Call
    Send the user's prompt and your tool definitions to the model using the Chat Completions API. The model will analyze the prompt and decide if it needs to call one of your functions to answer the user's question.
  3. Handle the Tool Call Response
    If the model decides to use a tool, the API response will contain a `tool_calls` object instead of a standard text message. Your code must parse this object to get the function name and the arguments the model generated.
  4. Execute and Return Results
    Run your actual function with the arguments from the model. Then, append the `tool_calls` from the model and the result from your function to the message history. Make a final API call with this updated history to get a natural language response.
Starter code
import os
import json
from openai import OpenAI

# --- 1. Setup --- 
# Make sure to set your OPENAI_API_KEY environment variable
# export OPENAI_API_KEY='your-api-key'

# For this example, we'll use a mock function. In a real scenario, this
# would make an API call to a weather service.
def get_current_weather(location, unit="fahrenheit"):
    """Mock function to get the current weather in a given location."""
    if "tokyo" in location.lower():
        return json.dumps({"location": "Tokyo", "temperature": "10", "unit": "celsius"})
    elif "san francisco" in location.lower():
        return json.dumps({"location": "San Francisco", "temperature": "72", "unit": "fahrenheit"})
    elif "paris" in location.lower():
        return json.dumps({"location": "Paris", "temperature": "22", "unit": "celsius"})
    else:
        return json.dumps({"location": location, "temperature": "unknown"})

# --- 2. Main Execution Logic ---
def run_conversation(user_prompt: str):
    client = OpenAI()
    messages = [{"role": "user", "content": user_prompt}]
    
    # --- 3. Define Tools ---
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "Get the current weather in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city and state, e.g., San Francisco, CA",
                        },
                        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                    },
                    "required": ["location"],
                },
            },
        }
    ]
    
    # --- 4. First API Call ---
    print(f"\n> User: {user_prompt}")
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )
    response_message = response.choices[0].message
    tool_calls = response_message.tool_calls

    # --- 5. Handle Tool Calls ---
    if tool_calls:
        print(f"> Assistant needs to call a tool: {tool_calls[0].function.name}")
        messages.append(response_message)  # Extend conversation with assistant's reply
        
        available_functions = {
            "get_current_weather": get_current_weather,
        }
        
        for tool_call in tool_calls:
            function_name = tool_call.function.name
            function_to_call = available_functions[function_name]
            function_args = json.loads(tool_call.function.arguments)
            function_response = function_to_call(**function_args)
            
            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": function_name,
                    "content": function_response,
                }
            )
        
        # --- 6. Second API Call ---
        print("> Executed tool and sending result back to model...")
        second_response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
        )
        final_message = second_response.choices[0].message.content
        print(f"> Assistant: {final_message}")
        return final_message
    else:
        final_message = response_message.content
        print(f"> Assistant: {final_message}")
        return final_message

# --- Run the example ---
if __name__ == "__main__":
    run_conversation("What is the weather like in San Francisco?")
    run_conversation("What about in Tokyo?")
    run_conversation("Hello, how are you today?")
Use OpenAI Function Calling for Reliable Tool Use — Action Pack