Aller au contenu principal

Module 3 — Tâches, dépendances et résultats attendus

Les agents ne travaillent pas dans le vide : ils exécutent des tâches, et c'est la qualité de la description de ces tâches qui détermine le résultat. Un agent brillant sur une tâche mal décrite produit du bruit ; un agent moyen sur une tâche précise produit un livrable exploitable.

L'anatomie d'une tâche CrewAI

Une tâche est un objet à trois champs, dont deux sont critiques : description, expected_output et agent. Un quatrième champ, context, sera introduit dans la section suivante.

from crewai import Task

tache_analyse = Task(
description=(
"Lis les spécifications techniques ci-jointes du produit "
"'FactureExpress' et produis la liste ordonnée de ses "
"fonctionnalités utilisateur. Ignore les détails d'implémentation "
"(bases de données, protocoles internes) : cette étape prépare "
"la rédaction utilisateur."
),
expected_output=(
"Une liste numérotée au format Markdown. Chaque entrée contient : "
"un intitulé court, un critère d'acceptation en une phrase, une "
"priorité parmi 'haute', 'moyenne', 'basse'. Entre 8 et 15 entrées."
),
agent=analyste,
output_file="livrables/01-fonctionnalites.md",
)

La description explique ce qu'il faut faire et pourquoi ; elle peut être longue. La expected_output décrit la forme du livrable que le module suivant devra consommer. Ces deux champs ne se recouvrent pas : l'un pilote le comportement, l'autre pilote le format. Confondre les deux est la première erreur des équipes débutantes.

Pourquoi la sortie attendue vaut plus que la description

Un agent qui ne sait pas à quoi doit ressembler son livrable improvise à chaque exécution. Une exécution produira une liste numérotée, la suivante un tableau, la troisième un paragraphe. Le relecteur en aval ne peut pas parser trois formats différents, et la chaîne casse silencieusement.

La expected_output est votre contrat. Elle doit préciser :

  • la structure attendue : liste, tableau, JSON, sections nommées ;
  • le volume attendu : nombre d'entrées, nombre de mots, bornes acceptables ;
  • les champs obligatoires de chaque entrée ;
  • ce qui est explicitement exclu — souvent la partie qui vous sauve, parce que les modèles adorent ajouter des « recommandations » que personne n'a demandées.

Une expected_output qui tient en une ligne est une chaîne fragile. Une expected_output qui tient en cinq lignes précise est une chaîne robuste.

Passer le contexte d'une tâche à l'autre

Par défaut, chaque tâche reçoit le résultat de la tâche précédente comme contexte. C'est ce qui permet à l'équipe de fonctionner comme une chaîne de production. Vous pouvez cependant être plus explicite avec context=[…] :

tache_redaction = Task(
description="Rédige la section 'Prise en main' de la documentation…",
expected_output=(
"Un document Markdown de 400 à 700 mots, avec un titre H2, deux "
"sous-titres H3 (installation, premier envoi), et un bloc de code "
"d'exemple en Python complet et exécutable."
),
agent=redacteur,
context=[tache_analyse],
output_file="livrables/02-prise-en-main.md",
)

Le paramètre context=[tache_analyse] garantit que la tâche de rédaction reçoit explicitement la sortie de la tâche d'analyse. Pour une chaîne linéaire à deux étapes, c'est redondant ; pour une chaîne où la troisième tâche a besoin de la première mais pas de la deuxième, c'est indispensable.

Ce qui traverse et ce qui reste

Il est tentant de croire que chaque tâche a accès à tout ce qui a été produit avant. Ce n'est pas le cas. Ce qui traverse, c'est la sortie finale de la tâche source, pas le raisonnement intermédiaire. L'analyste peut avoir exploré cinq hypothèses avant de trancher ; seule la conclusion est passée au rédacteur.

Cette caractéristique est saine : elle empêche le contexte cumulé d'exploser au bout de trois étapes. En contrepartie, elle vous oblige à mettre dans la expected_output tout ce qui doit être transmis. Si le relecteur a besoin de la priorité de chaque fonctionnalité, elle doit être dans la sortie de l'analyste, sinon elle est perdue.

Produire des fichiers exploitables

Le paramètre output_file demande à CrewAI d'écrire la sortie dans un fichier. Deux règles pratiques :

  • Utilisez une extension cohérente avec le format attendu (.md, .json, .yml) ; le nom du fichier est aussi un indice pour le modèle.
  • Créez le dossier livrables/ en amont, sinon l'écriture échoue à mi-exécution — CrewAI ne le crée pas pour vous dans les versions récentes.

Vous pouvez aussi utiliser output_json=MonSchema avec un modèle Pydantic pour forcer une sortie structurée validée. C'est très utile pour les tâches consommées par du code plutôt que par un autre agent.

Le test qui tue une équipe fragile

Rédigez les expected_output de vos tâches, puis lisez-les seuls, sans regarder les description. Si vous ne pouvez pas dire ce que fait la chaîne, vos sorties attendues sont trop vagues — et votre équipe se comportera de la même façon devant elles.

En résumé

  • Une tâche a une description (comportement) et une sortie attendue (forme du livrable) — les deux champs ne se recouvrent pas.
  • La expected_output doit préciser structure, volume, champs obligatoires et exclusions ; elle est le contrat entre tâches.
  • Le paramètre context=[…] rend explicites les dépendances entre tâches et vous protège des chaînes qui perdent une entrée à la troisième étape.
  • Seule la sortie finale d'une tâche traverse ; mettez-y tout ce que la suivante devra consommer, sinon vous perdez l'information sans erreur visible.

Module suivant : le processus, séquentiel ou hiérarchique, qui pilote l'ordre d'exécution des tâches.