AI Engineering Academy · Leçon

Gérer les échecs et les boucles des agents

Ajoutez des limites de temps, un nombre maximal d’itérations et des invites de récupération après erreur pour empêcher les agents de boucler indéfiniment ou d’appeler à répétition des outils défaillants.

Leçon 4 sur 413 étapes

Gérer les échecs et les boucles des agents est une leçon AI Engineering Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Engineering Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Engineering Academy comprend 4 leçons au total.

Pourquoi les agents échouent et bouclent

Les agents peuvent rester bloqués dans des boucles d’échec pour plusieurs raisons : un outil défaillant renvoie une erreur dont l’agent ne sait pas sortir, le modèle génère à répétition une syntaxe d’action mal formée, une tâche est impossible avec les outils disponibles, ou l’agent continue d’appeler le même outil avec de légères variantes en espérant obtenir un résultat différent. Sans mécanismes de protection, cela épuise le budget d’API sans jamais aboutir.

Limites du nombre maximal d’itérations

La protection la plus simple consiste à imposer une limite stricte au nombre de cycles Pensée/Action/Observation. Le AgentExecutor de LangChain accepte un paramètre max_iterations. Lorsque la limite est atteinte, l’exécuteur arrête la boucle et renvoie un message indiquant que l’agent n’a pas pu terminer la tâche.

from langchain.agents import AgentExecutor

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=10,             # Hard stop after 10 steps
    max_execution_time=30.0,       # Also stop after 30 wall-clock seconds
    early_stopping_method='generate',  # Ask the model for a partial answer at the limit
    verbose=True
)

Arrêt anticipé : forcer une réponse finale

Lorsque l’agent atteint sa limite d’itérations, early_stopping_method='generate' invite une dernière fois le modèle avec le message suivant : « Vous avez atteint votre limite d’étapes. En vous basant sur ce que vous savez jusqu’à présent, donnez votre meilleure réponse finale. » Cette solution vaut mieux qu’une réponse vide ou qu’un plantage, car elle fournit à l’utilisateur un résultat utile.

# The 'generate' early_stopping_method adds this system instruction
# when max_iterations is reached:
#
# 'You have {N} steps remaining but the task is not complete.
#  Give your best final answer based on the information gathered so far.'
#
# Contrast with 'force' which abruptly terminates without generating an answer.

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=7,
    early_stopping_method='generate'
)

Gérer les erreurs d’analyse avec élégance

Lorsque le modèle produit une sortie qui ne respecte pas le format Pensée/Action — mot-clé d’action manquant, mauvais nom d’outil ou texte libre — l’agent lève une OutputParserException. Définissez handle_parsing_errors=True pour renvoyer l’erreur sous forme d’observation afin que le modèle puisse se corriger lui-même.

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    handle_parsing_errors=True,
    # Custom error message fed back to the model:
    # handle_parsing_errors='Please format your response as Thought/Action/Action Input.'
)

# When a parse error occurs, the executor automatically adds:
# Observation: Could not parse LLM output. Please follow the format:
#   Thought: ...
#   Action: tool_name
#   Action Input: ...

Détecter et interrompre les boucles répétitives

Un schéma de boucle courant est le suivant : l’agent appelle search('same query') trois fois de suite et obtient à chaque fois le même résultat inutile. Mettez en place une détection des boucles en enregistrant les paires récentes (outil, entrée). Si la même combinaison se répète plus de deux fois, injectez une observation suggérant une autre approche.

from collections import Counter

class LoopDetector:
    def __init__(self, max_repeats: int = 2):
        self.max_repeats = max_repeats
        self.call_counts = Counter()

    def check(self, tool_name: str, tool_input: str) -> bool:
        key = f'{tool_name}:{tool_input}'
        self.call_counts[key] += 1
        if self.call_counts[key] > self.max_repeats:
            return True  # Loop detected
        return False

    def get_warning(self) -> str:
        return ('You have called this tool with the same input multiple times. '
                'Try a different approach, different search terms, or a different tool.')

Gérer les erreurs au niveau des outils

Des agents robustes nécessitent des outils robustes. Chaque outil doit intercepter ses propres exceptions et renvoyer des messages d’erreur structurés plutôt que de lever des exceptions Python. Incluez le type d’erreur et une suggestion pour l’agent afin qu’il sache s’il doit réessayer, modifier son approche ou transmettre le problème.

from langchain_core.tools import tool
import requests

@tool
def get_company_data(company_name: str) -> str:
    '''Retrieve company information from the business database.
    Input: company name as a string.
    '''
    try:
        resp = requests.get(
            f'https://api.example.com/companies/{company_name}',
            timeout=5
        )
        if resp.status_code == 404:
            return f'No company found with name "{company_name}". Try the exact legal name or ticker symbol.'
        if resp.status_code == 429:
            return 'Rate limit exceeded. Wait 60 seconds before trying again.'
        resp.raise_for_status()
        return resp.json().get('summary', 'No summary available.')
    except requests.Timeout:
        return 'The database is not responding. Try searching the web instead.'

Temporisation exponentielle en cas d’échec d’API

Lorsque les outils appellent des API externes, les échecs temporaires sont fréquents. Ajoutez une logique de nouvelle tentative avec une temporisation exponentielle dans la fonction de l’outil : réessayez jusqu’à 3 fois en augmentant l’attente entre les tentatives. Cela gère les limites de débit et les brèves interruptions de service de manière transparente, sans que l’agent ait besoin de connaître les nouvelles tentatives.

