Expertise — Architecture agentique

Architecture agentique & LangGraph — notre cœur de métier.

En 2026, la valeur des systèmes IA passe massivement par les architectures agentiques — workflows multi-étapes, raisonnement long, outils externes, mémoire persistante, décisions autonomes. Nous mettons LangGraph en pivot, complété par les SDK natifs (Anthropic, OpenAI), les frameworks alternatifs (AutoGen, CrewAI, Pydantic AI), et des harness in-house sur-mesure quand le générique ne suffit pas.

LangGraph en pivot Harness in-house Multi-agent état de l'art Mémoire longue Évaluation d'agents
01 / Le constat

Pourquoi l'agentique est devenue le centre de gravité de l'IA en 2026.

Un LLM nu sait répondre à une question. Un système agentique sait résoudre un problème — planifier, exécuter, vérifier, se corriger, mobiliser des outils, persister une mémoire. C'est cette transition qui fait basculer l'IA d'assistant en exécutant.

De l'appel LLM nu au système agentique — la transition 2024 → 2026
2024 — APPEL LLM NU Utilisateur « Comment X ? » LLM Une passe forward, une réponse Texte de réponse À l'utilisateur de juger ⚠ Pas de mémoire · Pas d'outils · Pas de boucle 2026 — SYSTÈME AGENTIQUE Utilisateur « Résous X dans mon SI » BOUCLE AGENTIQUE — LANGGRAPH PLAN CALL TOOL OBSERVE REFLECT État global RAG · SQL · API Mémoire llm-as-judge Boucle jusqu'à condition de terminaison

À gauche : l'IA 2024 — un appel LLM nu, sans état ni outils. À droite : le système agentique 2026 — un graphe d'état déterministe (LangGraph) qui orchestre planification, appels d'outils, observation, réflexion, et boucle jusqu'à atteindre l'objectif.

Avant

L'IA répondait à une question

Un appel LLM, une réponse, une fin. Pas d'outils, pas d'état, pas de vérification. Le moindre problème complexe nécessitait l'humain dans la boucle à chaque étape.

Maintenant

L'IA résout un problème de bout en bout

Un graphe d'état qui planifie, appelle des outils, observe, réfléchit, persiste une mémoire, se corrige. L'humain ne valide plus à chaque étape : seulement aux décisions importantes.

Pivot

LangGraph est le standard 2026

Modélisation explicite : nœuds, arêtes, état partagé, checkpointing. Observable, reproductible, testable. Là où LangChain Agents v1 était une boîte noire, LangGraph est un graphe que vous lisez.

02 / Concepts fondamentaux

Anatomie d'un graphe LangGraph.

Quatre primitives suffisent à modéliser n'importe quel workflow agentique : l'état, les nœuds, les arêtes (et les arêtes conditionnelles), et le checkpointing. Maîtriser ces quatre concepts, c'est maîtriser 90 % du framework.

Les 4 primitives de LangGraph en un schéma
① ÉTAT GLOBAL (STATE) TypedDict partagé entre tous les nœuds — messages, scratchpad, résultats d'outils, mémoire, décisions class GraphState(TypedDict): messages: list, plan: str, tool_results: list, done: bool START ② NŒUD planner def planner(state) ③ arête ③ ARÊTE CONDITIONNELLE need_tool done ② NŒUD call_tool RAG, SQL, API retour à planner END ④ CHECKPOINTER Persistance de l'état à chaque transition — SQLite, Postgres, Redis. Permet pause / reprise, time-travel, replay. checkpointer = PostgresSaver.from_conn_string(...) · graph.compile(checkpointer=checkpointer)

L'état (TypedDict) circule entre les nœuds. Les arêtes conditionnelles aiguillent le flow selon l'état courant. Le checkpointer persiste chaque transition — c'est ce qui permet l'observabilité, le replay et le human-in-the-loop.

Un exemple minimal — l'agent qui décide d'appeler un outil ou de répondre

Voici un graphe LangGraph à 2 nœuds qui illustre les 4 primitives en action. L'agent analyse la question, et soit appelle un outil (RAG), soit répond directement.

