Skip to main content

Overview

Function calling allows you to define custom functions that models can invoke during a conversation. Unlike the built-in tools (web_search and fetch_url), custom functions let you connect the model to your own systems—databases, APIs, business logic, or any external service.

Custom Integrations

Connect models to your databases, APIs, and internal systems.

Multi-Turn Pattern

Model requests a function call, you execute it, then return results.
Built-in vs Custom Tools: Use web_search and fetch_url for web information retrieval. Use function calling when you need the model to interact with your own systems or perform custom operations.

How It Works

Function calling follows a multi-turn conversation pattern:
1

Define Functions

Specify the functions available to the model, including their names, descriptions, and parameter schemas.
2

Send Initial Request

Send your prompt along with the function definitions. The model decides if and when to call a function.
3

Receive Function Call

If the model needs to call a function, it returns a function_call item in the response output with the function name and arguments.
4

Execute the Function

Your code executes the actual function logic using the provided arguments.
5

Return Results

Send the function output back to the model as a function_call_output item.
6

Get Final Response

The model uses the function results to generate its final response.

Defining Functions

Define functions using the tools parameter with type: "function". Each function needs a name, description, and a JSON Schema for its parameters.
tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get the current weather for a location.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "City name, e.g., 'San Francisco'"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "Temperature unit"
                }
            },
            "required": ["location"]
        }
    }
]

Function Schema Properties

PropertyTypeRequiredDescription
typestringYesMust be "function"
namestringYesFunction name the model will use to call it
descriptionstringYesClear description of what the function does and when to use it
parametersobjectYesJSON Schema defining the function’s parameters
strictbooleanNoEnable strict schema validation
Write clear, specific descriptions. The model uses these to decide when to call each function. Include details about what the function returns and any constraints.

Strict Mode

Setting strict: true ensures function calls reliably adhere to your schema. When enabled, the model will always include all required parameters with the correct types.
{
    "type": "function",
    "name": "get_weather",
    "description": "Get weather for a location",
    "strict": True,
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "City name"
            },
            "unit": {
                "type": "string",
                "enum": ["celsius", "fahrenheit"]
            }
        },
        "required": ["location", "unit"],
        "additionalProperties": False
    }
}
When using strict mode:
  • Set additionalProperties: false on your parameter object
  • Mark all fields in properties as required
  • Use "type": ["string", "null"] for optional fields that can be null
Strict mode is recommended for production applications where consistent function call structure is important.

Basic Example

Here’s a complete example showing the full function calling flow:
from perplexity import Perplexity
import json

client = Perplexity()

# 1. Define your function tools
tools = [
    {
        "type": "function",
        "name": "get_horoscope",
        "description": "Get today's horoscope for an astrological sign.",
        "parameters": {
            "type": "object",
            "properties": {
                "sign": {
                    "type": "string",
                    "description": "An astrological sign like Taurus or Aquarius"
                }
            },
            "required": ["sign"]
        }
    }
]

# Your actual function implementation
def get_horoscope(sign: str) -> str:
    # In a real app, this might call an external API
    return f"{sign}: Today brings new opportunities for growth."

# 2. Send initial request with tools
response = client.responses.create(
    model="openai/gpt-5.2",
    tools=tools,
    input="What is my horoscope? I am an Aquarius."
)

# 3. Process the response and handle function calls
next_input = [item.model_dump() for item in response.output]

for item in response.output:
    if item.type == "function_call":
        # 4. Execute the function
        args = json.loads(item.arguments)
        result = get_horoscope(args["sign"])

        # 5. Add the function result to the input
        next_input.append({
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": json.dumps({"horoscope": result})
        })

# 6. Send the function results back to get the final response
final_response = client.responses.create(
    model="openai/gpt-5.2",
    input=next_input
)

print(final_response.output_text)

Handling Function Calls

When the model decides to call a function, the response contains a function_call item in the output array:
{
  "output": [
    {
      "type": "function_call",
      "call_id": "call_abc123",
      "name": "get_horoscope",
      "arguments": "{\"sign\": \"Aquarius\"}"
    }
  ]
}

Function Call Properties

PropertyDescription
typeAlways "function_call"
call_idUnique identifier for this call—use this when returning results
nameThe function name the model is calling
argumentsJSON string containing the function arguments
The arguments field is a JSON string, not a parsed object. Always use json.loads() (Python) or JSON.parse() (JavaScript) to parse it.

Returning Function Results

After executing the function, return the results using function_call_output:
{
    "type": "function_call_output",
    "call_id": "call_abc123",  # Must match the original call_id
    "output": "{\"horoscope\": \"Aquarius: Today brings new opportunities.\"}"
}

Function Output Properties

PropertyDescription
typeMust be "function_call_output"
call_idThe call_id from the corresponding function_call
outputJSON string containing the function’s return value
Structure your output as JSON for consistency. The model will parse and use this data to formulate its response.

Multiple Functions

You can define multiple functions for the model to choose from:
tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get current weather for a location.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "City name"}
            },
            "required": ["location"]
        }
    },
    {
        "type": "function",
        "name": "get_stock_price",
        "description": "Get current stock price for a ticker symbol.",
        "parameters": {
            "type": "object",
            "properties": {
                "ticker": {"type": "string", "description": "Stock ticker symbol"}
            },
            "required": ["ticker"]
        }
    }
]

response = client.responses.create(
    model="openai/gpt-5.2",
    tools=tools,
    input="What's the weather in NYC and the current price of AAPL?"
)

# Handle each function call in the response
for item in response.output:
    if item.type == "function_call":
        if item.name == "get_weather":
            # Execute weather function
            pass
        elif item.name == "get_stock_price":
            # Execute stock price function
            pass

Combining with Built-in Tools

You can use custom functions alongside built-in tools like web_search:
tools = [
    {"type": "web_search"},
    {
        "type": "function",
        "name": "save_to_database",
        "description": "Save information to the user's database.",
        "parameters": {
            "type": "object",
            "properties": {
                "data": {"type": "string", "description": "Data to save"}
            },
            "required": ["data"]
        }
    }
]

response = client.responses.create(
    model="openai/gpt-5.2",
    tools=tools,
    input="Search for the latest AI news and save a summary to my database.",
    instructions="Use web_search to find information, then save_to_database to store it."
)

Best Practices

Write Clear Descriptions

The model relies on function descriptions to decide when to call them. Be specific:
# Good - clear and specific
{
    "name": "get_user_orders",
    "description": "Retrieve a user's order history from the database. Returns the last 10 orders including order ID, date, items, and total amount. Use this when the user asks about their past purchases or order status."
}

# Less effective - vague
{
    "name": "get_orders",
    "description": "Gets orders."
}

Define Precise Parameter Schemas

Use JSON Schema features to constrain parameters:
"parameters": {
    "type": "object",
    "properties": {
        "status": {
            "type": "string",
            "enum": ["pending", "shipped", "delivered"],
            "description": "Filter orders by status"
        },
        "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 10,
            "description": "Number of orders to return"
        }
    },
    "required": ["status"]
}

Handle Errors Gracefully

Return error information in a structured way:
try:
    result = execute_function(args)
    output = json.dumps({"success": True, "data": result})
except Exception as e:
    output = json.dumps({"success": False, "error": str(e)})

next_input.append({
    "type": "function_call_output",
    "call_id": item.call_id,
    "output": output
})

Next Steps