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.

This guide covers function tools that your application executes. For tools executed automatically by Mixlayer, see Server-Side Tools.

Mixlayer supports tool calling through both Chat Completions and Responses. The model behavior is the same, but the request and follow-up item formats differ.

The loop

  1. Define your tools in the tools array on the request.
  2. Send the request. If the model decides to invoke a tool, Chat Completions returns finish_reason: "tool_calls" with an assistant tool_calls array. Responses returns a function_call output item.
  3. Execute the tool in your code.
  4. Send a follow-up request with the tool result. Chat Completions uses a tool role message. Responses uses a function_call_output input item.
  5. The model returns its final answer, conditioned on the tool result.

Defining tools

The parameters field is a JSON Schema describing the tool’s arguments.

1{
2 "type": "function",
3 "function": {
4 "name": "get_weather",
5 "description": "Get the current weather for a city.",
6 "parameters": {
7 "type": "object",
8 "properties": {
9 "city": {
10 "type": "string",
11 "description": "City name, e.g. 'San Francisco'"
12 }
13 },
14 "required": ["city"]
15 },
16 "strict": true
17 }
18}

Set strict: true if you want the model’s arguments to be guaranteed to match the schema.

Tool names must be 1-64 characters and contain only ASCII letters, numbers, _, or -.

Sending Tool Results

1{
2 "messages": [
3 { "role": "user", "content": "What is the weather in Paris?" },
4 {
5 "role": "assistant",
6 "tool_calls": [{
7 "id": "call_abc123",
8 "type": "function",
9 "function": {
10 "name": "get_weather",
11 "arguments": "{\"city\":\"Paris\"}"
12 }
13 }]
14 },
15 {
16 "role": "tool",
17 "tool_call_id": "call_abc123",
18 "content": "{\"temp_c\":18,\"condition\":\"cloudy\"}"
19 }
20 ]
21}

Worked example: Chat Completions weather lookup

The full loop, end to end:

file=tool-call.sh
$# 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.6-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.6-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

Chat Completions does not currently support the OpenAI tool_choice parameter. Responses supports tool_choice: "auto" and tool_choice: "none". Forced tool choice is not supported.

Tool calling is supported on the Qwen 3.5 family. See Models for the up-to-date list of capable models.