Call functions
One tool call per response, covering simple and multiple-tool patterns.
Overview
The two simplest patterns: one tool, one call (simple), and many tools available with the model picking one (multiple).
Simple tool calling
Suppose your application has access to a get_current_weather function that takes two named arguments, location and unit:
# Hypothetical function in your app
get_current_weather(location="San Francisco, CA", unit="fahrenheit")Make this function available to the model by passing its description to the tools key alongside the user’s query. Suppose the user asks, “What is the current temperature of New York?”
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.reka.ai/v1",
api_key=os.environ["REKA_API_KEY"],
)
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
}
]
response = client.chat.completions.create(
model="deepseek4-flash",
messages=[
{
"role": "system",
"content": "You are a helpful assistant that can access external functions. The responses from these function calls will be appended to this dialogue. Please provide responses based on the information from these function calls."
},
{
"role": "user",
"content": "What is the current temperature of New York?"
}
],
tools=tools,
)
print(response.choices[0].message.tool_calls)The model responds with a single function call in the tool_calls array, specifying the function name and arguments needed to get the weather for New York:
[
{
"id": "call_aisak3q1px3m2lzb41ay6rwf",
"type": "function",
"function": {
"name": "get_current_weather",
"arguments": "{\"location\": \"New York, NY\", \"unit\": \"fahrenheit\"}"
}
}
]You can now programmatically execute the function call to answer the user’s question.
id is an opaque string of the form call_ followed by 24 characters; echo it back unchanged as tool_call_id on the tool message. Non-streaming calls carry exactly id, type and function; index appears only on streamed deltas.
Streaming
Tool calling also works with streaming responses. The call arrives in pieces on delta.tool_calls: the first delta carries the id and function name, then the arguments string follows as several fragments. Keep a buffer per index, append each fragment, and parse the JSON once the stream ends. On reasoning models, reasoning_effort: "none" skips the thinking so the first chunks are the call itself:
import json
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.reka.ai/v1",
api_key=os.environ["REKA_API_KEY"],
)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current temperature for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and country e.g. Bogotá, Colombia"
}
},
"required": ["location"],
"additionalProperties": False
}
}
}
]
stream = client.chat.completions.create(
model="deepseek4-flash",
reasoning_effort="none",
messages=[
{
"role": "user",
"content": "What's the weather in NYC?"
}
],
tools=tools,
stream=True,
)
# Arguments arrive as fragments: concatenate per index, parse at the end.
calls = {}
for chunk in stream:
delta = chunk.choices[0].delta if chunk.choices else None
for tc in (delta.tool_calls or []) if delta else []:
call = calls.setdefault(tc.index, {"id": None, "name": None, "arguments": ""})
if tc.id:
call["id"] = tc.id
if tc.function and tc.function.name:
call["name"] = tc.function.name
if tc.function and tc.function.arguments:
call["arguments"] += tc.function.arguments
for call in calls.values():
print(call["name"], json.loads(call["arguments"]))The deltas look like this:
# delta 1: index, id, type, name and empty arguments
[{ "index": 0, "id": "call_fwbx4e156wigo9ayq7tszngh", "type": "function",
"function": { "name": "get_weather", "arguments": "" } }]
# deltas 2-4: argument fragments for the same index
[{ "index": 0, "function": { "arguments": "{\"location\": \"" } }]
[{ "index": 0, "function": { "arguments": "New York City, USA" } }]
[{ "index": 0, "function": { "arguments": "\"}" } }]
# concatenated: {"location": "New York City, USA"}The first delta for each call carries index, id, type, function.name and function.arguments: ""; later deltas for the same index carry only function.arguments fragments. Fragment boundaries vary, so concatenate per index and parse once the stream ends.
Tool calls don’t show up in message.content. When a model decides to call a tool, the call lands in message.tool_calls. message.content is null on a tool-calling turn unless the model wrote a short preamble (the DeepSeek models sometimes do); never parse the call out of content. Read it from message.tool_calls[0].function.name and .arguments; the latter is a JSON-encoded string.
Multiple tool calling
Multiple tool calling makes several functions available and lets the model choose the best one based on the user’s intent. The model has to understand the request and pick the appropriate tool from the options.
The example below provides two tools to the model. The model responds with one tool invocation.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.reka.ai/v1",
api_key=os.environ["REKA_API_KEY"],
)
tools = [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
},
{
"type": "function",
"function": {
"name": "get_current_stock_price",
"description": "Get the current stock price for a given stock symbol",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "The stock symbol, e.g. AAPL, GOOGL, TSLA"
},
"exchange": {
"type": "string",
"description": "The stock exchange (optional)",
"enum": ["NYSE", "NASDAQ", "LSE", "TSX"]
}
},
"required": ["symbol"]
}
}
}
]
response = client.chat.completions.create(
model="deepseek4-flash",
messages=[
{
"role": "user",
"content": "What's the current price of Apple's stock?"
}
],
tools=tools,
)
print(response.choices[0].message.tool_calls)In this example, both weather and stock functions are available. The model correctly identifies that the user is asking about stock prices and calls the get_current_stock_price function.
Select a specific tool
To force the model to use a specific tool, pass the tool’s name to the tool_choice parameter:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.reka.ai/v1",
api_key=os.environ["REKA_API_KEY"],
)
tools = [
{
"type": "function",
"function": {
"name": "get_current_stock_price",
"description": "Get the current stock price for a given stock symbol",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "The stock symbol, e.g. AAPL, GOOGL, TSLA"
}
},
"required": ["symbol"]
}
}
}
]
response = client.chat.completions.create(
model="deepseek4-flash",
messages=[
{
"role": "user",
"content": "What's the current price of Apple's stock?"
}
],
tools=tools,
tool_choice={
"type": "function",
"function": {
"name": "get_current_stock_price"
}
},
)
print(response.choices[0].message.tool_calls)This forces the model to use the specified function regardless of the user’s phrasing.
tool_choice options
The tool_choice parameter controls how the model uses functions. It accepts:
"auto"(default): the model decides whether to call a function or generate a text response."none": the model never calls functions, only generates text."required": the model must call at least one function. Forcing a call can produce one with emptyarguments(seen onglm5.3), so validate arguments before executing, or stay onautothere.{"type": "function", "function": {"name": "get_current_stock_price"}}: forces a call to that one function; the model only chooses the arguments.
Next: Call functions in parallel.