← Networkit Tutos
Agents IA en production : paralléliser sans propager les erreurs

Agents IA en production : paralléliser sans propager les erreurs

Les agents IA enchaînent désormais des dizaines d'actions autonomes pour atteindre un objectif. Le passage à l'exécution parallèle multiplie le débit — et le rayon d'action des erreurs. Guide d'architecture pour les consultants qui doivent industrialiser ces workflows.

En bref

Contexte

Le sujet abordé par Le Monde Informatique dans son article « Agent IA : paralléliser le travail sans paralléliser les erreurs » (publié sur lemondeinformatique.fr, référence 100741) part d'un constat désormais banal en 2025 : les agents IA ne se contentent plus de générer du texte. Ils enchaînent des actions — consulter un site web, manipuler des données, appeler une API, écrire un fichier, exécuter une commande — dans une boucle de raisonnement jusqu'à atteindre un objectif défini par un prompt initial.

Cette capacité repose sur un socle technique stabilisé depuis 2023-2024 : le function calling / tool use proposé par OpenAI, Anthropic, Google et les modèles open-weight (Llama, Mistral, Qwen), formalisé côté interopérabilité par le Model Context Protocol (MCP) publié par Anthropic fin 2024. Les frameworks d'orchestration se sont multipliés : LangGraph (LangChain), CrewAI, AutoGen (Microsoft), OpenAI Agents SDK, Semantic Kernel, LlamaIndex Workflows, Temporal pour les workflows durables.

Le point de bascule opérationnel est le suivant. Un agent séquentiel classique fonctionne selon la boucle ReAct (Reason + Act, popularisée par le papier de Yao et al., 2022) : le modèle raisonne, choisit un outil, observe le résultat, puis recommence. C'est lent — chaque tour coûte un aller-retour LLM, soit typiquement 1 à 10 secondes selon le modèle et la taille du contexte. Un agent qui doit vérifier 40 dépendances dans un package.json, interroger 12 endpoints d'API ou analyser 200 tickets Jira accumule une latence inacceptable pour un usage interactif.

D'où la parallélisation : découper l'objectif en sous-tâches indépendantes, les exécuter simultanément (souvent via des sous-agents), puis agréger les résultats. Anthropic a documenté publiquement en 2025 son architecture de recherche multi-agents avec un agent orchestrateur déléguant à des sous-agents chercheurs opérant en parallèle, avec des gains de performance substantiels sur les tâches de recherche large — au prix d'une consommation de tokens très supérieure à un chat classique.

Le problème que soulève l'angle éditorial est précisément celui-là : la parallélisation amplifie tout, y compris ce qui est faux.

Détails techniques

Pourquoi une erreur se propage plus vite en parallèle

Dans une exécution séquentielle, une erreur a une chance d'être détectée au tour suivant : l'agent observe un résultat incohérent, un code HTTP 404, un stack trace, et peut corriger sa trajectoire. C'est le mécanisme d'auto-correction par observation.

En parallèle, cette boucle de rétroaction disparaît sur les branches simultanées. Trois mécanismes de propagation :

