Function Calling
How It Works
- You send a request with a
toolsarray defining available functions. - The model decides whether to call a function and responds with a
tool_callsarray. - Your code executes the function and collects the result.
- You send the result back as a message with
role: "tool". - The model incorporates the result and generates a final response.
Defining Tools
Each tool has a type (always "function"), a name, a description, and a JSON Schema for parameters:
config.json
json
{ "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current weather for a given city. Returns temperature in Celsius and conditions.", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "City name, e.g. 'San Francisco'" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature unit" } }, "required": ["city"] } } } ] }
Write clear, specific descriptions. The model uses these to decide when to call each function.
Supported Models
Function calling is supported by most chat models:
- OpenAI: GPT-4.1, GPT-4.1-mini, GPT-4.1-nano, GPT-4o, GPT-5, o3, o4-mini
- Anthropic: Claude Opus 4, Claude Sonnet 4, Claude Haiku 3.5
- Google: Gemini 2.5 Pro, Gemini 2.5 Flash
- DeepSeek: DeepSeek V3, DeepSeek R1
- Qwen: Qwen3, Qwen-Plus, Qwen-Max
Complete Example: Weather Query
This example shows a full multi-turn conversation with function calling.
example.py
python
from openai import OpenAI import json client = OpenAI( base_url="https://api.chuizi.ai/v1", api_key="ck-your-key-here", ) # Define the tool tools = [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current weather for a city.", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "City name"}, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature unit", }, }, "required": ["city"], }, }, } ] # Step 1: Send the initial request with tools messages = [{"role": "user", "content": "What's the weather in Tokyo and London?"}] response = client.chat.completions.create( model="openai/gpt-4.1", messages=messages, tools=tools, tool_choice="auto", ) assistant_message = response.choices[0].message # Step 2: The model returns tool_calls if assistant_message.tool_calls: # Add the assistant's message (with tool_calls) to the conversation messages.append(assistant_message) # Step 3: Execute each function and add results for tool_call in assistant_message.tool_calls: args = json.loads(tool_call.function.arguments) # Your actual function implementation if tool_call.function.name == "get_weather": # In production, this would call a real weather API result = { "city": args["city"], "temperature": 22, "unit": args.get("unit", "celsius"), "conditions": "partly cloudy", } # Add the tool result to the conversation messages.append( { "role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result), } ) # Step 4: Send results back to get the final response final_response = client.chat.completions.create( model="openai/gpt-4.1", messages=messages, tools=tools, ) print(final_response.choices[0].message.content)
Tips
- Write detailed descriptions. The model relies on
descriptionfields to decide which function to call and how to fill parameters. Vague descriptions lead to wrong calls. - Validate arguments. The model may produce invalid JSON or missing fields. Always validate before executing.
- Limit the number of tools. Providing too many tools (>20) can degrade model performance. Group related functionality into fewer, broader tools.
- Use
tool_choice: "required"when you know the user's intent requires a function call. This prevents the model from generating a text response instead.
Next Steps
- Structured Output — get JSON responses matching your schema without tool use
- Streaming — stream function call arguments as they are generated
- Chat Completions API — full
toolsandtool_choiceparameter reference