Перейти до вмісту

Виклик функцій

Перетворити 299 ендпоінтів на 299 інструментів для LLM — очевидний підхід, але хибний. Нижче — схема, яка працює, і чотири збої, які варто врахувати ще під час проєктування.

Не створюйте 299 інструментів

У всіх великих провайдерів якість падає, щойно список інструментів зростає: схеми з’їдають контекстне вікно ще до початку розмови, а коли описи кількох інструментів перетинаються, модель гірше вибирає. Маючи 299 ендпоінтів, більшість із яких приймають ті самі чотири поля, ви витрачали б тисячі токенів на кожен хід — і лише для того, щоб модель частіше помилялася з вибором.

Створіть один інструмент, максимум два. Модель передає маршрут як аргумент, а не вибирає серед сотень схем.

Варіант з одним інструментом

опис інструмента
{
  "name": "occult_api",
  "description":
    "Vedic astrology calculations from the Occult API. Call this for anything involving a birth chart, panchanga, dasha, muhurta, matching or numerology. Do not compute astrology yourself - planetary positions require an ephemeris and cannot be derived from a date.",
  "input_schema": {
    "type": "object",
    "properties": {
      "route": {
        "type": "string",
        "description": "Endpoint path, e.g. /api/astro/panchanga/. Use the catalogue at https://occultapi.com/llms.txt to choose one."
      },
      "body": {
        "type": "object",
        "description": "Request body. Always include date_time (ISO 8601 with offset), latitude, longitude, timezone_as_float. Batch calculations with a keys array where the endpoint supports it."
      }
    },
    "required": ["route", "body"]
  }
}

Опис робить дві справи. Він підказує, коли звертатися до інструмента, і каже моделі не рахувати самій — а це важливіше, ніж здається. Модель, яку спитали про накшатру, охоче видасть правдоподібну відповідь зі своїх навчальних даних, якщо ніщо не нагадає їй, що для положень планет потрібні ефемериди.

Обробник

node
async function occultApi({ route, body }) {
  const response = await fetch(`${process.env.OCCULT_API_BASE}${route}`, {
    method: "POST",
    headers: {
      "X-API-Key": process.env.OCCULT_API_KEY,   // server-side only
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });

  const payload = await response.json();

  // 402 means out of credits. It is NOT transient - retrying spends nothing
  // and fixes nothing, so surface it rather than backing off.
  if (response.status === 402) {
    return { error: "insufficient_credits", retryable: false };
  }

  // The envelope is the same on every endpoint: branch on is_error, and hand
  // the model the message rather than a stack trace it cannot act on.
  if (payload.is_error) {
    return { error: payload.message, retryable: false };
  }

  return payload.data;
}

Адаптуючи його під себе, збережіть три речі. Ключ читається на сервері: ключ у браузерному коді — це ключ, яким уже витрачає кредити хтось інший. 402 не повторюється: він означає, що баланс порожній, тож цикл повторів лише марнує час і нічого не виправляє. Повідомлення про помилку передається моделі: API вказує, яке поле хибне, і модель із цією підказкою сама виправить запит на наступному ході.

Варіант із двома інструментами — коли моделі треба пошукати

Якщо користувачі ставлять відкриті запитання, модель не знатиме, який маршрут їй потрібен. Дайте їй ще й інструмент пошуку: пошук кредитів не коштує, тож розвідка безкоштовна, а платите ви лише за відповідь.

опис інструментів
[
  {
    "name": "occult_search",
    "description": "Find the right Occult API endpoint by name or by what it calculates, e.g. 'manglik' or 'sunrise'. Returns routes and their request fields. Costs nothing.",
    "input_schema": {
      "type": "object",
      "properties": { "query": { "type": "string" } },
      "required": ["query"]
    }
  },
  {
    "name": "occult_call",
    "description": "Call an Occult API endpoint found with occult_search. One credit per successful call (the PDF reports and chat cost 25); failures are free.",
    "input_schema": {
      "type": "object",
      "properties": {
        "route": { "type": "string" },
        "body": { "type": "object" }
      },
      "required": ["route", "body"]
    }
  }
]

Спрямуйте occult_search на /llms.txt або повніший /llms-full.txt — обидва файли існують саме для цього. Якщо ваш фреймворк генерує інструменти зі специфікації, є й специфікація OpenAPI 3.1.

Чотири збої, які варто врахувати заздалегідь

  • Окремий виклик на кожен розрахунок. Більшість ендпоінтів приймають масив keys і рахують кілька речей за один запит і один кредит. Модель, якщо її не попередити, зробить чотири виклики й витратить чотири кредити. Напишіть про це в описі інструмента.
  • Повтор після 402. Це проблема балансу, а не мережі. Позначте в обробнику, що цю помилку повторювати не можна: сама модель за кодом статусу різниці не побачить.
  • Ключ потрапляє на клієнт. Інструменти мають виконуватися на вашому сервері. Моделі ніколи не потрібно бачити ключ, а якщо архітектура це дозволяє, до витоку ключа — лише одна промпт-ін’єкція.
  • Вигадані назви полів. Моделі вгадують date чи lat, а насправді поля називаються date_time, latitude, longitude і timezone_as_float. Укажіть їх в описі, щоб модель не дізнавалася про них через помилку 400.

Як виглядає справжній виклик

curl
curl -X POST https://api.occultapi.com/api/astro/panchanga/ \
  -H 'X-API-Key: yt_live_your_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "date_time": "2026-09-17T06:00:00+05:30",
    "latitude": 26.9124,
    "longitude": 75.7873,
    "timezone_as_float": 5.5,
    "keys": ["tithi", "nakshatra_segments", "yogam", "karana"]
  }'

Чотири розрахунки — один кредит. Відповідь містить X-Credits-Charged і X-Credits-Remaining — це найпростіший спосіб показувати поточні витрати у власному інтерфейсі.

Далі