Kryyt / Developers
Function Calling
The model requests a function. Your application decides whether and how to execute it.
Declare a read-only tool
{
"model": "deepseek-v4.1-flash",
"messages": [
{
"role": "user",
"content": "When is the Chandigarh office open?"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_office_hours",
"description": "Look up the public opening hours for a supported office.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"enum": [
"Chandigarh",
"London"
]
}
},
"required": [
"city"
],
"additionalProperties": false
}
}
}
],
"tool_choice": "auto",
"max_tokens": 512
}Handle a tool call
The following fragment assumes client, messages, and tools are already defined. Keep the complete assistant message before appending tool results. Bound the loop and reject unknown tools or invalid arguments.
import json
hours = {"Chandigarh": "09:00-18:00", "London": "09:00-17:00"}
for _ in range(4):
response = client.chat.completions.create(
model="deepseek-v4.1-flash", messages=messages, tools=tools,
tool_choice="auto", max_tokens=512,
)
message = response.choices[0].message
messages.append(message.model_dump(exclude_none=True))
if not message.tool_calls:
print(message.content or "")
break
for call in message.tool_calls:
args = json.loads(call.function.arguments)
if (call.function.name != "get_office_hours"
or not isinstance(args, dict)
or not isinstance(args.get("city"), str)
or args.get("city") not in hours):
raise ValueError("Tool request is not allowed")
messages.append({
"role": "tool", "tool_call_id": call.id,
"content": json.dumps({"hours": hours[args["city"]]}),
})
else:
raise RuntimeError("Tool-call budget exhausted")Permissions belong in your application
Function arguments and tool results are untrusted data. Enforce user authorization, tenant boundaries, input validation, timeouts, and an execution budget. Require confirmation for consequential actions. Never use a model-generated function name or argument as executable code.