Inquir Compute · вызов инструментов

Бэкенд для вызова инструментов LLM (function calling)

Function calling в LLM (OpenAI, Anthropic, Gemini) — это JSON-контракт: модель объявляет схему инструмента, ваш оркестратор отправляет POST на соответствующий маршрут шлюза, а обработчик возвращает модели структурированный JSON. Эта страница — про слой трансляции между спецификацией function calling и HTTP-эндпоинтом: авторизация, паттерн диспетчеризации и круг через шлюз. Многошаговые agentic-воркфлоу — на странице /agentic-workflow-backend.

Обновлено: 2026-06-28

Суть ответа

Бэкенд для вызова инструментов LLM (function calling). Каждое определение функции сопоставляется маршруту шлюза Inquir. Модель получает структурированный манифест инструментов; когда она запрашивает вызов, оркестратор отправляет POST на шлюз с API-ключом. Обработчик функции работает изолированно, получает только нужные ему секреты и возвращает структурированный JSON.

Когда подходит

  • Продакшен-приложения на LLM с function calling OpenAI, tool use Anthropic или function declarations Gemini
  • Инструменты, которые работают с приватными данными, вызывают внешние API или имеют побочные эффекты

На что обратить внимание

  • Выполнение инструментов прямо в цикле LLM: ни изоляции, ни ретраев, ни наблюдаемости по инструментам.
  • Открытые HTTP-эндпоинты без авторизации: инструменты может вызвать кто угодно, а не только ваш пайплайн модели.
  • Секреты в переменных окружения, общих для всех инструментов: ротация одного ломает всё.

Почему function calling нужен настоящий бэкенд

Function calling в LLM (OpenAI, Anthropic, Gemini) позволяет модели запрашивать вызовы инструментов. В демо они выполняются локально рядом с циклом модели. В проде функциям инструментов нужны авторизация, подстановка секретов, лимиты запросов, трассировка выполнения и async-обработка шагов, которые длятся дольше одного раунда.

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

Типичные антипаттерны вызова инструментов

Выполнение инструментов прямо в цикле LLM: ни изоляции, ни ретраев, ни наблюдаемости по инструментам.

Открытые HTTP-эндпоинты без авторизации: инструменты может вызвать кто угодно, а не только ваш пайплайн модели.

Секреты в переменных окружения, общих для всех инструментов: ротация одного ломает всё.

Serverless-функции как слой вызова инструментов

Каждое определение функции сопоставляется маршруту шлюза Inquir. Модель получает структурированный манифест инструментов; когда она запрашивает вызов, оркестратор отправляет POST на шлюз с API-ключом. Обработчик функции работает изолированно, получает только нужные ему секреты и возвращает структурированный JSON.

Для инструментов с async-работой — веб-скрейпинг, массовое чтение из базы, ML-инференс — HTTP-обработчик ставит durable-задачу в очередь и сразу возвращает ссылку на задачу. Оркестратор опрашивает статус или получает колбэк, когда результат готов; очередь повторяет упавшую работу с backoff.

Паттерны бэкенда для вызова инструментов

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

Быстрые инструменты (поиск, расчёт, форматирование) возвращают результат сразу, в окне одного раунда модели.

Async-вызовы со ссылкой на задачу

Медленные инструменты возвращают jobId; оркестратор опрашивает статус или ждёт колбэк. Модель продолжает планировать, пока инструмент работает в фоне.

Кэширование результатов инструментов

Кэшируйте детерминированные результаты в обработчике (ключ — хеш входа, хранилище — ваше): шлюз ответы не кэширует, так что кэш и его инвалидация под вашим контролем.

Трассировка вызовов инструментов

Каждый вызов инструмента создаёт запись выполнения: вход, выход, длительность, ошибка. Сопоставляйте с ID вызовов модели для сквозных трасс.

Как реализовать бэкенд для вызова инструментов

1

Описать схему инструмента

Напишите определение функции в формате OpenAI/Anthropic. Имя каждого инструмента соответствует маршруту шлюза.

2

Реализовать и задеплоить обработчики

Одна функция на инструмент. Провалидируйте вход, обратитесь к внешним системам с ограниченными секретами, верните структурированный JSON.

3

Подключить оркестратор к шлюзу

Оркестратор отправляет POST на маршруты шлюза с API-ключом. Шлюз проверяет авторизацию до запуска кода обработчика.

Поток вызова инструмента: от схемы к обработчику

Модель видит определение функции; оркестратор сопоставляет его маршруту шлюза; шлюз проверяет авторизацию; обработчик работает изолированно.

tool-definition.json (передаётся в LLM)
{
  "type": "function",
  "function": {
    "name": "search_customer",
    "description": "Look up a customer by ID or email",
    "parameters": {
      "type": "object",
      "properties": {
        "query": { "type": "string", "description": "Customer ID or email" }
      },
      "required": ["query"]
    }
  }
}
tools/search-customer.mjs (функция за шлюзом)
export async function handler(event) {
  // Auth enforced at gateway — API key checked before this code runs
  const { query } = JSON.parse(event.body || '{}');
  if (!query) return { statusCode: 400, body: JSON.stringify({ error: 'query required' }) };
  const results = await db.customers.search(query); // DB_URL from workspace secrets
  return { statusCode: 200, body: JSON.stringify({ customers: results }) };
}
orchestrator/dispatch.mjs (модель → шлюз)
// When the model returns a tool_call, dispatch it to the gateway
async function dispatchToolCall(toolCall) {
  const { name, arguments: args } = toolCall.function ?? toolCall;
  // Map tool name to gateway route
  const routeMap = {
    search_customer: process.env.GATEWAY_URL + '/tools/search-customer',
  };
  const url = routeMap[name];
  if (!url) throw new Error(`Unknown tool: ${name}`);
  const res = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': process.env.TOOLS_API_KEY, // auth enforced at gateway route
    },
    body: JSON.stringify(typeof args === 'string' ? JSON.parse(args) : args),
  });
  if (!res.ok) throw new Error(`Tool ${name} returned ${res.status}`);
  return res.json(); // structured result passed back to the model
}

Когда нужен бэкенд для вызова инструментов

Когда это уместно

  • Продакшен-приложения на LLM с function calling OpenAI, tool use Anthropic или function declarations Gemini
  • Инструменты, которые работают с приватными данными, вызывают внешние API или имеют побочные эффекты

Когда лучше выбрать другое

  • Чисто локальное выполнение инструментов в демо без требований к авторизации и секретам

Частые вопросы

Как обрабатывать ошибки вызова инструментов?

Возвращайте из обработчика структурированный JSON с ошибкой. Передайте ошибку модели как результат инструмента — пусть модель решит, повторить, уточнить или сдаться.

Могут ли инструменты вызывать другие инструменты?

Да — один обработчик инструмента может запустить другой шаг пайплайна. Держите общий граф вызовов под контролем оркестратора, чтобы избежать бесконечных циклов.