首页 / 文章

LangGraph、OpenAI Agents SDK或Claude Agent SDK:将相应原语与工作负载匹配。

四种示例工作负载——语音处理、持久性退款、代码迁移以及MCP操作——展示了在何种情况下适合使用哪种代理框架,并附有关于锁定效应、持久性及实时性的说明。

发布者:REACTAPP.TOP阅读约 11 分钟2534 词

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

2026年的各类对比仍集中在三种智能体框架上,每种框架都基于不同的核心理念。LangGraph是一种图计算运行时,其节点为普通函数,边则决定状态转换方式。OpenAI Agents SDK以任务交接为核心,智能体通过带类型标注的会话将工作传递给另一个智能体,并原生支持MCP协议。而Claude Agent SDK则与众不同:它为智能体提供了一台真正的计算机,因为Anthropic基于bash执行、文件写入及钩子机制构建了该框架,认为一个功能强大的智能体需要真正的命令行环境。

选择哪种框架取决于架构对比中很少被提及的一个因素:智能体要执行的是何种类型的工作?

三种基本要素

LangGraph专为有状态的工作流设计。首先需要定义状态模式,然后一个带类型的对象会从图中的第一个节点移动到最后一个节点。由于检查点机制会在每个节点保存状态,因此程序在崩溃后或等待人工审批时可以继续运行,并且上下文不会丢失。2025年10月22日正式发布的LangChain 1.0中引入的create_agent函数实际上只是该运行时机制的接口层,这也就结束了关于应使用LangChain还是LangGraph的争论。

OpenAI Agents SDK包含九个核心组件,分别是Agents、Handoffs、Tools、Guardrails、Sessions和Realtime。其最基本的单元是一个智能体将任务传递给另一个智能体。2025年,通过LiteLLM支持了100多种模型,实现了与提供方的解耦。MCP被视为一等工具类型,而语音功能则内置于gpt-realtime-2系列模型中。

Claude Agent SDK以shell环境为核心。其工具箱包含Bash、Read、Write、Edit、Glob和Grep等工具,还有名为PreToolUse、PostToolUse和Stop的生命周期钩子,以及在不同隔离的上下文窗口中运行的子代理。2025年底,Anthropic将其名称从Claude Code SDK改为现名,因为该框架不仅可用于编程,还能支持深度研究、视频制作和笔记记录等功能。虽然Bedrock、Vertex和Azure Foundry可以运行它,但仅允许使用Claude模型。

2025年的一种错误认知

去年有一种普遍的假设认为OpenAI Agents SDK只能使用OpenAI的模型。这一观点已经过时约15个月了。官方仓库除了支持OpenAI Responses API外,还通过LiteLLM和Any-LLM集成支持大约100种其他模型。

# 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."

使用 Gemini 模型名称创建 LitellmModel,表明该框架能够处理 OpenAI 生态系统之外的模型,而 @function_tool 装饰器的功能无论底层使用何种模型都保持一致。非 OpenAI 模型的支持程度以尽力而为为原则,不同服务提供商的功能完备性存在差异。由于无法设定严格的模型限制,这些框架便在底层架构设计上展开竞争。

拥有四个智能体的测试公司

