API

Вызов инструментов

Модель не вызывает ваши функции сама. Она предлагает вызов (tool_calls), вы исполняете его у себя и возвращаете результат сообщением с role: tool. После этого модель отвечает человеку.

Работает в /chat/completions, /responses и /messages. Есть не у всех моделей — смотрите страницу модели.

tools в каждом запросе

Массив tools нужно передавать и в первом вызове, и когда отдаёте результаты. Иначе схема на следующем шаге пропадёт.

Три шага

  1. Запрос с массивом tools.
  2. Если finish_reason = tool_calls — исполните функции локально.
  3. Добавьте сообщение ассистента и результаты role: "tool", снова вызовите модель.

Шаг 1:

JSON
{
  "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, плюс история:

JSON
{
  "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 — без него модель не поймёт, к чему относится результат.

Агентский цикл

Пока модель просит инструменты — исполняйте и спрашивайте снова. Ограничьте число итераций.

Python
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" } }Конкретная функция

Параллельные вызовы

По умолчанию модель может попросить несколько инструментов сразу. Чтобы по одному:

JSON
{ "parallel_tool_calls": false }

Стриминг

С stream: true куски tool_calls приходят в delta.tool_calls. Соберите их до finish_reason: "tool_calls", потом исполняйте.

Рассуждения между вызовами

Reasoning-модели могут думать между вызовами инструментов. Это больше токенов и задержка. Когда модель вернула tool_calls вместе с reasoning_details, отдайте reasoning_details обратно без правок вместе с результатами инструментов — иначе цепочка мышления рвётся. Подробнее: токены рассуждений.

Поиск в сети и другие вызовы, которые исполняет AITUNNEL, а не ваш код — серверные инструменты.