Aller au contenu

Appel de fonctions

Donner à un LLM 299 endpoints sous forme de 299 outils, c’est l’approche évidente, et la mauvaise. Voici la structure qui fonctionne, et les quatre échecs à anticiper dès la conception.

Ne définissez pas 299 outils

Chez tous les grands fournisseurs, la qualité se dégrade à mesure que la liste d’outils s’allonge : les schémas remplissent la fenêtre de contexte avant même le début de la conversation, et la précision du choix chute dès que plusieurs outils ont des descriptions qui se recoupent. Avec 299 endpoints, dont la plupart prennent les quatre mêmes champs, vous dépenseriez des milliers de tokens par tour pour rendre le modèle moins bon dans ses choix.

Définissez un outil, ou deux. Le modèle passe la route en argument, au lieu de choisir parmi des centaines de schémas.

La structure à un seul outil

définition de l’outil
{
  "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"]
  }
}

La description remplit deux rôles. Elle dit quand recourir à l’outil, et elle dit de ne pas faire le calcul soi-même — ce qui compte plus qu’il n’y paraît. Un modèle à qui l’on demande un nakshatra en produira volontiers un plausible à partir de ses données d’entraînement, si rien ne lui indique que les positions planétaires exigent des éphémérides.

Le gestionnaire

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;
}

Trois choses méritent d’être conservées quand vous l’adaptez. La clé est lue côté serveur : une clé dans du code navigateur, c’est une clé que quelqu’un d’autre dépense déjà. Un 402 n’est pas réessayé : il signifie que le solde est vide, et une boucle de nouvelles tentatives fait perdre du temps sans rien régler. Le message d’erreur est transmis tel quel : l’API indique quel champ était incorrect, et un modèle qui reçoit cette information corrige lui-même sa requête au tour suivant.

La structure à deux outils, quand le modèle doit explorer

Si vos utilisateurs posent des questions ouvertes, le modèle ne saura pas de quelle route il a besoin. Donnez-lui aussi un outil de recherche : chercher ne coûte aucun crédit, l’exploration est donc gratuite et seule la réponse est facturée.

définitions des outils
[
  {
    "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"]
    }
  }
]

Faites pointer occult_search vers /llms.txt ou vers la version plus complète /llms-full.txt : les deux existent précisément pour cela. Il existe aussi une spécification OpenAPI 3.1, si votre framework génère les outils à partir d’une spécification.

Quatre échecs à anticiper

  • Un appel par calcul. La plupart des endpoints prennent un tableau keys et calculent plusieurs choses en une seule requête, pour un crédit. Livré à lui-même, un modèle fera quatre appels et paiera quatre crédits. Précisez-le dans la description de l’outil.
  • Réessayer un 402. C’est un problème de solde, pas de réseau. Marquez-le comme non réessayable dans le gestionnaire, car le modèle ne peut pas faire la différence à partir du seul code de statut.
  • La clé qui atteint le client. L’exécution des outils se fait sur votre serveur. Le modèle n’a jamais besoin de voir la clé, et toute conception où il pourrait la voir n’est qu’à une injection de prompt d’une fuite.
  • Des noms de champs inventés. Les modèles devinent date ou lat. Les vrais champs sont date_time, latitude, longitude et timezone_as_float. Mettez-les dans la description au lieu de laisser le modèle les découvrir à coups d’erreurs 400.

À quoi ressemble vraiment un appel

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"]
  }'

Quatre calculs, un crédit. La réponse contient X-Credits-Charged et X-Credits-Remaining : c’est le moyen le plus économique d’afficher un coût cumulé dans votre propre interface.

Suivant