graph.py Python · LangGraph 0.3+
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.checkpoint.postgres import PostgresSaver

# ① État global partagé
class GraphState(TypedDict):
    messages: Annotated[list, add_messages]
    needs_tool: bool

# ② Nœud "planner" — décide de la suite
def planner(state: GraphState) -> GraphState:
    last = state["messages"][-1].content
    decision = llm.invoke(f"Cette question nécessite-t-elle un RAG ? {last}")
    return {"needs_tool": "oui" in decision.content.lower()}

# ② Nœud "call_rag" — appelle le retrieval
def call_rag(state: GraphState) -> GraphState:
    docs = retriever.invoke(state["messages"][-1].content)
    response = llm.invoke(f"Docs: {docs}\nRéponds.")
    return {"messages": [response]}

# ③ Arête conditionnelle
def router(state: GraphState) -> str:
    return "call_rag" if state["needs_tool"] else END

# Construction du graphe
g = StateGraph(GraphState)
g.add_node("planner", planner)
g.add_node("call_rag", call_rag)
g.add_edge(START, "planner")
g.add_conditional_edges("planner", router)
g.add_edge("call_rag", END)

# ④ Checkpointer pour persistance & replay
checkpointer = PostgresSaver.from_conn_string(POSTGRES_URI)
graph = g.compile(checkpointer=checkpointer)
Pourquoi cette structure compte

Chaque appel à graph.invoke() est observable étape par étape, persisté dans le checkpointer, et reproductible à l'identique. Quand quelque chose part de travers en production, vous avez l'historique exact — pas une trace dégradée, l'état réel à chaque transition.

03 / Patterns état de l'art 2026

Six patterns agentiques que nous maîtrisons.

Chacun adresse une famille de problèmes distincte. Le choix se fait sur deux questions : est-ce que la solution se découpe en étapes prévisibles à l'avance ? et est-ce qu'il faut plusieurs spécialités ?

① ReAct — Reason + Act

Quand : tâches à 1-5 outils, raisonnement court

Le pattern le plus simple, et souvent le plus efficace. L'agent alterne pensée (« je dois chercher X »), action (appel d'outil), observation (résultat), jusqu'à atteindre la réponse.

  • Implémentation native dans LangGraph via create_react_agent
  • Idéal pour les agents Q&A avec accès à un RAG ou à des APIs
  • Faible coût en tokens, latence prévisible
  • Limitation : tourne en rond si l'objectif est vague ou si les outils sont mal nommés
START REASON ACT (tool) OBSERVE END si pas fini si fini

② Plan-and-Execute

Quand : tâches longues (10+ étapes), plan révisable

L'agent commence par produire un plan explicite en plusieurs étapes, puis exécute chaque étape une par une. À chaque étape, il peut re-planifier si une étape a échoué ou si de nouvelles informations émergent.

  • Sépare le « quoi faire » (planner LLM Opus) du « faire » (exécuteur LLM Haiku/Sonnet)
  • Économie de coût : le modèle de raisonnement n'est invoqué qu'une fois par re-planification
  • Auditable : le plan est explicite, on peut le valider avant exécution
  • Limitation : marche mal si le plan ne peut pas être anticipé
START PLANNER LLM Opus → [step1, step2, step3] EXEC 1 EXEC 2 EXEC 3 REPLAN ? END re-plan

③ Reflexion / Self-correction

Quand : qualité critique, droit à l'erreur faible

Après chaque tentative, un nœud séparé critique le résultat (« est-ce que cette réponse est juste, complète, traçable ? »). Si la critique est négative, l'agent retravaille — jusqu'à max_iterations. Souvent réalisé via llm-as-judge avec un modèle différent du producteur.

  • Réduit drastiquement le taux d'hallucination sur les tâches critiques
  • Permet d'utiliser un modèle moins cher en producteur + Opus en critique
  • Coût : 2× à 5× plus de tokens vs ReAct simple
  • À combiner avec MLflow Evaluation pour tracer la qualité par itération
