Главная/Блог/Обзор/Tool Calling: Единый цикл для Claude,…
Обзор5 мин чтения · 13 августа 2026 г.

Tool Calling: Единый цикл для Claude, GPT и Open Source

Как написать один цикл вызова инструментов (tool calling) на Python или JS, который работает с Claude, GPT и Llama через OpenRouter без переписывания кода.

Tool Calling: Единый цикл для Claude, GPT и Open Source

Tool Calling (или Function Calling) — это механизм, позволяющий модели LLM запрашивать выполнение внешних функций в структурированном формате JSON. Вместо того чтобы полагаться на «галлюцинации» модели для получения точных данных (например, погоды или курсов валют), вы предоставляете ей описание функции. Модель возвращает запрос на её вызов, ваш код исполняет функцию и возвращает результат, после чего модель формирует финальный ответ.

Ключевая проблема большинства туториалов: они привязаны к одному провайдеру (обычно OpenAI). При переходе на Claude или open-source модели (Llama, Mistral) часто требуется переписывать схему инструментов или логику парсинга. OpenRouter решает эту проблему, предоставляя единый API-шлюз, совместимый с форматом OpenAI. Вы пишете цикл один раз, меняя только строку с именем модели.

011. Определение инструмента (Tool Schema)

Сначала определим инструмент. Мы используем стандартную схему JSON, понятную всем современным LLM. В примере — функция получения погоды get_weather. Обратите внимание: модель никогда не исполняет код сама, она только генерирует JSON-запрос.

Схема должна включать имя, описание и параметры (с типами данных и обязательными полями).

💡
Важно для практиков. Поле arguments в ответе модели — это строка, а не объект. Её нужно обязательно парсить через JSON.parse или json.loads. Также не доверяйте модели слепо: всегда проверяйте ключи JSON перед передачей в функцию, так как модель может выдать лишние или невалидные параметры.

022. Реализация цикла на Python

Для работы потребуется Python 3.10+ и библиотека openai (даже для работы с OpenRouter, так как API совместим). Установите пакет:

terminalbash
pip install openai

Ниже представлен полный цикл обработки. Он делает два запроса к API: первый — чтобы получить запрос на вызов инструмента, второй — чтобы получить финальный ответ на основе результата выполнения функции.

terminalpython
import json
import os
from openai import OpenAI

# Инициализация клиента OpenRouter
client = OpenAI(
    base_url="https://openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
)

# Схема инструмента
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the current weather for a location.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "City name, e.g. 'Paris'"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["location"]
        }
    }
}]

def get_weather(location, unit="celsius"):
    # Здесь должна быть реальная логика (API запрос)
    return {"location": location, "temperature": 18, "unit": unit, "sky": "clear"}

def run_tool_loop(model, user_message):
    messages = [{"role": "user", "content": user_message}]
    
    # Шаг 1: Запрос к модели
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        tools=tools
    )
    
    msg = response.choices[0].message
    
    # Если инструмент не нужен, возвращаем прямой ответ
    if not msg.tool_calls:
        return msg.content
    
    # Шаг 2: Добавляем ответ ассистента в контекст
    messages.append(msg)
    
    # Шаг 3: Исполняем инструменты
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = get_weather(**args)
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result)
        })
    
    # Шаг 4: Запрос финального ответа
    final = client.chat.completions.create(
        model=model,
        messages=messages,
        tools=tools
    )
    
    return final.choices[0].message.content

033. Реализация на JavaScript/TypeScript (Node.js)

Для Node.js 22+ используйте пакет openai. Логика идентична Python-версии.

terminaljavascript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://openrouter.ai/api/v1",
  apiKey: process.env.OPENROUTER_API_KEY,
});

const tools = [{
  type: "function",
  function: {
    name: "get_weather",
    description: "Get the current weather for a location.",
    parameters: {
      type: "object",
      properties: {
        location: { type: "string", description: "City name, e.g. 'Paris'" },
        unit: { type: "string", enum: ["celsius", "fahrenheit"] }
      },
      required: ["location"]
    }
  }
}];

function getWeather(location, unit = "celsius") {
  return { location, temperature: 18, unit, sky: "clear" };
}

async function runToolLoop(model, userMessage) {
  const messages = [{ role: "user", content: userMessage }];
  
  const response = await client.chat.completions.create({ model, messages, tools });
  const msg = response.choices[0].message;
  
  if (!msg.tool_calls) return msg.content;
  
  messages.push(msg);
  
  for (const call of msg.tool_calls) {
    const args = JSON.parse(call.function.arguments);
    const result = getWeather(args.location, args.unit);
    messages.push({
      role: "tool",
      tool_call_id: call.id,
      content: JSON.stringify(result)
    });
  }
  
  const final = await client.chat.completions.create({ model, messages, tools });
  return final.choices[0].message.content;
}

044. Сравнение моделей и производительность

Самое важное преимущество подхода — кросс-провайдерность. Ниже приведена таблица моделей, поддерживающих Tool Calling, и пример их поведения с одним и тем же кодом.

Модель (OpenRouter ID) Провайдер Тип Пример результата
anthropic/claude-opus-4.8 Anthropic Флагман «It's currently 18°C and clear in Paris.»
openai/gpt-4o OpenAI Универсальная «The weather in Paris is 18°C and clear.»
meta-llama/llama-3.1-405b Meta Open Source «Paris weather: 18°C, clear sky.»
⚠️
Совместимость. Не все модели поддерживают Tool Calling. Всегда проверяйте документацию модели или список доступных инструментов в панели OpenRouter перед интеграцией. Open-source модели (например, Llama 3.1) поддерживают эту функцию, но могут быть менее стабильны в форматировании JSON, чем проприетарные аналоги.

055. Обработка ошибок и Edge Cases

В продакшене необходимо добавить обработку ошибок при парсинге JSON. Модель может вернуть невалидную строку или параметры, отсутствующие в схеме.

  • Валидация JSON: Оберните json.loads в блок try/except. Если парсинг не удался, верните ошибку в чат, чтобы модель попробовала переформулировать запрос.
  • Проверка ключей: Используйте библиотеки валидации (например, pydantic в Python или zod в JS) для проверки входящих аргументов перед вызовом бизнес-логики.
  • Multiple Tool Calls: Модель может запросить выполнение нескольких функций одновременно. Цикл for call in msg.tool_calls обрабатывает массив, поэтому код выше уже готов к этому сценарию.

06Кому подойдёт / что запустится

Этот подход идеален для разработчиков, строящих AI-агентов или чат-ботов с доступом к внешним данным. Вам не нужно поддерживать отдельные SDK для OpenAI, Anthropic и Llama. Достаточно одного клиента OpenRouter.

Что запустится прямо сейчас:

  • Python 3.10+ с pip install openai.
  • Node.js 22+ с npm install openai.
  • Любая модель из каталога OpenRouter, помеченная как поддерживающая tools (Claude Opus/Sonnet, GPT-4o, Llama 3.1 405B/70B, Mistral Large).

Для тестирования скопируйте код Python, установите ключ API и запустите run_tool_loop("anthropic/claude-opus-4.8", "What's the weather in Paris?"). Результат будет получен через два API-вызова.

Источник: OpenRouter ↗