如果你是一名 Java / Python 后端开发,或者正在做 AI 应用落地,最近应该已经明显感受到一个趋势:AI Agent 已经不是概念热词,而是正在进入生产环境的开发范式。从对话机器人到自动化运维、从代码生成到企业知识库问答,底层的编排框架正在从前期的“一切靠 LangChain 拼装”转向“用 LangGraph 控制流程状态”。
但很多人学到这里会卡住。
我看到了太多类似的问题:
- 学完 LangChain 的基础链式调用,但一碰真实业务就不知道怎么扩展;
- 只会在 Jupyter Notebook 里跑 demo,不知道如何设计一个多步骤、有状态、可维护的 Agent 工作流;
- 搞不清楚 LangChain 和 LangGraph 到底是什么关系,是不是学了新的就要推倒旧的;
- 想参考“企业级 Agent”的课程,结果看完整套视频还是只会照抄代码,遇到报错就无从下手。
这篇文章就是想解决这些问题。我会结合 LangChain + LangGraph 的完整学习路径,把“从 0 基础到企业级 Agent 实战”这条路线拆开讲清楚:概念是什么、环境怎么搭、第一个 Agent 怎么写、状态如何管理、工具如何接入、常见的坑在哪里。
读完你可以得到三样东西:
- 一条清晰的学习路线,知道先学什么后学什么;
- 一套可以直接运行的 LangGraph Agent 示例代码;
- 一份关于工程落地的避坑清单和最佳实践。
如果你正准备系统学习 Agent 开发,或者想把手里的 LangChain 项目升级为真正的 Agent 架构,这篇文章值得收藏。
1. 这篇文章真正要解决的问题
先泼一盆冷水。很多人对 LangChain 有误解:以为它是“AI 全能框架”,装上之后就能自动变成 Agent。实际上,LangChain 更像是一个“积木箱”,里面有模型封装、Prompt 管理、文档加载、检索器、工具等部件;而 LangGraph 则是“流水线”本身,帮你把这些积木组装成可控的、有状态的工作流。
这两者结合起来,才是真正的 Agent 开发主线。
那么在学 LangChain + LangGraph 的过程中,最常见的痛点是什么?
1.1 痛点一:学完基础不会实战
大部分入门教程只教你调一遍Chain或AgentExecutor。这个能让你理解概念,但一旦真实业务需要以下能力,就懵了:
- 多步骤任务,步骤之间有依赖关系;
- 某个步骤失败之后要重试或走降级分支;
- 需要让模型“边执行边更新状态”,而不是一次生成完;
- 需要接入企业内部工具或 API,并控制权限与审计。
这些都不是简单的链式调用能覆盖的,需要图状态、条件路由、持久化和循环能力。
1.2 痛点二:分不清 LangChain 与 LangGraph
很多同学在学习的时候会问:既然有了 LangChain,为什么还要 LangGraph?我是不是只需要学一个就够了?
要分清这两个东西,有一个很朴素的理解方式:
- LangChain提供的是“零件”:模型封装、Prompt 模板、输出解析器、RAG 工具链、上层集成。
- LangGraph提供的是“装配图纸和流水线”:你定义状态、节点、边,LangGraph 负责按照图结构执行,支持循环、分支、断点、持久化。
在企业级场景中,前者管“怎么和模型/工具交互”,后者管“整个任务怎么走到结束”。
1.3 痛点三:缺乏企业级工程视角
能跑通 demo 和能上生产之间,差着一整套工程能力:记忆如何管理、Agent 如何持久化、如何接入已有系统、如何做权限控制、如何手工干预流程、如何记录与追溯。
一个合格的 Agent 开发课程或实战项目,不应该只是教“调用 LLM”,它还必须覆盖:工作流设计、状态管理、工具设计、错误处理、可观测性,以及和现有业务系统的集成方式。
1.4 什么人适合读这篇文章
如果你是下面这几类读者,这篇文章会很合适:
- 已经用过 LangChain,但想再进一步学习 LangGraph,并搞清楚二者的合理分工;
- 想从零开始学习 Agent 开发,但不想只是复制文档样例,而是想理解设计思路;
- 准备做企业内部的自动化 Agent 项目,正在寻找一个可以落地的技术选型;
- 已经买了或准备买一套 LangChain + LangGraph 视频课程,希望有一个配套的“路线图”来帮你更快消化。
需要说明的是,本文不会逐帧讲解课程视频,而是提取出这套课程背后真正值得学的核心技术骨架,并附带可运行代码和排查指南。
2. LangChain 与 LangGraph 的核心概念与关系
在动手写代码之前,先把概念建立起来。
2.1 LangChain 到底是干什么的
LangChain 的目标,是让开发者能够用统一的方式接入大语言模型,并组装出“模型 + 工具 + 数据”的应用。
它的核心能力包括:
- 统一的 Model I/O 接口:无论是 OpenAI、Claude 还是国产模型,都可以通过一个封装好的接口调用;
- Prompt 模板管理:把用户输入、系统提示词、历史对话组合起来;
- 输出解析器:把模型的文本输出解析成结构化对象;
- RAG 工具链:文档加载、切分、向量化、检索、重排;
- 工具与 Agent 组件:让模型能够调用外部 API 或函数。
简单说,LangChain 解决的是“让模型更好用、更可控、更容易连接外部世界”的问题。
2.2 LangGraph 解决的是什么
LangGraph 的核心思想是:把 Agent 看作一张有状态的计算图。
你已经写过有限的链式代码,比如:
retriever -> prompt -> model -> output parser这在简单场景里没问题,但真实 Agent 会反复执行这样的过程:
模型判断 -> 决定调用工具 -> 执行工具 -> 把结果交还模型 -> 模型再判断 -> 是继续调用还是输出最终答案?这是一个循环,LangChain 的Chain模型很难优雅地表达这种循环。LangGraph 正好解决了这个问题。它允许你定义:
- 节点:一个函数或一个 Chain,负责处理一个逻辑步骤;
- 边:节点之间的连接,表示执行顺序;
- 条件边:根据当前状态决定下一步走向哪个节点;
- 状态:一个在整个图执行过程中不断更新的对象,保存消息、临时变量、中间结果;
- 持久化:每一步执行后保存状态,支持断点续跑或人工介入。
2.3 两者的分工配合
可以这样理解:
| 维度 | LangChain | LangGraph |
|---|---|---|
| 定位 | 模型封装与应用组件库 | Agent 流程编排框架 |
| 核心抽象 | Chain / Tool / Retriever | StateGraph / State / Node / Edge |
| 擅长 | 单步模型调用、RAG、工具接入 | 多步骤、循环、分支、状态管理 |
| 执行模式 | 静态顺序或简单决策 | 有条件路由、循环、可暂停 |
| 生产能力 | 需要额外组装 | 原生支持持久化与断点 |
在实际开发中,你不会只用 LangChain 或只用 LangGraph,而是把两者结合起来:
LangChain 负责模型调用和工具封装 LangGraph 负责流程编排和状态管理这也是 LangChain 官方推荐的演进路线:当你开始做复杂 Agent 的时候,把流程层迁移到 LangGraph,而模型调用、RAG、工具接入这些,仍然可以继续用 LangChain 体系。
2.4 Agent 的核心机制
不管是 LangChain 还是 LangGraph,Agent 背后的核心机制都差不多:
- 思考(Plan):模型根据用户目标,规划下一步动作;
- 调用(Act):选择一个工具并传入参数;
- 观察(Observe):把工具执行结果返回给模型;
- 循环(Repeat):直到模型判断任务完成,输出最终结果。
很多新手学 Agent 会犯的第一个错误是:以为 Agent 是一套“模型内置能力”,实际上它是“编排代码 + 模型决策 + 工具执行”三者配合的结果。
LangGraph 的优势,在于它把这种循环显式建模成了图结构,让你能清楚地看到每一步的输入输出,方便调试、监控和干预。
3. 环境准备与前置条件
接下来进入实操。先把环境准备好。
3.1 运行环境要求
- 操作系统:Windows / macOS / Linux 均可;
- Python:建议 3.10 或以上版本;
- 包管理器:pip 或 uv;
- 模型 API Key:你至少需要一个可用的 LLM 服务商 API Key。
需要说明的是,不同课程、不同教程使用的 LangChain / LangGraph 版本可能差别很大。版本请以你实际安装的为准,本文重点演示的是通用思路。
3.2 安装 LangChain 与 LangGraph
建议创建独立虚拟环境。
python -m venv .venv source .venv/bin/activate # Windows 下使用 .venv\Scripts\activate然后安装核心依赖。这里的安装策略是:不一次性安装全家桶,而是按需安装,避免版本冲突。
pip install langgraph langchain langchain-openai python-dotenv如果后续要用到 RAG 场景,再自行追加安装向量库和文档加载相关的包,比如:
pip install langchain-community langchain-text-splitters3.3 配置模型访问
在项目根目录新建.env文件:
OPENAI_API_KEY=你的key OPENAI_BASE_URL=你的代理地址(如果服务商有)然后在代码里加载:
from dotenv import load_dotenv load_dotenv()如果你不是使用 OpenAI,而是使用国产模型或企业内部模型,LangChain 提供了大量模型封装,例如智谱、通义、百炼、DeepSeek 等,都可以在langchain社区包中查找。核心思路是一样的:把模型封装成 LangChain 的BaseChatModel对象。
3.4 验证环境
跑一个最小模型调用,确认环境和网络都通:
from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o-mini") response = llm.invoke("请用一句话说明 LangGraph 是什么") print(response.content)如果你能看到输出,说明环境就绪。
如果这里报网络错误、认证错误或模型不存在,先不要继续向下写代码,而是先修改模型配置或网络请求方式。这一步是最常见的“第一次卡顿点”。
4. 核心流程拆解:从 Chain 到 Graph
学习 LangGraph 的时候,最容易踩的心理误区是:觉得“图”很高深。其实你只需要抓住 5 个东西:状态、节点、边、编译、运行。
4.1 状态
状态是 LangGraph 的灵魂。它就像一个在图中传递的“共享画板”,所有节点都可以读取它、更新它。
状态的类型通常是TypedDict或者dataclass。最简单的状态只需要一个字段:消息列表。
from typing import TypedDict, Annotated from langgraph.graph.message import add_messages class AgentState(TypedDict): messages: Annotated[list, add_messages]这里的关键是Annotated[list, add_messages]。这表示:当多个节点都向messages字段写入内容时,不是替换,而是合并追加。
4.2 节点
节点就是普通的 Python 函数。它的输入是当前状态,输出是一个字典,字典里的 key 就是要更新的状态字段。
def chat_node(state: AgentState): response = llm.invoke(state["messages"]) return {"messages": response}4.3 边
边有两种:
add_edge:固定边,一个节点执行完,必然去下一个节点;add_conditional_edges:条件边,根据当前状态动态决定下一步。
4.4 编译
节点和边定义好之后,会得到一个StateGraph对象,调用.compile()就可以得到一个可执行对象。这个对象可以被invoke,也可以被后续的 Agent 作为工具调用。
graph = graph_builder.compile()4.5 运行
result = graph.invoke({"messages": [{"role": "user", "content": "你好"}]})这样,你就完成了一个最基本的 LangGraph 应用。
4.6 初始流程拆解
从学习路线上看,建议按这个顺序推进:
- 先写一个不带循环、仅包含固定边的 Graph;
- 再加入条件边,让工作流具备“判断”能力;
- 再接入工具调用,形成真正的 Agent 循环;
- 最后加入持久化、人工审批、多 Agent 协作。
很多课程会跳过第 2 步直接讲工具循环,这是看起来热闹但容易学完就忘的主要原因。建议你花时间把每一步都跑通。
5. 完整示例:用 LangGraph 构建一个带工具的 Agent
下面用三个递进的完整代码示例,展示如何用 LangGraph 编写 Agent。
5.1 示例一:最小可运行的 LangGraph 流程
先来一个最小示例,帮助你理解“节点 + 边 + 状态”的运行机制。
文件路径:examples/minimal_graph.py
from typing import TypedDict, Annotated from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o-mini") class AgentState(TypedDict): messages: Annotated[list, add_messages] def chat_node(state: AgentState): response = llm.invoke(state["messages"]) return {"messages": response} graph_builder = StateGraph(AgentState) graph_builder.add_node("chat", chat_node) graph_builder.add_edge(START, "chat") graph_builder.add_edge("chat", END) graph = graph_builder.compile() def main(): result = graph.invoke({"messages": [{"role": "user", "content": "你好,请自我介绍一下"}]}) print(result["messages"]) if __name__ == "__main__": main()这个示例里发生了什么?
StateGraph(AgentState)创建了一个图,图的类型是AgentState;add_node("chat", chat_node)注册了一个节点;add_edge(START, "chat")表示从起点进入chat节点;add_edge("chat", END)表示执行完chat后结束;compile()编译成可执行对象。
运行方式:
python examples/minimal_graph.py预期结果是控制台打印出模型回复的消息对象。
这个例子里还没有循环,也没有工具调用,但它能帮助你建立“图”的心智模型。
5.2 示例二:带工具调用的 Agent
接下来是真正意义上的 Agent:模型可以决定调用工具,工具结果会交还给模型,直到模型认为不需要再调用工具。
为了简化演示,我实现一个“获取当前时间”工具和一个“计算器”工具。
文件路径:examples/agent_with_tools.py
import datetime from typing import TypedDict, Annotated from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langgraph.prebuilt import ToolNode, tools_condition from langchain_openai import ChatOpenAI from langchain_core.tools import tool @tool def current_time(): """获取当前北京时间,并以字符串返回。""" return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") @tool def add_numbers(a: float, b: float) -> float: """两个数字相加。""" return a + b tools = [current_time, add_numbers] llm = ChatOpenAI(model="gpt-4o-mini") llm_with_tools = llm.bind_tools(tools) class AgentState(TypedDict): messages: Annotated[list, add_messages] def agent_node(state: AgentState): response = llm_with_tools.invoke(state["messages"]) return {"messages": response} graph_builder = StateGraph(AgentState) graph_builder.add_node("agent", agent_node) graph_builder.add_node("tools", ToolNode(tools)) graph_builder.add_edge(START, "agent") graph_builder.add_conditional_edges("agent", tools_condition) graph_builder.add_edge("tools", "agent") graph = graph_builder.compile() def main(): result = graph.invoke({"messages": [{"role": "user", "content": "现在是几点?顺便计算一下 123 + 456 等于多少?"}]}) for message in result["messages"]: print(f"{message.__class__.__name__}: {message.content}") if __name__ == "__main__": main()这段代码里值得重点理解的是:
@tool装饰器把一个普通 Python 函数变成了工具;llm.bind_tools(tools)让模型具备“知道有哪些工具可用”的能力;ToolNode(tools)是 LangGraph 预置的“工具执行节点”;tools_condition是预置的条件函数:如果模型输出的消息里带有tool_calls,就路由到tools节点;否则路由到END。
这个图的结构就是:
START -> agent -> tools -> agent -> ... -> 直到模型不再调用工具,然后到 END这是最经典的单 Agent 循环架构。
如果你运行失败,大部分情况是因为版本不匹配。新版本的 LangGraph 建议优先使用langgraph.prebuilt中的ToolNode和tools_condition,而不要自己手写工具调用解析逻辑。
5.3 示例三:加入记忆与持久化
企业级 Agent 和 demo 的一个明显区别是:Agent 需要“记住”对话历史。LangGraph 提供了持久化机制,可以让每个会话的消息状态保存下来。
文件路径:examples/agent_with_memory.py
from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langgraph.prebuilt import ToolNode, tools_condition from langchain_openai import ChatOpenAI from langchain_core.tools import tool from typing import TypedDict, Annotated @tool def current_time(): """获取当前北京时间,并以字符串返回。""" import datetime return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") tools = [current_time] llm = ChatOpenAI(model="gpt-4o-mini").bind_tools(tools) class AgentState(TypedDict): messages: Annotated[list, add_messages] def agent_node(state: AgentState): response = llm.invoke(state["messages"]) return {"messages": response} graph_builder = StateGraph(AgentState) graph_builder.add_node("agent", agent_node) graph_builder.add_node("tools", ToolNode(tools)) graph_builder.add_edge(START, "agent") graph_builder.add_conditional_edges("agent", tools_condition) graph_builder.add_edge("tools", "agent") # MemorySaver 是内存检查点,生产环境可以替换为数据库实现 memory = MemorySaver() graph = graph_builder.compile(checkpointer=memory) CONFIG = {"configurable": {"thread_id": "user-session-001"}} def main(): # 第一轮对话 result1 = graph.invoke( {"messages": [{"role": "user", "content": "我的名字是张三,请记住"}]}, config=CONFIG, ) print(result1["messages"][-1].content) # 第二轮对话 result2 = graph.invoke( {"messages": [{"role": "user", "content": "我叫什么名字?"}]}, config=CONFIG, ) print(result2["messages"][-1].content) if __name__ == "__main__": main()重点是.compile(checkpointer=memory)和thread_id。
checkpointer负责在每一步执行后保存状态;thread_id是会话标识。同一个thread_id下的多轮调用会共享同一个状态。
运行这个示例,你会看到:第二轮 Agent 知道用户叫张三。
如果你希望持久化到数据库,而不是内存,可以自己实现或使用 LangGraph 提供的 Postgres 等 Checkpoint 后端。企业级项目通常不会使用内存方案。
6. 运行结果与效果验证
6.1 怎么运行
项目目录结构建议如下:
agent-demo/ ├── .env ├── examples/ │ ├── minimal_graph.py │ ├── agent_with_tools.py │ └── agent_with_memory.py └── requirements.txt依次运行:
python examples/minimal_graph.py python examples/agent_with_tools.py python examples/agent_with_memory.py6.2 预期输出
示例二的预期结果是:控制台打印出多轮消息记录,包括一次AIMessage中包含工具调用指令,然后是一条ToolMessage包含工具结果,最后是一条AIMessage汇总答案。
类似这种顺序(具体输出取决于模型):
AIMessage: content='' tool_calls=[{'function': {'name': 'current_time', 'arguments': '{}'}}] ToolMessage: content='2025-01-18 14:30:00' AIMessage: content='现在是 2025年01月18日 14点30分。'如果最终AIMessage.content非空,说明 Agent 完成了任务。
6.3 如何判断成功
判断标准不是“它没有报错”,而是这三点同时满足:
- 工具被实际调用;
- 工具结果成功注入模型上下文;
- 模型最终输出自然语言答案。
如果没有满足第 1 条,很可能是模型绑定的工具格式不匹配或提示词没写清楚;如果没有满足第 2 条,检查是否使用了正确的ToolNode;如果没有满足第 3 条,可以检查模型是否有足够的上下文推理能力。
6.4 运行失败先看哪里
运行失败不要急着改代码,按以下顺序排查:
- 看 API Key 是否能正常调用模型;
- 看模型名是否存在于服务商的模型列表;
- 看 LangChain / LangGraph 版本是否匹配;
- 看日志中是否有
tool_calls相关报错; - 看
MemorySaver是否在多个线程上混用。
7. LangGraph 常见问题与排查思路
下面是 LangChain + LangGraph 开发中最高频的问题整理。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
pip install langgraph报依赖冲突 | Python 版本过低或与 LangChain 版本不匹配 | 查看错误日志中的依赖冲突要求 | 升级到 Python 3.10+,在干净的虚拟环境中重装 |
| 模型调用报 401 / 403 | API Key 未加载或服务商拒绝访问 | 先打印.env中的 Key 是否存在,再确认服务商后台是否开通模型权限 | 正确配置环境变量和模型服务商权限 |
模型返回没有tool_calls | 模型不支持 function calling 或提示词未明确 | 改用一个支持工具调用的模型,检查bind_tools是否正确 | 替换模型,或检查是否传入了正确的工具 schema |
ToolNode报工具不存在 | 工具列表与图节点注册不一致 | 打印绑定到模型的tools和ToolNode的 tools 列表 | 统一工具来源,让两端使用同一份工具列表 |
| 多轮对话“丢失记忆” | 未使用 checkpointer,或每次使用不同thread_id | 检查compile是否传了 checkpointer,检查调用时的config是否一致 | 使用同一个 checkpointer 和同一个thread_id |
| 执行流程卡在某一步不结束 | 模型的循环判断没有走到终止条件 | 开启 LangGraph 的可视化或断点调试,观察每次路由目标 | 增加最大步数限制,或调整条件边逻辑 |
| Agent 调用了错误工具 | 工具描述不清或模型能力有限 | 检查工具 docstring 是否准确描述功能和参数 | 重写工具说明,必要时在输入里增加约束提示词 |
| 状态字段被覆盖而不是追加 | 没有使用add_messagesreducer | 检查状态定义中的Annotated是否写对 | 在字段类型上增加Annotated[list, add_messages] |
| 生产环境状态丢失 | 使用MemorySaver,进程重启后状态清空 | 确认持久化后端类型 | 替换为数据库 Checkpoint 后端 |
这里单独说一下最容易忽视的坑:工具描述词质量。
@tool装饰器会把函数的 docstring 作为工具的描述传给模型。如果 docstring 写得太模糊,模型可能无法准确决定什么时候调用工具。例如:
@tool def current_time(): """获取当前时间。""" ...和:
@tool def current_time(): """获取当前北京时间,并以字符串返回。当用户询问日期、时间、今天是几号时使用。""" ...第二种写法在实际使用中准确率会明显更高,因为模型需要依赖描述来规划调用。
8. 企业级 Agent 落地的最佳实践
看完上面的例子,很多同学会进入第二个阶段:想把自己的业务逻辑做成一个完整 Agent。这个阶段考验的不是写代码的能力,而是设计和分层的功力。
8.1 一个 Agent 不要做太多事
在业务中,我见过最大的反模式是:把所有工具塞进一个 Agent,让 Agent 解决所有问题。这种做法在实验环境勉强能跑,但到生产环境你会发现:
- 提示词太长,模型上下文占用高;
- 工具选择容易混乱,Agent 频繁调用错误工具;
- 单个系统难以维护,改动一个工具可能影响其他功能;
- 权限和审计无法细化。
更合理的做法是:把一个复杂业务流程拆成多个专业 Agent,再用一个主管 Agent(Supervisor)做调度。每个子 Agent 只负责一个小领域,拥有自己的工具集和提示词;主管 Agent 根据用户意图把请求路由到正确的子 Agent。
LangGraph 对多 Agent 的支持很直接,它本质上就是一张更大的图。你可以把子 Agent 做成匿名的“计算节点”,再添加一条从主管到子 Agent、再回到主管的环路。
8.2 状态设计要有边界
Agent 的状态字段决定了整个流程的可见数据。
建议将下面的信息显式设计进状态:
- 用户输入与系统消息;
- 当前任务的目标;
- 已执行过的步骤;
- 中间结果或工具返回值;
- 额外的业务上下文,如用户 ID、租户 ID、审批状态。
不要一味把所有内容都塞进messages。过大的消息列表会增加成本和延迟,也影响模型推理质量。合理的做法是:保留必要的历史消息用于上下文理解,但把业务元数据放在独立的字段中。
8.3 用人工介入兜底
LangGraph 的一大优势是可以挂载interrupt_before或类似机制,让 Agent 在关键步骤等待人工审批。这在企业级流程里几乎必不可少。
比如一个自动发邮件的 Agent,在下发正式邮件之前,应该有一个“等待人工确认收件人和内容”的节点。这类设计在 LangGraph 中相比自己维护状态机要简洁得多。
8.4 可观测性
Agent 在真实生产环境里是“黑盒”风险非常高的系统。你不仅需要知道最终结果,还需要知道:
- 在哪个节点耗时最长;
- 调用了哪些工具,参数是什么;
- 有没有出现死循环;
- 上一轮和下一轮之间状态发生了什么变化。
LangGraph 官方提供的可视化调试工具和 LangSmith 是很好的辅助。如果没有条件使用,至少要在自己的节点函数里写结构化日志,把关键状态变化和工具调用记录下来。
8.5 接入现有系统的最小成本原则
企业级项目几乎不可能完全重建现有系统。更务实的做法是:把 Agent 定位成一个“编排层”,通过 API 网关或消息队列对接现有服务,而不是让 Agent 直接访问数据库。
这样做的原因有三点:
- 安全。Agent 不需要成为核心数据系统的直接客户端;
- 可审计。所有经过网关的请求都可以记录和追溯;
- 可维护。把 Agent 的系统边界保持在“工作流 + 工具”层面,后续升级 Agent 时不影响底层系统。
8.6 注意 Agent 的失控风险
如果允许 Agent 自动执行一系列业务操作,一定要设置最大迭代步数。
以开源框架中常见的防护思路为例,最好在每次循环里增加“步数计数器”,超过阈值直接终止并转入人工处理。在这个问题上,核心思想是一致的。
8.7 关于 Skill 与 Agent 的边界
在 Agent 开发的热词里,“Skill”这个词也越来越常见。
通俗理解,Skill 是“可复用的能力单元”,比如文档总结、SQL 查询、代码审查;Agent 则是“根据任务目标自主编排 Skill 的实体”。
你可以把 Skill 理解为函数,把 Agent 理解为控制流。在 LangGraph 里,Skill 往往可以封装成一个子图或工具,而 Agent 节点决定何时调用它。实际项目中,建议先梳理业务需要哪些 Skill,再围绕 Skill 设计 Agent 的工具集和路由逻辑。
9. 学习路线与后续方向
9.1 推荐的 Agent 开发学习路线
结合前面讲的概念,整理出一条可以照做的路线:
- 先掌握 LangChain 基础:模型调用、Prompt、输出解析、Chain 组合;
- 理解 RAG 的完整链路:文档加载、切分、向量化、检索、答案生成;
- 学习 LangChain 的 Agent 基础组件:Tool 定义、模型绑定;
- 切换到 LangGraph:掌握 State / Node / Edge / Compile 四种核心抽象;
- 实现一个最小 Agent 循环;
- 加入工具调用、条件路由和持久化;
- 尝试把 Agent 拆成多 Agent 协作结构;
- 把 Agent 接入 Web 框架或消息队列,完成工程化;
- 加入人工审批、审计、监控和错误恢复机制。
这套路线的核心思想是:先自底向上理解每个组件,再自顶向下设计 Agent 系统。
如果你正在跟着视频课程学习,也可以把这套路线当作课程目录的“导航”,避免自己陷入“只看不动手”的状态。
9.2 需要继续深入的方向
- Agent 记忆机制:短期记忆、长期记忆、向量记忆、摘要记忆;
- Agent 工具的自定义与安全边界:如何让 Agent 安全地操作企业内部系统;
- 多 Agent 协作模式:主管/工人模式、辩论模式、流水线模式;
- Agent 评估体系:如何自动评估 Agent 每一次回答的质量;
- LangGraph 源码实现:理解图执行引擎的调度原理,有助于排查复杂问题;
- RAG 与 Agent 的结合:让 Agent 在回答专业问题时先检索企业知识库。
其中,Agent 的评估体系是企业级落地最容易被忽视的部分。好的 Agent 不是“写”出来的,而是反复“评”出来的。建议在你第一个 Agent 跑通后,立刻建立一组典型测试问题,形成回归用例,避免后续改动导致能力回退。
LangChain 自动生成测试用例的方向也值得关注。它可以辅助产出覆盖 Prompt 分支、工具调用路径、边界情况的测试集,从而让 Agent 开发也能像传统后端一样有基本的回归保障。
9.3 给你的下一步建议
如果你的手头暂时没有明确业务项目,可以尝试做这几个小练习:
- 写一个“文件管理 Agent”:让它能够列出目录、读取文件、按需总结内容;
- 写一个“周报生成 Agent”:接上内部 API 或数据库,自动汇总数据并生成文字;
- 写一个“SQL 查询 Agent”:通过自然语言生成 SQL,并加上“执行前人工确认”节点。
这三个练习基本覆盖了 RAG、Tool Calling、人工审批等企业级 Agent 的核心能力。
记住:Agent 开发的难度不在于“调用模型”,而在于“把任务拆解成可控的图结构”。当你发现自己能把一个复杂任务拆成节点、边、状态的那一刻,LangGraph 才算是真正入门了。
建议把文章中的示例代码保存下来,结合自己的业务场景改一遍。即使是简单的“把用户问题送进模型再返回结果”这个流程,亲手写一遍和看一遍的收获完全不同。