Tool Calling
Let models call functions you define. The model decides when to call a tool, generates the arguments, and you execute the function and return the result. Same format as OpenAI function calling.
Define tools
Tools are JSON Schema descriptions of functions the model can call:
- Python
- Node.js
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["city"],
},
},
}
]
response = client.chat.completions.create(
model="phi-4-mini",
messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
tools=tools,
)
const tools = [
{
type: "function" as const,
function: {
name: "get_weather",
description: "Get current weather for a city",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "City name" },
unit: { type: "string", enum: ["celsius", "fahrenheit"] },
},
required: ["city"],
},
},
},
];
const response = await client.chat.completions.create({
model: "phi-4-mini",
messages: [{ role: "user", content: "What's the weather in Tokyo?" }],
tools,
});
Handle tool calls
When the model decides to call a tool, finish_reason is "tool_calls" and the response contains the function name and arguments:
choice = response.choices[0]
if choice.finish_reason == "tool_calls":
for tool_call in choice.message.tool_calls:
name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
# Execute your function
if name == "get_weather":
result = get_weather(args["city"], args.get("unit", "celsius"))
# Return the result to the model
messages.append(choice.message)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
})
# Continue the conversation with tool results
follow_up = client.chat.completions.create(
model="phi-4-mini",
messages=messages,
tools=tools,
)
Parallel tool calls
Models can request multiple tool calls in a single response. Process all of them before continuing:
if choice.finish_reason == "tool_calls":
messages.append(choice.message)
for tool_call in choice.message.tool_calls:
result = dispatch_tool(tool_call.function.name, tool_call.function.arguments)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
})
Force or prevent tool use
Control when the model uses tools:
# Force a specific tool
response = client.chat.completions.create(
model="phi-4-mini",
messages=messages,
tools=tools,
tool_choice={"type": "function", "function": {"name": "get_weather"}},
)
# Let the model decide (default)
tool_choice="auto"
# Prevent tool use
tool_choice="none"
On-device considerations
Tool calling works on-device with models that support it. Keep in mind:
- Smaller models are less reliable at generating valid tool call arguments. Use structured decoding to enforce argument schemas.
- Latency -- tool calls add a round-trip. The model generates the call, you execute it, then the model processes the result.
- Model support -- not all models support tool calling. Check the model catalog for the
toolscapability flag.
Related
- Control -- parameters that shape model behavior
- Structured Decoding -- enforce valid JSON in tool arguments
- Workflows -- chain tool calls into multi-step processes