écrits/tutorial/2026/05
Tutorial23 mai 2026·30 min

Tutoriel CrewAI 2026 : Construire des systèmes multi-agents IA en production avec Python

Apprenez à concevoir des équipes d'agents IA basées sur des rôles qui collaborent sur de vraies tâches de recherche, de rédaction et d'analyse. Ce tutoriel pratique vous guide pas à pas : installation de CrewAI, branchement des outils, orchestration séquentielle et hiérarchique, ajout de mémoire, et déploiement d'une équipe prête pour la production avec observabilité complète.

Les boucles à agent unique sont géniales — jusqu'au jour où votre problème implique réellement plusieurs spécialistes. La recherche, la rédaction, la revue de code, l'analyse financière : ce sont des sports d'équipe, pas des numéros en solo. CrewAI prend cette intuition et la transforme en abstraction programmable : vous définissez un équipage d'agents basés sur des rôles, vous donnez à chacun un objectif et une histoire, vous les équipez d'outils, et vous les laissez collaborer séquentiellement ou hiérarchiquement vers un objectif partagé.

Contrairement aux frameworks à base de graphes comme LangGraph ou aux exécuteurs à agent unique comme OpenAI Agents SDK, CrewAI traite l'orchestration comme un organigramme d'entreprise. Dans ce tutoriel vous allez installer CrewAI à partir de zéro, construire une équipe d'étude de marché de quatre agents, y brancher des outils de navigation et d'écriture de fichiers, basculer entre processus séquentiel et hiérarchique, ajouter une mémoire longue durée, et instrumenter le tout pour la production.

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • Python 3.10 ou plus récent installé
  • Une clé API OpenAI ou Anthropic (ou une installation locale d'Ollama)
  • Une clé Serper.dev gratuite pour la recherche web (optionnelle mais recommandée)
  • Une familiarité de base avec les classes Python, les décorateurs et async/await
  • Un éditeur de code (VS Code avec l'extension Python recommandé)

Ce que vous allez construire

À la fin de ce tutoriel, vous aurez :

  1. Un projet CrewAI échafaudé avec uv et la CLI officielle
  2. Une équipe de quatre agents — Chercheur, Analyste, Rédacteur, Éditeur — qui produit une note de marché soignée
  3. Des outils de recherche web et d'écriture de fichiers branchés aux bons agents
  4. Un pipeline séquentiel et une variante hiérarchique pilotée par un manager
  5. Une mémoire court terme et long terme activée avec des embeddings
  6. Des callbacks personnalisés qui diffusent les pensées des agents et les appels d'outils en temps réel
  7. Un endpoint FastAPI qui déclenche l'équipe à la demande
  8. De l'observabilité via la télémétrie CrewAI Plus et des logs structurés

Étape 1 : Installer CrewAI

CrewAI est livré comme un seul paquet avec des extras optionnels pour les outils, les embeddings et les helpers de déploiement. Commencez par un environnement isolé — uv est l'option la plus rapide en 2026.

mkdir market-crew && cd market-crew
uv venv --python 3.11
source .venv/bin/activate
uv pip install "crewai[tools]" python-dotenv fastapi uvicorn

Ou avec pip classique :

python -m venv .venv
source .venv/bin/activate
pip install "crewai[tools]" python-dotenv fastapi uvicorn

Vérifiez l'installation :

crewai version
# CrewAI version: 0.86.x

Étape 2 : Échafauder le projet

CrewAI fournit une CLI qui génère la structure de dossiers attendue par le framework. Lancez le générateur depuis le dossier parent.

cd .. && crewai create crew market-crew

Quand on vous le demande, choisissez openai comme fournisseur et gpt-4o-mini comme modèle. La CLI dépose cette structure :

market-crew/
├── src/
│   └── market_crew/
│       ├── config/
│       │   ├── agents.yaml
│       │   └── tasks.yaml
│       ├── crew.py
│       ├── main.py
│       └── tools/
├── .env
├── pyproject.toml
└── README.md

Les deux fichiers YAML sont l'endroit où la majeure partie de votre travail va vivre. agents.yaml définit les rôles et les objectifs ; tasks.yaml définit ce que chaque agent doit produire.

Ajoutez vos secrets à .env :

OPENAI_API_KEY=sk-...
SERPER_API_KEY=...      # depuis serper.dev, optionnel
MODEL=gpt-4o-mini

Étape 3 : Définir les agents

Ouvrez src/market_crew/config/agents.yaml et remplacez le contenu placeholder par quatre rôles spécialisés.

researcher:
  role: >
    Chercheur de marché senior spécialisé dans {industry}
  goal: >
    Rassembler les faits, statistiques et citations les plus récents
    et crédibles à propos de {topic}, issus de sources web publiques
    publiées au cours des douze derniers mois.
  backstory: >
    Vous avez passé une décennie chez McKinsey à diriger des recherches
    primaires et secondaires. Vous triangulez chaque affirmation entre
    au moins deux sources indépendantes et vous étiquetez chaque
    information avec sa date de publication et son URL.
  verbose: true
  allow_delegation: false
 
analyst:
  role: >
    Analyste stratégique pour {industry}
  goal: >
    Transformer les notes brutes du chercheur en SWOT, en matrice
    concurrentielle et en trois recommandations actionnables pour
    {target_audience}.
  backstory: >
    Vous écrivez ce genre de mémos de deux pages que les CEO lisent
    réellement. Vous refusez d'inclure toute affirmation qui n'est pas
    appuyée par une source citée des notes du chercheur.
  verbose: true
 
writer:
  role: >
    Rédacteur éditorial senior
  goal: >
    Produire une note exécutive de 1200 mots sur {topic} qu'un
    investisseur pourrait lire en moins de six minutes et transférer
    à ses partenaires.
  backstory: >
    Vous avez écrit la newsletter hebdomadaire Stratechery. Vous
    privilégiez les phrases courtes, les exemples concrets et
    exactement une thèse forte par publication.
  verbose: true
 
editor:
  role: >
    Rédacteur en chef
  goal: >
    Vérifier la note contre la liste de sources du chercheur, corriger
    la prose faible et s'assurer que chaque affirmation cite sa source.
  backstory: >
    Vous avez dirigé le bureau des standards à The Economist pendant
    huit ans. Vous ne laissez passer aucun chiffre non sourcé.
  verbose: true

CrewAI interpole les placeholders {industry}, {topic} et {target_audience} au moment de l'exécution à partir des entrées que vous passez à l'équipe.

Étape 4 : Définir les tâches

Éditez src/market_crew/config/tasks.yaml :

research_task:
  description: >
    Collectez au moins 12 trouvailles de haute qualité sur {topic} dans
    le secteur {industry}. Pour chaque trouvaille, capturez :
    l'affirmation, l'URL de la source, la date de publication et un
    résumé en une phrase.
  expected_output: >
    Une liste markdown d'au moins 12 puces. Chaque puce doit inclure
    l'URL de la source et la date. Aucune paraphrase sans citation.
  agent: researcher
 
analysis_task:
  description: >
    À partir des trouvailles du chercheur, produisez une analyse SWOT
    pour {target_audience} entrant sur le marché de {topic}, une
    matrice concurrentielle de 5 lignes, et exactement trois
    recommandations classées par impact.
  expected_output: >
    Un document markdown en trois sections : SWOT, Matrice
    concurrentielle, Recommandations. Toute affirmation chiffrée doit
    citer une trouvaille par URL.
  agent: analyst
  context:
    - research_task
 
writing_task:
  description: >
    Rédigez une note exécutive de 1200 mots sur {topic} destinée à
    {target_audience}. Ouvrez avec une thèse en une seule phrase.
    Utilisez le SWOT et les recommandations de l'analyste. Terminez
    par une section "À surveiller" listant trois indicateurs avancés.
  expected_output: >
    Une note markdown soignée, entre 1100 et 1300 mots, avec des
    titres H2 et des citations en ligne sous forme de liens markdown.
  agent: writer
  context:
    - research_task
    - analysis_task
 
editing_task:
  description: >
    Éditez la note pour la clarté et la précision. Toute affirmation
    chiffrée doit citer une source de la liste du chercheur. Signalez
    toute affirmation non soutenue en la remplaçant par un commentaire
    TODO.
  expected_output: >
    La note finale markdown, enregistrée dans `output/brief.md`.
  agent: editor
  context:
    - research_task
    - analysis_task
    - writing_task
  output_file: output/brief.md

Le champ context est l'endroit où vit le modèle de collaboration de CrewAI. Chaque tâche reçoit les sorties de ses dépendances comme entrée — aucun assemblage manuel de prompts requis.

Étape 5 : Câbler l'équipe

Ouvrez src/market_crew/crew.py. La CLI a généré un squelette ; remplacez-le par la version ci-dessous.

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai_tools import SerperDevTool, FileWriterTool
 
@CrewBase
class MarketCrew:
    """Équipe de recherche de marché avec quatre spécialistes."""
 
    agents_config = "config/agents.yaml"
    tasks_config = "config/tasks.yaml"
 
    @agent
    def researcher(self) -> Agent:
        return Agent(
            config=self.agents_config["researcher"],
            tools=[SerperDevTool()],
        )
 
    @agent
    def analyst(self) -> Agent:
        return Agent(config=self.agents_config["analyst"])
 
    @agent
    def writer(self) -> Agent:
        return Agent(config=self.agents_config["writer"])
 
    @agent
    def editor(self) -> Agent:
        return Agent(
            config=self.agents_config["editor"],
            tools=[FileWriterTool()],
        )
 
    @task
    def research_task(self) -> Task:
        return Task(config=self.tasks_config["research_task"])
 
    @task
    def analysis_task(self) -> Task:
        return Task(config=self.tasks_config["analysis_task"])
 
    @task
    def writing_task(self) -> Task:
        return Task(config=self.tasks_config["writing_task"])
 
    @task
    def editing_task(self) -> Task:
        return Task(config=self.tasks_config["editing_task"])
 
    @crew
    def crew(self) -> Crew:
        return Crew(
            agents=self.agents,
            tasks=self.tasks,
            process=Process.sequential,
            verbose=True,
        )

Quelques détails à noter :

  • Le décorateur @CrewBase câble les fichiers YAML aux objets Python au moment de la construction.
  • Les décorateurs @agent et @task décorent des méthodes fabriques ; l'ordre des décorateurs @task détermine l'ordre d'exécution en mode séquentiel.
  • Seul le chercheur reçoit la recherche web et seul l'éditeur reçoit l'écriture de fichier. Garder les surfaces d'outils étroites est le plus grand gain de fiabilité dans les systèmes multi-agents.

Étape 6 : Exécuter l'équipe

Éditez src/market_crew/main.py pour passer les entrées paramétrées.

from market_crew.crew import MarketCrew
 
def run():
    inputs = {
        "topic": "Agents IA de codage pour plateformes de développeurs en entreprise",
        "industry": "outils pour développeurs",
        "target_audience": "Responsables d'ingénierie en Series B",
    }
    MarketCrew().crew().kickoff(inputs=inputs)
 
if __name__ == "__main__":
    run()

Lancez-le :

crewai run

Vous verrez chaque agent annoncer son rôle, chercher sur le web, rédiger et passer le relais au suivant. La note finale arrive dans output/brief.md. Sur gpt-4o-mini l'exécution complète coûte environ dix centimes et prend environ quatre minutes.

Étape 7 : Passer à un processus hiérarchique

Le séquentiel convient à un pipeline fixe. Quand vous voulez qu'un manager décide qui travaille sur quoi, passez à Process.hierarchical. Remplacez la méthode crew :

from crewai import Agent
 
@crew
def crew(self) -> Crew:
    manager = Agent(
        role="Directeur éditorial",
        goal="Décider de l'ordre des tâches et déléguer au bon spécialiste",
        backstory="Ancien chef de bureau Bloomberg qui dirige des rédactions serrées.",
        allow_delegation=True,
        verbose=True,
    )
    return Crew(
        agents=self.agents,
        tasks=self.tasks,
        process=Process.hierarchical,
        manager_agent=manager,
        verbose=True,
    )

En mode hiérarchique, le manager lit la description de chaque tâche, choisit un agent, évalue la sortie et peut reboucler. Cela coûte plus de tokens mais gère les workflows ambigus bien mieux qu'un pipeline fixe.

Étape 8 : Ajouter de la mémoire

Par défaut, chaque exécution d'équipe démarre à neuf. Pour accumuler de la connaissance entre les exécutions, activez la mémoire.

from crewai import Crew, Process
 
@crew
def crew(self) -> Crew:
    return Crew(
        agents=self.agents,
        tasks=self.tasks,
        process=Process.sequential,
        memory=True,
        embedder={
            "provider": "openai",
            "config": {"model": "text-embedding-3-small"},
        },
        verbose=True,
    )

CrewAI maintient désormais trois magasins de mémoire :

  • Court terme : bloc-notes partagé pour l'exécution en cours
  • Long terme : magasin vectoriel persistant entre les exécutions (SQLite + Chroma sur disque par défaut)
  • Entité : entités extraites et leurs relations

Réinitialisez la mémoire avec crewai reset-memories. Pour des déploiements à l'échelle d'une équipe, remplacez l'embedder par bedrock ou vertex et pointez le magasin long terme vers une instance Postgres+pgvector managée.

Étape 9 : Diffuser les pensées des agents avec des callbacks

Pour l'intégration UI ou le débogage vous voulez généralement chaque étape en temps réel. CrewAI expose des callbacks par tâche et par étape.

from crewai.tasks.task_output import TaskOutput
 
def on_task_complete(output: TaskOutput) -> None:
    print(f"[task:{output.task.description[:60]}] -> {len(output.raw)} chars")
 
def on_step(step: dict) -> None:
    if step.get("tool"):
        print(f"  tool call: {step['tool']} args={step['tool_input']}")
 
@task
def research_task(self) -> Task:
    return Task(
        config=self.tasks_config["research_task"],
        callback=on_task_complete,
    )

Pour le streaming au niveau de l'étape, passez step_callback=on_step lors de la construction de chaque Agent. Branchez ces callbacks à des Server-Sent Events et vous obtenez un flux d'agent en direct dans votre application.

Étape 10 : Exposer l'équipe comme une API

CrewAI se marie très bien avec FastAPI. Créez src/market_crew/api.py :

from fastapi import FastAPI
from pydantic import BaseModel
from market_crew.crew import MarketCrew
 
app = FastAPI()
 
class BriefRequest(BaseModel):
    topic: str
    industry: str
    target_audience: str
 
@app.post("/brief")
def generate_brief(req: BriefRequest):
    result = MarketCrew().crew().kickoff(inputs=req.model_dump())
    return {"output": result.raw, "token_usage": result.token_usage}

Lancez-le :

uv run uvicorn market_crew.api:app --reload --port 8000

Testez avec curl :

curl -X POST http://localhost:8000/brief \
  -H "content-type: application/json" \
  -d '{"topic":"AI coding agents","industry":"developer tools","target_audience":"CTOs"}'

En production, lancez l'API derrière Gunicorn avec une classe de worker Uvicorn, fixez un timeout de requête d'environ cinq minutes pour les exécutions de l'équipe, et déchargez les kickoffs vers une file Celery ou Hatchet si vous attendez du trafic concurrent.

Étape 11 : Ajouter l'observabilité

CrewAI livre une télémétrie de première classe via CrewAI Plus, mais vous pouvez aussi utiliser OpenTelemetry directement. La voie gratuite reste les logs structurés.

import logging, json, time
 
class CrewLogFormatter(logging.Formatter):
    def format(self, record):
        payload = {
            "ts": int(time.time() * 1000),
            "level": record.levelname,
            "msg": record.getMessage(),
        }
        return json.dumps(payload)
 
handler = logging.StreamHandler()
handler.setFormatter(CrewLogFormatter())
logging.getLogger("crewai").addHandler(handler)
logging.getLogger("crewai").setLevel(logging.INFO)

Envoyez stdout vers Loki, Datadog ou un ClickHouse auto-hébergé et vous pouvez répondre à "quel agent a brûlé le plus de tokens la semaine dernière" sans monter un second projet. Pour les traces au niveau des spans, installez crewai[telemetry] et pointez OTEL_EXPORTER_OTLP_ENDPOINT vers votre collecteur.

Étape 12 : Tester l'équipe de manière déterministe

Les exécutions multi-agents sont non déterministes par défaut. Pour la CI, remplacez le LLM par un faux.

from crewai.llm import LLM
from market_crew.crew import MarketCrew
 
class FakeLLM(LLM):
    def __init__(self):
        super().__init__(model="fake")
        self.replies = iter([
            "- finding 1 (https://example.com 2026-01-01)",
            "## SWOT\n- strength: x",
            "Brief draft...",
            "Edited brief.",
        ])
 
    def call(self, messages, **kwargs):
        return next(self.replies)
 
def test_crew_smoke(monkeypatch):
    monkeypatch.setattr("crewai.agent.LLM", FakeLLM)
    out = MarketCrew().crew().kickoff(inputs={
        "topic": "x", "industry": "y", "target_audience": "z",
    })
    assert "Edited brief." in out.raw

Lancez avec uv run pytest. La suite entière se termine en moins d'une seconde et vous donne une couverture de régression sur le câblage des prompts et des outils sans consommer de crédits API.

Tester votre implémentation

Vérifiez le comportement de bout en bout :

  1. crewai run produit output/brief.md avec au moins 1100 mots
  2. La note contient au moins huit citations en ligne
  3. Une deuxième exécution de crewai run tire la mémoire long terme dans le prompt du chercheur (vérifiez le log verbose)
  4. L'endpoint FastAPI retourne un payload JSON avec output et token_usage
  5. Le test pytest avec LLM factice passe en moins d'une seconde

Dépannage

"AuthenticationError: Missing OPENAI_API_KEY" — assurez-vous que votre shell a chargé .env. uv run le fait automatiquement, python simple non. Ajoutez from dotenv import load_dotenv; load_dotenv() en haut de main.py.

Les agents hallucinent des sources — resserrez le prompt du chercheur. Ajoutez une règle explicite : "Si vous ne trouvez pas de source, écrivez NO_SOURCE plutôt que d'en inventer une." Puis faites en sorte que la tâche d'éditeur fasse échouer l'exécution si un token NO_SOURCE apparaît.

Les exécutions hiérarchiques tournent à l'infini — fixez max_iter=15 sur l'agent manager. Le défaut est 25, trop généreux pour la plupart des workflows.

La mémoire déborde entre sujetscrewai reset-memories --all entre des exécutions sans rapport, ou isolez la mémoire long terme en réglant CREWAI_STORAGE_DIR par projet.

Les appels d'outils retournent du HTML brut — enveloppez SerperDevTool avec un convertisseur markdown ou utilisez ScrapeWebsiteTool de crewai_tools pour nettoyer la sortie avant que l'agent ne la voie.

Prochaines étapes

  • Ajoutez une couche de sortie typée Pydantic AI devant l'équipe pour des schémas de note typés
  • Branchez un superviseur LangGraph par-dessus pour des workflows ramifiés
  • Programmez l'équipe sur un cron Hatchet et publiez la note sur Slack chaque lundi matin
  • Remplacez le rédacteur par un sous-processus Claude Agent SDK pour des budgets de raisonnement plus longs

Conclusion

La force de CrewAI est qu'elle vous oblige à penser votre workflow IA de la même manière que vous penseriez à composer une équipe humaine. Chaque agent a un poste, un livrable et une boîte à outils étroite. Une fois que les YAML sont corrects, le code Python reste sous les cent lignes, et le chemin de mise à niveau d'un simple pipeline séquentiel vers une équipe hiérarchique, dotée de mémoire et instrumentée pour l'observabilité est essentiellement de la configuration.

Si votre problème comporte réellement plusieurs spécialistes, arrêtez d'essayer de faire tout faire à un seul agent. Embauchez une équipe.