Виклик функцій
Перетворити 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"]
}
}Опис робить дві справи. Він підказує, коли звертатися до інструмента, і каже моделі не рахувати самій — а це важливіше, ніж здається. Модель, яку спитали про накшатру, охоче видасть правдоподібну відповідь зі своїх навчальних даних, якщо ніщо не нагадає їй, що для положень планет потрібні ефемериди.
Обробник
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 -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 — це найпростіший спосіб показувати поточні витрати у власному інтерфейсі.