Agents et outils LangChain : Construire des IA autonomes capables d'agir

tl;dr: Les agents LangChain sont des systèmes IA autonomes qui décident quels outils utiliser pour accomplir une tâche. Grâce au pattern ReAct (Reasoning + Acting), ils alternent réflexion et action. Ce guide couvre la création d'agents, l'intégration d'outils (recherche web, calcul, APIs), les patterns avancés, et les techniques de débogage pour construire des assistants IA véritablement intelligents.

💡 🤖 Les agents sont l’avenir de l’IA ! Contrairement aux chaînes fixes, ils décident autonomiquement quels outils utiliser pour atteindre un objectif, comme un assistant intelligent.

Les agents représentent l’évolution naturelle des systèmes IA : au lieu de suivre un workflow prédéfini, ils décident autonomiquement quelles actions entreprendre pour atteindre un objectif. Avec LangChain, créer des agents capables d’utiliser des outils (recherche web, calculs, APIs, bases de données) devient accessible. Dans cet article, nous explorons en profondeur comment construire des agents intelligents, de la théorie à la pratique avancée.

Schéma illustrant agents dans les systèmes d’agents d’intelligence artificielle

Qu’est-ce qu’un agent IA ?

Un agent est un système qui :

  1. Reçoit un objectif de l’utilisateur
  2. Raisonne sur les étapes nécessaires
  3. Sélectionne et utilise des outils de manière autonome
  4. Observe les résultats et ajuste sa stratégie
  5. Itère jusqu’à atteindre l’objectif

Différence entre Chain et Agent

AspectChain (Chaîne)Agent
WorkflowPrédéfini et fixeDécidé dynamiquement
LogiqueSéquentielle (A→B→C)Conditionnelle (si X alors Y)
OutilsTous utilisés systématiquementSélection intelligente
FlexibilitéFaibleÉlevée
ComplexitéSimpleModérée à élevée
Cas d’usageTâches répétitivesTâches exploratoires

Exemple concret :

  • Chain : “Traduis ce texte EN→FR, puis résume en 3 phrases”
  • Agent : “Trouve des informations sur le sujet X et crée un rapport” (l’agent décide s’il faut chercher sur le web, dans une base de données, calculer des statistiques, etc.)

Le pattern ReAct : Reasoning + Acting

Les agents LangChain utilisent principalement le pattern ReAct, publié par Google Research en 2022. Ce pattern alterne entre raisonnement (thinking) et action (doing).

Cycle ReAct

1. Thought (Pensée) : "Je dois chercher des informations sur X"
2. Action (Action) : Utiliser l'outil "Search"
3. Observation : Résultat de la recherche
4. Thought : "J'ai trouvé Y, maintenant je dois calculer Z"
5. Action : Utiliser l'outil "Calculator"
6. Observation : Résultat du calcul
7. Thought : "J'ai toutes les informations, je peux répondre"
8. Final Answer : Réponse complète

Exemple de trace ReAct

User: Quelle est la racine carrée de l'âge du président français actuel ?

Thought: Je dois d'abord trouver qui est le président et son âge
Action: Search
Action Input: "président français 2025 âge"
Observation: Emmanuel Macron, né en 1977, a 48 ans en 2025

Thought: Maintenant je dois calculer la racine carrée de 48
Action: Calculator
Action Input: sqrt(48)
Observation: 6.928

Thought: J'ai la réponse finale
Final Answer: La racine carrée de l'âge d'Emmanuel Macron (48 ans) est environ 6.93.
💡 💡 Le pattern ReAct combine raisonnement et action de manière itérative. C’est ce qui permet aux agents de décomposer des tâches complexes en étapes gérables et de s’adapter aux résultats obtenus.

Anatomie d’un agent LangChain

Composants essentiels

  1. LLM : Le “cerveau” qui raisonne et décide
  2. Tools : Les capacités d’action (recherche, calcul, APIs)
  3. Agent Type : La stratégie de décision (ReAct, Plan-and-Execute, etc.)
  4. Memory : Le contexte conversationnel (optionnel)

