Function Calling
Function calling allows models to generate structured arguments for functions you define. The model doesn't execute the function directly — instead, it outputs JSON that you can use to call the function in your code.
How It Works
- Define tools — Provide function schemas in your request
- Model decides — The model may choose to call one or more tools
- You execute — Parse the model's tool call and run the actual function
- Return results — Send the function output back to the model
- Model responds — The model uses the tool results to generate a final answer
Defining Tools
from openai import OpenAI
client = OpenAI(
base_url="https://openapi.linkwo.ai/v1",
api_key="YOUR_API_KEY"
)
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 name, e.g., Beijing"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location"]
}
}
}
]Complete Example
import json
response = client.chat.completions.create(
model="deepseek/deepseek-v4-pro",
messages=[{"role": "user", "content": "What's the weather like in Shanghai?"}],
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
if message.tool_calls:
for tool_call in message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
# Execute the function
if function_name == "get_weather":
result = get_weather(**function_args)
# Send result back to the model
response = client.chat.completions.create(
model="deepseek/deepseek-v4-pro",
messages=[
{"role": "user", "content": "What's the weather like in Shanghai?"},
message,
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
}
]
)
print(response.choices[0].message.content)Tool Choice
| Value | Description |
|---|---|
auto | Model decides whether to call tools (default) |
none | Model will never call tools |
required | Model must call at least one tool |
{"type": "function", "function": {"name": "..."}} | Force a specific function |
Multiple Tools
You can define multiple tools in a single request:
tools = [
{
"type": "function",
"function": {
"name": "search_products",
"description": "Search the product catalog",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"},
"category": {"type": "string"},
"max_price": {"type": "number"}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "place_order",
"description": "Place an order for a product",
"parameters": {
"type": "object",
"properties": {
"product_id": {"type": "string"},
"quantity": {"type": "integer"}
},
"required": ["product_id", "quantity"]
}
}
}
]Best Practices
- Write clear descriptions — The model relies on function and parameter descriptions to decide when and how to call them
- Use enums for constrained values — Restrict parameters with
enumwhen possible - Set required fields — Always mark necessary parameters as
required - Handle errors gracefully — Return error messages as tool results so the model can self-correct
- Limit tool count — Too many tools can confuse the model; keep it focused
Parallel Tool Calls
Some models support calling multiple tools in a single response. Handle this by iterating over message.tool_calls:
if message.tool_calls:
tool_results = []
for tool_call in message.tool_calls:
result = execute_function(tool_call.function.name, json.loads(tool_call.function.arguments))
tool_results.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})Related
- Chat Completions — Base API for chat
- Structured Output — Force JSON schema output
- Responses API — High-level agentic API