Перейти к основному содержанию
Вызов функций (он же tool use) — это когда модель не отвечает текстом, а возвращает структурированный запрос на вызов вашей функции: её имя и аргументы. Сам код функции выполняете вы, на своей стороне, а результат отдаёте модели обратно. Дальше она уже формулирует человеческий ответ. Звучит просто, но именно на этом механизме держатся все агенты: модель не умеет ходить в базу, считать погоду или дёргать чужой API — зато умеет попросить вас это сделать и разобраться с тем, что вы вернули. Схема всегда одна и та же:
  1. Вы описываете доступные функции (схему) и шлёте обычный запрос с tools=.
  2. Модель отвечает не текстом, а массивом tool_calls — что и с какими аргументами вызвать.
  3. Вы выполняете функцию у себя и шлёте второй запрос, дописав в историю ответ модели и результат вызова.
  4. Модель возвращает финальный текст.

Полный пример на Python

Возьмём классику — функцию get_weather(city). В реальности она бы дёргала какой-нибудь сервис погоды; здесь для наглядности возвращаем заглушку.
import json
from openai import OpenAI

client = OpenAI(
    api_key="sk-ВАШ_КЛЮЧ",
    base_url="https://www.ruapi.ai/v1",
)

# Это ваш реальный код. Модель его НЕ выполняет — только просит вызвать.
def get_weather(city: str) -> str:
    # тут был бы запрос к погодному API
    return f"В городе {city} сейчас +18°C, переменная облачность"

# Описание функции для модели: что она умеет и какие аргументы принимает
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Возвращает текущую погоду в указанном городе",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "Название города, например «Москва»",
                    }
                },
                "required": ["city"],
            },
        },
    }
]

messages = [{"role": "user", "content": "Какая сейчас погода в Москве?"}]

# Шаг 1. Первый запрос — отдаём модели вопрос и список инструментов
response = client.chat.completions.create(
    model="claude-opus-4-8",  # точные имена — на странице цен основного сайта
    messages=messages,
    tools=tools,
)

message = response.choices[0].message

# Шаг 2. Проверяем, захотела ли модель вызвать функцию
if message.tool_calls:
    # ВАЖНО: сначала дописываем в историю сам ответ модели (с tool_calls)
    messages.append(message)

    # Шаг 3. Обрабатываем каждый вызов (их может быть несколько)
    for tool_call in message.tool_calls:
        # Аргументы приходят СТРОКОЙ с JSON — её нужно распарсить
        args = json.loads(tool_call.function.arguments)

        if tool_call.function.name == "get_weather":
            result = get_weather(args["city"])
        else:
            result = "Неизвестная функция"

        # Результат вызова отдаём отдельным сообщением role="tool"
        messages.append(
            {
                "role": "tool",
                "tool_call_id": tool_call.id,  # привязка к конкретному вызову
                "content": result,
            }
        )

    # Шаг 4. Второй запрос — теперь модель видит результат и даёт финальный ответ
    final = client.chat.completions.create(
        model="claude-opus-4-8",
        messages=messages,
        tools=tools,
    )
    print(final.choices[0].message.content)
else:
    # Модель решила ответить сразу, без вызова функции
    print(message.content)
Tool use поддерживают только способные модели — семейства Claude и GPT, например. Старые и облегчённые модели могут игнорировать tools=. Какие модели что умеют — смотрите по бейджам возможностей на странице «Цены» основного сайта.

Подводные камни

В одном ответе message.tool_calls бывает массивом из нескольких вызовов — например, погода сразу в двух городах. Обходите его циклом и на каждый tool_call добавляйте отдельное сообщение role="tool" со своим tool_call_id. Если хоть один вызов оставить без ответа — следующий запрос упадёт с ошибкой.
Порядок в messages строгий: сперва дописываете сам ответ ассистента (объект message с tool_calls), и только после него — сообщения role="tool" с результатами. Если отправить результат без предшествующего ответа ассистента, API вернёт ошибку о несогласованной истории.
tool_call.function.arguments — это строка с JSON, а не готовый словарь. Перед использованием её обязательно нужно распарсить: json.loads(...). Прямое обращение по ключу к строке выдаст ошибку.

Что дальше