Tool mocking et fault injection pour agents IA

Simuler outils et pannes pour tester comment les agents réagissent aux erreurs.
Sur cette page
  1. Idée en 30 secondes
  2. Le problème
  3. Quand l'utiliser
  4. Implémentation
  5. Comment cela fonctionne dans un test
  6. 1. Fixer le contrat du mock tool
  7. 2. Injecter la panne de manière contrôlée
  8. 3. Vérifier retry et fallback
  9. 4. Fixer la structure d'erreur
  10. 5. Exécuter ces tests dans CI
  11. Erreurs typiques
  12. Le mock ne correspond pas au contrat réel
  13. Vérifier seulement le happy path
  14. Fault injection aléatoire
  15. Pas de vérification de stop_reason et error shape
  16. Pas de vérification des effets secondaires pendant retry
  17. Mélange des checks unit et intégration
  18. En bref
  19. FAQ
  20. Et ensuite

Idée en 30 secondes

Tool mocking et fault injection permettent de reproduire des erreurs API de façon contrôlée, puis de vérifier comment l'agent les gère, sans réseau réel et sans bruit non déterministe.

La valeur principale : reproduire précisément timeout, 5xx ou une réponse cassée, puis valider retry, fallback et stop reason.

Le problème

Sans mocks ni fault injection, l'équipe voit généralement seulement le happy path :

  • l'outil répond vite ;
  • la réponse est valide ;
  • l'agent termine le run sans erreur.

En production, c'est rare. Les outils peuvent retourner timeout, pannes partielles, champs vides ou latency instable.

Sans tests dédiés aux erreurs, cela mène souvent à :

  • des pannes imprévisibles sur des scénarios critiques ;
  • des répétitions d'appels sans fin ;
  • des incidents coûteux et bruités, difficiles à reproduire.

Quand l'utiliser

Cette approche est nécessaire si l'agent dépend d'outils externes :

  • API de paiement, CRM, recherche, services backend ;
  • outils avec retry/backoff ;
  • scénarios où un stop_reason correct est critique ;
  • scénarios avec fallback (par exemple outil de secours ou réponse sûre).

Si une panne d'outil peut être modélisée localement, c'est un bon candidat pour un test de fault injection.

Implémentation

En pratique, la règle est simple : un type de panne, un test, des conditions contrôlées. Les exemples ci-dessous sont schématiques et non liés à un framework précis.

Comment cela fonctionne dans un test

Cycle court d'un test avec fault injection
  • Test case - un comportement à vérifier.
  • Mock tool - fixer le contrat input/output.
  • Inject fault - injecter une panne précise (timeout, 5xx, bad_payload).
  • Run - exécuter une étape concrète de l'agent.
  • Assertions - vérifier retry, fallback, stop_reason et format d'erreur.

1. Fixer le contrat du mock tool

PYTHON
class FakePaymentsAPI:
    def __init__(self, mode: str = "ok"):
        self.mode = mode

    def refund(self, order_id: str):
        if self.mode == "ok":
            return {"status": "approved", "order_id": order_id}
        if self.mode == "timeout":
            raise TimeoutError("payments_timeout")
        if self.mode == "http_500":
            raise RuntimeError("payments_500")
        return {"status": None}

Le mock doit reproduire le contrat réel de l'outil aussi fidèlement que possible. Sinon, les tests donnent un faux sentiment de sécurité.

2. Injecter la panne de manière contrôlée

PYTHON
def test_timeout_fault_is_injected():
    payments = FakePaymentsAPI(mode="timeout")
    agent = Agent(payments_api=payments)

    result = agent.handle_refund("order-8472")

    assert result.stop_reason in {"tool_error_handled", "fallback_used"}

Le profil de panne doit être explicite et répétable : le même test doit toujours reproduire la même forme de panne.

3. Vérifier retry et fallback

PYTHON
def test_retry_then_fallback():
    payments = FlakyPaymentsAPI(fail_times=2, then="timeout")
    backup = FakeBackupTool()
    agent = Agent(payments_api=payments, backup_tool=backup, max_retries=2)

    result = agent.handle_refund("order-9001")

    assert payments.calls == 2
    assert result.selected_tool == "backup_tool"
    assert result.stop_reason == "fallback_used"

Il faut vérifier non seulement le fait qu'une erreur se produit, mais aussi la politique de récupération qui suit.

Pour les flux de retry, il faut contrôler non seulement le nombre de tentatives, mais aussi les conditions où le système arrête de réessayer et passe en fallback ou en échec.