Création d’un agent simple

from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Tool
from langchain.prompts import PromptTemplate

# 1. LLM (le cerveau)
llm = ChatOpenAI(model="gpt-4", temperature=0)

# 2. Définition des outils
def search_web(query: str) -> str:
    """Recherche sur le web"""
    # Implémentation réelle avec une API de recherche
    return f"Résultats pour '{query}': ..."

def calculate(expression: str) -> str:
    """Calcule une expression mathématique de manière sécurisée"""
    import ast
    import operator

    # Opérateurs autorisés
    operators = {
        ast.Add: operator.add,
        ast.Sub: operator.sub,
        ast.Mult: operator.mul,
        ast.Div: operator.truediv,
        ast.Pow: operator.pow,
        ast.USub: operator.neg,
    }

    def eval_expr(node):
        if isinstance(node, ast.Num):  # Nombre
            return node.n
        elif isinstance(node, ast.BinOp):  # Opération binaire
            return operators[type(node.op)](eval_expr(node.left), eval_expr(node.right))
        elif isinstance(node, ast.UnaryOp):  # Opération unaire
            return operators[type(node.op)](eval_expr(node.operand))
        else:
            raise ValueError(f"Expression non autorisée: {node}")

    try:
        node = ast.parse(expression, mode='eval')
        return str(eval_expr(node.body))
    except Exception as e:
        return f"Erreur de calcul: {str(e)}"

tools = [
    Tool(
        name="Search",
        func=search_web,
        description="Utile pour rechercher des informations actuelles sur le web. Input: une requête de recherche."
    ),
    Tool(
        name="Calculator",
        func=calculate,
        description="Utile pour effectuer des calculs mathématiques. Input: une expression Python (ex: '2+2' ou 'sqrt(16)')."
    )
]

# 3. Prompt ReAct standard
prompt = PromptTemplate.from_template("""
Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Question: {input}
{agent_scratchpad}
""")

# 4. Création de l'agent
agent = create_react_agent(llm, tools, prompt)

# 5. Executor (gère l'exécution)
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,  # Affiche les traces
    max_iterations=5,  # Limite de sécurité
    handle_parsing_errors=True  # Gestion des erreurs
)

# 6. Utilisation
result = agent_executor.invoke({
    "input": "Quelle est la racine carrée de 144 et qui a inventé les mathématiques ?"
})

print(result["output"])

Sortie (avec verbose=True) :

> Entering new AgentExecutor chain...
Thought: I need to calculate the square root of 144 and find who invented mathematics
Action: Calculator
Action Input: sqrt(144)
Observation: 12.0
Thought: Now I need to find who invented mathematics
Action: Search
Action Input: who invented mathematics
Observation: Mathematics wasn't "invented" by one person, but developed over millennia...
Thought: I now have all the information needed
Final Answer: La racine carrée de 144 est 12. Les mathématiques n'ont pas été inventées par une seule personne, mais se sont développées au fil des millénaires...

Outils intégrés dans LangChain

LangChain propose des dizaines d’outils prêts à l’emploi.

Outils de recherche

from langchain_community.tools import DuckDuckGoSearchRun, WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper

# Recherche web avec DuckDuckGo
search = DuckDuckGoSearchRun()

# Wikipedia
wikipedia = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())

tools = [
    Tool(
        name="WebSearch",
        func=search.run,
        description="Recherche sur le web pour des informations actuelles"
    ),
    Tool(
        name="Wikipedia",
        func=wikipedia.run,
        description="Recherche sur Wikipedia pour des informations encyclopédiques"
    )
]

Outils de calcul et code

from langchain_experimental.tools import PythonREPLTool
from langchain.tools import ShellTool

# Exécution de code Python
python_repl = PythonREPLTool()

# Exécution de commandes shell
shell = ShellTool()

