DEV Community

Cover image for Pourquoi les agents IA échouent en production (et comment tester chaque mode de défaillance)
Antoine Laurent
Antoine Laurent

Posted on • Originally published at apidog.com

Pourquoi les agents IA échouent en production (et comment tester chaque mode de défaillance)

Votre agent a fonctionné dans la démo : il a lu le ticket, appelé trois API et publié un résumé clair. Après le déploiement, il a envoyé deux fois le même e-mail au même client, a épuisé le budget de jetons dans une boucle de réessai, puis a transmis au frontend une charge utile impossible à analyser.

Essayez Apidog dès aujourd’hui

L'écart entre un prototype fonctionnel et un agent fiable se situe rarement dans le modèle. Il se trouve dans les appels API que l'agent effectue : chaque outil est une requête HTTP pouvant échouer, expirer, être limitée ou renvoyer une réponse inattendue. Testez ces appels comme n'importe quelle API de production, sinon une seule mauvaise réponse peut déclencher un incident.

La bonne nouvelle : la fiabilité d'un agent se teste. Vous pouvez forcer les chemins d'échec avant que les utilisateurs ne les découvrent. Ce guide couvre cinq modes de défaillance et montre comment les vérifier à la frontière API. Une plateforme comme Apidog permet de définir les contrats, simuler les dépendances et valider les réponses.

Les agents échouent à la limite de l'API, pas dans le prompt

Quand un agent se comporte mal en production, le premier réflexe consiste à modifier le prompt. Cela peut aider, mais l'échec vient souvent d'ailleurs :

  1. Le modèle choisit un outil.
  2. Votre code transforme ce choix en requête HTTP.
  3. Un service externe répond.
  4. Votre code renvoie le résultat au modèle.

Trois de ces quatre étapes relèvent de l'intégration API classique. L'agent augmente toutefois le risque : au lieu de lever proprement une exception, le modèle peut raisonner sur une réponse incomplète ou erronée et agir avec assurance.

La question utile n'est donc pas : « Le modèle est-il assez intelligent ? », mais :

Ai-je testé toutes les façons dont les appels API de mon agent peuvent échouer ?

Mode de défaillance 1 : appels d'outils hors contrat

Le cas le plus fréquent : l'agent appelle la bonne API avec de mauvais arguments.

Exemple : un agent de réservation envoie ceci à POST /reservations :

{
  "guests": "two"
}
Enter fullscreen mode Exit fullscreen mode

Alors que le contrat attend :

{
  "guests": 2
}
Enter fullscreen mode Exit fullscreen mode

L'API peut répondre avec un 400, ou pire, retourner un 200 contenant une erreur métier dans le corps. Si votre agent interprète ce 200 comme un succès, il poursuit un flux invalide.

À mettre en place

Définissez le schéma de chaque outil que l'agent peut invoquer :

{
  "type": "object",
  "required": ["guests", "date"],
  "properties": {
    "guests": {
      "type": "integer",
      "minimum": 1
    },
    "date": {
      "type": "string",
      "format": "date"
    }
  },
  "additionalProperties": false
}
Enter fullscreen mode Exit fullscreen mode

Puis validez systématiquement la requête sortante avant de l'envoyer :

const valid = validateReservationPayload(toolArguments);

if (!valid) {
  throw new Error("Appel d'outil invalide : contrat POST /reservations non respecté");
}
Enter fullscreen mode Exit fullscreen mode

Utilisez ce guide sur le test des appels d'outils d'un agent IA pour approfondir ce point, ainsi que la méthode complète pour tester les agents qui appellent vos API.

Dans Apidog, chargez les schémas de vos outils et exécutez les appels réels de l'agent contre ces définitions. Toute non-conformité doit produire un échec explicite avec le champ concerné.

Mode de défaillance 2 : erreurs en amont et limites de débit

Chaque dépendance externe peut répondre avec :

  • 429 Too Many Requests
  • 500 Internal Server Error
  • un délai d'attente
  • une réponse vide ou mal formée

Un agent robuste applique des réessais limités avec backoff. Un agent fragile abandonne immédiatement ou réessaie en boucle jusqu'à épuiser les jetons, le budget et les limites de débit.

Les modèles de récupération d'erreur d'agent sont d'ailleurs une question fréquente dans les discussions du SDK Anthropic.

Testez une séquence d'échec contrôlée

Simulez la dépendance avec cette séquence :

  1. 429 avec l'en-tête Retry-After
  2. 500
  3. 200 avec une réponse valide

Votre test doit vérifier que l'agent :

  • respecte Retry-After ;
  • applique un backoff avec gigue ;
  • limite le nombre de tentatives ;
  • s'arrête proprement après un seuil ;
  • ne répète pas une opération non idempotente.