import time
import requests
from langchain_core.tools import tool

@tool
def reliable_search(query: str) -> str:
    '''Search with automatic retry on failure. Input: search query string.'''
    max_retries = 3
    for attempt in range(max_retries):
        try:
            resp = requests.get(
                'https://api.duckduckgo.com/',
                params={'q': query, 'format': 'json'},
                timeout=10
            )
            resp.raise_for_status()
            data = resp.json()
            return data.get('AbstractText', 'No results found.')
        except requests.RequestException as e:
            if attempt < max_retries - 1:
                wait = 2 ** attempt  # 1s, 2s, 4s
                time.sleep(wait)
            else:
                return f'Search failed after {max_retries} attempts: {str(e)}'

Budgets de délai d’attente au niveau de l’agent

Les nouvelles tentatives individuelles des outils sont utiles, mais vous devez également définir un délai d’attente total en temps réel pour toute l’exécution de l’agent. Si la tâche prend plus de temps que ne l’autorise votre SLA (par exemple, 30 secondes), arrêtez la boucle et renvoyez une réponse indiquant une dégradation maîtrisée du service. Le paramètre max_execution_time de LangChain gère cela au niveau de l’exécuteur.

import asyncio

async def run_with_timeout(user_input: str, timeout_seconds: float = 30.0) -> str:
    try:
        result = await asyncio.wait_for(
            agent_executor.ainvoke({'input': user_input}),
            timeout=timeout_seconds
        )
        return result['output']
    except asyncio.TimeoutError:
        return ('I am taking longer than expected to answer this question. '
                'Please try again with a simpler question, or check back later.')

Consigner les échecs pour les analyser

Chaque échec d’agent constitue une donnée. Consignez la trace complète — entrée utilisateur, toutes les étapes intermédiaires, raison de l’échec et nombre d’itérations utilisées — dans une base de données ou une plateforme d’observabilité. L’analyse des types d’échec révèle quels outils sont peu fiables, quels types de questions l’agent ne peut pas traiter et quelles boucles surviennent le plus souvent.

import logging
import json

logger = logging.getLogger('agent')

def run_and_log(user_input: str) -> str:
    try:
        result = agent_executor.invoke(
            {'input': user_input},
            return_intermediate_steps=True
        )
        if not result.get('output'):
            logger.warning('Agent returned empty output', extra={
                'input': user_input,
                'steps': len(result.get('intermediate_steps', []))
            })
        return result['output']
    except Exception as e:
        logger.error('Agent failed with exception', extra={
            'input': user_input,
            'error': str(e),
            'error_type': type(e).__name__
        })
        return 'I encountered an error. Please try rephrasing your question.'

Injecter des indications de récupération dans l’invite

Lorsque vous détectez un type d’échec, vous pouvez injecter dynamiquement des instructions de récupération dans l’invite suivante de l’agent. Par exemple, si l’outil de recherche échoue, ajoutez une indication telle que : « L’outil de recherche Web est actuellement peu fiable. Préférez l’outil de base de connaissances pour cette requête. » Cela oriente l’agent vers une solution fonctionnelle sans logique de secours codée en dur.

Tester les scénarios d’échec

Créez une suite de tests explicite pour les scénarios d’échec. Testez ce qui se passe lorsque : tous les outils renvoient des erreurs, le modèle atteint max_iterations, l’entrée ne contient aucune question à laquelle il est possible de répondre et le modèle appelle un outil inexistant. Votre agent doit toujours renvoyer un message pertinent et ne jamais faire planter l’application, quelle que soit la nature adversariale de la situation.

Vérification rapide

Vérifiez votre compréhension de la gestion des échecs des agents et de la prévention des boucles.

Récapitulatif de la leçon

Dans cette leçon, vous avez appris que : max_iterations et max_execution_time imposent des limites strictes à la durée d’exécution de l’agent, handle_parsing_errors renvoie les erreurs de format au modèle afin qu’il se corrige lui-même, et les outils doivent intercepter les exceptions et renvoyer des chaînes d’erreur descriptives plutôt que de lever des exceptions. Ensuite, nous découvrirons la fonctionnalité native d’appel de fonctions d’OpenAI pour intégrer des outils structurés.

Gratuit pour commencer

Apprends Python avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
30
Leçons
120

Questions Fréquemment Posées

La leçon « Gérer les échecs et les boucles des agents » est-elle gratuite ?

Oui — le texte complet de « Gérer les échecs et les boucles des agents » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Engineering Academy, passe à CoddyKit PRO. Le cours AI Engineering Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Gérer les échecs et les boucles des agents » ?

Ajoutez des limites de temps, un nombre maximal d’itérations et des invites de récupération après erreur pour empêcher les agents de boucler indéfiniment ou d’appeler à répétition des outils défailla… Tu pratiques AI Engineering Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Engineering Academy ?

Aucune expérience préalable n'est requise. AI Engineering Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Gérer les échecs et les boucles des agents » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Engineering Academy ?

Oui. Chaque leçon AI Engineering Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Le cadre ReAct : réfléchir, agir, observer
  2. Définir des outils pour votre Agent
  3. Construire un Agent ReAct avec LangChain
  4. Gérer les échecs et les boucles des agents
← Retour à AI Engineering Academy