tools = [
    Tool(
        name="Python",
        func=python_repl.run,
        description="Exécute du code Python. Utile pour calculs, data science, graphiques."
    ),
    Tool(
        name="Shell",
        func=shell.run,
        description="Exécute des commandes système. ATTENTION: dangereux en production."
    )
]
⚠️ Warning
🔒 Sécurité critique : PythonREPLTool et ShellTool peuvent exécuter du code arbitraire ! Ne les utilisez JAMAIS avec des inputs utilisateurs non validés. Réservez-les aux environnements de développement isolés.

Outils de données structurées

from langchain.agents import create_sql_agent
from langchain.sql_database import SQLDatabase

# Connexion à une base de données
db = SQLDatabase.from_uri("sqlite:///mydatabase.db")

# Agent SQL automatique
sql_agent = create_sql_agent(
    llm=llm,
    db=db,
    agent_type="openai-tools",
    verbose=True
)

# L'agent génère automatiquement les requêtes SQL
result = sql_agent.run("Combien d'utilisateurs ont plus de 30 ans ?")

Outils API personnalisés

import requests

def get_weather(city: str) -> str:
    """Récupère la météo d'une ville"""
    api_key = "YOUR_API_KEY"
    url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}"
    response = requests.get(url)
    data = response.json()
    temp = data["main"]["temp"] - 273.15  # Kelvin vers Celsius
    description = data["weather"][0]["description"]
    return f{city}: {temp:.1f}°C, {description}"

weather_tool = Tool(
    name="Weather",
    func=get_weather,
    description="Donne la météo actuelle d'une ville. Input: nom de la ville en anglais."
)

Outils RAG

from langchain.tools.retriever import create_retriever_tool

# Supposons que vous avez un retriever RAG configuré
retriever = vectorstore.as_retriever()

# Transformer le retriever en outil d'agent
retriever_tool = create_retriever_tool(
    retriever,
    name="DocumentSearch",
    description="Recherche dans la documentation interne de l'entreprise. Utile pour les questions sur les procédures, politiques, et produits."
)

tools = [search, calculator, retriever_tool]

Types d’agents disponibles

LangChain propose plusieurs architectures d’agents selon vos besoins.

ReAct Agent (recommandé)

Utilisation : Cas général, bon équilibre flexibilité/fiabilité

from langchain.agents import create_react_agent

agent = create_react_agent(llm, tools, prompt)

Avantages : Traçabilité, robuste, bien documenté Limites : Peut être verbeux

OpenAI Functions Agent

Utilisation : Avec OpenAI/GPT-4 pour plus de fiabilité

from langchain.agents import create_openai_functions_agent

agent = create_openai_functions_agent(llm, tools, prompt)

Avantages : Meilleure sélection d’outils, moins d’erreurs de parsing Limites : Uniquement compatible OpenAI/Azure

Structured Chat Agent

Utilisation : Outils avec inputs complexes (JSON)

from langchain.agents import create_structured_chat_agent

agent = create_structured_chat_agent(llm, tools, prompt)

Avantages : Supporte des outils avec multiples paramètres Exemple : send_email(to: str, subject: str, body: str)

Utilisation : Questions nécessitant plusieurs recherches successives

from langchain.agents import create_self_ask_with_search_agent

agent = create_self_ask_with_search_agent(llm, [search_tool], prompt)

Pattern : L’agent se pose des sous-questions avant de répondre

Plan-and-Execute Agent

Utilisation : Tâches complexes nécessitant une planification

from langchain.agents import PlanAndExecute
from langchain_experimental.plan_and_execute import load_agent_executor

agent_executor = load_agent_executor(llm, tools, verbose=True)

Pattern :

  1. Planifie toutes les étapes
  2. Exécute chaque étape
  3. Révise le plan si nécessaire

Comparaison des types d’agents