Pseudo-code de récupération :

for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
  const response = await callDependency();

  if (response.ok) {
    return response.data;
  }

  if (response.status === 429) {
    const retryAfter = response.headers.get("Retry-After");
    await sleep(toMilliseconds(retryAfter) + jitter());
    continue;
  }

  if (response.status >= 500) {
    await sleep(exponentialBackoff(attempt) + jitter());
    continue;
  }

  throw new Error(`Erreur non récupérable : ${response.status}`);
}

throw new Error("Nombre maximal de tentatives atteint");
Enter fullscreen mode Exit fullscreen mode

Pour les opérations à effet de bord, ajoutez une clé d'idempotence. Sans elle, un réessai peut provoquer un double débit, une double commande ou un double e-mail.

Simulez aussi explicitement les limites de débit. Consultez le guide sur la signification d'une réponse de dépassement de limite de débit, puis appliquez les stratégies du guide sur la récupération d'erreurs d'agent IA.

Mode de défaillance 3 : sortie non déterministe

Même avec une température à zéro, les sorties ne sont pas toujours identiques d'une exécution à l'autre. Le matériel, le traitement par lots et les changements côté fournisseur introduisent des variations. Le fil de discussion vLLM sur les limites des graines et de la température pour la reproductibilité l'illustre bien.

Évitez donc les assertions exactes sur le texte généré :

// Fragile
expect(answer).toBe("Votre réservation est confirmée.");

// Robuste
expect(answer).toMatchSchema(BookingResponseSchema);
expect(answer.total).toBeGreaterThanOrEqual(0);
expect(answer.total).toBeLessThanOrEqual(cartTotal);
expect(answer.reservationId).toBeDefined();
Enter fullscreen mode Exit fullscreen mode

Préférez les assertions sur

  • le schéma JSON ;
  • les clés obligatoires ;
  • l'absence de champs interdits ;
  • la cible et la forme de l'appel d'outil ;
  • les plages numériques ;
  • les invariants métier.

Un test qui vérifie que total est compris entre 0 et le montant du panier détecte une régression réelle sans casser à cause d'une reformulation du modèle.

Consultez le guide sur le test des agents IA non déterministes et celui sur le fonctionnement de la mémoire de l'agent, car l'état rend ces tests plus complexes.

Mode de défaillance 4 : coût incontrôlé

Les agents fonctionnent en boucle, et les boucles coûtent de l'argent. Un agent bloqué peut répéter un appel défaillant des milliers de fois et faire exploser les coûts en quelques heures.

Le coût est aussi un signal de fiabilité : les bugs qui gaspillent des jetons rendent souvent l'agent plus lent et moins prévisible.

Ajoutez des budgets d'exécution

Suivez au minimum :

  • le nombre d'appels d'outils ;
  • le nombre de tentatives par dépendance ;
  • les jetons consommés ;
  • la durée totale ;
  • le coût estimé par tâche.

Exemple de garde budgétaire :

if (run.toolCalls > 20) {
  throw new Error("Budget d'appels d'outils dépassé");
}

if (run.tokenCount > MAX_TOKENS_PER_TASK) {
  throw new Error("Budget de jetons dépassé");
}
Enter fullscreen mode Exit fullscreen mode

Lors de vos tests de récupération, vérifiez aussi le nombre d'appels. Un agent qui finit par réussir après quarante appels reste un incident de coût en attente.

Pour des leviers concrets côté ligne de commande, consultez le guide sur la réduction des coûts de jetons d'agent.

Mode de défaillance 5 : garde-fous manquants

Les pannes les plus coûteuses sont celles où l'agent exécute correctement une action qui n'aurait jamais dû être automatique : envoyer un e-mail, supprimer un enregistrement, déclencher une commande ou modifier une donnée sensible.

Les garde-fous doivent se trouver entre la décision du modèle et l'action réelle.

Implémentez trois niveaux de protection

  1. Liste blanche pour les actions autorisées sans validation.
  2. Approbation humaine pour les actions destructrices ou irréversibles.
  3. Exécution à blanc pour voir ce que l'agent ferait sans effet de bord.

Exemple :

const requiresApproval = [
  "send_email",
  "delete_customer",
  "create_order"
];

if (requiresApproval.includes(tool.name)) {
  return {
    status: "approval_required",
    proposedAction: tool
  };
}
Enter fullscreen mode Exit fullscreen mode

Ensuite, testez réellement ce comportement :

  • simulez le point de terminaison à effet de bord ;
  • exécutez l'agent ;
  • vérifiez qu'il demande une confirmation ;
  • vérifiez qu'aucun appel réel n'est envoyé avant l'approbation.