Pour les outils avec effets secondaires (changements d'état), il faut vérifier que retry ne crée pas d'opérations dupliquées.

4. Fixer la structure d'erreur

PYTHON
def test_error_envelope_is_stable():
    payments = FakePaymentsAPI(mode="http_500")
    agent = Agent(payments_api=payments)
    result = agent.handle_refund("order-1122")

    assert result.error["code"] == "tool_error"
    assert result.error["tool"] == "payments_api"
    assert result.error["retryable"] is True

Un format d'erreur stable simplifie le debug, les alertes et les checks de regression.

5. Exécuter ces tests dans CI

Ces tests doivent tourner sur chaque PR via l'étape standard pytest dans CI, si les changements touchent la logique d'outils, les retries ou les règles de fallback.

Erreurs typiques

Le mock ne correspond pas au contrat réel

Le test passe, mais en production l'agent tombe parce que la structure des champs ou le code d'erreur diffère.

Cause typique : le mock renvoie une payload simplifiée qui ne ressemble pas à l'API réelle.

Vérifier seulement le happy path

Les tests n'ont que "réponse réussie", sans timeout, 5xx ni payload invalide.

Cause typique : pas de liste obligatoire de profils de panne pour chaque outil critique.

Fault injection aléatoire

Le même test passe parfois et échoue parfois.

Cause typique : pannes aléatoires sans seed fixé ou timeouts instables.

Pas de vérification de stop_reason et error shape

L'équipe vérifie seulement le texte final, et la logique de recovery reste non testée.

Cause typique : absence d'assertions structurelles sur stop_reason, error.code, selected_tool.

Pas de vérification des effets secondaires pendant retry

Le retry gère l'erreur en apparence, mais crée une opération dupliquée ou une écriture en double.

Cause typique : tests limités à stop_reason et fallback, sans vérification de l'idempotence de la couche outil.

Mélange des checks unit et intégration

Le test est nommé unit, mais appelle une API réelle.

Cause typique : pas de frontière claire entre tests locaux (mocks/fault injection) et couche d'intégration.

En bref

En bref
  • Tool mocking et fault injection valident la gestion des pannes d'outils par l'agent.
  • Un type de panne doit être couvert par un test déterministe dédié.
  • Vérifiez non seulement le texte, mais aussi retry, fallback, stop_reason et format d'erreur.
  • Les tests fault critiques doivent tourner sur chaque PR.

FAQ

Q : Peut-on tester les pannes sans API réelle ?
R : Oui. Au niveau unit, c'est standard : fakes et mocks donnent un signal stable et reproductible.

Q : Qu'est-ce qui compte le plus : retry ou fallback ?
R : Les deux. Retry couvre les pannes courtes ; fallback protège le scénario quand l'outil principal reste indisponible.

Q : Combien de profils de panne faut-il par outil ?
R : Minimum trois : timeout, erreur serveur (5xx) et payload invalide.

Q : Est-ce que cela remplace eval harness et regression ?
R : Non. Ces tests couvrent le comportement local de la couche outil. Le comportement système sur scénarios complets est validé via eval harness et regression.

Et ensuite

Ajoutez les cas de pannes dans Eval Harness et figez-les dans Golden Datasets. Pour contrôler les changements entre versions, ajoutez Regression Testing, et analysez les incidents avec Replay and Debugging.

⏱️ 6 min de lectureMis à jour 13 mars 2026Difficulté: ★★☆
Intégré : contrôle en productionOnceOnly
Ajoutez des garde-fous aux agents tool-calling
Livrez ce pattern avec de la gouvernance :
  • Budgets (steps / plafonds de coût)
  • Permissions outils (allowlist / blocklist)
  • Kill switch & arrêt incident
  • Idempotence & déduplication
  • Audit logs & traçabilité
Mention intégrée : OnceOnly est une couche de contrôle pour des systèmes d’agents en prod.
Auteur

Cette documentation est organisée et maintenue par des ingénieurs qui déploient des agents IA en production.

Le contenu est assisté par l’IA, avec une responsabilité éditoriale humaine quant à l’exactitude, la clarté et la pertinence en production.

Les patterns et recommandations s’appuient sur des post-mortems, des modes de défaillance et des incidents opérationnels dans des systèmes déployés, notamment lors du développement et de l’exploitation d’une infrastructure de gouvernance pour les agents chez OnceOnly.