TypeComplexitéFiabilitéPerformanceMeilleur pour
ReAct⭐⭐⭐⭐⭐⭐⭐⭐⭐Usage général
OpenAI Functions⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐Production avec OpenAI
Structured Chat⭐⭐⭐⭐⭐⭐⭐⭐⭐Outils complexes
Self-Ask⭐⭐⭐⭐⭐⭐⭐Recherche approfondie
Plan-and-Execute⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐Tâches multi-étapes

Cas d’usage avancés

Agent de recherche et d’analyse de données

from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_community.tools import DuckDuckGoSearchRun
from langchain_experimental.tools import PythonREPLTool
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

# Outils
search = DuckDuckGoSearchRun()
python = PythonREPLTool()

tools = [
    Tool(name="Search", func=search.run, description="Recherche web"),
    Tool(name="Python", func=python.run, description="Exécute du Python pour calculs et visualisations")
]

# Prompt spécialisé
prompt = ChatPromptTemplate.from_messages([
    ("system", """Tu es un analyste de données expert. Tu peux:
    1. Rechercher des informations sur le web
    2. Effectuer des calculs et créer des graphiques avec Python

    Réponds de manière structurée avec des chiffres précis."""),
    ("human", "{input}"),
    MessagesPlaceholder("agent_scratchpad")
])

# LLM configuré une seule fois
llm = ChatOpenAI(model="gpt-4", temperature=0)

# Agent
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# Utilisation
result = agent_executor.invoke({
    "input": """
    Recherche les revenus 2024 d'Apple, Google et Microsoft.
    Calcule la moyenne et crée un graphique en barres comparatif.
    Sauvegarde le graphique dans 'comparison.png'.
    """
})

Comportement :

  1. Recherche les revenus sur le web (3 recherches)
  2. Extrait les chiffres
  3. Génère le code Python pour le graphique
  4. Exécute le code
  5. Confirme la création du fichier

Agent de support client avec RAG

from langchain.tools.retriever import create_retriever_tool
from langchain.agents import create_openai_functions_agent
from langchain.memory import ConversationBufferMemory

# Outil RAG sur la documentation produit
doc_retriever = vectorstore.as_retriever()
doc_tool = create_retriever_tool(
    doc_retriever,
    "ProductDocs",
    "Recherche dans la documentation produit et les FAQs"
)

# Outil de ticket
def create_ticket(issue: str) -> str:
    """Crée un ticket de support"""
    ticket_id = generate_ticket_id()
    save_to_database(ticket_id, issue)
    return f"Ticket #{ticket_id} créé avec succès"

ticket_tool = Tool(
    name="CreateTicket",
    func=create_ticket,
    description="Crée un ticket si le problème ne peut pas être résolu immédiatement"
)

tools = [doc_tool, ticket_tool]

# Mémoire conversationnelle
memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True
)

# Agent avec mémoire
prompt = ChatPromptTemplate.from_messages([
    ("system", """Tu es un assistant support client.
    1. Cherche d'abord dans la documentation
    2. Si tu ne trouves pas de solution, crée un ticket
    3. Sois courtois et professionnel"""),
    MessagesPlaceholder("chat_history"),
    ("human", "{input}"),
    MessagesPlaceholder("agent_scratchpad")
])

agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    memory=memory,
    verbose=True
)

# Conversation
agent_executor.invoke({"input": "Comment réinitialiser mon mot de passe ?"})
# → Recherche dans la doc, trouve la procédure, explique

agent_executor.invoke({"input": "Ça ne fonctionne toujours pas"})
# → Utilise le contexte précédent, crée un ticket

Agent de veille automatisée

from langchain.tools import Tool
from datetime import datetime

def fetch_rss_feeds(topics: str) -> str:
    """Récupère les derniers articles RSS"""
    # Implémentation avec feedparser
    return "Articles récents sur ..."

def summarize_article(url: str) -> str:
    """Résume un article web"""
    # Implémentation avec BeautifulSoup + LLM
    return "Résumé: ..."