L'OWASP Top 10 pour les applications LLM fournit une bonne base de contrôle. Pour aller plus loin, consultez le guide sur les garde-fous des agents IA.

Comment structurer un test d'agent

Les cinq modes suivent la même boucle de test :

  1. Capturez les schémas d'outils afin de disposer de contrats vérifiables.
  2. Simulez chaque dépendance pour contrôler les délais, codes HTTP et corps de réponse.
  3. Exécutez l'agent sur des scénarios normaux et des scénarios d'échec.
  4. Faites des assertions sur les requêtes, la récupération, le nombre d'appels et les garde-fous.

Exemple de scénario de test :

it("respecte Retry-After et ne double pas une commande", async () => {
  mockPaymentApi
    .replyOnce(429, {}, { "Retry-After": "1" })
    .replyOnce(200, { paymentId: "pay_123" });

  const result = await agent.run({
    task: "Encaisser la commande order_42"
  });

  expect(result.status).toBe("success");
  expect(mockPaymentApi.requestCount()).toBe(2);
  expect(mockPaymentApi.requests[0].headers["idempotency-key"])
    .toBe(mockPaymentApi.requests[1].headers["idempotency-key"]);
});
Enter fullscreen mode Exit fullscreen mode

Commencez avec un outil critique, puis ajoutez les autres. La configuration est rentabilisée dès qu'elle détecte un appel cassé avant vos utilisateurs.

Liste de contrôle de la fiabilité des agents

Avant de passer un agent en production, vérifiez les points suivants :

  • Chaque appel d'outil est validé contre un schéma.
  • Les violations de contrat font échouer les tests.
  • Les réponses 429, 500 et les délais d'attente sont simulés.
  • L'agent applique un backoff et limite ses tentatives.
  • Les opérations répétées sont idempotentes.
  • Les tests valident la structure et le sens, pas des chaînes exactes.
  • Les jetons et appels d'outils sont mesurés par exécution.
  • Un plafond budgétaire arrête les boucles incontrôlées.
  • Les actions destructrices passent par une liste blanche ou une approbation humaine.
  • Le chemin de garde-fou est testé avec une simulation.

Où Apidog s'intègre — et où il ne s'intègre pas

Apidog n'est pas un framework d'agent, un hôte de modèle ou un harnais d'évaluation. Il ne construit ni n'exécute votre agent.

Son rôle est de gérer la couche API dont dépend votre agent :

  • définir et stocker les contrats des outils ;
  • valider les requêtes sortantes ;
  • simuler des réponses 429, 500, des délais d'attente et des corps mal formés ;
  • vérifier les schémas, clés obligatoires et plages de valeurs des réponses.

C'est exactement la couche où se produisent les défaillances décrites ici. Consultez aussi l'aperçu des tests d'agents IA pour replacer ces pratiques dans une stratégie QA plus large.

Questions fréquemment posées

La fiabilité d'un agent est-elle un problème de modèle ou d'ingénierie ?

Principalement d'ingénierie. Le choix du modèle compte, mais les incidents les plus fréquents — mauvais appels d'outils, limites de débit non gérées et garde-fous absents — sont des problèmes d'intégration et de test.

Puis-je tester un agent sans appeler ses API réelles ?

Oui, et vous devriez le faire. Simulez les dépendances pour forcer les erreurs, contrôler le timing et éviter les effets de bord réels.

Comment tester une sortie qui change à chaque exécution ?

Validez la structure et les invariants métier plutôt que le texte exact. Vérifiez les schémas, les champs requis, la forme des appels d'outils et les plages numériques. Le guide tester les agents IA non déterministes détaille cette approche.

Que tester en premier ?

Commencez par les garde-fous sur les actions destructrices, puis la récupération d'erreur. Ce sont les protections les plus efficaces contre les actions nuisibles et les boucles coûteuses.

Commencez par un mode de défaillance

N'essayez pas de tout couvrir d'un coup. Choisissez le risque le plus important pour votre agent, souvent les garde-fous ou la récupération après erreur.

Cette semaine :

  1. simulez une défaillance ;
  2. exécutez l'agent ;
  3. observez les appels sortants ;
  4. ajoutez des assertions sur le comportement attendu.

La première fois que vous verrez votre agent gérer proprement un 429 simulé avec un backoff limité, au lieu de tourner en boucle jusqu'à épuiser le budget, vous aurez une raison concrète de lui faire confiance.

Téléchargez Apidog pour concevoir les contrats, simuler les défaillances et vérifier les réponses dont votre agent dépend.

Top comments (0)