Tool Calling

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

  1. Define your tools in the tools array on the request.
  2. 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 a tool_calls array.
  3. Execute the tool in your code.
  4. Send a follow-up request that includes the original messages, the assistant’s tool-call message, and a new tool role message containing the result.
  5. 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.