def save_to_notion(content: str) -> str:
    """Sauvegarde dans Notion"""
    # Implémentation avec l'API Notion
    return "Sauvegardé dans Notion"

tools = [
    Tool(name="FetchNews", func=fetch_rss_feeds, description="Récupère les dernières actualités"),
    Tool(name="Summarize", func=summarize_article, description="Résume un article"),
    Tool(name="SaveNotion", func=save_to_notion, description="Sauvegarde dans Notion")
]

# Agent de veille
prompt = ChatPromptTemplate.from_messages([
    ("system", """Tu es un agent de veille technologique.
    Tâches quotidiennes:
    1. Chercher les actualités sur {topics}
    2. Résumer les 5 articles les plus importants
    3. Sauvegarder dans Notion avec tags appropriés"""),
    ("human", "Effectue la veille du jour"),
    MessagesPlaceholder("agent_scratchpad")
])

agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# Exécution automatique (via cron ou scheduler)
result = agent_executor.invoke({
    "input": f"Effectue la veille pour {datetime.now().strftime('%Y-%m-%d')}"
})

CAgent multi-agents (orchestration)

from langchain.agents import AgentExecutor

# Agent 1 : Recherche
research_agent = create_react_agent(llm, [search_tool], research_prompt)
research_executor = AgentExecutor(agent=research_agent, tools=[search_tool])

# Agent 2 : Analyse
analysis_agent = create_react_agent(llm, [python_tool], analysis_prompt)
analysis_executor = AgentExecutor(agent=analysis_agent, tools=[python_tool])

# Agent 3 : Rédaction
writing_agent = create_react_agent(llm, [], writing_prompt)
writing_executor = AgentExecutor(agent=writing_agent, tools=[])

# Orchestrateur (meta-agent)
def delegate_to_research(query: str) -> str:
    return research_executor.invoke({"input": query})["output"]

def delegate_to_analysis(data: str) -> str:
    return analysis_executor.invoke({"input": data})["output"]

def delegate_to_writing(outline: str) -> str:
    return writing_executor.invoke({"input": outline})["output"]

meta_tools = [
    Tool(name="Research", func=delegate_to_research, description="Agent de recherche"),
    Tool(name="Analysis", func=delegate_to_analysis, description="Agent d'analyse"),
    Tool(name="Writing", func=delegate_to_writing, description="Agent de rédaction")
]

# Meta-agent qui coordonne
meta_agent = create_react_agent(llm, meta_tools, meta_prompt)
meta_executor = AgentExecutor(agent=meta_agent, tools=meta_tools, verbose=True)

# Utilisation
result = meta_executor.invoke({
    "input": "Crée un rapport complet sur les tendances IA 2025"
})
# → Délègue la recherche, puis l'analyse, puis la rédaction

Patterns avancés et optimisations

Retry automatique avec fallback

from langchain.agents import AgentExecutor

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=10,
    max_execution_time=60,  # Timeout après 60s
    early_stopping_method="generate",  # Génère une réponse même si incomplet
    handle_parsing_errors=True,  # Gère les erreurs de parsing
    return_intermediate_steps=True  # Retourne tous les steps pour debugging
)

# Avec retry manuel
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=10)
)
def run_agent_with_retry(query):
    return agent_executor.invoke({"input": query})

result = run_agent_with_retry("Question complexe")

Validation des outputs d’outils

from pydantic import BaseModel, Field, validator

class WeatherOutput(BaseModel):
    """Modèle validé pour la météo"""
    temperature: float = Field(..., ge=-50, le=60, description="Température en °C")
    description: str = Field(..., min_length=3)

    @validator('temperature')
    def temp_must_be_reasonable(cls, v):
        if not -50 <= v <= 60:
            raise ValueError('Température hors limites')
        return v

def safe_weather_tool(city: str) -> str:
    """Outil météo avec validation"""
    raw_data = get_weather_api(city)
    validated = WeatherOutput(**raw_data)  # Pydantic valide
    return f"{validated.temperature}°C, {validated.description}"

