Pourquoi un pipeline parallèle puis séquentiel
Le besoin
Un service interne (par exemple l'équipe qui organise les déplacements d'une entreprise) reçoit des demandes du type : « Nous partons à 2 de Lyon à Lisbonne pour 3 nuits, nous aimons la culture et la gastronomie, budget 900 euros tout compris. » Il doit répondre avec un itinéraire réaliste (des options qui existent vraiment dans le catalogue) et dans le budget.
Un seul agent avec trois outils pourrait le faire. Mais il appellerait les outils l'un après l'autre, mélangerait tout dans un seul prompt, et c'est lui qui additionnerait les prix : trois sources d'erreur.
Découper : dépendances et parallélisme
| Étape | Dépend de… | Qui la fait ? |
|---|---|---|
| Chercher les transports | la demande seule | agent LLM transport + outil |
| Chercher les hébergements | la demande seule | agent LLM hebergement + outil |
| Chercher les activités | la demande seule | agent LLM activites + outil |
| Assembler l'itinéraire | les 3 recherches | agent LLM assembleur, sortie structurée |
| Vérifier le budget | l'itinéraire | code Python (BaseAgent), aucun LLM |
Les trois recherches ne dépendent que de la demande : elles peuvent tourner en même temps. L'assemblage attend les trois. Le contrôle attend l'assemblage. D'où la forme :
flowchart TB
D["Demande"] --> S1
subgraph SEQ["SequentialAgent planificateur_voyage"]
direction TB
subgraph S1["1. ParallelAgent recherches"]
direction LR
T["transport"]
H["hebergement"]
A["activites"]
end
S1 --> S2["2. assembleur"]
S2 --> S3["3. controle_budget"]
end
Les briques ADK utilisées
Agent(alias deLlmAgent) : un agent piloté par un modèle, avec une instruction et des outils.ParallelAgent: un agent de workflow (il n'appelle pas de modèle lui-même) qui exécute ses sous-agents en concurrence. Chaque sous-agent tourne dans sa propre branche : ils ne voient pas les messages des autres pendant l'exécution.SequentialAgent: agent de workflow qui exécute ses sous-agents dans l'ordre, avec la même session.- L'état de session (
session.state) : un dictionnaire partagé par tous les agents d'une exécution. Avecoutput_key="transport", la réponse finale d'un agent est copiée dansstate["transport"]. BaseAgent: la classe de base de tous les agents. En héritant d'elle, on écrit un agent déterministe (même entrée, même sortie) en pur Python.
Pourquoi les trois agents de recherche peuvent-ils être placés dans un ParallelAgent ?
Le parallélisme n'est correct que si les tâches sont indépendantes. L'assembleur, lui, dépend des trois résultats : il doit venir après, dans le SequentialAgent.
Qui fait quoi : LLM ou code ?
Règle simple : le modèle choisit, le code compte. Le modèle est bon pour comparer des options en langage naturel et rédiger un programme de visite. Il est mauvais pour garantir qu'une addition est juste ou qu'un identifiant existe. Le contrôle budgétaire relit donc les identifiants choisis (T2, H2, A1…) et va chercher les prix dans le catalogue.
sequenceDiagram
participant ASM as assembleur (LLM)
participant ST as state
participant CB as controle_budget (Python)
ASM->>ST: itineraire = {transport_id: T2, hebergement_id: H2, ...}
CB->>ST: lit itineraire, voyageurs, nuits, budget_max
CB->>CB: prix depuis donnees.py, total, identifiants inconnus ?
CB->>ST: controle_budget = {total, respecte, erreurs}
L'assembleur écrit dans son texte « total : 650 EUR ». Que fait le contrôle budgétaire de ce chiffre ?
Un chiffre produit par un LLM peut être faux. Le contrôle ne fait confiance qu'aux identifiants, qu'il vérifie, et aux prix de la source de vérité (donnees.py).
Exercice : redécouper un autre besoin
Un service RH veut préparer l'arrivée d'un nouvel employé : commander un ordinateur, créer ses comptes, réserver une formation d'accueil, puis envoyer un e-mail récapitulatif qui cite les trois. Dessinez le pipeline : qu'est-ce qui est parallèle, qu'est-ce qui est séquentiel, et quelle étape confieriez-vous à du code ?
Voir la solution
- En parallèle : commande du matériel, création des comptes, réservation de la formation. Aucune ne dépend des autres.
- Ensuite, en séquence : un agent LLM qui rédige l'e-mail en lisant les trois résultats dans l'état (
{materiel},{comptes},{formation}). - En code : la vérification que les trois étapes ont réussi (codes retour des API) avant l'envoi, et l'envoi lui-même.
flowchart LR
subgraph P["ParallelAgent"]
M["materiel"]
C["comptes"]
F["formation"]
end
P --> V["verification (BaseAgent)"] --> E["redaction e-mail (LLM)"]
Résultat obtenu
Exécution réelle du 2026-10-15 avec gemini-3.5-flash : les trois agents de recherche ont appelé leur outil dans un ordre non déterministe (ici activités, puis transport, puis hébergement), preuve qu'ils tournent en concurrence :
[activites] outil chercher_activites({'ville': 'Lisbonne', 'centres_interet': ['culture', 'gastronomie']})
[transport] outil chercher_transports({'destination': 'Lisbonne', 'origine': 'Lyon'})
[hebergement] outil chercher_hebergements({'ville': 'Lisbonne', 'prix_nuit_max': 120})
...
[controle_budget] Budget OK : 800 EUR pour 900 EUR max. Détail : {'transport': 192, 'hebergement': 294, 'activites': 314}Je sais faire
- Je repère les étapes indépendantes d'un processus et je les place dans un
ParallelAgent - J'enchaîne les étapes dépendantes avec un
SequentialAgent - Je sais expliquer le rôle de
output_keyet de l'état de session - Je confie au code ce qui doit être exact (calculs, existence des identifiants)