
各位 CSDN 的读者朋友们大家好。进入 2026 年AI 大模型应用开发的底层逻辑已经彻底变了。以前我们聊的是“怎么调 API”、“怎么写 Prompt”但现在企业级项目里聊得最多的四个词变成了LangChain、LangGraph、MCP 和 Agent。很多朋友会被这四者之间的关系绕晕甚至有人误以为它们是对立或替代关系其实并不是。如果你准备在 2026 年进入或转型 AI 应用开发这四者基本是绕不开的技术栈底座。这篇文章不是零散的知识点罗列而是一套从入门到企业级实战的完整拆解。我会从基础概念讲起帮你理清 LangChain 与 LangGraph 的区别再讲清楚 MCP 协议为什么是 Agent 时代的“USB-C 接口”最后用一个真实的客服工单 Agent 项目把四者串起来跑通。整套代码都给你贴出来按步骤复制即可运行希望能帮你省下到处找资料的时间。文中所有代码示例都以当前主流稳定版本思路编写具体版本号请结合你的实际环境调整关键是掌握架构思路和核心 API 用法。1. 先理清概念LangChain、LangGraph、MCP、Agent 到底是什么关系1.1 从一次真实的业务需求说起假设你所在的公司要做一个人力资源内部助手。员工可以直接在对话框里问“我的年假还剩几天”“帮我查一下本月的考勤异常”或者“请帮我发起一个请假审批流程”。这个需求看起来很普通但真要落地你至少会遇到几个问题大模型本身无法实时访问公司的人力系统数据库。大模型不具备执行“发起审批”这类写操作的能力。对话过程中模型自己并不知道应该在什么时候调用查询接口、什么时候调用审批接口。如果把所有接口全部暴露给模型调用路径会变得混乱且难以控制。答案就是用LangChain做基础应用框架用LangGraph做流程编排用MCP统一接入各种外部系统和工具最终生成一个真正的Agent智能体来面向用户。1.2 四个概念的正确定位先给一张总览表方便大家建立整体认知技术定位一句话解释典型场景LangChain大模型应用开发框架封装了模型调用、Prompt、输出解析、向量检索等基础组件搭一个带 RAG 的问答机器人LangGraph大模型 Agent 编排框架用图结构定义 Agent 的状态流转、循环、分支、并行复杂任务需要多步骤决策时用MCP模型上下文协议统一了 AI 应用与外部工具、数据源的通信接口让 Agent 能调用公司内部 API、数据库、浏览器、设计工具等Agent智能体应用形态能自主理解任务、调用工具、多步推理并完成任务客服机器人、代码助手、自动化运维助手简单来说LangChain 是“工具箱”里面有很多好用的工具LangGraph 是“图纸”定义了 Agent 完成任务的路径MCP 是“插头标准”让 Agent 能即插即用地连接外部世界最终组装出来的东西才是 Agent。1.3 LangChain 与 LangGraph 的核心区别很多初学者在这里被绕晕我直接说结论LangChain的 core 能力是 LLM 调用封装、Prompt 管理、Output Parser、Memory 抽象、文档加载、向量存储接入。LangGraph是构建在 LangChain 生态之上的一个低层编排框架。它不再沿用 LangChain 早期版本那种 Chain 的线性串联方式而是把 Agent 的推理和执行建模成一个有状态图StateGraph。如果你把 LangChain 想象成积木那么 LangGraph 就是搭积木时的“骨架”与“规则”。它允许你定义节点Node、边Edge、条件边Conditional Edge、循环Cycle以及子图Subgraph。这恰好对应了 Agent 运行时的真实需求Agent 需要“思考 → 调用工具 → 观察结果 → 再思考”这样的循环而不是一条直线走到底。用伪代码来对比一下# LangChain 风格的 Linear Chain线性链路 prompt ChatPromptTemplate.from_template(讲一个关于{subject}的故事) chain prompt | model | StrOutputParser() result chain.invoke({subject: 程序员})# LangGraph 风格的图编排 from langgraph.graph import StateGraph, START, END graph StateGraph(AgentState) graph.add_node(agent, agent_node) graph.add_node(tools, tools_node) graph.add_edge(START, agent) graph.add_conditional_edges(agent, should_continue, {continue: tools, end: END}) graph.add_edge(tools, agent)前者适合流程固定的场景后者适合 Agent 需要动态决策的场景。企业级 Agent 几乎都会选后者。1.4 MCP 协议登场Agent 时代的“USB-C 接口”MCPModel Context Protocol最早由 Anthropic 提出是一个开放协议。它解决的问题很朴素如果每个 Agent 都要对接不同的数据库、HTTP API、文件系统、浏览器、设计工具就会产生大量定制化代码每接一家系统就要写一套不同的实现。MCP 把“工具接入”标准化了。它采用客户端-服务端架构MCP Server暴露工具、数据资源或 Prompt 模板的一方比如“飞书 MCP Server”“数据库 MCP Server”“GitHub MCP Server”。MCP Client嵌入在 AI 应用中与 MCP Server 通信。从 2025 年到 2026 年MCP 的生态扩展速度非常快。大量主流系统都开始提供 MCP Server例如各类数据库、对象存储、消息队列、IM 工具、设计工具、浏览器自动化工具。这意味着你的 Agent 不再需要手写每一种工具接入逻辑只要对接 MCP 标准就能以相对统一的方式调用大量现成能力。2. 环境准备与项目基础2.1 版本与依赖说明在开始之前先说明一下环境。本文示例采用 Python 3.10 及以上的版本。由于 LangChain、LangGraph、MCP 相关包更新速度很快我强烈建议你在虚拟环境中安装避免全局环境冲突。# 创建虚拟环境 python -m venv aienv source aienv/bin/activate # Windows 使用 aienv\Scripts\activate # 安装核心依赖 pip install --upgrade langchain pip install --upgrade langchain-openai pip install --upgrade langgraph pip install --upgrade mcp pip install --upgrade langchain-mcp-adapters需要说明的是这里的langchain-mcp-adapters是 LangChain 官方提供的 MCP 适配包用于把 MCP 工具转换成 LangChain 可用的 Tool 对象。不同版本的 API 具体写法可能有差异但整体思路一致。2.2 模型配置本文示例默认使用 OpenAI 兼容接口。你可以直接配置 OpenAI 的 API Key也可以使用国内大模型平台提供的 OpenAI 兼容端点例如 DeepSeek、通义千问、智谱、Kimi 等。这是企业项目里的常见做法因为模型切换成本很低。export OPENAI_API_KEYyour-api-key export OPENAI_BASE_URLhttps://api.openai.com/v1如果你使用的是国内大模型的兼容端点只需要把OPENAI_BASE_URL改成对应平台的地址并替换模型名称即可。2.3 项目结构规划为了培养工程化习惯我们不要把所有代码写在一个 Jupyter Notebook 或一个 main.py 里。企业级实战需要清晰的目录层次ai-agent-project/ ├── .env # 环境变量文件 ├── requirements.txt # 依赖清单 ├── agent/ │ ├── __init__.py │ ├── state.py # Agent 状态定义 │ ├── tools.py # 工具定义MCP 原生工具 │ ├── graph.py # LangGraph 图结构构建 │ └── main.py # 入口运行 ├── mcp_servers/ │ ├── ticket_server.py # 工单系统 MCP Server 示例 │ └── __init__.py └── README.md先创建一个requirements.txt内容如下langchain langchain-openai langgraph mcp langchain-mcp-adapters python-dotenv安装依赖pip install -r requirements.txt3. LangChain 基础企业应用开发的底座3.1 ChatPromptTemplate 与模型调用LangChain 最基础的用法是封装模型调用。对于企业项目我们通常使用ChatPromptTemplate来管理 Prompt这样 Prompt 和代码可以解耦。# agent/prompt.py from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder prompt ChatPromptTemplate.from_messages( [ ( system, 你是一位专业的企业客服助手名叫小勤。 你擅长回答员工关于考勤、年假、报销、工单等问题。 回答时请使用简体中文并力求简洁准确。 如果信息不足请明确告知用户不要编造数据。, ), MessagesPlaceholder(variable_namemessages), ] )这里使用了MessagesPlaceholder目的是把对话历史动态插入到 Prompt 中。这是企业级对话系统的标配因为模型本身不记住上下文所有历史消息都需要我们传给模型。3.2 工具封装从函数到 ToolLangChain 可以把一个普通 Python 函数注册为 Tool让模型在需要的时候调用它。来看一个很简单的查询年假工具# agent/tools.py from datetime import datetime from langchain_core.tools import tool tool def get_annual_leave_balance(employee_id: str) - str: 根据员工ID查询年假剩余天数。 Args: employee_id: 员工ID例如 E10001。 # 这里模拟查询内部HR系统 data { E10001: 12, E10002: 8, E10003: 0, } balance data.get(employee_id, 0) return f员工 {employee_id} 当前年假剩余 {balance} 天。注意 Docstring 很重要因为 LangChain 会把函数的名称、描述、参数信息一并发给大模型作为模型判断是否调用这个工具的依据。3.3 基础 Agent 执行器与其实战限制早期 LangChain 提供了AgentExecutor它内部实现了“模型 → 决定调工具 → 执行工具 → 回到模型”的循环。看一段简单的使用示例from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_openai import ChatOpenAI from agent.prompt import prompt from agent.tools import get_annual_leave_balance model ChatOpenAI(modelgpt-4o, temperature0) tools [get_annual_leave_balance] agent create_tool_calling_agent(model, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue) result executor.invoke({messages: [{role: user, content: E10001的年假还剩几天}]}) print(result[output])这段代码能跑通但存在两个明显问题循环控制不够细你很难精准控制“最多调用多少次工具”“超过多少轮就停止”。状态管理能力弱AgentExecutor 内部帮你管理了中间状态但如果你希望介入每一步、检查工具结果、动态调整下一步计划就非常吃力。可观测性不足在复杂生产环境中需要细粒度追踪 Agent 每步的输入输出、耗时和 token 消耗AgentExecutor 很难满足这种要求。所以 2026 年的企业项目中更多人会选择直接用 LangGraph 来构建 Agent。它虽然多写几行代码但换来了极强的控制力与可观测性。4. LangGraph 深入解析用图来编排 Agent4.1 核心概念State、Node、EdgeLangGraph 的核心思想非常直观其实就是一个状态机State Machine由三个要素组成State状态定义 Agent 处理过程中的数据模型。它是一张 TypedDict描述“这轮对话内存放了什么”。每次节点执行后都会更新 State。Node节点一个节点就是一个函数或可调用对象接收当前 State返回更新后的 State 内容。Edge边定义节点的执行顺序。边可以是有条件的Conditional Edge即根据当前 State 动态决定下一步进入哪个节点。4.2 构建一个带工具调用的 LangGraph Agent下面我们直接写一个标准的 ReAct Agent 图结构。先定义 State# agent/state.py from typing import TypedDict, Annotated, Sequence from langchain_core.messages import BaseMessage from langgraph.graph.message import add_messages class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], add_messages]这里的Annotated[Sequence[BaseMessage], add_messages]是 LangGraph 的推荐写法。add_messages是一个归约器Reducer它告诉 LangGraph当不同节点都返回新的messages字段时不是直接覆盖旧消息而是把新消息追加到旧消息列表后面。这种机制保证了对话历史在多个图节点之间正确传递。接下来构建图# agent/graph.py from typing import Literal from langchain_core.messages import AIMessage, ToolMessage from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph, START, END from langgraph.prebuilt import ToolNode, tools_condition from agent.state import AgentState from agent.prompt import prompt from agent.tools import get_annual_leave_balance # 1. 初始化模型和工具 tools [get_annual_leave_balance] model ChatOpenAI(modelgpt-4o, temperature0) model_with_tools model.bind_tools(tools) # 2. 定义 Agent 节点模型在这里决定调用哪个工具还是直接回复 def agent_node(state: AgentState): messages state[messages] response model_with_tools.invoke(prompt.invoke({messages: messages})) return {messages: [response]} # 3. 构建图 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, # 这是 LangGraph 预置的条件函数 { tools: tools, # 如果模型想调用工具进入 tools 节点 END: END, # 否则结束 }, ) graph_builder.add_edge(tools, agent) # 工具执行完回到 agent 继续推理 agent_graph graph_builder.compile()注意tools_condition是 LangGraph 预置的判断函数它检查 AI 消息里是否包含tool_calls。如果有就返回tools否则返回END。这是 Agent 循环的核心实现。4.3 条件路由与分支控制的高级写法上面的示例使用了预置函数tools_condition方便快捷。但真实项目中我们经常需要自定义判断逻辑比如如果用户消息中包含“加急”关键词先走加急处理节点。如果工具执行结果中出现了错误标记走异常兜底节点。如果问题属于财务类直接路由到财务专用 Agent 子图。这时候就需要写自己的条件函数。写法如下def router(state: AgentState) - Literal[agent, sensitive_check, __end__]: last_message state[messages][-1] if not isinstance(last_message, AIMessage): return agent if not last_message.tool_calls: # 没有工具调用直接结束 return __end__ # 如果工具名涉及删除操作先进入敏感操作审查节点 for tc in last_message.tool_calls: if tc[name] delete_ticket: return sensitive_check return agent然后在add_conditional_edges中使用graph_builder.add_conditional_edges(agent, router, { sensitive_check: sensitive_check, agent: tools, __end__: END, })这种写法在企业级项目中非常常见。因为安全风控、敏感操作确认、多部门路由等需求都要靠条件边来实现。4.4 持久化记忆从 MemorySaver 到数据库 CheckpointAgent 是无状态的。每次执行图它都不知道之前的对话已经聊到哪了。为了让 Agent 记住历史LangGraph 引入了 Checkpoint检查点的概念。最简单的内存级保存from langgraph.checkpoint.memory import MemorySaver memory MemorySaver() agent_graph graph_builder.compile(checkpointermemory) # 运行时传入 thread_id 作为会话标识 config {configurable: {thread_id: user-001}} result agent_graph.invoke( {messages: [{role: user, content: E10001的年假还剩几天}]}, configconfig, )第二次对话时只要传入相同的thread_idLangGraph 就会自动加载历史消息Agent 就能“记住”上轮对话内容。这就是多轮对话记忆的实现机制。生产环境中MemorySaver只适合本地测试因为数据在内存里且进程退出即消失。企业项目应该把 Checkpoint 存储到 PostgreSQL、Redis 等持久化组件中。LangGraph 生态中可以通过langgraph-checkpoint-postgres或langgraph-checkpoint-redis实现。思路是修改compile(checkpointer...)的参数Agent 业务代码几乎不用改。4.5 子图Subgraph复杂系统的模块化利器当一个 Agent 逻辑变复杂后把所有节点都塞进一个图会让图变得难以维护。LangGraph 支持把一个编好的图当作另一个图的节点这种节点叫子图。举个例子假设客服 Agent 在处理“报销”类问题时需要进入一个专门的报销子流程里面包含“查询报销单状态”“上传附件”“提交财务审核”三个节点。我们可以先独立构建报销子图再在主图中把它注册为一个节点。from langgraph.graph import StateGraph, START, END # 报销子图 reimburse_graph StateGraph(AgentState) reimburse_graph.add_node(query_status, query_status_node) reimburse_graph.add_node(check_attachment, check_attachment_node) reimburse_graph.add_edge(START, query_status) reimburse_graph.add_edge(query_status, check_attachment) reimburse_graph.add_edge(check_attachment, END) reimburse_app reimburse_graph.compile() # 主图 main_graph StateGraph(AgentState) main_graph.add_node(agent, agent_node) main_graph.add_node(reimburse, reimburse_app) # 子图作为节点 main_graph.add_conditional_edges(agent, router) main_graph.add_edge(reimburse, agent)这种模块化设计让复杂 Agent 像是乐高积木一样可以被拆分、替换和复用。在团队协作中不同人负责不同的子图模块然后在一张主图中完成组装开发效率提升非常明显。5. MCP让 Agent 与外部世界无缝对接5.1 为什么需要 MCP从“定制接口”到“标准协议”在企业实践中Agent 需要连接的内部系统非常多企业微信、钉钉、飞书、HR 系统、工单系统、数据库、云平台、监控系统等。如果每个系统都靠自己开发对接代码Agent 的所有代码几乎全是胶水代码而且每换一个系统就要重新开发。MCP 的解决方案是所有工具提供方都实现成 MCP Server所有 Agent 框架都支持 MCP Client。那么模型与任意系统对接就变成了“客户端连接服务端”的标准动作。用一个通俗的比喻没有 MCP 之前Agent 连接每个软件都需要专门定制一根电源线有了 MCP所有软件都给你提供同一个 USB-C 口Agent 随身带一根标准线就能走天下。5.2 MCP 的工作流程MCP 的工作流程可以拆成几步AI 应用MCP Client向 MCP Server 发起初始化请求。MCP Server 返回工具清单、资源清单、Prompt 模板。AI 应用把工具清单注入到大模型的上下文让模型知道“我现在有这些能力可用”。模型根据用户需求决定调用哪个工具。AI 应用把调用参数发给 MCP Server。MCP Server 执行对应操作查数据库、调接口、操作文件等把结果返回。模型拿到结果组织自然语言回复用户。整个链路中模型不需要知道具体工具的技术细节MCP Server 也不需要知道模型来自哪一家。这就是协议的威力。5.3 用 Python 快速写一个 MCP Server下面我用 FastMCP 写一个最简单的 MCP Server模拟查询工单系统的接口。需要先安装fastmcp库pip install fastmcp创建mcp_servers/ticket_server.py# mcp_servers/ticket_server.py from fastmcp import FastMCP # 创建 MCP Server名称是 gift-server mcp FastMCP(ticket-server) # 模拟工单数据 TICKET_DB { T1001: {title: 会议室投影仪故障, status: 处理中, priority: 高}, T1002: {title: 申请开通云数据库权限, status: 已完成, priority: 中}, T1003: {title: 办公电脑蓝屏, status: 待受理, priority: 紧急}, } mcp.tool() def query_ticket_status(ticket_id: str) - str: 查询工单状态。 Args: ticket_id: 工单编号例如 T1001。 ticket TICKET_DB.get(ticket_id) if not ticket: return f未找到工单 {ticket_id}。 return ( f工单 {ticket_id}{ticket[title]} f状态{ticket[status]}优先级{ticket[priority]}。 ) mcp.tool() def create_ticket(title: str, description: str, priority: str 中) - str: 创建新工单。 Args: title: 工单标题。 description: 工单描述。 priority: 优先级可选值低、中、高、紧急。 ticket_id fT{len(TICKET_DB) 1004} TICKET_DB[ticket_id] { title: title, status: 待受理, priority: priority, } return f工单创建成功编号{ticket_id}。 if __name__ __main__: mcp.run()运行这个 Serverpython mcp_servers/ticket_server.pyFastMCP 的mcp.tool()装饰器会自动把函数注册为 MCP 工具函数名和 Docstring 会变成工具的元信息供模型识别。5.4 在 LangGraph Agent 中调用 MCP 工具现在我们要做的就是让刚才的 LangGraph Agent 能够调用这个 MCP Server 暴露出来的工具。langchain-mcp-adapters提供了现成的桥接能力核心思路是把 MCP 工具列表转换成 LangChain Tool 对象再塞给bind_tools或ToolNode。# agent/tools.py 追加 from contextlib import asynccontextmanager from langchain_mcp_adapters.tools import load_mcp_tools from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client asynccontextmanager async def mcp_tools_from_server(): 连接到本地 MCP Server并加载全部工具。 server_params StdioServerParameters( commandpython, args[mcp_servers/ticket_server.py], ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await load_mcp_tools(session) yield tools然后在 graph 构建时稍作调整。由于 MCP 工具加载是异步的在异步环境中使用更自然。如果你希望在同步环境中使用可以采用asyncio.run()来加载工具列表import asyncio from agent.tools import mcp_tools_from_server # 在应用启动时加载 MCP 工具 mcp_tools asyncio.run(mcp_tools_from_server()) all_tools [get_annual_leave_balance] mcp_tools这样all_tools就同时包含了本地函数工具和 MCP Server 暴露的远程工具。接着和之前一样把all_tools传给model.bind_tools(all_tools)以及ToolNode(all_tools)即可。这里要提醒大家的是MCP 协议和 LangChain 的集成方式在版本迭代中可能会有 API 变化。如果发现某个适配函数用法不对优先去查你当前安装版本对应的官方文档确保接口写法一致。5.5 企业里常见 MCP Server 场景结合 2026 年的生态情况企业项目里最常用的 MCP Server 类型包括但不限于领域示例场景效果数据库操作让 Agent 通过 MCP 连接 MySQL/PostgreSQL通过自然语言查询业务数据并自动生成图表办公协作飞书、钉钉、企业微信 MCP ServerAgent 直接创建日程、发消息、拉会议纪要设计工具Figma MCP Server设计师用聊天方式生成或修改设计稿软件开发GitHub、GitLab MCP ServerAgent 自动创建 Issue、提交 PR、查看 CI 状态浏览器自动化Playwright MCP ServerAgent 自动操作网页完成表单填写、数据采集支付与财务企业内部财务系统 MCP ServerAgent 查询报销单状态、发起对公付款申请可以看出MCP Server 本质上就是“把系统的能力暴露给 AI”的标准层。对已经存在大量内部系统的传统企业来说MCP 的适配成本远低于重新开发 Agent 侧对接逻辑。6. 企业级完整实战智能客服工单 Agent现在我们把前面的知识点组合起来做一个更完整的实战项目。这个项目模拟一个企业内部智能客服 Agent它的能力包括查询员工年假余额本地工具。查询工单状态、创建新工单通过 MCP Server 调用。支持多轮会话记忆LangGraph Checkpoint。有节点路由和安全保护逻辑条件边。6.1 定义状态和工具# agent/state.py from typing import TypedDict, Annotated, Sequence from langchain_core.messages import BaseMessage from langgraph.graph.message import add_messages class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], add_messages]# agent/tools.py from langchain_core.tools import tool tool def get_annual_leave_balance(employee_id: str) - str: 根据员工ID查询年假剩余天数。 data {E10001: 12, E10002: 8, E10003: 0} balance data.get(employee_id, 0) return f员工 {employee_id} 当前年假剩余 {balance} 天。6.2 构建 Agent 图# agent/graph.py from typing import Literal from langchain_core.messages import AIMessage from langchain_openai import ChatOpenAI from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import StateGraph, START, END from langgraph.prebuilt import ToolNode from agent.state import AgentState from agent.prompt import prompt from agent.tools import get_annual_leave_balance # 加载 MCP 工具的代码略参考上一节 from agent.mcp_client import load_all_tools all_tools load_all_tools() # 返回 [get_annual_leave_balance, mcp_query_ticket, mcp_create_ticket] model ChatOpenAI(modelgpt-4o, temperature0) model_with_tools model.bind_tools(all_tools) def agent_node(state: AgentState): messages state[messages] response model_with_tools.invoke(prompt.invoke({messages: messages})) return {messages: [response]} def router(state: AgentState) - Literal[agent, tools, __end__]: last_message state[messages][-1] if isinstance(last_message, AIMessage) and last_message.tool_calls: return tools return __end__ def build_graph(): graph_builder StateGraph(AgentState) graph_builder.add_node(agent, agent_node) graph_builder.add_node(tools, ToolNode(all_tools)) graph_builder.add_edge(START, agent) graph_builder.add_conditional_edges(agent, router) graph_builder.add_edge(tools, agent) memory MemorySaver() return graph_builder.compile(checkpointermemory)6.3 编写入口与多轮运行# agent/main.py from agent.graph import build_graph app build_graph() config {configurable: {thread_id: employee-001}} # 第一轮查询年假 result app.invoke( {messages: [{role: user, content: 你好我是E10001帮我查年假还剩几天}]}, configconfig, ) print(result[messages][-1].content) # 第二轮创建工单基于同一 thread_idAgent 记得刚才的对话上下文 result app.invoke( {messages: [{role: user, content: 我投影仪坏了帮我创建一个紧急工单标题是会议室投影仪故障描述是开会时投影仪无法开机。}]}, configconfig, ) print(result[messages][-1].content) # 第三轮查询刚才创建的工单状态这里需要模型先调用 MCP 工具查询 result app.invoke( {messages: [{role: user, content: 我刚才创建的工单现在什么状态}]}, configconfig, ) print(result[messages][-1].content)运行之后你会看到模型在对话过程中自动决定调用不同工具并且能结合历史消息完成上下文理解。这就是 LangChain LangGraph MCP Agent 四者协同工作的完整闭环。6.4 可视化 LangGraph 执行流程LangGraph 的图天生可以被渲染成文本或 HTML这对于调试和分析非常有帮助。最简单的文本情况你可以通过app.get_graph().draw_ascii()打印出图结构print(app.get_graph().draw_ascii())输出大致是-------- | START | -------- | v -------- | agent | -------- | v ------- | tools | ------- | v ------- | agent | -------如果是复杂图建议用app.get_graph().draw_mermaid_png()导出图片团队沟通和文档输出时非常直观。7. 常见问题与排查思路7.1 LangGraph 中模型一直不调用工具现象问了需要调用工具的问题但模型直接给出自然语言答案没有执行工具函数。可能原因model.bind_tools(tools)里的工具列表为空或格式不对。模型的型号不支持 Function Calling / Tool Calling。当前模型需要通过不同的参数格式来绑定工具。排查步骤打印model_with_tools的绑定类型确认tools确实传入了。查看模型输出是否存在tool_calls字段。更换模型版本测试例如换用gpt-4o或qwen-max等支持工具调用的主流模型。确认工具函数的 Docstring 描述足够清晰避免模型无法判断什么时候用。7.2 MCP Server 连接失败现象Agent 启动时提示无法连接 MCP Server或调用工具时超时。可能原因MCP Server 进程本身启动失败端口或命令参数错误。Stdio 通信模式下command和args配置不正确。依赖包版本不兼容。排查步骤先在命令行手动运行 MCP Server确认能正常启动。检查 MCP Server 的日志输出看看是否有异常堆栈。确认协议版本兼容性尽量使用同一代际的mcp和fastmcp版本。如果使用网络传输模式Streamable HTTP检查网络连通性和鉴权信息。7.3 Agent 循环失控无限调用工具现象Agent 不停调用工具不生成最终回答消耗大量 token。可能原因工具返回结果不足以让模型得出明确结论。图的循环条件设计缺少深度限制。条件边配置有误tools节点结束后没有正确回到agent或结束。排查与解决方案在工具节点中增加“最大调用次数”统计超过次数强制结束。检查tools到agent的边是否存在。在系统 Prompt 中加入“如果无法通过工具解决请直接告知用户”的指令。7.4 对话“失忆”无法进行多轮交互现象同一thread_id下继续对话Agent 不记得之前的消息。可能原因每次运行重新创建了checkpointer没有持久化保存 checkpoint。传入的config中thread_id不一致。messages字段没有在 State 中使用add_messages归约器。排查步骤确认compile(checkpointer...)已生效。确认每次invoke使用同一个config。检查 State 定义中是否使用了Annotated[..., add_messages]。7.5 工具调用报错“The agent execution provider did not respond in time”现象某些 Agent 执行环境中工具调用或模型响应超时。可能原因模型推理时间过长超过了执行环境的超时上限。MCP Server 响应慢阻塞了整体流程。网络不稳定。排查步骤增大客户端超时配置。将耗时操作改为异步执行或队列化处理。对 MCP Server 做性能压测确认响应时间在合理范围。8. 最佳实践与工程化建议8.1 用 LangGraph 替代 AgentExecutor 作为 Agent 主框架在企业项目里我的建议是不要再用 LangChain 的AgentExecutor作为生产环境主框架。它已经是一个偏旧的设计。LangGraph 提供了更细粒度的控制并且天然适配流式输出、断点续跑、人工介入Human-in-the-loop、人机协同审核等企业级场景。这些能力在客服、审批、审核、运维自动化的场景里几乎是刚需。8.2 工具接入优先走 MCP而不是写大量 Custom Tool假如你的公司内部已经有人提供 MCP ServerAgent 侧接入成本确实很低。反过来如果你发现某个系统要被多个 Agent 复用可以把它的能力包装成 MCP Server 而不是写一个只属于某个项目的 LangChain Tool。这样可以实现一次开发、多处复用的效果。8.3 安全边界工具权限最小化Agent 能调用工具意味着模型的每一次决策都可能触发真实系统操作所以安全设计比传统应用更关键。我的建议是所有写操作默认不进主流程例如“创建工单”“审批通过”等操作在 LangGraph 中使用interrupt机制暂停图执行等待用户确认后再继续。MCP Server 内部做权限校验不能在 MCP 层无条件信任来自 Agent 的调用。不同角色使用不同模型配置普通员工用轻量模型管理员用更强模型。8.4 可观测性优先链路追踪 Token 消耗Agent 项目最怕的是“黑盒”。一个复杂任务模型调用了 8 次工具每次调用的输入输出是什么消耗了多少 token都需要记录。生产环境推荐使用 LangSmith 或者自建日志系统。自建的话至少要把graph.invoke()的中间状态落库尤其记录每个节点的输入、输出和耗时。8.5 缓存与性能优化对常见的查询类工具例如查年假、查考勤可以在 MCP Server 层做短时缓存避免频繁查询。对模型层可以使用 Prompt 缓存机制降低 token 成本。对话轮次较多时及时清理或压缩历史消息避免上下文超长。8.6 配置管理与灰度发布Agent 的 Prompt、模型名称、温度参数、工具列表都应该做成配置项而不是硬编码在代码里。建议使用 Apollo 或 Nacos 这类配置中心来管理 Agent 的运行时配置。当我们需要切换模型供应商或调整 Prompt 时只需要通过配置中心发布Agent 进程在监听配置变更后自动更新不需要重启服务。这一点在大模型应用迭代频繁的阶段特别重要。8.7 测试策略单元测试对每个工具函数做独立测试确保参数校验和异常处理正确。图结构测试设计测试用例覆盖所有条件边的走向。集成测试启动真实 MCP Server验证 Agent 端到端流程。回归测试Prompt 改动后要有一批标准问题集来做回归验证防止模型回答质量下降。9. 总结与后续学习路线回顾一下本文从一个大模型应用开发的真实场景出发拆解了 LangChain、LangGraph、MCP、Agent 四者的关系与定位。LangChain 提供的是一整套应用开发的基础组件LangGraph 提供了可控的 Agent 编排能力MCP 则统一了外部工具接入标准最终它们组合成一个能真正落地运行的智能客服 Agent 项目。如果你是从零开始建议按这个顺序继续深入先熟练掌握 LangChain 的 Prompt 管理、Model 调用、Output Parser、RAG 基础链路。再用 LangGraph 重写一个你自己之前做过的 LangChain Agent体会图编排的灵活性。阅读 MCP 协议官方文档动手写一个接入公司内部数据的 MCP Server。深入了解 LangGraph 的interrupt机制、Streaming、Subgraph完成一个带人工确认的 Agent 流程。最后考虑生产环境落地把 Checkpoint 从内存换成数据库接入日志、链路追踪、配置中心。在实际项目中最需要优先关注的风险主要有三个一是工具调用的安全性凡是写操作都要加人工确认二是模型幻觉工具返回的数据要让模型严格“引用”而不是自由发挥这点可以通过 Prompt 约束和输出校验来缓解三是成本控制复杂 Agent 单次对话可能消耗大量 token需要做好日志统计和预算告警。希望这篇实战拆解能帮你少踩一些坑。如果你正准备搭建自己的企业级 AI Agent不妨先照着这篇文章把最小闭环跑通然后再逐步扩展成符合业务需求的生产系统。技术选型没有银弹但 LangChain LangGraph MCP 的组合在 2026 年的企业级大模型应用开发中绝对是一套值得投入学习的成熟方案。