Caching des résultats d’outils

from functools import lru_cache
from datetime import datetime, timedelta

# Cache simple avec TTL
cache = {}
cache_ttl = {}

def cached_tool(func):
    def wrapper(query: str) -> str:
        # Vérifie le cache
        if query in cache:
            if datetime.now() - cache_ttl[query] < timedelta(hours=1):
                print(f"[CACHE HIT] {query}")
                return cache[query]

        # Exécute et cache
        result = func(query)
        cache[query] = result
        cache_ttl[query] = datetime.now()
        return result

    return wrapper

@cached_tool
def expensive_search(query: str) -> str:
    """Recherche coûteuse avec cache"""
    return search_api(query)

Streaming des réponses

from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

# LLM avec streaming
llm = ChatOpenAI(
    model="gpt-4",
    streaming=True,
    callbacks=[StreamingStdOutCallbackHandler()]
)

# Agent avec streaming
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)

# Les réponses s'affichent token par token
result = agent_executor.invoke({"input": "Question longue..."})

Rate limiting et quotas

from ratelimit import limits, sleep_and_retry
import time

# Limite : 10 appels par minute
@sleep_and_retry
@limits(calls=10, period=60)
def rate_limited_tool(query: str) -> str:
    """Outil avec rate limiting"""
    return expensive_api_call(query)

# Compteur de tokens/coût
class CostTracker:
    def __init__(self, budget_usd=10):
        self.total_tokens = 0
        self.total_cost = 0
        self.budget = budget_usd

    def track(self, tokens: int, cost_per_1k: float = 0.03):
        self.total_tokens += tokens
        self.total_cost += (tokens / 1000) * cost_per_1k

        if self.total_cost > self.budget:
            raise Exception(f"Budget dépassé : ${self.total_cost:.2f}")

        print(f"Coût actuel : ${self.total_cost:.2f}/{self.budget}")

tracker = CostTracker(budget_usd=5)

# Callback personnalisé
class CostTrackingCallback:
    def on_llm_end(self, response, **kwargs):
        tokens = response.llm_output.get('token_usage', {}).get('total_tokens', 0)
        tracker.track(tokens)

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    callbacks=[CostTrackingCallback()]
)

Debugging et monitoring

Activer les logs détaillés

import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("langchain.agents")

# Ou avec LangSmith (recommandé)
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-api-key"
os.environ["LANGCHAIN_PROJECT"] = "mon-projet-agents"

Callback personnalisé pour debugging

from langchain.callbacks.base import BaseCallbackHandler

class DebugCallback(BaseCallbackHandler):
    def on_agent_action(self, action, **kwargs):
        print(f"\n🤖 Action: {action.tool}")
        print(f"📝 Input: {action.tool_input}")

    def on_tool_start(self, serialized, input_str, **kwargs):
        print(f"\n🔧 Outil lancé: {serialized.get('name', 'unknown')}")

    def on_tool_end(self, output, **kwargs):
        print(f"✅ Résultat: {output[:100]}...")

    def on_tool_error(self, error, **kwargs):
        print(f"❌ Erreur: {error}")

    def on_agent_finish(self, finish, **kwargs):
        print(f"\n🏁 Agent terminé")
        print(f"📊 Iterations: {finish.return_values}")

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    callbacks=[DebugCallback()],
    verbose=True
)

Analyse des traces

result = agent_executor.invoke(
    {"input": "Question"},
    return_intermediate_steps=True
)

# Afficher toutes les étapes
for i, (action, observation) in enumerate(result["intermediate_steps"]):
    print(f"\n--- Étape {i+1} ---")
    print(f"Outil: {action.tool}")
    print(f"Input: {action.tool_input}")
    print(f"Output: {observation[:200]}")

# Compter les appels par outil
from collections import Counter
tool_usage = Counter([action.tool for action, _ in result["intermediate_steps"]])
print(f"\nUtilisation des outils: {tool_usage}")

