# Tool calling Source: https://docs.getworg.com/tool-calling You describe functions in tools. The model answers with the calls it wants made, your code runs them, and you send the results back. ## Lanes Tool calling works on `deepseek-v4.1-flash:cached`, `deepseek-v4.1-flash:standard` and `qwen3.8-27b:standard`. Each of them returned several calls in one reply, in a stream as well, and used the results it was sent back. ## Ask for a call ```bash curl https://api.getworg.com/v1/chat/completions \ -H "Authorization: Bearer $WORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-v4.1-flash:cached", "messages": [{"role": "user", "content": "What is the weather in Jakarta and in Bandung right now?"}], "tools": [{ "type": "function", "function": { "name": "get_weather", "description": "Current weather for a city", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"] } } }], "reasoning_effort": "none", "max_tokens": 300 }' ``` ```python import json import os from openai import OpenAI client = OpenAI( base_url="https://api.getworg.com/v1", api_key=os.environ["WORG_API_KEY"], ) tools = [{ "type": "function", "function": { "name": "get_weather", "description": "Current weather for a city", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"], }, }, }] def get_weather(city): # Your own code: call a weather service, read a database, and so on. temps = {"Jakarta": 31, "Bandung": 24} return {"city": city, "temp_c": temps.get(city, 28), "sky": "cloudy"} messages = [{"role": "user", "content": "What is the weather in Jakarta and in Bandung right now?"}] while True: response = client.chat.completions.create( model="deepseek-v4.1-flash:cached", messages=messages, tools=tools, reasoning_effort="none", max_tokens=500, ) message = response.choices[0].message if not message.tool_calls: print(message.content) break # Send the assistant turn back unchanged, then one tool message per call. messages.append(message.model_dump(exclude_none=True)) for call in message.tool_calls: args = json.loads(call.function.arguments) messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps(get_weather(**args)), }) ``` The reply has `finish_reason: "tool_calls"` and one entry per call in `message.tool_calls`, each with an `id`, the function `name`, and its `arguments` as a JSON string. For the question above every lane asked for `get_weather` twice, once for Jakarta and once for Bandung. ## Send the results back 1. Append the assistant message as you received it, with its `tool_calls`. 2. For each call, append a message with `role: "tool"`, the call's `tool_call_id`, and the result as text in `content`. 3. Send the whole list again. Repeat until the reply has no `tool_calls`. The Python tab above runs this loop. ## tool_choice - `"auto"`, the default: the model decides whether to call a function. - `"required"`: the model must call at least one function. - `{"type": "function", "function": {"name": "get_weather"}}`: the model must call that function. It fills in arguments even when the conversation gives none, so check them. `"parallel_tool_calls": false` asks for one call per reply. Only `deepseek-v4.1-flash:standard` follows it; on the other lanes, handle several calls in one reply. ## Good to know - Tool definitions count as input tokens on every request that carries them. - In a stream, the arguments arrive in pieces. See [Tool calls in a stream](https://docs.getworg.com/streaming#tool-calls). - The model only asks for a call. Nothing runs unless your code runs it, so check the arguments before you act on them. > Tools or structured output? > > Use tools when the model should choose an action. Use [structured output](https://docs.getworg.com/structured-output) when you need data back in a fixed shape. Next: [Structured output](https://docs.getworg.com/structured-output) ยท [Streaming](https://docs.getworg.com/streaming)