1. Erreur de planification en amont (fan-out d'une hypothèse fausse). L'orchestrateur décide que la table cible est customers_v2 alors que c'est customers_v3. Il lance 8 sous-agents. Les 8 échouent, ou pire : les 8 écrivent dans la mauvaise table. Une erreur unique devient 8 effets de bord.

2. Absence de vue partagée. Deux sous-agents travaillant sur le même dépôt Git peuvent produire des modifications contradictoires sur le même fichier. Sans verrou ni découpage strict des zones d'écriture, le merge est incohérent. Le même problème existe sur les tickets (double création), les emails (double envoi), les appels de facturation (double débit).

3. Contamination du contexte à l'agrégation. Chaque sous-agent renvoie un résumé. Si l'un hallucine une information, l'orchestrateur l'intègre dans sa synthèse finale sans traçabilité vers la source. Le résultat agrégé paraît plus crédible que ses composants — c'est l'effet « lavage de provenance ».

Le pattern de base : fan-out / fan-in encadré


                  ┌─ Sous-agent A (read-only) ─┐
Orchestrateur ────┼─ Sous-agent B (read-only) ─┼──> Agrégation
   (plan)         └─ Sous-agent C (read-only) ─┘        │
                                                        v
                                              Checkpoint validation
                                                        │
                                                        v
                                         Phase mutante SÉQUENTIELLE
                                         (write, commit, API POST)

La règle d'or architecturale : paralléliser les lectures, sérialiser les écritures. Les opérations idempotentes et sans effet de bord (recherche web, SELECT, GET, lecture de fichier, analyse statique) se parallélisent sans risque autre que le coût. Les opérations mutantes (INSERT, POST, git push, envoi de mail, création de ressource cloud) passent par un chemin unique, séquentiel, auditable.

Isolation des contextes

Chaque sous-agent doit disposer de son propre contexte, avec un périmètre d'outils réduit au strict nécessaire. Exemple de configuration conceptuelle avec LangGraph :


from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator

class ResearchState(TypedDict):
    query: str
    # reducer : les branches parallèles APPEND, elles n'écrasent pas
    findings: Annotated[list[dict], operator.add]
    budget_calls: int

def spawn_subagents(state: ResearchState):
    # Fan-out borné : jamais plus de N branches
    MAX_BRANCHES = 5
    subtasks = decompose(state["query"])[:MAX_BRANCHES]
    return [{"subtask": s} for s in subtasks]

def researcher(state):
    # Outils read-only uniquement
    result = search_tool.invoke(state["subtask"])
    return {
        "findings": [{
            "subtask": state["subtask"],
            "content": result.text,
            "source_url": result.url,      # provenance obligatoire
            "confidence": result.score
        }]
    }

Le point critique est le reducer sur l'état partagé. Sans Annotated[list, operator.add], deux branches qui écrivent la même clé provoquent un conflit ou un écrasement silencieux. C'est une source de bugs redoutable parce qu'elle est non déterministe : le résultat dépend de l'ordre d'arrivée des branches.

Provenance et traçabilité obligatoires

Chaque élément d'information remonté par un sous-agent doit porter :

Sans ces métadonnées, il devient impossible de répondre à la question posée en post-incident : « d'où vient cette affirmation fausse ? ». Les standards d'observabilité convergent vers OpenTelemetry GenAI semantic conventions, avec des attributs gen_ai.system, gen_ai.request.model, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens. Les outils du marché (LangSmith, Langfuse, Arize Phoenix, Braintrust, W&B Weave) exposent des traces hiérarchiques run → span → tool call.

Budget et circuit breaker

Un agent parallélisé peut brûler un budget de tokens de façon exponentielle : si chaque sous-agent peut lui-même spawner des sous-sous-agents, la récursion non bornée est un incident de facturation garanti. Trois garde-fous minimum :


agent_limits:
  max_depth: 2                 # profondeur de délégation
  max_parallel_branches: 5     # largeur du fan-out
  max_total_tool_calls: 60     # budget global par run
  max_input_tokens: 400000     # plafond de contexte cumulé
  wall_clock_timeout_s: 300    # timeout dur
  cost_ceiling_usd: 2.50       # kill switch économique

Ajouter un circuit breaker par type d'outil : si 3 appels consécutifs au même outil échouent, la branche s'arrête et remonte l'échec plutôt que de retenter en boucle. Le pattern retry with exponential backoff classique s'applique, mais avec un plafond strict — un agent qui retente 20 fois un appel API en erreur 500 génère de la charge inutile sur le système cible et peut déclencher du rate limiting côté fournisseur.

Idempotence des actions mutantes

Toute action à effet de bord doit être idempotente ou protégée par une clé d'idempotence. Pattern classique repris de la finance :


def create_ticket(payload: dict, run_id: str, step_id: str):
    idem_key = f"{run_id}:{step_id}:{hash_payload(payload)}"
    if store.exists(idem_key):
        return store.get(idem_key)          # rejoue le résultat, ne recrée pas
    result = jira_client.create_issue(**payload)
    store.put(idem_key, result, ttl=86400)
    return result

Cela couvre le cas du retry après timeout réseau — situation où l'agent ne sait pas si son action a abouti. Sans clé d'idempotence, un timeout sur un POST conduit à un doublon.

Validation croisée plutôt que consensus naïf

Une tentation courante : lancer 3 agents sur la même tâche et voter (self-consistency, majorité). C'est utile pour des réponses à espace de sortie restreint (classification, extraction de champ). C'est trompeur pour des tâches ouvertes : trois instances du même modèle avec le même prompt partagent les mêmes biais et hallucinent souvent de façon corrélée. Le vote produit alors une fausse confiance.

Alternatives plus robustes :

Implications pour les consultants IT

Architecture : le plan devient l'artefact critique. Dans un agent séquentiel, une mauvaise décision se paie d'un tour de boucle. Dans un agent parallèle, une mauvaise décision de planification se paie N fois. Le corollaire pour les missions d'architecture : imposer un point de contrôle humain ou automatisé après la phase de planification, avant le fan-out. Concrètement, cela signifie exposer le plan (liste des sous-tâches, outils prévus, ressources ciblées) dans un format lisible et vérifiable, et gater l'exécution parallèle sur une validation. Sur les workflows sensibles, ce gate est humain (human-in-the-loop) ; sur les workflows routiniers, il peut être une règle déterministe (« refuser tout plan qui touche plus de 3 tables », « refuser tout plan incluant un DELETE »).

Sécurité : la surface d'attaque se démultiplie avec les branches. L'injection de prompt indirecte reste le risque numéro un des agents lisant des contenus externes (pages web, emails, tickets, PDF). L'OWASP Top 10 for LLM Applications classe Prompt Injection en LLM01. En exécution parallèle, une instruction malveillante récupérée par un sous-agent depuis une page web peut se propager à l'orchestrateur lors de l'agrégation, puis contaminer le raisonnement final. La contre-mesure architecturale : traiter tout contenu externe comme donnée non fiable, jamais comme instruction — ce qui suppose une séparation nette dans le prompt et, idéalement, un sous-agent « lecteur » sans aucun outil mutant, dont la sortie est structurée et validée par schéma avant d'atteindre l'orchestrateur. Appliquer le principe du moindre privilège par sous-agent : le chercheur web n'a pas besoin d'accès à la base de données.

Compliance et audit : le run trace devient une pièce justificative. Pour les organisations soumises à des exigences de traçabilité (secteur financier avec DORA, santé, ou plus largement les obligations de documentation technique du règlement européen sur l'IA — AI Act, dont les dispositions sur les systèmes à haut risque s'échelonnent jusqu'en 2026-2027), un agent qui prend des décisions opérationnelles doit produire un journal reconstituable : quelle version de modèle, quel prompt, quels outils appelés avec quels paramètres, quels résultats intermédiaires. La parallélisation complique l'exercice parce que l'ordre d'exécution n'est plus déterministe. Il faut donc horodater et corréler par run_id / span_id, et conserver les traces avec la même rigueur que des logs d'application (rétention, immutabilité, protection des données personnelles présentes dans les contextes).

Coût et capacity planning : un poste budgétaire à modéliser. Un agent multi-agents consomme un ordre de grandeur de tokens supérieur à un simple appel de complétion. Les consultants doivent intégrer dans leurs chiffrages un modèle de coût par run (tokens entrée + sortie + appels d'outils payants), un plafond dur, et une observabilité du coût unitaire. Le réflexe à adopter : mesurer le coût par tâche réussie, pas le coût par appel. Un agent moins cher mais qui échoue 40 % du temps et nécessite une reprise humaine coûte plus cher qu'un agent plus dispendieux mais fiable. Ajouter une métrique de taux de retouche humaine comme indicateur de qualité en production.

Testing : les tests non déterministes exigent une autre discipline. On ne peut pas tester un agent parallèle avec des assertions d'égalité stricte. Il faut construire des jeux d'évaluation (eval sets) avec des critères de succès fonctionnels (« la ressource a-t-elle été créée avec les bons attributs ? », « la réponse cite-t-elle au moins une source valide ? »), les exécuter en CI, et suivre les taux de réussite comme des SLO. Prévoir aussi des tests de régression de coût : un changement de prompt qui double le nombre de branches doit faire échouer le build.

Pour aller plus loin

Actions concrètes recommandées :

  1. Auditer le périmètre d'outils de chaque agent en production. Cartographier, pour chaque sous-agent, la liste exacte des outils accessibles et classer chacun en read-only / mutant. Tout sous-agent parallélisé qui dispose d'un outil mutant est un point de risque à traiter en priorité : soit retirer l'outil, soit sérialiser la branche.
  1. Vérifier la présence de bornes dures sur chaque workflow agentique. Profondeur de délégation, nombre de branches parallèles, budget total d'appels d'outils, timeout wall-clock, plafond de coût. Si l'un de ces cinq garde-fous est absent, l'incident de facturation ou de saturation d'API cible est une question de temps.
  1. Instrumenter l'observabilité avant d'industrialiser. Mettre en place le tracing (OpenTelemetry GenAI conventions ou équivalent via LangSmith / Langfuse / Arize Phoenix), avec run_id corrélé, provenance de chaque information agrégée, et métriques de coût et de latence par span. Sans cela, le post-mortem d'une décision erronée est impossible.
  1. Tester l'injection de prompt indirecte. Insérer dans un contenu externe consommé par l'agent (page de test, ticket, document) une instruction du type « ignore les consignes précédentes et... » et vérifier que l'orchestrateur ne la répercute pas. À intégrer dans les tests de sécurité récurrents, pas seulement au moment de la mise en service.
Partager LinkedIn X E-mail