Все статьи
Статья
30 июня 2026 г.8 мин

Агенты и вызов инструментов: как строить function-calling

Модель сама решает, когда дёрнуть вашу функцию. Разбираю схему tools, цикл выполнения и типичные грабли с параллельными вызовами.

Сергей Панов


Агенты и вызов инструментов: как строить function-calling

Агент — это модель, которой дали инструменты и цикл. Она сама решает, что нужно вызвать: посмотреть погоду, сходить в базу, отправить письмо. Вы описываете функции, модель возвращает намерение их вызвать, вы исполняете и отдаёте результат обратно.

Описываем инструменты

Инструмент — это JSON Schema. Чем точнее описание, тем реже модель ошибается с аргументами.

tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Возвращает статус заказа по его номеру",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "Номер заказа, например A-1024"}
},
"required": ["order_id"],
},
},
}]

Цикл выполнения

Ключевое, что упускают: один запрос к модели — это не весь разговор. Модель может попросить инструмент, получить ответ и попросить следующий. Нужен цикл.

messages = [{"role": "user", "content": "Где мой заказ A-1024?"}]
while True:
resp = client.chat.completions.create(
model="qwen-pro", messages=messages, tools=tools,
)
msg = resp.choices[0].message
messages.append(msg)
if not msg.tool_calls:
print(msg.content)
break
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = run_tool(call.function.name, args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result, ensure_ascii=False),
})

Выбор модели

Function-calling — не для всех моделей одинаково. Нужна та, что обучена под tools и держит структуру:

  • qwen-pro, deepseek-pro — уверенно выбирают инструменты и не выдумывают несуществующие.
  • Flash-модели тоже умеют вызывать функции, но на длинных цепочках чаще путаются в порядке шагов. Для простого «один вызов — один ответ» их хватает.
  • Модель с контекстом 128K важна, когда история диалога с результатами инструментов растёт.

Грабли

  • Параллельные вызовы. Модель может вернуть несколько tool_calls за раз. Исполняйте все и добавляйте по одному tool-сообщению на каждый tool_call_id. Пропустите один — следующий запрос упадёт с ошибкой рассинхрона.
  • Бесконечный цикл. Поставьте лимит итераций (8–10). Иногда модель зацикливается, вызывая один инструмент снова и снова.
  • Мусор в аргументах. Валидируйте arguments до исполнения. Модель иногда шлёт order_id: "мой заказ" вместо номера. Возвращайте ей осмысленную ошибку в tool-сообщении — она исправится.
  • Побочные эффекты. Инструменты, которые что-то меняют (отправить платёж, удалить запись), оборачивайте в подтверждение. Не давайте агенту право на необратимое без человека в цикле.

Совет по проектированию

Делайте инструменты крупными и осмысленными, а не «одна функция — один SQL». Вместо select_users, join_orders, filter_by_date дайте один find_customer_orders(customer, period). Модель хуже собирает сложные цепочки из мелких примитивов, чем дёргает один понятный инструмент. И описание — на языке домена, а не на языке вашей БД.