以一家中型金融科技企业为例,暂称 Meridian,其四个智能体正在不同团队中开发中。

  • 一个语音客服智能体,通过电话处理账单相关问题。
  • 一个多智能体退款工作流,会在将工单转交财务部门之前先检查欺诈规则。
  • 一个内部代码迁移智能体,能够遍历庞大的 Java 代码库,进行语法转换并提交拉取请求。
  • 一个通过MCP服务器查询Sentry、Linear、PagerDuty和Postgres的运营控制面板。
  • 以下四个构建方案展示了哪种框架适合各自的需求。

    工作负载一:语音与实时流媒体

    语音团队需要在严格的延迟限制下工作,流媒体传输的延迟必须低于500毫秒,同时还要处理用户突然接入的情况。语音转文本、文本输入模型再生成语音的输出流程速度过慢,因为每次网络传输都会增加延迟。

    OpenAI Agents SDK非常适合此场景。gpt-realtime-2模型能够直接传输音频令牌,而RealtimeAgent则封装了这一功能。在2026年中,LangGraph和Claude Agent SDK均未能提供此类级别的原生实时处理能力。

    # 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与RealtimeSession负责处理传入和传出的音频流以及工具调用循环,而使用@function_tool声明的工具会在实时会话中运行,方式与在文本代理中相同。该框架会暴露事件循环,而WebSocket状态则不会被显示。

    在LangGraph或Claude Agent SDK中实现这一功能需要编写自定义的WebSocket代码、进行语音活动检测,并处理复杂的中断逻辑,这会让代理项目变成一个媒体处理管道项目。如果公司政策要求必须使用Claude或Gemini作为语音模型,那么情况就有所不同。Anthropic后来添加了实时处理功能,因此2026年中之后阅读相关内容的人应核实各功能的兼容性。

    第二类工作负载:需人工审批的持久化编排

    退款流程需要先进行欺诈检测,再提交财务审批;对于金额超过500美元的退款,还需等待人工审核,最后将决策结果写入Postgres数据库。该流程必须能够抵御服务器崩溃,并在遇到人工处理延迟时仍能保持上下文不丢失。

    LangGraph非常适合这一需求。检查点机制与中断机制相结合,恰好提供了长时运行业务流程所需的控制流。实际应用团队也认可这一架构:Uber称其通过LangGraph在AutoCover和Validator系统中节省了约21,000小时的开发时间;LinkedIn则发表了一篇关于Hiring Assistant系统中分层语义记忆树的论文,而其监督节点与子节点的设计则在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)
    

    暂停与恢复的模式能够确保代码的持久执行。在财务审批节点中调用interrupt()函数会将当前状态写入检查指针,此时系统可能会关闭。数小时后,当恢复状态被设置为“已批准”时,操作会在同一线程ID下从暂停处继续执行,而无需重新进行欺诈检测。

    不过这种持久性方案也存在一些限制。开源运行时将状态保存在进程内存中的MemorySaver中,因此在高负载情况下真正的崩溃恢复需要依赖Postgres支持的LangGraph Platform,或是自定义的PostgresSaver机制。

    OpenAI Agents SDK提供了用于对话状态管理的Sessions以及用于长期任务的Sandbox Agents,但缺乏在任意图结构上实现节点级检查点的功能。Claude Agent SDK则将JSONL格式的会话状态保存在本地,或通过Managed Agents来实现持久化存储,但为此需要使用仅支持Claude模型的方案。目前,LangGraph拥有成熟的任务编排能力。

    第三类工作负载:文件与Shell操作

    来自开发者体验团队的迁移工具需要遍历一个包含40万行代码的Java项目库,应用语法修改,运行单元测试并提交拉取请求。这意味着要读取和编辑文件、执行Shell命令以及处理编译错误。几乎所有工作都集中在Bash和Edit操作上。

    Claude Agent SDK可直接对应于此,因为Anthropic的理念是为智能体提供一台计算机。它拥有Bash、Read、Write、Edit、Glob和Grep等原生工具,其钩子功能则充当控制界面。PreToolUse钩子可用于设置限制,防止有害命令的执行,而PostToolUse钩子则可用于运行格式化工具或代码检查工具。子智能体会在独立的上下文中分担转换任务,因此交给子智能体的长篇编译错误日志不会污染主智能体的界面。

    # 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)
    

    allowed_tools列表用于设定智能体的运行环境。钩子机制提供了一种位于智能体循环内部而非其周围的约束机制:PreToolUse钩子在工具被调用之前执行,而拒绝决策则会立即终止该调用。Lint子智能体拥有自己的工具和上下文窗口。最新版本的SDK已不再推荐在AgentDefinition中使用tools字段,转而使用skills字段,不过旧方式仍然有效。注释中的代码示例展示了如何从本地磁盘上的JSONL文件中恢复会话状态。

    在 LangGraph 中,这些 Shell 原语需要被编写为自定义的 Python 函数。OpenAI SDK 的 Sandbox Agents 在容器中运行,架构上与之类似,但其原语集合并未以类似基于文件的方式命名或暴露。问题在于模型锁定效应——那些严格禁止在模型层面出现锁定效应的团队无法使用 Claude Agent SDK,只能自行重新实现 bash 和编辑相关原语,转而使用 LangGraph。

    第四类工作负载:以 MCP 为主的协调任务

    平台团队的控制台能够响应工程师输入的单一问题。在背后,该代理会从 Sentry 获取错误信息、从 Linear 获取工单数据、从 PagerDuty 获取事件记录,以及从 Postgres 获取用户信息。其几乎所有精力都用于协调第三方 MCP 服务器,而用于生成答案的部分则非常少。

    在这一点上,OpenAI Agents SDK与Claude Agent SDK处于同一水平。两者都以MCP作为核心构建模块,且服务器功能表现为本地函数。LangGraph也能使用MCP,但在2026年中使用它需要更多的冗余代码,因此团队通常会自行将服务器封装成工具。这两款领先产品之间的差异属于次要考量因素。

    • 若需要第一方追踪、严格的约束机制以及将任务分配给专业子代理,或希望通过LiteLLM将简单的合成任务转交给成本更低的提供商,可选择OpenAI Agents SDK。
    • 若看重钩子生命周期管理、严格的子代理隔离机制以及Claude在工具使用方面的可靠性,可选择Claude Agent SDK。

    为常见SaaS工具定制API封装会占用大量工程时间。MCP标准化了上下文与工具发现机制,因此框架只需避免干扰,且两种SDK都原生支持该模式。

    按工作负载总结

    • 支持实时语音插入的功能:OpenAI Agents SDK。
    • 需要人工审批的持久多智能体流程:LangGraph。
    • 文件处理、命令行操作及代码迁移任务:Claude Agent SDK。
    • 复杂的MCP编排需求:OpenAI Agents SDK或Claude Agent SDK。

    关于CrewAI的说明

    许多读者期望在此类对比中看到CrewAI。经核查,其当前版本Flows的采用情况以及企业案例的研究深度均不如其他三个选项,因此未将其纳入,以免用较弱的依据填充内容。

    真正的选择

    有四种智能体最终被集成到三种框架中:OpenAI SDK中的语音与平台智能体、LangGraph中的退款流程智能体,以及Claude Agent SDK中的迁移智能体。争论哪种框架更优是个错误的思路,关键在于让框架的核心原语与工作需求相匹配。

    下一轮竞争可能会再次围绕稳定性问题展开,因为LangGraph Platform正在与Anthropic的托管智能体服务竞争。LangGraph或许会获得一流的实时处理原语,而Anthropic则可能向其他模型提供商开放其SDK。在那时之前,这些原语将决定系统的架构设计。

    相关阅读

  • 使用 OpenTelemetry 在 Vertex AI Agent Engine 中追踪 LangGraph Agent — Agent Engine 默认不会追踪 LangGraph Agent。需在启动时添加 OpenTelemetry,隐藏凭证信息,为关键函数添加装饰,并将跟踪数据发送至 Cloud Trace。
  • 2026 年的 LangGraph 与 Google ADK:显式编排还是 Agent 组合 — 对比了构建 Agent 的两种方式:LangGraph 的状态与图控制机制与 ADK 的以 Agent 为中心的组合方式,以及如何决定谁来负责工作流的管理。