ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LangChain Agent集成MCP与记忆系统:企业级应用实战指南

LangChain Agent集成MCP与记忆系统:企业级应用实战指南 在实际 AI 应用工程化过程中 LangChain Agent 真正难的点并不是“能调用工具”而是“工具从哪来、如何被模型理解、以及多次对话后 Agent 还能不能记住用户的关键信息”。MCPModel Context Protocol恰好补上了工具接入方式不统一这一环而企业级 Agent 记忆系统则决定了应用从“能跑通 demo”走向“能长期稳定服务”。这篇内容围绕 LangChain Agent 集成 MCP 的完整流程展开并给出可落地的 Agent 记忆系统设计思路适合正在做 Agent 应用、想解决工具集成和记忆持久化问题的开发者阅读。整篇文章会以一个最小可运行的示例为主线逐步拆解 MCP Server、MCP Client、LangChain Agent、检查点记忆、向量记忆和上下文压缩之间的关系最后补充生产环境最常遇到的故障现象和排查路径。1. 先理清 LangChain Agent、MCP 和记忆三者的分工1.1 Agent 不是固定调用链而是“模型做决策、工具执行”很多初学者会把 Agent 理解成一段 if-else 编排代码比如“先调用搜索再调用数据库最后生成答案”。这种固定流程在单一场景下能跑通但一旦业务规则变化、工具数量增加代码就会变得难以维护。LangChain 中的 Agent 核心思路是把“下一步做什么”交给大模型来推理模型根据用户输入、可用工具列表和当前上下文推理出需要调用哪个工具、传入什么参数然后执行工具把结果交回给模型继续生成。这种机制的优势是任务规划灵活缺点是模型可能选错工具或生成错误参数。所以生产环境里Agent 不只是“模型加几个函数”还需要有工具描述、参数校验、调用日志、失败重试和结果截断等保护机制。把 Agent 当作一个稳定的执行框架来设计而不是当作一个临时脚本是后续工程化的前提。1.2 MCP 解决的问题是工具协议标准化在没有 MCP 之前LangChain Agent 接入一个外部能力通常需要专门写一个 Tool 类定义 name、description、args_schema 和 _run 方法如果要接另一个服务又要重复写一套。每个服务都有自己的鉴权方式、请求格式和数据返回结构Agent 项目里的工具代码会迅速膨胀而且很难复用。MCP 把这个过程标准化了工具提供方实现一个 MCP Server通过 JSON-RPC 暴露工具列表和工具调用入口工具使用方通过 MCP Client 发现工具、获取参数 Schema、发起调用。LangChain 社区提供的 MCP 适配组件可以把 MCP Server 暴露的工具直接转换成 LangChain 可识别的工具列表Agent 不需要关心工具背后的 HTTP 接口、数据库连接还是本地命令只要面向协议编码。1.3 为什么要把记忆单独拿出来做企业级设计单轮对话场景里Agent 只要把当次工具调用结果拼进上下文即可。到了企业级场景用户会连续提问比如“帮我查一下上周的订单数据”之后又追问“那退款率呢”如果没有记忆第二个问题就丢失了“上周订单”这个关键条件。更复杂的情况是 Agent 需要在多次会话之间记住用户的偏好、常用地址、项目代号或审批规则。记忆的难点不在“存起来”而在“何时存、何时取、如何不污染当前上下文”。如果每轮对话都把全部历史记录塞给模型很快会超出上下文窗口推理成本和延迟也会上升。所以企业级 Agent 记忆系统的核心设计目标有三个保存必要信息、检索相关信息、控制上下文体量。组件解决的问题典型实现手段Agent让模型决定调用什么工具完成目标LangChain Agent、LangGraphMCP统一工具的发现、描述和调用协议MCP Server、MCP Client记忆让 Agent 在轮次之间保持上下文一致Checkpointer、向量存储、摘要压缩2. 环境准备和项目结构设计2.1 语言与依赖选型目前 LangChain 的 Python 生态最成熟MCP 的 Python SDK 也足够稳定所以下面示例以 Python 3.10 以上环境为基础。实际项目落地前先确认你的 LangChain 版本、LangChain MCP 适配器版本和 MCP SDK 版本是否匹配不要直接复制最新版本的安装命令却不看版本兼容性。建议在一个干净的虚拟环境中操作python -m venv .venv source .venv/bin/activate pip install --upgrade pip核心依赖可以按下面这组安装这是截至本文写作时常见的组合pip install langchain langchain-openai langchain-core mcp如果计划使用 LangGraph 做持久化和更精细的流程控制可以额外安装pip install langgraph这里要注意一点LangChain 和 LangGraph 是两个不同层次的框架。LangChain 提供模型封装、提示词模板、工具调用等基础能力LangGraph 更关注 Agent 的状态流转和可控编排。中小项目可以用 LangChain Agent 快速跑通生产级别建议把状态管理和记忆交给 LangGraph。2.2 最小项目结构为了不让示例变成面条代码建议按职责拆分模块即使是最小项目也保留清晰边界agent_mcp_demo/ ├── .env ├── requirements.txt ├── mcp_server.py ├── mcp_client.py ├── agent_app.py └── memory/ ├── __init__.py ├── short_term.py └── long_term.pymcp_server.py模拟业务系统暴露一个查询工具。mcp_client.py负责连接 MCP Server加载工具列表。agent_app.py创建 LangChain Agent接入 MCP 工具和记忆模块。memory/独立处理短期记忆和长期记忆。这样的结构在学习阶段可能显得“重”但进入生产后你会感谢这种拆分因为定位问题、替换组件、写单元测试都会更容易。2.3 环境变量设计项目根目录创建一个 .env 文件把模型 API Key、MCP Server 地址等敏感信息放在环境变量中OPENAI_API_KEYsk-xxxx OPENAI_MODEL_NAMEgpt-4o-mini MCP_SERVER_URLhttp://localhost:8000/mcp注意不同模型的工具调用能力差异很大如果模型本身不支持 function callingLangChain Agent 就很难稳定工作。所以环境准备阶段要先确认模型具备工具调用能力且 API 端点的兼容性没有问题。建议不要为了省事把 API Key 写在代码里。特别是 Agent 项目日志一旦打印出请求体或异常信息密钥就可能泄露。3. 从零实现一个 MCP Server再接入 LangChain Agent3.1 先实现一个提供业务数据的 MCP Server下面用 FastMCP 实现一个最小 Server。它暴露一个get_user_orders工具入参是用户 ID返回订单列表。这个工具在真实项目里可以换成查询 CRM、ERP 或订单中台但协议层完全一致。# mcp_server.py from mcp.server.fastmcp import FastMCP mcp FastMCP(order-service) mcp.tool() def get_user_orders(user_id: str) - str: 根据用户 ID 查询最近订单列表 if user_id u_1001: return 订单号: SO20250101, 金额: 199.00, 状态: 已发货; 订单号: SO20250102, 金额: 89.00, 状态: 待付款 return 该用户暂无订单 if __name__ __main__: mcp.run(transportstdio)mcp.tool() 装饰器把函数暴露成一个 MCP 工具。函数名和 docstring 都会成为工具描述的一部分模型会根据这些信息判断“什么时候该调用这个工具”。transportstdio 表示通过标准输入输出与客户端通信适合本地进程集成。如果是远程服务可以换成 sse 或 streamable-http但需要考虑鉴权和网络隔离。3.2 用 MCP 客户端连接并加载工具LangChain 生态里可以使用mcp的客户端或者 LangChain 的 MCP 适配器。下面这个客户端负责连接 Server拿到工具列表。# mcp_client.py from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from contextlib import AsyncExitStack from langchain_mcp_adapters.tools import load_mcp_tools class McpToolLoader: def __init__(self, command: str, args: list[str]): self.command command self.args args self.exit_stack AsyncExitStack() self.session None async def load_tools(self): server_params StdioServerParameters( commandself.command, argsself.args, envNone, ) read, write await self.exit_stack.enter_async_context( stdio_client(server_params) ) self.session await self.exit_stack.enter_async_context( ClientSession(read, write) ) await self.session.initialize() tools await load_mcp_tools(self.session) return tools async def close(self): await self.exit_stack.aclose()关键点StdioServerParameters 描述要启动的子进程命令这里就是python mcp_server.py。ClientSession 负责与 Server 建立会话。load_mcp_tools 是 LangChain MCP 适配器提供的函数把 MCP 工具转换成 Agent 可用的 Tool 对象。3.3 在 LangChain 中创建 Agent创建 Agent 时需要把模型、工具和提示词组合起来。下面是最常见的 create_agent 用法# agent_app.py import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import create_agent from langchain.agents.output_parsers import OpenAIToolsAgentOutputParser from mcp_client import McpToolLoader load_dotenv() async def build_agent(): loader McpToolLoader( commandpython, args[mcp_server.py], ) tools await loader.load_tools() llm ChatOpenAI( modelos.getenv(OPENAI_MODEL_NAME, gpt-4o-mini), api_keyos.getenv(OPENAI_API_KEY), temperature0, ) agent create_agent( llmllm, toolstools, system_prompt( 你是一个企业订单助手。用户询问订单信息时你必须先调用工具查询 不要凭记忆编造订单数据。工具返回结果后用简洁的中文概括给用户。 ), ) return agent这里有一个容易被忽略的点system_prompt 不只是“人设”它也是一种安全约束。对于企业级 Agent建议在系统提示词里明确“哪些信息不能编造”“必须依赖工具结果”“遇到敏感问题如何拒绝”。3.4 验证 Agent 能否调用 MCP 工具编写一个运行入口传入用户问题并观察输出# run_demo.py import asyncio from agent_app import build_agent async def main(): agent await build_agent() result await agent.ainvoke({messages: [(user, 请查一下 u_1001 用户的最近订单)]}) print(result[messages][-1].content) asyncio.run(main())预期 normal 流程是模型发现需要调用get_user_orders工具Agent 执行工具拿到订单字符串模型再把字符串整理成自然语言答复。如果看到ToolNotFoundError或agent did not respond通常意味着工具加载失败或模型没有返回工具调用指令这会在后面的排查部分专门说明。4. 企业级 Agent 记忆系统实战4.1 记忆的分类短期、长期和程序性知识设计记忆系统之前先把记忆分类否则后续实现会变成“所有东西都塞向量库”。短期记忆指当前会话内的消息记录。它决定了 Agent 在同一个会话里能理解前文和后文。长期记忆指跨会话存储的用户偏好、历史事实、业务上下文。例如用户常用的收货地址、客户等级、历史订单偏好。程序性知识指 Agent 如何执行任务的规则和方法。这类内容更适合放在 system prompt 或工作流定义中而不是记忆系统里。企业级记忆系统主要处理前两类。短期记忆的关键是“存得下、剪得掉”长期记忆的关键是“检索准、更新对”。4.2 短期记忆基于 Checkpointer 的会话持久化在 LangGraph 里Checkpointer 负责把 Agent 每一步的状态持久化到存储中。最轻量的方式是使用MemorySaver但生产环境建议换成 Redis 或数据库实现因为 MemorySaver 只在进程内有效服务重启就会丢失。# memory/short_term.py from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import StateGraph, MessagesState from langgraph.prebuilt import ToolNode # 这里以 LangGraph 状态图为示例 checkpointer MemorySaver() def build_graph_with_checkpointer(agent_node): graph StateGraph(MessagesState) graph.add_node(agent, agent_node) graph.add_node(tools, ToolNode(tools)) graph.add_edge(agent, tools) graph.add_edge(tools, agent) graph.set_entry_point(agent) return graph.compile(checkpointercheckpointer)使用 Checkpointer 之后每次调用都需要传入configurable.thread_id它相当于会话 IDconfig {configurable: {thread_id: user_session_123}} result await app.ainvoke( {messages: [(user, 那退款率呢)]}, configconfig, )这个 thread_id 让 Agent 在上一个问题的基础上继续推理而不是每次从零开始。4.3 长期记忆基于向量的用户画像和事实缓存长期记忆的典型做法是把关键信息向量化后存入向量数据库。下面用一个简化示例说明设计思路当用户提出一个包含可记忆信息的问题时系统先抽取一条事实写入向量库下次用户提到类似内容时从向量库检索出相关记忆拼接到当前上下文中。# memory/long_term.py from langchain_openai import OpenAIEmbeddings from langchain_core.vectorstores import InMemoryVectorStore class LongTermMemory: def __init__(self, embedding_model: str): self.embeddings OpenAIEmbeddings(modelembedding_model) self.vector_store InMemoryVectorStore(self.embeddings) async def remember(self, user_id: str, fact: str): doc f{user_id}: {fact} await self.vector_store.aadd_texts([doc]) async def recall(self, user_id: str, query: str, k: int 3) - str: docs await self.vector_store.asimilarity_search(query, kk) filtered [d.page_content for d in docs if d.page_content.startswith(user_id)] return \n.join(filtered) if filtered else 这里的 InMemoryVectorStore 只是为了讲清楚流程生产环境建议替换为支持持久化的向量库。检索时按 user_id 做过滤很重要否则一个用户的记忆可能被另一个用户检索出来这在多租户场景是严重事故。4.4 记忆管理的清理、过期和权限控制记忆系统不能只写不删。实际项目中至少要考虑三个问题过期用户画像可能变化比如用户三个月前常买某品类现在兴趣已经转移记忆系统要有时间戳和淘汰策略。清理用户主动要求删除记忆时系统必须能按用户 ID 清除否则会触碰隐私合规问题。权限不同角色的用户能看到的记忆范围不同。比如普通用户只能看到自己的订单记录客服人员才能查看辅助信息。可维护一张记忆元数据表来支撑这些能力字段含义示例user_id用户标识u_1001memory_key记忆类别address / preferencecontent记忆内容默认收货地址北京市朝阳区created_at写入时间2025-01-01 10:00:00expire_at过期时间2025-06-01 10:00:00source来源user_input / agent_extract这张表最好与向量库配合SQL 负责精确过滤和管理元数据向量库负责语义检索。不要试图让向量库承担所有管理功能。注意长期记忆写入前一定要做内容校验。不要直接把用户原话写入记忆因为可能包含敏感信息、脏数据或无关闲聊。建议先让模型抽取结构化记忆点再由程序确认后再入库。5. 验证、日志和常见问题排查5.1 验证链从 MCP 连通性到 Agent 决策跑通 demo 之后验证不能只看“程序不报错”。推荐按这条链路逐层确认MCP Server 是否能单独启动工具能否被客户端发现。工具调用是否能在不经过 Agent 的情况下返回正确数据。Agent 是否能根据用户问题选择正确工具。Agent 是否能正确处理工具返回的异常数据。记忆模块是否能在第二轮对话中命中预期信息。上下文压缩后Agent 是否仍然保留关键信息。每一步都可以写一个独立的小测试脚本。比如单独验证 MCP 工具可以临时调用load_tools后直接打印工具列表。5.2 日志记录的关键内容Agent 项目日志比普通 Web 服务更难排查因为同一个请求会经历“模型推理 - 工具调用 - 模型再推理”。建议至少记录用户问题原文模型选择的工具名和参数工具返回的原始结果记忆模块写入和检索的内容最终的模型回复每个阶段的耗时下面是一个建议的日志输出格式[AGENT] question请查一下 u_1001 的最近订单 [AGENT] tool_usedget_user_orders args{user_id:u_1001} [TOOL] result订单号: SO20250101, 金额: 199.00, 状态: 已发货 [AGENT] memory_writeu_1001 default_address北京市朝阳区 [AGENT] final_answer该用户最近有两笔订单...日志中不要记录 API Key、完整 token、用户隐私明文等敏感字段。5.3 常见坑与排查表问题现象常见原因检查方式处理建议Agent 说没有可用工具MCP Server 未启动或工具加载失败打印 tools 列表长度查看 MCP Client 日志先单独运行 mcp_server.py再检查 StdioServerParameters 参数工具调用返回空结果或异常MCP Server 内部报错或入参校验失败在 MCP Server 中增加 try-except打印入参检查工具函数的 docstring 和参数名模型依赖于描述生成正确参数模型反复选择错误工具工具描述不清晰工具之间边界模糊查看完整 tool schema 和提示词重写工具 description明确“何时使用、何时不用”第二轮对话丢失上文没有使用 Checkpointer或 thread_id 不一致检查每次请求是否传入同一个 thread_id使用持久化 Checkpointer并将 thread_id 绑定到用户会话检索到的记忆与问题无关向量检索没有按用户过滤或 k 值过大打印 recall 返回结果增加 user_id 过滤调小 k增加相关性阈值上下文过长导致推理变慢全部历史都塞入模型没有压缩摘要记录 token 使用量和上下文长度加入消息摘要压缩超过阈值后把旧消息替换为摘要Agent 调用工具后没有最终回答输出解析器异常或模型未按格式返回查看原始推理输出日志升级到兼容版本或改用 LangGraph 的 prebuilt agent5.4 排查 Agent 问题时按这个顺序来很多 Agent 问题看起来像模型问题实际是数据和配置问题。建议按以下顺序排查输入是否正确用户问题是否清晰是否缺少必要参数。工具是否就绪MCP Server 是否存活工具列表是否加载。工具描述是否准确模型是否可能误解工具用途。工具返回是否符合预期返回数据是否被截断、格式是否异常。记忆是否被正确写入和检索检查写入内容是否包含噪声。模型版本和参数是否合适temperature 过高会导致工具选择不稳定。是否到达上下文窗口限制查看 token 用量和报错信息。6. 生产环境部署的注意事项与最佳实践6.1 学习环境与生产环境的差异学习环境里所有组件可以跑在同一个进程里但生产环境必须拆开。MCP Server 应该作为独立服务调用方通过受控网络访问记忆系统使用独立存储不要依赖进程内内存Agent 服务则要保持无状态方便水平扩容。维度学习环境生产环境MCP Server本地 stdio 子进程独立部署走 HTTP/SSE 协议增加鉴权短期记忆MemorySaverRedis 或 Postgres 持久化长期记忆InMemoryVectorStore生产级向量数据库支持过滤和备份模型配置环境变量直接配通过配置中心管理支持模型灰度切换日志控制台直接打印结构化日志接入日志平台和告警安全不重点关注工具权限隔离敏感数据脱敏用户数据隔离6.2 安全边界和工具权限Agent 的工具能力越强越要限制“谁能用、能用到什么程度”。建议为每个工具定义最小权限范围并在工具内部做二次校验不要只依靠提示词约束模型。比如查询订单工具应该校验调用者是否属于该用户的数据范围、是否具备查询权限、请求频率是否异常。MCP Server 侧也要做接收方校验。如果 Server 暴露在网络上不能接受任何来源的匿名调用至少要校验调用方身份。这类校验在协议层做不要放在 Agent 代码里。6.3 推理成本控制Agent 项目成本通常高于普通聊天应用原因是一次用户请求可能要经历多轮“模型决策 - 工具调用 - 模型总结”。优化方向有三个工具描述尽量精简减少模型处理无关工具的负担。上下文压缩策略要主动不要等超限再截断。对失败的调用尽早终止设置最大迭代步数避免模型在错误路径上反复尝试。LangGraph 中可以设置recursion_limit控制最大执行步数建议设置为 10 到 15防止异常情况下无限循环。6.4 发布前检查清单上线一个 LangChain Agent MCP 记忆系统的服务前至少确认以下项目MCP Server 工具是否在无人值守下能稳定启动。Agent 是否能在工具不可用时给出明确失败提示而不是幻觉。记忆写入是否经过内容校验用户能否删除自己的记忆。日志是否包含请求链路跟踪 ID方便问题回溯。是否有超时控制和最大步数限制。是否有针对敏感数据的数据脱敏处理。是否做了模型输出格式校验避免直接透传工具的异常内容。完成这些检查后项目才算从“能跑 demo”进入“能上线”的阶段。对于刚开始接触 LangChain、Agent 和 MCP 的开发者建议先按这篇文章的最小示例跑通再加入短期记忆最后引入向量长期记忆每一步都验证后再进入下一步。这样比一次性搭建完整系统更容易定位问题也更容易理解每个组件存在的理由。
返回列表