START PRODUCTEUR Sonnet 4.6 — rapide CRITIQUE Opus 4.7 — llm-as-judge score ≥ τ ? END OK retry

④ Multi-agent Supervisor-Worker

Quand : sous-tâches hétérogènes, spécialités distinctes

Un agent superviseur reçoit la requête et l'aiguille vers l'agent spécialisé adéquat (researcher, coder, writer, reviewer…). Chaque worker a son propre prompt, ses propres outils, son propre modèle. Le superviseur synthétise.

  • Excellente séparation des préoccupations
  • Permet d'utiliser le bon modèle état de l'art pour chaque rôle (Opus en researcher, Codestral en coder)
  • Implémentable nativement avec LangGraph + command pattern
  • Limitation : le superviseur peut devenir un bottleneck — limiter à 5-7 workers
SUPERVISOR routes & synthesis Researcher Opus + RAG Coder Codestral Reviewer Sonnet SYNTHÈSE Opus final answer

⑤ Swarm (agents pair-à-pair)

Quand : pas de hiérarchie naturelle, handoffs dynamiques

Pas de superviseur central : chaque agent peut passer la main (handoff) à n'importe quel autre agent du swarm en fonction du contexte. Modélisé par OpenAI dans Swarm/Agents SDK et désormais natif dans LangGraph via langgraph-swarm.

  • Plus fluide pour les workflows émergents (support client multi-domaines)
  • Plus difficile à observer et à débugger qu'un supervisor
  • Souvent combiné à une mémoire partagée (Mem0, Letta)
  • Bien adapté aux SDK natifs OpenAI Agents et Anthropic Agent SDK
Triage agent Billing agent Tech agent Sales agent handoff dynamique entre tous les agents

⑥ Hierarchical Teams

Quand : problèmes très larges, équipes spécialisées

Un superviseur de top niveau dirige plusieurs équipes, chacune avec son propre sous-superviseur et ses workers. Idéal pour les problèmes très larges qu'on peut décomposer en domaines (recherche / synthèse / vérification, ou métier A / métier B / métier C).

  • S'apparente à une organisation d'entreprise classique
  • Permet la composition de sous-graphes LangGraph indépendants
  • Coût de coordination élevé : à n'utiliser que quand strictement nécessaire
  • Combiné avec des memory stores partagés entre équipes pour la cohérence
TOP SUPER. Équipe A Équipe B Équipe C w1 w2 w1 w2 w1 w2 sous-graphes LangGraph composables
04 / Harness sur-mesure

Concevoir un harness d'agents in-house.

Les frameworks (LangGraph, CrewAI, AutoGen) couvrent 80 % des besoins. Mais pour les usages critiques — audit AI Act, replay forensique, contrôle de flux financier, contraintes de latence sub-second, environnements air-gap — il faut souvent concevoir un harness in-house qui s'inspire des frameworks mais reste votre code.

Quand un framework générique ne suffit plus

Cas 1

Audit forensique exigé

Trace immuable de chaque décision, signature cryptographique des transitions, time-travel queries. Plus de boîte noire — exigence des secteurs régulés (banque, santé, défense).

Cas 2

Latence sub-second

Frameworks Python introduisent 50-200 ms d'overhead par nœud. Pour les usages temps-réel (trading, voix), un harness Rust/Go ou Python optimisé devient nécessaire.

Cas 3

Air-gap & bibliothèques restreintes

Pas de packages PyPI tiers, audit ANSSI de chaque dépendance, contraintes linux/amd64 seul. Un harness in-house minimise la surface d'attaque.

Cas 4

Intégration profonde au SI

Bus d'événements existant (Kafka, NATS), workflow engine maison, persistence custom. Le framework générique combat votre architecture au lieu de la servir.

