Tool calling
Describe your functions with JSON Schema and the model decides when to call them and with which arguments. Your code runs the function and sends the result back.
API reference: Chat completions
Models
The Qwen models on ARK Cloud (Qwen3.6-35B-A3B, Qwen3.5-122B-A10B, Qwen3.8-Flash-Next, Qwen3.8-27B, Qwen3.5-4B) call tools. Bielik-11B-v3.0-Instruct does not.
1. Offer the tools
import json
tools = [{
"type": "function",
"function": {
"name": "get_exchange_rate",
"description": "Current exchange rate between two currencies.",
"parameters": {
"type": "object",
"properties": {
"base": {"type": "string", "description": "ISO 4217 code, e.g. EUR"},
"quote": {"type": "string", "description": "ISO 4217 code, e.g. PLN"},
},
"required": ["base", "quote"],
},
},
}]
messages = [{"role": "user", "content": "How many zloty is 250 euro today?"}]
response = client.chat.completions.create(
model="arklabsai/Qwen3.6-35B-A3B",
messages=messages,
tools=tools,
)
call = response.choices[0].message.tool_calls[0]
print(call.function.name, json.loads(call.function.arguments))
# get_exchange_rate {'base': 'EUR', 'quote': 'PLN'}const tools = [{
type: "function",
function: {
name: "get_exchange_rate",
description: "Current exchange rate between two currencies.",
parameters: {
type: "object",
properties: {
base: { type: "string", description: "ISO 4217 code, e.g. EUR" },
quote: { type: "string", description: "ISO 4217 code, e.g. PLN" },
},
required: ["base", "quote"],
},
},
}];
const messages = [{ role: "user", content: "How many zloty is 250 euro today?" }];
const response = await client.chat.completions.create({
model: "arklabsai/Qwen3.6-35B-A3B",
messages,
tools,
});
const call = response.choices[0].message.tool_calls[0];
console.log(call.function.name, JSON.parse(call.function.arguments));curl https://api.ark-labs.cloud/api/v1/chat/completions \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "arklabsai/Qwen3.6-35B-A3B",
"messages": [{"role": "user", "content": "How many zloty is 250 euro today?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_exchange_rate",
"description": "Current exchange rate between two currencies.",
"parameters": {
"type": "object",
"properties": {
"base": {"type": "string"},
"quote": {"type": "string"}
},
"required": ["base", "quote"]
}
}
}]
}'When the model wants a tool, finish_reason is tool_calls and the message carries the calls instead of text:
{
"index": 0,
"message": {
"role": "assistant",
"tool_calls": [
{
"id": "call_6f0f2c8d0b3c4f6a9d1e2b7c5a8e4f10",
"index": 0,
"type": "function",
"function": { "name": "get_exchange_rate", "arguments": "{\"base\": \"EUR\", \"quote\": \"PLN\"}" }
}
],
"refusal": null,
"annotations": []
},
"finish_reason": "tool_calls"
}2. Run the tool and return the result
Append the assistant message with its tool_calls, then one tool message per call with the result, and ask again. ARK hands results to the model in conversation order, so keep each tool message right after the call it answers.
messages.append(response.choices[0].message) # the assistant turn with tool_calls
rate = 4.27 # your code calls the real service here
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps({"rate": rate})})
final = client.chat.completions.create(
model="arklabsai/Qwen3.6-35B-A3B",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)Control when tools are used
tool_choice | Behaviour |
|---|---|
"auto" (default) | The model decides whether to call a tool. |
"none" | No tool calls; the tools are left out of the prompt. |
"required" | The model must call at least one tool. |
{"type": "function", "function": {"name": "…"}} | The model must call that tool. |
{"type": "allowed_tools", "allowed_tools": {"mode": "auto", "tools": […]}} | Restrict the call to a subset of the offered tools. |
Set parallel_tool_calls: false to receive at most one call per turn. On the Qwen models a forced choice is enforced, not just requested: the reply is a call to the tool.
Tool calls in a stream
When streaming, each tool call arrives in a single chunk with its complete arguments string, rather than in fragments, so you can parse it as soon as it arrives. The final content chunk carries finish_reason: "tool_calls".
Good to know
strict: truein a function definition is accepted, but arguments are not validated against the schema: validate them in your code.- Tools and thinking work together: with
reasoning_effortmediumorhigh, the Qwen models think before they call a tool (see Reasoning). - Custom tools (
{"type": "custom", "custom": {…}}) and the legacyfunctions/function_callfields are supported for older clients. - The Anthropic API supports tools too, with
tool_useandtool_resultblocks. See Messages API.