Limites et pièges à éviter

Boucles infinies

Problème : L’agent répète les mêmes actions indéfiniment

Solution :

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=10,  # Force l'arrêt après 10 itérations
    max_execution_time=60  # Timeout après 60 secondes
)

Hallucinations d’outils

Problème : L’agent invente des outils qui n’existent pas

Solution : Descriptions précises et prompt explicite

Tool(
    name="Weather",  # Nom court et clair
    func=get_weather,
    description="""Donne la météo ACTUELLE d'une ville.
    Input: Nom de la ville en anglais (ex: 'Paris', 'London').
    Ne PAS utiliser pour des prévisions ou des données historiques."""
)

# Prompt strict
prompt = PromptTemplate.from_template("""
Tu dois UNIQUEMENT utiliser les outils listés ci-dessous.
N'invente JAMAIS un outil qui n'est pas dans cette liste.

Outils disponibles:
{tools}
...
""")

Coûts élevés

Problème : Les agents font de nombreux appels LLM

Solutions :

# 1. Utiliser un modèle moins cher pour le raisonnement
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)  # 60x moins cher que GPT-4

# 2. Limiter les itérations
agent_executor = AgentExecutor(agent=agent, tools=tools, max_iterations=5)

# 3. Caching agressif
from langchain.cache import SQLiteCache
from langchain.globals import set_llm_cache
set_llm_cache(SQLiteCache(database_path=".langchain.db"))

# 4. Budget hard limit
class BudgetExceededError(Exception):
    pass

class BudgetCallback(BaseCallbackHandler):
    def __init__(self, max_usd=5):
        self.total_cost = 0
        self.max_cost = max_usd

    def on_llm_end(self, response, **kwargs):
        tokens = response.llm_output.get('token_usage', {}).get('total_tokens', 0)
        self.total_cost += (tokens / 1000) * 0.03  # $0.03 per 1K tokens

        if self.total_cost > self.max_cost:
            raise BudgetExceededError(f"Budget dépassé: ${self.total_cost:.2f}")
🔎 Tip
💰 Astuce coûts : Un agent peut consommer 5-10× plus de tokens qu’une chaîne simple ! Utilisez gpt-4o-mini pour le raisonnement (60× moins cher que GPT-4) et réservez les modèles puissants aux tâches complexes.

Erreurs de parsing

Problème : L’agent génère un format invalide

Solution :

agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    handle_parsing_errors=True,  # Gère automatiquement
    # Ou message personnalisé:
    handle_parsing_errors="Vérifie ton format de réponse et réessaie."
)

Sécurité

Problème : Outils dangereux (Shell, Python REPL)

Solutions :

# 1. Environnement sandboxé
from langchain_experimental.tools import PythonREPLTool

python = PythonREPLTool()
python.globals = {"__builtins__": {}}  # Désactive les built-ins dangereux

# 2. Validation des inputs
def safe_shell(command: str) -> str:
    """Shell avec whitelist"""
    allowed_commands = ["ls", "pwd", "date", "whoami"]
    cmd = command.split()[0]

    if cmd not in allowed_commands:
        return f"Commande '{cmd}' non autorisée"

    # Exécute seulement si autorisé
    return subprocess.check_output(command, shell=True).decode()

# 3. Audit logging
class SecurityCallback(BaseCallbackHandler):
    def on_tool_start(self, serialized, input_str, **kwargs):
        tool_name = serialized.get("name")
        if tool_name in ["Shell", "Python"]:
            log_security_event(f"Execution: {tool_name} - {input_str}")

Exercices pratiques

Exercice 1 : Agent de veille technologique

Objectif : Créer un agent qui surveille l’actualité tech et génère un résumé quotidien.

Spécifications :

  • Recherche automatique sur des sites tech (DuckDuckGo)
  • Extraction des tendances principales
  • Génération d’un résumé structuré avec bullet points
  • Sauvegarde du résumé dans un fichier Markdown

