Tool / function calling
Let the model invoke real code in your app — query a database, send an email, hit a third-party API — and feed the result back. The OpenAI tools + tool_calls protocol works exactly as documented: same request shape, same response shape.
How it works
- You declare functions the model is allowed to call, with JSON-Schema parameters, in the
toolsarray. - The model decides whether to call one (or several) and returns the call(s) in
choices[0].message.tool_callswith afinish_reasonoftool_calls. - You execute the function(s) yourself, then send the conversation back with the tool output as a
role: "tool"message. - The model continues the conversation, now armed with the tool result.
Worked example — a weather agent
Step 1: ask the model. Note the tools array — that's how you tell it what's available.
# Python tools = [ { "type": "function", "function": { "name": "get_current_weather", "description": "Get the current weather for a location.", "parameters": { "type": "object", "properties": { "city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}, }, "required": ["city"], }, }, }, ] resp = client.chat.completions.create( model="deepseek-v4", messages=[{"role": "user", "content": "What's the weather in Bangalore?"}], tools=tools, ) call = resp.choices[0].message.tool_calls[0] args = json.loads(call.function.arguments) # {"city": "Bangalore", "unit": "c"}
Step 2: run your function, then send the conversation back including the tool result.
weather = my_get_weather(args["city"], args["unit"]) # your code final = client.chat.completions.create( model="deepseek-v4", messages=[ {"role": "user", "content": "What's the weather in Bangalore?"}, resp.choices[0].message, # the assistant turn with tool_calls { "role": "tool", "tool_call_id": call.id, "content": json.dumps(weather), }, ], tools=tools, ) print(final.choices[0].message.content)
Multi-step agents
The same pattern loops. After step 2 the model may issue another tool_calls — run those, append, repeat. Set a hop cap (we recommend ≤ 6) to avoid runaway agent loops, and watch the request log to see what the model is doing.
Parallel tool calls
One assistant turn can include multiple tool calls in the same tool_calls array. Run them concurrently and reply with one role: "tool" message per tool_call_id.
Forcing a specific tool
Use tool_choice:
| Value | Behavior |
|---|---|
"auto" | Default. Model decides. |
"none" | Model cannot use tools. |
"required" | Model must emit at least one tool call. |
{"type":"function","function":{"name":"get_current_weather"}} | Force this specific tool. |
Which Ollima-routed models support it
All qwen3-*, deepseek-*, and glm-* aliases support tool calling. If a request includes tools on a model that doesn't, we return 400 with error.type = "tool_use_unsupported". The full live list with its tool-support flag is at /models.