Tool Calling
Tool calling lets the model decide to invoke one of your functions to fetch data or take action — for example, looking up the weather, querying a database, or sending an email. The model doesn’t execute the tool itself; it returns the function name and arguments, your code runs the function, and you send the result back in a follow-up message.
The loop
- Define your tools in the
toolsarray on the request. - Send the request. If the model decides to invoke a tool, the response will have
finish_reason: "tool_calls"and the assistant message will include atool_callsarray. - Execute the tool in your code.
- Send a follow-up request that includes the original messages, the assistant’s tool-call message, and a new
toolrole message containing the result. - The model returns its final answer, conditioned on the tool result.
Defining tools
Each tool is a JSON object with type: "function" and a function definition. The parameters field is a JSON Schema describing the tool’s arguments.
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. 'San Francisco'"
}
},
"required": ["city"]
},
"strict": true
}
}Set strict: true if you want the model’s arguments to be guaranteed to match the schema.
Worked example: weather lookup
The full loop, end to end:
# Step 1: Send the request with tools defined.
curl https://models.mixlayer.ai/v1/chat/completions \
-H "Authorization: Bearer $MIXLAYER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen/qwen3.5-27b",
"messages": [
{"role": "user", "content": "What is the weather in Paris?"}
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}]
}'
# Response includes:
# "tool_calls": [{
# "id": "call_abc123",
# "type": "function",
# "function": {"name": "get_weather", "arguments": "{\"city\":\"Paris\"}"}
# }]
# and "finish_reason": "tool_calls"
# Step 2: Run the tool yourself, then send a follow-up with the result.
curl https://models.mixlayer.ai/v1/chat/completions \
-H "Authorization: Bearer $MIXLAYER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen/qwen3.5-27b",
"messages": [
{"role": "user", "content": "What is the weather in Paris?"},
{"role": "assistant", "tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {"name": "get_weather", "arguments": "{\"city\":\"Paris\"}"}
}]},
{"role": "tool", "tool_call_id": "call_abc123", "content": "{\"temp_c\": 18, \"condition\": \"cloudy\"}"}
]
}'Streaming with tool calls
When stream: true and the model invokes a tool, tool_calls arrive in deltas across multiple chunks. Each chunk’s delta.tool_calls[].function.arguments is a partial JSON string fragment — accumulate them per tool_calls[].index until the final chunk arrives with finish_reason: "tool_calls".
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"id":"call_abc","function":{"name":"get_weather","arguments":""}}]}}]}
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"city\":"}}]}}]}
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"Paris\"}"}}]}}]}
data: {"choices":[{"delta":{},"finish_reason":"tool_calls"}]}Notes
Mixlayer does not currently support the OpenAI tool_choice parameter. The
model decides automatically whether to invoke a tool based on the
conversation. If you need to force a tool call, prompt the model explicitly
in the system or user message.
Tool calling is supported on the Qwen 3.5 family. See Models for the up-to-date list of capable models.