Les 5 patterns de design qu'on applique

  1. State machine explicite — chaque transition est une fonction nommée et testable, l'état est un dataclass immuable copié à chaque pas (pas de mutations cachées).
  2. Event sourcing — chaque transition produit un événement persisté avant exécution. Le replay devient déterministe (en présence d'outils déterministes ou avec snapshots LLM).
  3. Supervision arborescente — calque sur OTP/Erlang. Chaque agent enfant a un parent qui décide de la stratégie de reprise (restart, escalate, ignore).
  4. Circuit breakers & budgets — limites strictes : max_tokens, max_steps, max_cost_eur, max_latency_ms. Un agent qui dépasse est tué, pas redémarré indéfiniment.
  5. Observabilité native — chaque transition émet OpenTelemetry GenAI + MLflow Trace + métriques Prometheus. Pas d'instrumentation ajoutée après coup.
harness_core.py Squelette · Python 3.12
from dataclasses import dataclass, replace
from typing import Callable, Protocol
import mlflow

@dataclass(frozen=True)
class AgentState:
    messages: tuple
    plan: str | None
    budget_eur: float
    budget_steps: int
    decisions: tuple

class Transition(Protocol):
    name: str
    def __call__(self, state: AgentState) -> AgentState: ...

class Harness:
    def __init__(self, transitions, router, event_store, supervisor):
        self.transitions = {t.name: t for t in transitions}
        self.router = router
        self.event_store = event_store
        self.supervisor = supervisor

    def step(self, state: AgentState) -> AgentState:
        next_name = self.router(state)
        if next_name == "END" or state.budget_steps <= 0:
            return state

        with mlflow.start_span(name=next_name) as span:
            self.event_store.append("transition_start", next_name, state)
            try:
                new_state = self.transitions[next_name](state)
                self.event_store.append("transition_ok", next_name, new_state)
            except Exception as e:
                self.event_store.append("transition_fail", next_name, e)
                return self.supervisor.handle(state, next_name, e)
            return replace(new_state, budget_steps=new_state.budget_steps - 1)

    def run(self, initial: AgentState) -> AgentState:
        state = initial
        while self.router(state) != "END" and state.budget_steps > 0:
            state = self.step(state)
        return state
05 / Écosystème 2026

Comparatif des frameworks agentiques.

Aucun framework n'est universel. Nous choisissons par cas d'usage. LangGraph reste notre pivot, mais nous utilisons régulièrement les SDK natifs (Anthropic, OpenAI) et les frameworks spécialisés.

Framework Force principale Observabilité Multi-agent Production Notre usage
LangGraph State machines explicites, checkpointing, human-in-the-loop natif native LangSmith excellent prod-grade Pivot 80 % des cas
LangChain Briques (LLM wrappers, retrievers, parsers) — pas pour les agents v1 native LangSmith via LangGraph prod-grade Composants RAG et tools
LlamaIndex RAG premium, ingestion, indexation, agentic RAG OK via OTel workflows prod-grade RAG complexe + agentic RAG
AutoGen (Microsoft) Multi-agent conversationnel, group chat tracing partiel cœur de cible en montée POC multi-agent rapide
CrewAI Rôles & processus métaphoriques (équipe), DX basique cœur jeune Démos métier, POC business
Pydantic AI Agents typés, validation forte, output structuré Logfire natif simple prod-grade Agents single-purpose typés
Anthropic Agent SDK Tool use natif Claude, computer use, MCP console Anthropic simple prod-grade Quand tout passe par Claude
OpenAI Agents SDK Successeur Swarm, handoffs natifs Traces OpenAI swarm prod-grade Swarm GPT-5 simple
Mastra TypeScript-first, agents stateful, workflows en cours workflows jeune Front Next.js + agents
Notre arbre de décision

① Tout passe par Claude → Anthropic Agent SDK · ② Tout passe par GPT-5 avec handoffs simples → OpenAI Agents SDK · ③ Stack TypeScript / Next.js → Mastra · ④ RAG complexe en cœur du système → LlamaIndex · ⑤ Tout le reste, et notamment les workflows critiques en production → LangGraph.

06 / Mémoire d'agents

Mémoire longue : Letta, Mem0, MLflow Trace.

Un agent sans mémoire est un poisson rouge. Trois couches de mémoire à concevoir séparément : la mémoire de travail (état du graphe), la mémoire épisodique (historiques de conversations passées), et la mémoire sémantique (faits stables, préférences utilisateur).

Trois couches de mémoire d'un agent — et où elles vivent
① MÉMOIRE DE TRAVAIL État du graphe LangGraph Messages, scratchpad, plan, résultats d'outils. Vit le temps d'une invocation. Stockage : • Checkpointer Postgres / Redis • Time-travel possible • TTL court (heures) → LangGraph natif ② MÉMOIRE ÉPISODIQUE Historique conversations « Qu'as-tu dit à cet utilisateur la semaine dernière ? » — récupéré par similarité ou recence. Stockage : • Vector DB par user_id • Summarization périodique • TTL semaines / mois → Mem0, Letta, LangMem ③ MÉMOIRE SÉMANTIQUE Faits stables & préférences « L'utilisateur préfère le tutoiement. » — extrait des conversations, validé, persisté. Stockage : • KG ou base structurée • Extraction LLM périodique • Persistance longue durée → Letta, KG custom Une mémoire mal pensée fuit, hallucine, ou ralentit. Une mémoire bien conçue rend l'agent vraiment utile.
07 / Évaluation d'agents

Mesurer ce qu'un agent fait vraiment.

Évaluer un agent, ce n'est pas évaluer une réponse : c'est évaluer une trajectoire — la séquence d'étapes prise pour atteindre un objectif. Trois familles de métriques se combinent.

Métrique

Success rate

Le résultat final correspond-il à l'attendu ? Mesuré par llm-as-judge (Claude Opus en évaluateur), ou par règles déterministes quand c'est possible (assertion sur la sortie).

Métrique

Trajectory eval

Les bons outils ont-ils été appelés, dans le bon ordre ? L'agent a-t-il évité les détours inutiles ? Métriques : tool selection precision, path efficiency, redundant steps.

Métrique

Cost & latency

Tokens consommés (par modèle), latence end-to-end, coût €/trajectoire. Indispensable pour le pilotage en production. Tracé via MLflow + Langfuse.

Outils

RAGAS, DeepEval, LangSmith

RAGAS et DeepEval pour le RAG en sortie. LangSmith Evals pour les trajectoires LangGraph. MLflow Evaluation pour orchestrer tout ça dans des suites reproductibles.

Notre principe

La métrique précède le code. Avant d'écrire le premier nœud LangGraph, nous construisons un jeu d'évaluation représentatif de 100 à 500 trajectoires de référence. Sans ce jeu, vous codez en aveugle et la régression est invisible.

08 / Sécurité & guardrails

Un agent autonome est un risque autonome.

Plus un agent a d'autonomie (outils, accès SI, budget de tokens), plus la surface d'attaque s'élargit : prompt injection indirecte (via documents), data exfiltration via tool, jailbreak progressif, dérive de plan. Notre approche d'ingénierie est defense-in-depth, à 4 couches.

Couche 1

Garde-fous d'input

NeMo Guardrails ou Lakera Guard avant tout LLM : détection prompt injection, filtrage hors-domaine, classification topic. Llama Guard 3 pour la modération de contenu.

Couche 2

Allow-list d'outils

Chaque agent a une liste explicite d'outils autorisés, avec des arguments validés (Pydantic AI). Pas d'exec(), pas de fetch() arbitraire. Sandboxing des actions sensibles.

Couche 3

DLP & output filtering

Microsoft Presidio en sortie pour caviarder les PII. Classifieurs de toxicité. Validation que la réponse ne contient pas d'informations sensibles exfiltrées via tool calls.

Couche 4

Red teaming continu

Pyrit (Microsoft) et Garak orchestrent des attaques connues en continu. Chaque release d'agent passe par une batterie de tests adversariaux avant promotion.

Cette architecture est exigée par l'AI Act (art. 9 — gestion des risques, art. 15 — exactitude, robustesse, cybersécurité). Nous concevons les agents avec ces couches dès le jour 1, pas en rattrapage après incident.

Un projet agentique à challenger ?

Architecture agentique, choix LangGraph vs harness in-house, sélection des frameworks, évaluation, sécurisation — échangeons. Première analyse de faisabilité offerte, sous 24 h ouvrées.