当业务需要构建一个真正的 AI Agent 时,最让人纠结的往往不是模型选型,而是 Agent 框架选型。LangChain、LangGraph、Deep Agents、ADK,这四个名字频繁出现在技术社区和项目文档里,但它们的定位、抽象层次、适用场景其实差异很大。如果用错方向,后期重构成本会非常高。
这篇文章不打算只做概念罗列,而是围绕选型这一核心问题,拆解四个框架的定位与内部机制,对比它们在流程控制、状态管理、工具调用、生产部署上的真实差异,最后给出一套可以直接落地的最小示例和选型建议。无论你是刚接触 Agent 开发的新手,还是已经在业务中落地过多个 Agent 的开发者,这篇文章都能帮你理清思路。
1. 背景:为什么 Agent 开发需要框架
在正式对比之前,先统一一下语境。很多人在刚开始接触 Agent 时,会把“Agent 框架”和“模型调用库”“业务系统”混在一起,结果代码越写越乱,分支逻辑全堆在一个巨大的循环里,最后完全没法维护。
1.1 Agent 框架解决什么问题
Agent 的核心能力,是让大模型在“理解任务”的基础上,自主决定调用哪些工具、按什么顺序调用、如何根据中间结果调整下一步动作。这个过程包含几个关键环节:
- 任务规划:把用户请求拆解为多个步骤。
- 工具调用:根据模型输出触发外部 API、代码函数或数据库操作。
- 状态管理:记录每一步的输入输出、中间变量、上下文记忆。
- 循环控制:决定何时终止、何时回溯、何时交给另一个子任务。
- 人工介入:在关键节点暂停,等待人工确认或补充信息。
如果没有框架,这些逻辑全部要自己手写。你会很快发现,循环、重试、上下文传递、异常恢复、并发控制这些细节比预想中复杂得多。Agent 框架的核心价值,就是把这些通用能力抽象出来,让你把精力放在业务逻辑和 Prompt 设计上。
1.2 四个框架的宏观定位差异
四个框架虽然都叫 Agent 框架,但抽象层次和设计哲学并不同:
- LangChain:一个“全家桶”式工具集,提供模型封装、Prompt 模板、向量存储、工具调用等大量组件。它的口号是“让大模型应用开发模块化”,适合快速搭建、原型验证和中小型业务。
- LangGraph:一个基于图状态机的编排框架,强调可控制、可复现、可中断的 Agent 流程。它把 Agent 定义为“节点 + 边 + 状态”的图,适合需要精细流程控制、复杂状态流转、生产级可观测性的场景。
- Deep Agents:由 LangChain 团队开源的一套轻量级 Agent 架构教程,核心是 Orchestrator-Worker 模式,强调任务的自动分层拆解和中断恢复能力。
- ADK:Google 开源的 Agent 开发套件,与 Vertex AI、Gemini 生态紧密集成,支持多 Agent 协作、代码执行、企业级可观测性。
简单来说,如果追求快速上手和生态丰富,LangChain 是首选;如果需要复杂流程控制,LangGraph 更合适;如果想研究轻量级编排思想,Deep Agents 值得阅读;如果团队已经使用 Google Cloud 生态,ADK 会更顺手。
1.3 你应该重点看什么
这篇文章的重点不是给你一个非此即彼的结论,而是帮你建立一套选型判断标准。读完你会明白:
- 什么场景用 LangChain 的 Agent 就够,不需要引入 LangGraph。
- 什么场景必须用 LangGraph 的图编排,否则流程会失控。
- Deep Agents 和 LangGraph 在“中断恢复”上有什么本质区别。
- ADK 的“代码执行”和“多 Agent 协作”能力适合什么业务。
2. 环境准备与基础概念
无论你最终选择哪个框架,都需要先准备好 Python 环境和基础依赖。以下是本文示例使用的通用环境,版本信息以我实际测试环境为例,实际情况请以官方最新文档为准。
2.1 Python 环境
建议使用 Python 3.10 及以上版本。如果你同时安装多个框架,遇到依赖冲突的可能性很高,推荐使用虚拟环境隔离。
# 创建虚拟环境 python3 -m venv agent_env # 激活虚拟环境 # Linux/macOS source agent_env/bin/activate # Windows agent_env\Scripts\activate # 升级 pip pip install --upgrade pip2.2 安装框架依赖
| 框架 | 安装命令 | 说明 |
|---|---|---|
| LangChain | pip install langchain langchain-openai | 核心包 + OpenAI 接入 |
| LangGraph | pip install langgraph | 依赖 LangChain 生态 |
| Deep Agents | git clone https://github.com/langchain-ai/deepagents.git | 目前以源码方式使用为主 |
| ADK | pip install google-adk | Google 官方 Agent 开发套件 |
需要说明的是,Deep Agents 虽然发布时提供了pip install deepagents的方式,但它的迭代速度非常快,很多示例代码以仓库内的脚本为准。如果安装遇到问题,优先检查官方 README。
2.3 必须理解的四个通用概念
在对比之前,先把四个框架都会用到的通用概念讲清楚,后面才不会混淆。
模型(Model)
Agent 底层的 LLM 接口,通常包括模型名称、温度、API Key 等参数。LangChain 用ChatOpenAI、ChatAnthropic等封装类;ADK 用LiteLlm等统一接口。
工具(Tool)
Agent 可以调用的外部函数,比如搜索、计算器、数据库查询、HTTP 请求。在 LangChain 生态中,最常用的是@tool装饰器,把普通 Python 函数声明为可被模型调用的工具。
状态(State)
Agent 执行过程中的全局数据集合。包含用户输入、模型输出、工具结果、中间变量等。LangGraph 把 State 定义为 TypedDict,ADK 用 Session 持久化状态。
节点(Node)与边(Edge)
图编排中的概念。节点是执行单元(一个函数或一个子 Agent),边是节点之间的连接关系,条件边则根据当前状态动态决定下一个节点。
3. 核心框架逐个拆解
3.1 LangChain:快速上手的生态全家桶
LangChain 是很多人接触 Agent 开发的第一站。它的核心价值不在于某个单独技术,而在于把模型调用、提示词管理、工具定义、记忆存储、检索增强这些能力统一封装成了可组合的模块。
LangChain AgentExecutor 的典型流程
LangChain 在langchain.agents模块中提供了create_tool_calling_agent和AgentExecutor。整体执行逻辑是:
- 模型接收用户输入和工具列表。
- 模型决定是否调用工具,并返回结构化调用参数。
- AgentExecutor 执行对应工具,将结果追加到消息历史。
- 模型再次接收新消息,继续决策。
- 直到模型不再调用工具,输出最终答案。
我们看一个最简示例。假设我们让 Agent 自己写代码并执行:
# 文件路径:examples/langchain_agent.py import os from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain_core.tools import tool os.environ["OPENAI_API_KEY"] = "your-api-key" @tool def python_interpreter(code: str) -> str: """执行一段 Python 代码并返回结果。""" try: exec_globals = {} exec(code, exec_globals) result = exec_globals.get("result", "执行成功,但未定义 result 变量") return str(result) except Exception as e: return f"执行失败: {e}" model = ChatOpenAI(model="gpt-4o", temperature=0) prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个会使用工具的AI助手。"), ("placeholder", "{messages}"), ("placeholder", "{agent_scratchpad}"), ]) agent = create_tool_calling_agent(model, [python_interpreter], prompt) executor = AgentExecutor(agent=agent, tools=[python_interpreter], verbose=True) response = executor.invoke({ "input": "请计算 23 的阶乘,并返回完整数值。" }) print(response["output"])这段代码里,create_tool_calling_agent是 LangChain 封装好的工具调用型 Agent 创建函数,AgentExecutor负责执行循环。agent_scratchpad是 LangChain 内部维护的中间推理记录,用来在多轮工具调用中保留模型的历史输出。
LangChain 优势在于组件丰富、文档多、社区案例多,大部分主流模型和向量数据库都有现成封装。但它的循环逻辑相对黑盒,一旦遇到复杂分支、人工审批、多 Agent 协作,直接改 AgentExecutor 内部逻辑会非常痛苦。
什么时候选 LangChain
- 目标是快速验证 Agent 能力。
- 流程简单,只有“调用 1-3 个工具”的固定模式。
- 需要用到 LangChain 生态中的文档加载器、向量存储、Embedding 模型。
如果你的 Agent 需要处理复杂分支、循环回溯、状态回滚,建议继续往下看 LangGraph。
3.2 LangGraph:图状态机驱动的生产级编排
LangGraph 的出现,正是为了解决 LangChain AgentExecutor 流程难以精细控制的问题。它的核心思想是:把 Agent 的整体执行过程建模成一张有向图。图节点是“做什么”,图的边是“接下来做什么”,图的状态是“目前已知什么”。
状态、节点、边三个核心抽象
LangGraph 中最基础的概念是StateGraph。我们定义一个“输入问题 -> 分析 -> 决定调用哪个工具 -> 汇总答案”的小型流程:
# 文件路径:examples/langgraph_basic.py import operator from typing import Annotated, TypedDict from langgraph.graph import StateGraph, START, END class AgentState(TypedDict): # 使用 operator.add 实现列表追加合并 messages: Annotated[list, operator.add] current_step: str def node_step1(state: AgentState): # 打印当前状态,方便观察流转 print(f"=== step1: {state['messages'][-1]}") return {"messages": ["step1 已完成"], "current_step": "step2"} def node_step2(state: AgentState): print(f"=== step2: 上一步是 {state['current_step']}") return {"messages": ["step2 已完成"], "current_step": "end"} def should_continue(state: AgentState): # 条件边:根据当前步骤决定下一个节点 if state["current_step"] == "step2": return "step2" return END graph = StateGraph(AgentState) # 添加节点 graph.add_node("step1", node_step1) graph.add_node("step2", node_step2) # 添加边 graph.add_edge(START, "step1") graph.add_conditional_edges("step1", should_continue, {"step2": "step2", "end": END}) graph.add_edge("step2", END) app = graph.compile() result = app.invoke({"messages": ["用户问题:今天天气怎么样?"], "current_step": "start"}) print(result["messages"])这里最关键的是Annotated[list, operator.add]。在 LangGraph 中,State 的每个字段默认是“覆盖”语义,但通过 reducer 可以改成“累加”语义。operator.add会让同一个字段在多个节点返回时自动合并成列表,非常适合保存多轮消息历史。
节点函数接收当前 State,返回一个字典,LangGraph 会把返回值合并进全局 State。
条件路由与循环控制
LangGraph 最强的地方,是它的条件边和循环能力。在传统的 Agent 实现里,循环通常依赖 while 和递归,状态难以追踪。LangGraph 则把循环表达为图的“回边”,每次循环都是一次节点执行,状态变化能被完整记录下来,天然适合回溯和审计。
# 文件路径:examples/langgraph_loop.py from typing import Annotated, TypedDict from operator import add from langgraph.graph import StateGraph, START, END class LoopState(TypedDict): messages: Annotated[list, add] attempt: int def run_again(state: LoopState): # 模拟工具调用,如果 attempt 还小,继续循环 attempt = state["attempt"] + 1 print(f"第 {attempt} 次尝试") return {"attempt": attempt} def route(state: LoopState): if state["attempt"] >= 3: return END return "loop_node" graph = StateGraph(LoopState) graph.add_node("loop_node", run_again) graph.add_edge(START, "loop_node") # 回边:loop_node 执行后可以继续返回 loop_node graph.add_conditional_edges("loop_node", route, {"loop_node": "loop_node", "end": END}) graph.add_edge("loop_node", END) app = graph.compile() app.invoke({"messages": [], "attempt": 0})LangGraph 的循环不是通过 Python 的 while 实现的,而是通过图结构本身实现的。每次调用app.invoke()会启动一次完整的图执行,直到没有边可以继续走为止。这样的好处是,每一步都成为一个可观测、可检查、可持久化的执行单元。
中断、子图与并行分支
LangGraph 支持中断和人工介入,这在真实业务中非常关键。例如审批流中,Agent 在生成结论后暂停,等待人工确认,确认后再继续。LangGraph 的interrupt()机制可以做到这一点。
它同时支持子图,可以把一个复杂的 Agent 拆成多个小图,然后在父图中调用。对于多个独立分支,LangGraph 可以使用SendAPI 实现并行执行,而不会把并发逻辑藏在代码内部。
什么时候选 LangGraph
- 流程存在分支、循环、回退、重试。
- 需要人工审批和中断恢复。
- 需要记录完整执行轨迹供审计和排查。
- 需要多个子 Agent 协作,且协作关系复杂。
如果你读过 LangChain 的官方文档,会发现 LangChain 已经推荐将复杂 Agent 构建在 LangGraph 之上,而不是单独使用AgentExecutor。这是一个重要信号:LangChain 和 LangGraph 不是竞争关系,而是互补关系。
3.3 Deep Agents:轻量级的多层编排范式
Deep Agents 严格来说不是一个“框架”那样的大而全平台,它更像是一个开源项目或一套设计范式。它由 LangChain 团队开源,核心思路是模仿“人类团队协作”:一个 Orchestrator(主编排器)负责理解任务、拆分任务、分发给多个 Worker(工作器),Worker 执行完成后把结果返回给 Orchestrator,由 Orchestrator 汇总输出。
Orchestrator-Worker 模式
Deep Agents 的关键概念包括:
- Orchestrator:负责任务拆解和结果汇总,通常由较强的 LLM 担任。
- Worker:负责执行具体子任务,可以调用工具,也可以是一个子 Agent。
- 中断恢复:当 Worker 需要人工输入或遇到无法自动完成的任务时,会保存当前进展并暂停,等待用户介入。
- 无状态化:每个 Step 都是独立可恢复的执行单元,便于长期运行和故障恢复。
这种模式特别适合长耗时、多阶段、需要动态拆分的任务。比如“调研竞品并生成对比报告”,Orchestrator 会先拆解出“获取竞品列表”“逐个抓取官网信息”“分析功能差异”“生成 Markdown 报告”等子任务,再分配给不同 Worker 并行或串行执行。
Deep Agents 与 LangGraph 的关系
很多新人会混淆 Deep Agents 和 LangGraph。其实 Deep Agents 内部就是基于 LangGraph 实现的。它把 LangGraph 的底层能力封装成了更高层的编排模式。从代码结构来看,Deep Agents 提供了几个核心函数,比如create_deep_agent,内部自动构建了 orchestrator 和 worker 节点的图结构。
我们来看一个使用 Deep Agents 的最小示例,这个示例会构建一个具备代码生成能力的 Agent:
# 文件路径:examples/deep_agents_demo.py import os from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langchain_core.tools.base import BaseTool import asyncio os.environ["OPENAI_API_KEY"] = "your-api-key" # 尝试导入 Deep Agents try: from deepagents import create_deep_agent except ImportError: print("请先安装或克隆 deepagents 仓库") raise @tool def calculator(expression: str) -> str: """计算数学表达式,例如 '2+3*4'。""" try: result = eval(expression) # 注意:生产环境请不要使用 eval return f"计算结果: {result}" except Exception as e: return f"计算失败: {e}" async def main(): model = ChatOpenAI(model="gpt-4o", temperature=0) agent = await create_deep_agent( model=model, tools=[calculator], system_prompt="你是一个擅长复杂任务拆解的助手。当任务需要多步骤完成时,请合理拆分子任务。", ) result = await agent.ainvoke( {"request": "请计算 (12345 * 6789) + 100,然后用中文解释计算过程。"} ) print(result["output"]) if __name__ == "__main__": asyncio.run(main())需要注意的是,Deep Agents 的 API 还在快速演进中,不同 commit 版本的create_deep_agent接口可能有差异。上面的例子只是一个参考思路,实际使用时以官方仓库的 README 为准。
什么时候选 Deep Agents
- 你的 Agent 任务天然适合“总-分-总”的层级结构。
- 你希望快速拥有任务拆解和工具调用能力,但不想手写过多图编排代码。
- 你想学习业界先进的 Agent 编排思想,而非直接上生产。
Deep Agents 的问题是,它封装度高,定制灵活度不如直接用 LangGraph。如果你需要高度自定义的流程,可能还是需要回到 LangGraph。
3.4 ADK:面向 Google Cloud 生态的 Agent 开发套件
ADK 全称 Agent Development Kit,是 Google 在 2025 年开源的 Agent 框架。它和前面几个框架最大的不同在于,它与 Google Cloud 和 Gemini 生态深度绑定,同时在设计上更强调企业级能力和多 Agent 协作。
ADK 的核心设计
ADK 的核心概念包括:
- Agent:可以被赋予 name、instruction、tools。
- Tool:可以是 Python 函数、OpenAPI 规范,也可以是 Google 预置的搜索、代码执行工具。
- Session:持久化 Agent 运行状态,支持对话历史和中间变量的存储与恢复。
- Runner:负责执行 Agent,支持流式输出和人工介入。
- Multi-Agent:允许一个 Agent 调用另一个子 Agent,形成层级协作。
ADK 的代码风格和 LangChain 很不一样。它更接近 Google 生态的 TypedDict 与 function calling 风格。看一个简单的搜索型 Agent 示例:
# 文件路径:examples/adk_demo.py import asyncio from google.adk.agents import Agent from google.adk.tools import FunctionTool from google.adk.runners import Runner def search_web(query: str) -> str: """模拟搜索工具,返回固定结果。实际项目请接入搜索API。""" return f"搜索『{query}』的模拟结果" async def main(): agent = Agent( name="assistant", instruction="你是一个有用的助手,请调用工具回答问题。", tools=[FunctionTool(func=search_web)], model="gemini-2.0-flash", ) runner = Runner(agent=agent, app_name="demo_app") result = await runner.run_async( user_id="user_001", session_id="session_001", message="帮我搜索一下 LangGraph 的最新版本。", ) print(result.messages[-1].content) if __name__ == "__main__": asyncio.run(main())留意上面的代码,Runner需要指定user_id和session_id,这说明 ADK 特别重视会话持久化和多用户场景。它天然面向生产,因此 Session 管理、上下文隔离和可观测性都是内置能力。
ADK 的代码执行与多 Agent 协作
ADK 支持在沙箱环境中执行代码。对于数据分析、代码生成类任务,这一能力非常实用。官方提供code_executor工具,可以运行 Python 代码并捕获输出。
多 Agent 协作方面,ADK 允许子 Agent 作为主 Agent 的工具被调用。这与 LangGraph 的“节点内嵌子图”思路类似,但 ADK 的封装方式更偏声明式,你只需要在tools列表中传入子 Agent 实例。
什么时候选 ADK
- 你的业务已经使用 Google Cloud、Vertex AI 或 Gemini 模型。
- 需要企业级会话管理和多租户隔离。
- 需要 OpenAPI 工具接入,希望省去手动封装 HTTP 请求的步骤。
- 团队更偏好 Google 官方工具链。
ADK 的局限也很明显:国内开发者接入 Google Cloud 生态存在一定门槛,且社区规模和文档丰富程度目前仍不如 LangChain/LangGraph。如果你没有 Google 生态绑定需求,选型优先级可以往后放。
4. 框架横向深度对比
4.1 对比维度与表格
| 对比维度 | LangChain | LangGraph | Deep Agents | ADK |
|---|---|---|---|---|
| 定位 | 生态工具集 | 图状态编排框架 | 编排范式/轻量框架 | Google 云原生 Agent 框架 |
| 核心抽象 | Agent/Chain/Tool | StateGraph/Node/Edge | Orchestrator/Worker | Agent/Session/Runner |
| 流程控制 | 较弱,固定循环 | 强,支持分支、循环、回退 | 强,内置任务拆解 | 强,支持多 Agent 层级协作 |
| 状态管理 | 消息历史为主 | 自定义 State,支持 reducer | 基于 LangGraph State | Session 持久化 |
| 中断恢复 | 不支持 | 支持 interrupt() | 支持 | 支持 |
| 子图/子 Agent | 通过工具间接实现 | 原生支持子图 | 原生支持 Worker | 原生支持子 Agent |
| 并行分支 | 需自己实现 | 支持 Send API | 部分支持 | 部分支持 |
| 生态丰富度 | 极高 | 高 | 中 | 中 |
| 学习曲线 | 平缓 | 较陡 | 中等 | 中等 |
| 生产可观测性 | 需要自己集成 | 内置逐步追踪 | 基于 LangGraph | 内置 OpenTelemetry |
| 与云厂商绑定 | 无 | 无 | 无 | Google Cloud |
4.2 从“LangChain 是否过时”看你该怎么选
网上经常能看到“LangChain 过时了吗”这类讨论。我的观点是:LangChain 并没有过时,它的组件库仍然很有价值,但作为 Agent 执行框架,确实在向 LangGraph 迁移。你可以这样理解:
- LangChain 的 Chain 和 AgentExecutor 是“入门级编排”。
- LangGraph 是“生产级编排”。
- LangChain 中非编排的模块,比如文档加载器、Embedding 封装、模型调用统一接口,仍然可以继续使用。
所以在 2025 年的实践中,推荐组合是:“LangChain 组件层 + LangGraph 编排层”。Deep Agents 则是在这个组合之上的一套更高层模式。
4.3 关于框架安全边界的提醒
无论选哪个框架,都必须注意一个问题:Agent 可以自主调用工具。工具一旦能执行代码、写文件、调用网络 API,就相当于把一把万能钥匙交给了模型。在开发阶段建议:
- 工具函数中严格校验输入。
- 调用数据库、文件系统、外部 API 时使用最小权限账号。
- 执行代码的工具(如 Python Interpreter)必须在 Docker 沙箱或受限环境中运行。
- 对模型可以调用的工具列表做白名单,而不是给全量工具。
- 记录工具调用的完整日志,方便事后审计。
5. 实战:用 LangGraph 实现一个可中断的编排 Agent
这一节我们做一个更贴近真实业务的综合示例。需求如下:
用户输入一个产品需求,Agent 需要经过“需求解析 -> 技术方案设计 -> 代码生成 -> 人工确认 -> 输出结果”五个阶段。其中“人工确认”阶段使用中断机制,等待用户批准后才继续输出。
这个示例会用到 LangGraph 的节点、条件边、中断和状态管理。代码可以在本地直接运行,只需要把 API Key 替换成你自己的。
5.1 创建项目结构
agent_demo/ ├── agent/ │ ├── __init__.py │ ├── state.py │ ├── nodes.py │ ├── graph.py │ └── tools.py ├── main.py └── requirements.txt5.2 定义状态
# 文件路径:agent_demo/agent/state.py from typing import Annotated, TypedDict from operator import add class AgentState(TypedDict): user_request: str # 用户原始输入 analysis: str # 需求解析结果 design: str # 技术方案 generated_code: str # 生成的代码 review_result: str # 人工审批结果 messages: Annotated[list, add] # 逐步日志5.3 定义节点
# 文件路径:agent_demo/agent/nodes.py import time def analyze_request(state: AgentState): """节点1:解析需求。实际项目可以调用 LLM,这里使用规则模拟。""" request = state["user_request"] analysis = f"已解析需求: {request}。识别到核心模块: 用户模块、数据处理模块。" print(f"[节点1] {analysis}") return {"analysis": analysis, "messages": ["完成需求解析"]} def design_solution(state: AgentState): """节点2:生成技术方案。""" analysis = state["analysis"] design = f"基于{analysis},建议采用分层架构,使用 FastAPI + React。" print(f"[节点2] {design}") return {"design": design, "messages": ["完成方案设计"]} def generate_code(state: AgentState): """节点3:生成代码。实际项目应调用 LLM 生成,这里给一个示例片段。""" design = state["design"] code = f'# 根据设计生成代码\n# {design}\nprint("hello agent")' print(f"[节点3] 生成代码片段: {code}") return {"generated_code": code, "messages": ["完成代码生成"]} def review_node(state: AgentState): """节点5:人工审批后需要执行的节点。""" code = state["generated_code"] review_result = f"人工审批通过,代码已发布: {code}" print(f"[节点5] {review_result}") return {"review_result": review_result, "messages": ["审批通过,输出结果"]}5.4 构建图并加入中断
# 文件路径:agent_demo/agent/graph.py from langgraph.graph import StateGraph, START, END from langgraph.types import interrupt from agent.state import AgentState from agent.nodes import ( analyze_request, design_solution, generate_code, review_node, ) def human_approval(state: AgentState): """节点4:中断等待人工审批。""" print("=== 即将进入人工审批环节 ===") # interrupt 会暂停图执行,并返回一个待处理问题 decision = interrupt({ "question": "是否批准生成的代码?", "generated_code": state["generated_code"], }) # 恢复执行时,decision 为用户传入的值 return {"messages": [f"人工审批结果: {decision}"]} def should_finish(state: AgentState): """条件判断:是否继续执行最终节点。""" # 恢复执行时,我们从最新消息获取审批结果 last_message = state["messages"][-1] if state["messages"] else "" print(f"=== 判断审批结果: {last_message} ===") if "同意" in str(last_message) or True: return "finish" return "finish" # 简化示例,无论结果如何都进入收尾 def build_graph(): graph = StateGraph(AgentState) # 注册节点 graph.add_node("analyze", analyze_request) graph.add_node("design", design_solution) graph.add_node("generate", generate_code) graph.add_node("approval", human_approval) graph.add_node("finish", review_node) # 顺序连接 graph.add_edge(START, "analyze") graph.add_edge("analyze", "design") graph.add_edge("design", "generate") graph.add_edge("generate", "approval") graph.add_conditional_edges("approval", should_finish, {"finish": "finish"}) graph.add_edge("finish", END) return graph.compile()5.5 运行与恢复中断
# 文件路径:agent_demo/main.py from agent.graph import build_graph app = build_graph() # 第一次执行:在审批环节中断 config = {"configurable": {"thread_id": "demo_thread_001"}} state = app.invoke( {"user_request": "开发一个用户登录功能", "messages": []}, config=config, ) print("=== 图执行中断,当前等待人工审批 ===") # 恢复执行:传入人工审批结果 updated_state = app.invoke( interrupt_value="同意发布", config=config, ) print("=== 最终输出 ===") print(updated_state["messages"])这是一个典型的“人机协同 Agent”模式。生产环境中,可以把thread_id绑定到数据库记录,在 Web 后端保存中断状态,等人工点击“通过/拒绝”按钮后,再调用app.invoke(interrupt_value=...)恢复执行。
5.6 这个案例对你的业务有什么启发
从上面的代码可以看到,LangGraph 的 Agent 并不是一个只靠一次模型调用就能完成的“智能对话框”,而是一个可以暂停、等待、恢复、审计的执行系统。这对于需要把 Agent 接入真实业务审批流的团队来说,价值非常大。
Deep Agents 也支持类似的中断恢复,它的设计思路是把“长期运行的多步 Agent”做得更自动化。如果你主要是想快速获得深度的任务拆解能力,可以结合 Deep Agents 的文档,把上面示例中的节点替换为真实的 LLM 调用。
6. 常见问题与排查思路
6.1 常见问题汇总
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
langgraph安装后无法导入 | 依赖冲突或 Python 版本过低 | 升级到 Python 3.10+,使用虚拟环境重新安装 |
| 图执行时 State 字段没有更新 | 没有通过 return 字典返回新值 | 节点函数必须返回包含字段更新的字典 |
| 并行分支无法同时执行 | 使用普通add_edge而非SendAPI | 在 LangGraph 中使用Send实现并行执行 |
| interrupt 后无法恢复 | 没有保存或传入相同的thread_id | 恢复时使用与中断时相同的config |
| Deep Agents 接口报错 | 版本迭代导致 API 变化 | 切换到官方仓库的最新代码,按 README 调用 |
| ADK Runner 找不到 Session | session_id或user_id未传入 | 确保每次run_async都传入完整标识 |
| LangChain Agent 循环次数过多 | 工具返回内容过长或错误一直重试 | 在 AgentExecutor 中设置max_iterations |
| 模型返回非法 JSON 工具参数 | 模型输出不稳定 | 启用结构化输出或 function calling 模式 |
6.2 排查清单
如果你遇到了 Agent 行为不符合预期的问题,可以按下面顺序排查:
- 先确认模型消费:查看 API 调用日志,确认模型到底生成了哪些内容。
- 再确认工具调用:确认工具是否被正确触发,输入参数是否符合预期。
- 检查状态变化:在 LangGraph 中打印每个节点的 state,看状态是否正确流转。
- 检查中断点:如果流程卡住,确认中断点的
thread_id是否一致。 - 检查工具异常:工具内部 try-except 是否吞掉了异常,导致模型拿到的结果不准确。
- 检查提示词:有时候模型不调用工具,是因为提示词中工具说明不够清晰。
6.3 如何避免常见的框架误用
- 不要用 LangChain 的 AgentExecutor 强行实现复杂状态机,应该换 LangGraph。
- 不要把 LangGraph 当普通函数调用链,要理解 State 的合并规则。
- 不要在生产环境直接运行 “执行任意代码” 的工具,必须沙箱化。
- 不要在多 Agent 协作中把所有逻辑写在一个 Agent 里,要拆分子 Agent。
7. 最佳实践与工程建议
7.1 框架选型决策路径
根据上面的分析,我整理了一个简单的决策路径,你可以直接用来指导选型:
- 如果项目需要快速原型验证、工具简单、流程固定:选 LangChain。
- 如果项目包含复杂流程、分支循环、人工审批、需要可观测性:选 LangGraph。
- 如果任务天然是“总-分-总”结构,希望快速获得任务拆解能力:选 Deep Agents。
- 如果项目在 Google Cloud 生态内,或需要企业级会话管理:选 ADK。
- 如果以上需求混合存在,优先考虑 LangGraph + LangChain 组合,再根据团队能力决定是否采用 Deep Agents 模式。
7.2 代码组织与状态管理
生产项目中,Agent 代码不应该散落在 Notebook 或脚本里。建议按以下方式组织:
src/ ├── agents/ │ ├── __init__.py │ ├── base_agent.py │ ├── graph_builder.py │ └── nodes/ │ ├── planner.py │ ├── executor.py │ └── reviewer.py ├── tools/ │ ├── search.py │ ├── http_client.py │ └── db_client.py ├── state/ │ └── schemas.py ├── services/ │ └── agent_runner.py └── config/ └── settings.py状态管理方面,建议把 Agent 的 State 字段划分为三类:
- 输入字段:用户原始请求,只读。
- 中间字段:各节点产生的分析结果,只追加不改写。
- 输出字段:最终交付内容。
这样可以避免节点之间互相覆盖,也方便回溯。
7.3 可观测性与可维护性
Agent 应用最大的风险是“黑盒”。模型调了哪个工具、为什么调、工具返回了什么东西、状态怎么流转的,都需要记录下来。具体做法:
- 每个节点开始和结束时打印状态摘要。
- 记录模型 API 调用日志,包括输入输出 token 数。
- 记录工具调用日志,包括参数和返回结果。
- 使用 LangGraph 的
get_state和update_stateAPI 检查状态。 - ADK 场景下使用 OpenTelemetry 导出指标。
7.4 安全与合规边界
再强调一次安全边界。Agent 一旦接入生产环境,相当于一个“能自主操作电脑的员工”。请务必做到:
- 不向模型暴露生产数据库的高权限账号。
- 不把 API Key 写在代码仓库里,使用环境变量或密钥管理服务。
- 工具调用前做参数校验。
- 涉及外部 API 调用时,设置超时和重试上限。
- 对 Agent 生成的内容做敏感信息脱敏。
- 在测试环境充分验证后再发布到生产。
7.5 性能优化与成本控制
Agent 项目的成本,主要来自模型 API 调用。控制成本的手段包括:
- 设置
max_iterations和recursion_limit,防止无限循环。 - 在节点中缓存稳定的工具结果。
- 尽量使用结构化输出,减少无效生成。
- 对长流程使用“先规划后执行”模式,避免反复重新理解任务。
- 使用流式输出,让用户早点看到进度。
8. 总结与下一步学习方向
这篇文章从四个主流 Agent 框架的定位讲起,拆解了 LangChain、LangGraph、Deep Agents、ADK 的核心设计和适用场景,并通过横向对比帮你建立了一套选型判断路径。同时给出了一个完整的 LangGraph 中断式 Agent 示例,覆盖状态定义、节点编写、图构建、中断恢复和运行验证。
如果你还在犹豫从哪里开始,我的建议是:不要一次学完四个框架,先选一个最容易上手的去跑通一个完整案例。入门阶段推荐先学 LangChain,理解模型调用、工具定义和消息传递;然后学 LangGraph,掌握 StateGraph、节点、条件边和中断机制;有精力再研究 Deep Agents 的编排思想;最后在实际业务需要时接触 ADK。
下一步可以继续深入的方向包括:LangGraph 的条件边与子图高级用法、Deep Agents 的 Orchestrator-Worker 模式源码解析、ADK 的多 Agent 协作与代码执行、Agent 记忆机制的设计、AI Agent 在业务中的安全和评测方案。
如果这篇文章对你有帮助,欢迎收藏备用。如果你在选型或实现过程中遇到其他问题,也欢迎在评论区留言,我会优先解答大家问得最多的问题。