Outils à implémenter :

  • DuckDuckGoSearchRun pour la recherche
  • Outil personnalisé pour sauvegarder en Markdown
  • Optionnel : Outil de scraping pour extraire le contenu complet

Points clés :

  • Limiter les itérations pour contrôler les coûts
  • Gérer les erreurs de réseau avec retry
  • Structurer le prompt pour obtenir des résumés concis

Exercice 2 : Agent SQL conversationnel

Objectif : Construire un agent qui répond à des questions en langage naturel sur une base de données.

Spécifications :

  • Connexion à une base de données SQLite (ou PostgreSQL)
  • Compréhension de questions complexes (“Quels sont les 5 meilleurs clients du mois dernier ?”)
  • Génération automatique de requêtes SQL optimisées
  • Retour des résultats sous forme de tableaux ou graphiques

Outils à implémenter :

  • create_sql_agent avec un schéma de base de données
  • Validation des requêtes avant exécution (read-only)
  • Outil de visualisation avec matplotlib/plotly

Extensions :

  • Ajout d’un cache pour les requêtes fréquentes
  • Support de plusieurs bases de données
  • Génération d’insights automatiques (“Cette tendance est inhabituelle…”)

Exercice 3 : Agent multi-outils de productivité

Objectif : Créer un assistant personnel qui combine plusieurs outils.

Spécifications :

  • Recherche web (actualités, informations)
  • Calculs mathématiques et conversions
  • Gestion d’une todo-list (ajout, lecture, suppression)
  • Envoi d’emails ou notifications Slack

Outils à implémenter :

  • Recherche : DuckDuckGoSearchRun
  • Calcul : Outil personnalisé avec sympy ou numpy
  • Todo-list : Outil CRUD avec stockage JSON
  • Communication : API Slack ou SMTP

Points clés :

  • L’agent doit décider intelligemment quel outil utiliser
  • Gestion de la mémoire pour le contexte conversationnel
  • Confirmation utilisateur avant actions critiques (envoi email)

Extensions :

  • Intégration calendrier (Google Calendar API)
  • Rappels automatiques
  • Résumés de fin de journée
💡 🎯 Démarrage rapide : Commencez par l’exercice 1 (veille techno) qui est le plus simple. Une fois maîtrisé, passez aux exercices 2 et 3 qui nécessitent une gestion plus complexe des outils et des états.

Conclusion

Les agents LangChain représentent un saut qualitatif dans les capacités des systèmes IA : de simples générateurs de texte à des assistants autonomes capables d’actions concrètes. En maîtrisant les concepts de ce guide, vous pouvez construire :

Agents de recherche qui collectent et analysent des données automatiquement

Assistants de support qui consultent vos docs et créent des tickets

Systèmes de veille qui surveillent et résument l’actualité

Workflows complexes avec orchestration multi-agents

Outils métiers intégrant vos APIs et bases de données

Checklist avant de déployer un agent

  • Outils bien définis : Descriptions claires, validations des inputs
  • Limites configurées : max_iterations, max_execution_time
  • Gestion d’erreurs : handle_parsing_errors=True
  • Monitoring : LangSmith ou callbacks personnalisés
  • Budget contrôlé : Rate limiting, caching, modèle optimisé
  • Sécurité : Outils dangereux sandboxés ou désactivés
  • Tests : Dataset de cas d’usage avec résultats attendus
  • Logs : Audit trail pour les actions critiques

Évolutions futures

  • LangGraph : Framework avancé pour agents avec graphes d’états complexes
  • Multi-agent orchestration : Équipes d’agents spécialisés collaborant
  • Agents multimodaux : Utilisation d’images, audio, vidéo
  • Apprentissage continu : Agents qui s’améliorent au fil des interactions

Pour aller plus loin :


Retour à la Formation LangChain | Module suivant : Guide Pratique et Cookbook →