API
Вызов инструментов
Модель не вызывает ваши функции сама. Она предлагает вызов (tool_calls), вы исполняете его у себя и возвращаете результат сообщением с role: tool. После этого модель отвечает человеку.
Работает в /chat/completions, /responses и /messages. Есть не у всех моделей — смотрите страницу модели.
tools в каждом запросе
Массив tools нужно передавать и в первом вызове, и когда отдаёте результаты. Иначе схема на следующем шаге пропадёт.
Три шага
- Запрос с массивом
tools. - Если
finish_reason=tool_calls— исполните функции локально. - Добавьте сообщение ассистента и результаты
role: "tool", снова вызовите модель.
Шаг 1:
{
"model": "claude-sonnet-4.5",
"messages": [
{ "role": "user", "content": "Какая погода в Москве?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Текущая погода в городе",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "Город, например Москва" }
},
"required": ["city"]
}
}
}
]
}curl https://api.aitunnel.ru/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-aitunnel-xxx" \
-d '{
"model": "claude-sonnet-4.5",
"messages": [
{ "role": "user", "content": "Какая погода в Москве?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Текущая погода в городе",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "Город, например Москва" }
},
"required": ["city"]
}
}
}
]
}'Шаг 3 — тот же tools, плюс история:
{
"model": "claude-sonnet-4.5",
"messages": [
{ "role": "user", "content": "Какая погода в Москве?" },
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"Москва\"}"
}
}
]
},
{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "{\"temp\": -3, \"conditions\": \"снег\"}"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Текущая погода в городе",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
}
]
}Не забудьте положить в messages ответ ассистента с tool_calls — без него модель не поймёт, к чему относится результат.
Агентский цикл
Пока модель просит инструменты — исполняйте и спрашивайте снова. Ограничьте число итераций.
def call_llm(msgs):
resp = client.chat.completions.create(
model="claude-sonnet-4.5",
tools=tools,
messages=msgs,
)
msgs.append(resp.choices[0].message)
return resp
def run_tool(tool_call):
name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
result = TOOL_MAPPING[name](**args)
return {
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result, ensure_ascii=False),
}
for _ in range(10):
resp = call_llm(messages)
calls = resp.choices[0].message.tool_calls
if not calls:
break
for call in calls:
messages.append(run_tool(call))
print(messages[-1].content)tool_choice
| Значение | Смысл |
|---|---|
auto | Модель сама решает, звать ли инструмент (по умолчанию) |
none | Не звать |
required | Обязан вызвать хотя бы один |
{ "type": "function", "function": { "name": "get_weather" } } | Конкретная функция |
Параллельные вызовы
По умолчанию модель может попросить несколько инструментов сразу. Чтобы по одному:
{ "parallel_tool_calls": false }Стриминг
С stream: true куски tool_calls приходят в delta.tool_calls. Соберите их до finish_reason: "tool_calls", потом исполняйте.
Рассуждения между вызовами
Reasoning-модели могут думать между вызовами инструментов. Это больше токенов и задержка. Когда модель вернула tool_calls вместе с reasoning_details, отдайте reasoning_details обратно без правок вместе с результатами инструментов — иначе цепочка мышления рвётся. Подробнее: токены рассуждений.
Поиск в сети и другие вызовы, которые исполняет AITUNNEL, а не ваш код — серверные инструменты.