Accueil / Articles

LangGraph, OpenAI Agents SDK ou Claude Agent SDK : Associer la primitive à la tâche.

Quatre charges de travail de référence, liées à la voix, aux remboursements durables, à la migration de code et aux opérations MCP, indiquent quel framework d’agent convient dans quelles situations, avec des notes sur le verrouillage, la durabilité et le temps réel.

Éditeur : REACTAPP.TOP11 min de lecture2534 mots

Sources: The Best Agent Framework in 2026: LangGraph vs OpenAI Agents SDK vs Claude Agent SDK

Les comparaisons en 2026 reviennent constamment à trois frameworks d’agents, chacun reposant sur une idée fondamentale différente. LangGraph est un environnement d’exécution graphique dans lequel les nœuds représentent des fonctions simples et les arêtes déterminent les transitions. Le SDK OpenAI Agents est axé sur les transferts de tâches, où un agent passe du travail à un autre via des sessions typées, avec un support natif pour MCP. Le SDK Claude Agent est le plus surprenant : il fournit à l’agent un ordinateur, car Anthropic l’a conçu sur la base de l’exécution en bash, de l’écriture de fichiers et d’hooks, convaincu qu’un agent performant a besoin d’un véritable shell.

Le choix approprié dépend de quelque chose que les comparaisons architecturales posent rarement : quel type de tâche l’agent accomplit-il ?

Les trois primitives

LangGraph est conçu pour les workflows à états. Un schéma d’états est déclaré, et un objet typé se déplace à travers le graphe du premier nœud au dernier. Comme les outils de vérification enregistrent cet état à chaque nœud, une exécution peut reprendre après une panne ou après avoir attendu une approbation humaine, tout en conservant son contexte intact. La fonction create_agent, introduite avec LangChain 1.0 disponible en général le 22 octobre 2025, n’est qu’une façade sur ce moteur d’exécution, ce qui met fin au vieux débat LangChain ou LangGraph.

Le SDK OpenAI Agents comprend neuf éléments de base, parmi lesquels Agents, Handoffs, Tools, Guardrails, Sessions et Realtime. Son unité atomique est un agent qui transmet une tâche à un autre. L’indépendance vis-à-vis des fournisseurs est apparue en 2025 avec le support de plus de 100 modèles via LiteLLM. MCP est un type d’outil de première classe, et la fonctionnalité vocale est intégrée nativement dans la famille de modèles gpt-realtime-2.

Le Claude Agent SDK est basé sur un environnement shell. Son ensemble d’outils comprend Bash, Read, Write, Edit, Glob et Grep, ainsi que des points d’ancrage de cycle de vie nommés PreToolUse, PostToolUse et Stop, et des sous-agents exécutés dans des fenêtres de contexte séparées et isolées. Anthropic a changé son nom de Claude Code SDK à la fin de 2025, car cet outil sert également à la recherche approfondie, à la création de vidéos et à la prise de notes, et pas seulement au codage. Seuls les modèles Claude sont autorisés, bien que Bedrock, Vertex et Azure Foundry puissent l’héberger.

Une croyance de 2025 à abandonner

Une supposition courante de l’année dernière affirme que l’OpenAI Agents SDK force l’utilisation des modèles OpenAI. Cela est désormais obsolète depuis environ quinze mois. Le dépôt officiel prend en charge l’API OpenAI Responses ainsi que près de 100 autres modèles grâce aux intégrations LiteLLM et Any-LLM.

# Install: pip install "openai-agents[litellm]"
# Env: export GEMINI_API_KEY=...
import os
from agents import Agent, Runner, function_tool
from agents.extensions.models.litellm_model import LitellmModel

@function_tool
def current_time_utc() -> str:
    """Return the current UTC time as an ISO-8601 string."""
    from datetime import datetime, timezone
    return datetime.now(timezone.utc).isoformat(timespec="seconds")

# OpenAI Agents SDK using Gemini via LiteLLM. No OpenAI key required.
gemini_model = LitellmModel(
    model="gemini/gemini-2.5-pro",
    api_key=os.environ["GEMINI_API_KEY"],
)

agent = Agent(
    name="time-agent",
    instructions="Answer time questions using the current_time_utc tool.",
    model=gemini_model,
    tools=[current_time_utc],
)

result = Runner.run_sync(agent, "What is the current UTC time?")
print(result.final_output)
# -> "The current UTC time is 2026-07-06T14:32:11+00:00."

