Виклик функцій
Перетворити кожен із 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 — це найпростіший спосіб показувати поточні витрати у вашому інтерфейсі.