La création de LitellmModel à partir d’un modèle Gemini montre que le framework permet d’opérer en dehors de l’écosystème OpenAI, et le décorateur @function_tool se comporte de manière identique quel que soit le modèle utilisé en sous-jacent. Les chemins non liés à OpenAI sont documentés selon les meilleures pratiques, avec une parité des fonctionnalités variable selon le fournisseur. Sans limites strictes imposées aux modèles, les frameworks se font concurrence sur leurs primitives architecturales.

Une entreprise de test avec quatre agents

Prenons une fintech de taille moyenne, appelons-la Meridian, qui développe actuellement quatre agents au sein d’équipes distinctes.

  • Un agent de support par voix qui répond aux questions de facturation par téléphone.
  • Un flux de travail de remboursement multi-agents qui vérifie les règles de fraude avant d’envoyer la demande au service financier.
  • Un agent de migration de code interne qui parcourt un grand répertoire Java, applique des transformations syntaxiques et ouvre des demandes de fusion de code.
  • Un tableau de bord opérationnel qui interroge Sentry, Linear, PagerDuty et Postgres via des serveurs MCP.
  • La liste des quatre versions montre quel framework convient à chacune d’elles.

    Charge de travail un : voix et streaming en temps réel

    L’équipe chargée de la voix doit respecter un budget de latence strict, inférieur à 500 ms pour le streaming, et doit également gérer les interruptions de la part des utilisateurs. L’étape de conversion parole en texte, suivie de l’alimentation d’un modèle de texte vers un système de synthèse vocale, est trop lente, car chaque saut réseau ajoute un délai.

    Le SDK OpenAI Agents convient. Le modèle gpt-realtime-2 transmet nativement des tokens audio, et RealtimeAgent encapsule cette fonctionnalité. Ni LangGraph ni le Claude Agent SDK ne proposaient de primitive en temps réel natif à ce niveau au milieu de 2026.

    # Install: pip install openai-agents
    # Env: export OPENAI_API_KEY=...
    import asyncio
    from agents import function_tool
    from agents.realtime import RealtimeAgent, RealtimeRunner
    
    @function_tool
    def lookup_billing_balance(account_id: str) -> str:
        """Return the current outstanding balance for an account."""
        # In production, this hits the billing service. Here it is a stub.
        return "42.17 USD outstanding as of 2026-07-06."
    
    voice_agent = RealtimeAgent(
        name="meridian-billing-voice",
        instructions=(
            "You are Meridian's billing voice assistant. Answer politely, briefly. "
            "Confirm the account_id before disclosing any balance."
        ),
        tools=[lookup_billing_balance],
    )
    
    async def main():
        runner = RealtimeRunner(
            starting_agent=voice_agent,
            config={"model_settings": {"model_name": "gpt-realtime-2.1"}},
        )
    
        # session handles the audio stream and tool calls
        session = await runner.run()
    
        async with session:
            # Wire the audio input source here via sounddevice or pyaudio
            async for event in session:
                if event.type == "history_updated":
                    # The item contains the finalized transcript once the turn ends
                    print(f"History updated with item: {event.item}")
                elif event.type == "error":
                    print(f"Error: {event.error}")
                    break
    
    asyncio.run(main())
    

    RealtimeAgent et RealtimeSession gèrent les flux audio entrants et sortants ainsi que le cycle d’appel des outils ; les outils déclarés avec @function_tool s’exécutent dans une session en temps réel de la même manière qu’auprès d’un agent textuel. Le framework met en évidence le cycle d’événements, tandis que l’état WebSocket reste invisible.

    Le faire avec LangGraph ou le Claude Agent SDK nécessiterait un code WebSocket personnalisé, une détection de l’activité vocale et des sématiques d’interruption complexes, ce qui transformerait un projet d’agent en un projet de pipeline multimédia. Si la politique de l’entreprise exige l’utilisation de Claude ou Gemini pour le modèle vocal, la réponse change. Anthropic a ajouté des fonctionnalités en temps réel plus tard, donc toute personne lisant ce texte après mi-2026 devrait vérifier l’équivalence des fonctionnalités.

    Charge de travail deux : orchestration durable avec approbation humaine

    Le processus de remboursement nécessite une vérification de fraude suivie d’une transmission à l’équipe financière, une attente pour une révision humaine des remboursements supérieurs à 500 $, ainsi qu’une décision finale enregistrée dans Postgres. Il doit résister aux pannes de serveur et gérer les pauses humaines asynchrones sans perdre de contexte.

    LangGraph convient parfaitement. Les pointeurs de sauvegarde combinés à la primitive d’interruption fournissent exactement le flux de contrôle requis par les processus métier à long terme. Les équipes de production soutiennent cette architecture : Uber affirme avoir économisé environ 21 000 heures de travail de développeurs en utilisant LangGraph pour ses systèmes AutoCover et Validator, et LinkedIn a publié une étude sur un arbre de mémoire sémantique hiérarchique pour son outil Hiring Assistant, dont la conception de superviseur et de sous-agent est abordée séparément dans des présentations techniques de LangChain.

    from typing import TypedDict, Literal
    from langgraph.graph import StateGraph, START, END
    from langgraph.checkpoint.memory import MemorySaver
    from langgraph.types import interrupt, Command
    from langchain_google_genai import ChatGoogleGenerativeAI
    
    # LangGraph is provider-agnostic. Here it uses Gemini.
    llm = ChatGoogleGenerativeAI(model="gemini-2.5-pro", temperature=0)
    
    class RefundState(TypedDict):
        order_id: str
        amount_usd: float
        customer_reason: str
        fraud_risk: Literal["low", "medium", "high"] | None
        finance_decision: Literal["approved", "denied"] | None
        human_review_needed: bool
    
    def fraud_check(state: RefundState) -> RefundState:
        """Run the LLM-backed fraud check against the customer's stated reason."""
        prompt = (
            f"Assess fraud risk for refund of ${state['amount_usd']:.2f}. "
            f"Customer reason: {state['customer_reason']!r}. "
            "Respond with one word: low, medium, or high."
        )
        verdict = llm.invoke(prompt).content.strip().lower()
        if verdict not in {"low", "medium", "high"}:
            verdict = "high"  # fail-closed on ambiguous LLM output
        return {**state, "fraud_risk": verdict}
    
    def finance_approval(state: RefundState) -> RefundState:
        """Above $500 or medium risk, pause for a human. Otherwise auto-approve."""
        needs_human = state["amount_usd"] > 500 or state["fraud_risk"] in {"medium", "high"}
        if needs_human:
            # Pause the graph. On resume, interrupt returns the human's decision.
            human_decision = interrupt({
                "order_id": state["order_id"],
                "amount_usd": state["amount_usd"],
                "fraud_risk": state["fraud_risk"],
                "prompt": "Approve (yes/no)?",
            })
            return {**state, "human_review_needed": True, "finance_decision": human_decision}
        return {**state, "human_review_needed": False, "finance_decision": "approved"}
    
    # Build the graph
    graph = StateGraph(RefundState)
    graph.add_node("fraud_check", fraud_check)
    graph.add_node("finance_approval", finance_approval)
    graph.add_edge(START, "fraud_check")
    graph.add_conditional_edges(
        "fraud_check",
        lambda s: "finance_approval" if s["fraud_risk"] != "high" else END,
    )
    graph.add_edge("finance_approval", END)
    
    # Checkpointer. For production, swap MemorySaver for PostgresSaver.
    compiled = graph.compile(checkpointer=MemorySaver())
    
    # Run it. Interrupt fires on the $850 refund and the graph pauses.
    config = {"configurable": {"thread_id": "order-4291"}}
    result = compiled.invoke(
        {
            "order_id": "4291",
            "amount_usd": 850.00,
            "customer_reason": "arrived damaged, no photo",
            "fraud_risk": None,
            "finance_decision": None,
            "human_review_needed": False,
        },
        config=config,
    )
    
    # Later, a human reviewer says yes. Resume with Command.
    final = compiled.invoke(Command(resume="approved"), config=config)
    

    Le schéma d’arrêt et de reprise assure une exécution fiable dans le code. L’appel à interrupt() à l’intérieur du nœud d’approbation financière enregistre l’état actuel dans le checkpointer, ce qui peut provoquer l’arrêt du système à ce moment-là. Des heures plus tard, une commande avec la valeur resume définie sur approved reprend là où elle s’était arrêtée, sous le même ID de thread, sans avoir à relancer la vérification de fraude.

    Une précaution concernant la fiabilité s’impose. L’environnement d’exécution open source enregistre l’état dans MemorySaver, qui se trouve dans la mémoire du processus. Une véritable récupération en cas de panne sous charge nécessite LangGraph Platform accompagné de Postgres, ou un PostgresSaver personnalisé.

    Le SDK OpenAI Agents propose des Sessions pour gérer l’état des conversations et des Sandbox Agents pour des tâches à long terme, mais rien qui égale le système de sauvegarde au niveau des nœuds sur un graphe arbitraire. Le SDK Claude Agent conserve localement l’état des sessions au format JSONL, ou utilise des Managed Agents pour assurer une durabilité hébergée, au détriment des modèles réservés à Claude. Pour l’instant, LangGraph détient le monopole de l’orchestration fiable.

    Tâche trois : travail avec des fichiers et une shell

    L’agent de migration de l’équipe chargée de l’expérience développeur doit parcourir un répertoire Java de 400 000 lignes, appliquer des modifications syntaxiques, exécuter des tests unitaires et ouvrir des demandes de fusion. Cela implique de lire et d’éditer des fichiers, d’exécuter des commandes de shell et de réagir aux erreurs de compilation. Bash et Edit représentent presque l’intégralité de cette tâche.

    Le Claude Agent SDK correspond directement à cela, puisque la philosophie d’Anthropic est de fournir aux agents un ordinateur. Il dispose d’outils natifs pour Bash, Read, Write, Edit, Glob et Grep, et ses hooks servent de surface de contrôle. Un hook PreToolUse peut imposer des restrictions contre les commandes destructrices, tandis qu’un hook PostToolUse peut exécuter des outils de formatage ou de vérification. Les sous-agents répartissent le travail de transformation dans des contextes isolés, de sorte qu’un long journal d’erreurs de compilateur transmis à un sous-agent ne pollue pas la fenêtre de l’agent principal.

    # Install: pip install claude-agent-sdk
    # Env: export ANTHROPIC_API_KEY=...
    import anyio
    from claude_agent_sdk import (
        ClaudeSDKClient,
        ClaudeAgentOptions,
        AgentDefinition,
        HookMatcher,
    )
    
    # PreToolUse hook: block Bash calls that look like rm -rf
    async def block_dangerous_bash(input_data, tool_use_id, context):
        if input_data.get("tool_name") == "Bash":
            cmd = input_data.get("tool_input", {}).get("command", "")
            if "rm -rf" in cmd or "rm  -rf" in cmd:
                return {
                    "hookSpecificOutput": {
                        "hookEventName": "PreToolUse",
                        "permissionDecision": "deny",
                        "permissionDecisionReason": "rm -rf blocked by policy",
                    }
                }
        return {}
    
    # Subagent: runs in isolated context to lint one file
    lint_agent = AgentDefinition(
        description="Run linters on a single file and return a concise report.",
        prompt=(
            "You are the lint subagent. Given a file path, run the project's linter "
            "on it and return a one-paragraph summary of failures. Do not fix anything."
        ),
        tools=["Bash", "Read"], # Note: tools is deprecated in favor of skills in recent SDKs
    )
    
    options = ClaudeAgentOptions(
        system_prompt=(
            "You are Meridian's code migration agent. Walk the target directory, "
            "apply the migration, run tests, and open a PR. Prefer small commits."
        ),
        allowed_tools=["Bash", "Read", "Write", "Edit", "Glob", "Grep"],
        hooks={"PreToolUse": [HookMatcher(hooks=[block_dangerous_bash])]},
        agents={"lint": lint_agent},
        # resume="mig-run-2026-07-06-01",  # uncomment to resume a prior session
    )
    
    async def main():
        async with ClaudeSDKClient(options=options) as client:
            await client.query(
                "Migrate services/payments/ from Java 17 to Java 21. "
                "For every file you touch, delegate to the `lint` subagent afterward. "
                "Do NOT commit or open PRs yet. Stop after changes are on disk."
            )
            async for message in client.receive_response():
                print(message)
    
    anyio.run(main)
    

    La liste allowed_tools définit l’environnement de l’agent. Les hooks fournissent une barrière de sécurité intégrée au cycle de l’agent et non autour de celui-ci : un hook PreToolUse s’exécute avant l’utilisation d’une outil, tandis qu’une décision de refus arrête immédiatement l’appel. Le sous-agent lint dispose de ses propres outils et de sa propre fenêtre de contexte. Les dernières versions du SDK déprécient le champ tools dans AgentDefinition au profit de skills, bien que celui-ci continue de fonctionner. La ligne de code commentée illustre la restauration de l’état de session à partir de fichiers JSONL sur le disque local.

    Dans LangGraph, ces primitives shell devraient être écrites sous forme de fonctions Python personnalisées. Les Sandbox Agents de l’SDK OpenAI s’exécutent dans des conteneurs, ce qui est similaire en termes d’architecture, mais l’ensemble des primitives n’est ni nommé ni exposé de la même manière centrée sur les fichiers. Le problème réside dans le verrouillage par le modèle : une équipe ayant une règle stricte contre le verrouillage au niveau du modèle ne peut pas utiliser le Claude Agent SDK et doit recourir à LangGraph pour réimplémenter elle-même les primitives bash et d’édition.

    Charge de travail quatre : orchestration axée sur MCP

    Le tableau de bord de l’équipe de la plateforme répond à une seule question saisie par un ingénieur. En arrière-plan, l’agent récupère les erreurs depuis Sentry, les tickets depuis Linear, les incidents depuis PagerDuty ainsi que les données des utilisateurs depuis Postgres. Presque tous ses efforts sont consacrés à coordonner les serveurs MCP de tiers, et très peu à composer la réponse.

    Ici, l’OpenAI Agents SDK et le Claude Agent SDK sont à égalité. Dans les deux cas, MCP constitue un élément de base essentiel, et les serveurs fonctionnent comme des fonctions locales. LangGraph peut également utiliser MCP, mais à mi-2026 cela nécessite plus de code générique, et les équipes ont tendance à intégrer eux-mêmes les serveurs dans des outils. Le critère décisif entre ces deux solutions leaders relève d’une contrainte secondaire.

    • Choisissez l’OpenAI Agents SDK pour le suivi en interne, des règles strictes et des transferts vers des sous-agents spécialisés, ou lorsque le routage de tâches de synthèse simples vers des fournisseurs moins chers via LiteLLM est avantageux.
    • Choisissez le Claude Agent SDK pour le cycle de vie des hooks, une isolation stricte des sous-agents et la fiabilité de l’utilisation des outils par Claude.

    Les enveloppes API personnalisées pour les outils SaaS courants consomment du temps d’ingénierie. Le standard MCP standardise le contexte et la découverte des outils, de sorte que le framework n’a qu’à rester en retrait, et les deux SDK prennent en charge nativement ce modèle.

    Résumé par type de travail

    • Voix en temps réel avec intervention simultanée : OpenAI Agents SDK.
    • Flux multi-agents durables avec approbation humaine : LangGraph.
    • Migration de fichiers, de shell et de code : Claude Agent SDK.
    • Orchestration intensive via MCP : OpenAI Agents SDK ou Claude Agent SDK.

    Une remarque sur CrewAI

    De nombreux lecteurs s’attendent à trouver CrewAI dans une comparaison de ce type. Après vérification, les preuves concernant sa version actuelle, son adoption par Flows ainsi que les études de cas dans le secteur enterprise n’étaient pas aussi solides que pour les trois autres solutions, c’est pourquoi elle a été exclusée plutôt que d’enrichir l’article avec des sources moins fiables.

    Le véritable choix

    Quatre agents ont été intégrés dans trois frameworks différents : les agents vocaux et de plateforme dans le SDK d’OpenAI, le flux de remboursement dans LangGraph, et l’agent de migration dans le SDK Claude Agent. Discuter de savoir quel framework est le meilleur est une approche erronée. La tâche consiste plutôt à aligner les primitives fondamentales d’un framework avec les besoins spécifiques du travail à effectuer.

    Le prochain tour de compétition risque de relancer le débat sur la durabilité, alors que LangGraph Platform concurrence les Managed Agents d’Anthropic. LangGraph pourrait obtenir des primitives en temps réel de premier ordre, ou bien Anthropic pourrait ouvrir son SDK à d’autres fournisseurs de modèles. Jusqu’à ce moment-là, ce sont ces primitives qui dictent l’architecture.

    Lectures complémentaires

  • Traçage des agents LangGraph sur Vertex AI Agent Engine avec OpenTelemetry — Agent Engine ne traque pas par défaut les agents LangGraph. Ajoutez OpenTelemetry au démarrage, masquez les identifiants, ornez les fonctions clés et envoyez les spans à Cloud Trace.
  • LangGraph vs Google ADK en 2026 : orchestration explicite ou composition d’agents — Comparaison de deux méthodes pour créer des agents : le contrôle basé sur l’état et le graphe de LangGraph contre la composition centrée sur les agents d’ADK, ainsi que la manière de déterminer qui doit gérer le flux de travail.