目录写在前面本文内容1. 记忆系统1.1 短期记忆线程内状态1.2 长期记忆跨线程持久化1.3 记忆系统真正难的地方2. RAG / 知识接入2.1 RAG 不等于向量库2.2 三种常见模式2.3 retrieval 常常先做成工具2.4 RAG 和 memory 的边界3. Multi-agent3.1 多代理到底在解决什么3.2 先把五种模式分清再谈实现3.3 subagents主代理当 supervisor子代理当工具3.4 handoffs让当前活跃角色发生切换3.5 skills不是换一个 agent而是让同一个 agent 按需加载专长3.6 router先做分类再并行派发3.7 custom workflow标准模式不够时直接上 LangGraph3.8 怎么选模式3.9 什么时候该用 Multi-agent4. 总结LangChain 全景地图4.1 核心能力回顾4.2 总结参考文档写在前面在上篇《LangChain 框架核心入门从组件到控制系统》中我们掌握了 LangChain 的核心开发能力核心组件model、messages、agent、streaming、structured output工具系统让 Agent 获得行动能力中间件与控制系统让 Agent 可控、可治理、可上线学完上篇你已经能搭建一个可控、可运行的 Agent 系统。但这还不够。真实场景里Agent 还需要记住用户记住偏好、历史、上下文而不是每轮对话都从零开始获取知识模型知识是静态的但业务数据是动态的怎么按需获取协作分工复杂任务一个 Agent 搞不定怎么拆给多个 Agent 协作这篇文章解决的就是这三个问题。本文内容记忆系统短期记忆与长期记忆RAG / 知识接入外部知识如何按需进入系统Multi-agent单代理装不下时如何拆分目标很简单一篇文章带你掌握 LangChain 的进阶能力。看完后你能构建有记忆、有知识、能协作的复杂 Agent 系统。1. 记忆系统Agent 怎样在当前线程里保留状态又怎样跨线程保留经验这里一定要先分开两类记忆。1.1 短期记忆线程内状态在 LangChain 里短期记忆的核心是thread、state、checkpointer。本质上它不是一个神奇记忆模块而是当前线程状态的持久化机制。from langchain.agents import create_agent from langgraph.checkpoint.memory import InMemorySaver agent create_agent( modelopenai:gpt-5.4, tools[], checkpointerInMemorySaver(), )短期记忆不是额外外挂而是 agent 状态如何跨轮次被保存。但短期记忆不等于把所有历史消息无限堆进去。长线程必须做三件事裁剪摘要只保留真正影响后续决策的信息这也是为什么短期记忆会和SummarizationMiddleware、ContextEditingMiddleware强绑定。1.2 长期记忆跨线程持久化长期记忆对应的是store。它不是当前线程的一部分而是跨线程、跨会话可复用的持久存储。官方文档常提三类长期记忆semantic memory用户资料、偏好、事实性知识episodic memory过去发生过的任务、事件、交互片段procedural memory做事规则、操作偏好、固定流程对开发者来说更关键的不是记住术语而是看明白长期记忆解决的是下次还能记得不是本轮不要忘。from dataclasses import dataclass from langchain.tools import ToolRuntime, tool dataclass class Context: user_id: str tool def get_user_preference(runtime: ToolRuntime[Context]) - str: item runtime.store.get((preferences,), runtime.context.user_id) return str(item.value) if item else No saved preference如果要写入长期记忆也是同样的入口tool def save_user_preference(key: str, value: str, runtime: ToolRuntime[Context]) - str: runtime.store.put((preferences,), runtime.context.user_id, {key: value}) return Preference saved长期记忆在 LangChain 里不是一个聊天外挂而是一个标准化的可读写存储接口。1.3 记忆系统真正难的地方记忆系统最难的地方从来不是怎么存而是三件事写什么什么时候写什么时候读如果什么都写store 会变垃圾场。如果什么都读模型上下文会被历史噪声淹没。所以记忆系统的设计本质上不是存储问题而是筛选问题。2. RAG / 知识接入这一章单独拿出来讲是因为它和 memory 有联系但不是一回事。RAG 要解决的问题是模型知识是静态的上下文窗口是有限的外部知识怎么在需要的时候进来2.1 RAG 不等于向量库很多人一学 RAG就等于一学向量数据库。这是不对的。RAG 的本质是按需取回外部知识并喂给模型。至于这个知识来自向量库SQL搜索引擎文档系统企业知识库API都只是实现形式。RAG 不是某种数据库技术而是一种知识接入模式。2.2 三种常见模式2-step RAG先检索再生成优点是稳、简单、可控适合大多数新手项目Agentic RAG让 agent 自己决定何时检索、检索几次、换什么检索策略更灵活但也更容易失控Hybrid RAG固定流程和 agent 决策混合比如先做一次基础检索再允许 agent 追问补检索开发上最实用的建议是默认先从 2-step 开始不要一上来就做全自动 agentic retrieval。2.3 retrieval 常常先做成工具从 LangChain 的整体抽象看retrieval 最自然的落点就是工具。因为检索本身就是一种外部能力调用。from langchain.tools import tool tool def search_docs(query: str) - str: Search the internal docs and return the most relevant passages. return Top passages for: query然后再交给 agentfrom langchain.agents import create_agent agent create_agent( modelopenai:gpt-5.4, tools[search_docs], system_promptUse search_docs when the answer depends on external knowledge., )RAG 在 LangChain 里最自然的入口不是先搭一整套大平台而是先把检索变成可调用能力。2.4 RAG 和 memory 的边界这两个概念经常被混写但你必须分清。memory更偏系统是否记得用户、记得过去交互、记得偏好和经验retrieval更偏系统是否能按需拿到外部知识一个是过去沉淀下来的内部记忆一个是当前按需拉取的外部知识。这就是它们应该分章讲的原因。3. Multi-agentMulti-agent 回答的问题是单个 agent 装不下时怎么拆这章还是先给结论多代理很重要但它不是默认起点。很多时候一个带动态工具、动态 prompt、合理 middleware 的单 agent已经足够解决问题。只有在这些信号很明显时多代理才真正有必要单 agent 的上下文已经严重过载提示词和工具描述越堆越大不同任务需要完全不同的角色、知识域和工具集不同团队要独立维护不同能力模块你明确需要并行执行、阶段切换或者强约束流程3.1 多代理到底在解决什么LangChain 官方文档对这件事的判断非常准确开发者口中的 multi-agent通常想解决的是上下文管理、分工维护和并行执行而不只是让系统更聪明。更直白一点说如果上下文无限大、延迟无限低你完全可以把所有知识和工具都塞进一个 agent但现实不是这样所以你必须决定谁看到什么谁在什么时候出手谁能调用哪些工具这就是官方反复强调的context engineering。多代理设计的核心不是多几个角色名而是把正确的信息交给正确的执行单元。3.2 先把五种模式分清再谈实现旧写法里最容易让读者混淆的一点是只记住了几个术语但不知道它们的边界。LangChain 官方 Multi-agent 一共讲了五种模式模式核心机制最适合什么问题主要代价subagents主代理把子代理当工具来调用中央调度、多领域隔离、强控制多一次协调调用链路更长handoffs工具更新状态切换当前活跃角色或阶段多轮对话、顺序约束、当前角色直接和用户对话状态设计更关键消息传递更敏感skills单 agent 按需加载专门技能提示和资料大量专业能力、按需加载上下文不像子代理那样天然隔离执行过程router先路由分类再把任务派给一个或多个专门代理输入类别清晰、需要并行查询多个领域路由本身通常是额外一步custom workflow用 LangGraph 自定义图混合确定性节点和 agent 节点标准模式不够用需要分支、循环、人工审批、复杂编排代码更多但控制力最强这个表最好反复看。因为后面所有怎么写代码其实都是在回答你到底是要中央调度、状态切换、按需加载、先分类还是完全自定义流程3.3subagents主代理当 supervisor子代理当工具subagents是最符合很多人直觉的多代理模式有一个主代理负责和用户对话、保留主线程记忆、决定调用谁子代理只处理自己那一小块任务。官方文档里对它的定义有几个关键词非常重要centralized control所有路由都经过主代理subagents via tools子代理通常是以 tool 的形式暴露给主代理stateless subagents子代理默认是无状态的记忆主要由主代理持有parallel execution主代理可以在一个回合里并行调用多个子代理什么时候优先考虑subagents你有多个明确领域比如日历、邮件、CRM、数据库、代码库子代理不需要直接和用户对话你希望主代理统一掌控流程和结果整合你非常在意上下文隔离不想把每个领域的长上下文都塞进主对话一个最小实现通常就是先创建子代理再把子代理包装成工具最后让主代理决定什么时候调用它们。from langchain.agents import create_agent from langchain.tools import tool research_agent create_agent( modelopenai:gpt-5.4, tools[], system_promptYou are a research specialist. Focus on facts, sources, and background., ) writer_agent create_agent( modelopenai:gpt-5.4, tools[], system_promptYou are a writing specialist. Turn notes into clean drafts., ) tool(research, descriptionResearch facts, sources, and background information) def call_research_agent(query: str) - str: result research_agent.invoke( {messages: [{role: user, content: query}]} ) return result[messages][-1].content tool(write_draft, descriptionWrite or revise article drafts) def call_writer_agent(task: str) - str: result writer_agent.invoke( {messages: [{role: user, content: task}]} ) return result[messages][-1].content supervisor create_agent( modelopenai:gpt-5.4, tools[call_research_agent, call_writer_agent], system_prompt( You are the supervisor. Use research for fact-finding and write_draft for drafting. You keep the conversation with the user and combine the results. ), )这段代码背后的开发含义比代码本身重要主代理负责调度和整合子代理负责在隔离上下文里完成局部任务主线程不需要吃下所有中间推理细节只需要拿回结果摘要官方文档还特别强调了几个设计点实际开发里非常有用第一工具暴露方式有两种。tool per agent一个子代理一个工具最直观也最容易细调输入输出single dispatch tool用一个统一的task(agent_name, description)调度多个子代理适合代理很多、团队很多、注册表可能动态变化的场景如果代理很多官方建议不要把所有代理都硬编码进主 prompt。你可以再提供一个list_agents或search_agents工具让主代理按需发现可用子代理这本质上也是progressive disclosure。第二同步还是异步要按业务链路决定。同步调用主代理必须等子代理结果回来最简单异步调用主代理只发起后台任务不阻塞当前对话官方给异步模式的建议非常实用通常做成三类工具即可。start_jobcheck_statusget_result这说明一件事这里的 async 不是 Python 语法层面的async/await而是产品层面的后台任务设计。第三subagents的关键不是多几个 agent而是上下文工程。你至少要认真设计三件事子代理的名字和描述这是主代理判断何时调用它的主要提示信号传给子代理的输入只传 query还是连任务约束、用户偏好、摘要一起传子代理返回什么是返回最终摘要还是返回完整对话历史绝大多数时候返回面向主代理的简洁结果比返回完整 transcript 更好。因为你做subagents的初衷本来就是为了隔离上下文而不是把所有上下文重新灌回主线程。3.4handoffs让当前活跃角色发生切换handoffs是另一种很常见、也很容易被误解的模式。它的核心不是神秘代理协议而是工具调用更新状态状态变化再触发 prompt、工具集或执行节点的变化。官方文档里讲得很清楚handoffs的关键词是state-driven behavior行为由状态决定tool-based transitions状态切换通常由工具触发direct user interaction切换后的角色可以继续直接和用户对话persistent state这个状态会跨回合保留所以它特别适合什么你要做多阶段对话你要强制顺序约束先收集信息再开放后续能力当前阶段的角色需要直接和用户继续聊下去比如客服流里必须先拿到保修编号再进入退款或维修流程。这种场景用handoffs就比subagents更自然。下面是一个简化版思路工具写状态middleware 根据状态切换当前阶段的 prompt 和工具集。from typing import Callable from typing_extensions import TypedDict from langchain.agents import create_agent from langchain.agents.middleware import ModelRequest, ModelResponse, wrap_model_call from langchain.messages import ToolMessage from langchain.tools import tool, ToolRuntime from langgraph.checkpoint.memory import InMemorySaver from langgraph.types import Command class SupportState(TypedDict, totalFalse): current_step: str warranty_status: str tool def record_warranty_status( status: str, runtime: ToolRuntime[None, SupportState], ) - Command: return Command( update{ messages: [ ToolMessage( contentfWarranty status recorded: {status}, tool_call_idruntime.tool_call_id, ) ], warranty_status: status, current_step: specialist, } ) wrap_model_call def apply_step_config( request: ModelRequest, handler: Callable[[ModelRequest], ModelResponse], ) - ModelResponse: step request.state.get(current_step, triage) configs { triage: { prompt: Collect warranty information before solving the issue., tools: [record_warranty_status], }, specialist: { prompt: Provide a solution based on warranty_status{warranty_status}., tools: [], }, } config configs[step] request request.override( system_promptconfig[prompt].format(**request.state), toolsconfig[tools], ) return handler(request) agent create_agent( modelopenai:gpt-5.4, tools[record_warranty_status], state_schemaSupportState, middleware[apply_step_config], checkpointerInMemorySaver(), )这段代码里有两个官方文档特别提醒的细节很多人第一次写会漏handoff 工具通常返回Command因为它要更新状态甚至跳转节点如果工具更新了消息历史必须补上和当前tool_call_id对应的ToolMessage否则消息序列会不完整这个模式还有两种落地方式单 agent middleware本质上是一个 agent根据状态动态换 prompt 和 tools多个 agent subgraphs每个角色是一个单独节点handoff 工具通过Command(goto...)跳到另一个节点前者实现更轻后者边界更清楚。但后者也更考验你对消息传递和上下文裁剪的掌控因为不同子图之间传什么消息得你自己明确决定。3.5skills不是换一个 agent而是让同一个 agent 按需加载专长skills是很多人容易忽视、但实际上非常实用的一种模式。它的想法不是多造几个代理而是让一个主 agent 在需要时加载某项专业能力对应的提示、知识、模板或参考资料。官方把它概括成几个关键词prompt-driven specializationprogressive disclosurelightweight compositionreference awareness这意味着skills更像什么更像是按需加载的专长包而不是一个完整的、独立执行的子代理。什么时候优先用skills你还是想维持一个主 agent专长很多但不是每次都要全部塞进上下文这些能力之间没有很强的流程切换约束你想让不同团队独立维护不同技能文件或知识包一个最小实现通常是做一个load_skill工具按名字返回该技能的提示和上下文。from pathlib import Path from langchain.agents import create_agent from langchain.tools import tool SKILLS { write_sql: Path(skills/write_sql.md), review_legal_doc: Path(skills/review_legal_doc.md), } tool def load_skill(skill_name: str) - str: Load a specialized skill prompt and references. return SKILLS[skill_name].read_text(encodingutf-8) agent create_agent( modelopenai:gpt-5.4, tools[load_skill], system_prompt( You are a helpful assistant. When the task becomes specialized, use load_skill to load the right skill first. ), )这段代码真正表达的是把专业知识做成按需读取的资产而不是默认塞进 system prompt。官方文档还给了几个很好的扩展方向动态工具注册加载某个 skill 时不只是注入提示也动态开放这类工具分层技能先加载data_science再按需加载pandas_expert或visualization引用外部资产skill 本身很短但它告诉 agent 相关脚本、模板、文档放在哪里需要时再读所以skills的核心收益是少塞上下文按需揭示能力。它本质上仍然是context engineering。3.6router先做分类再并行派发router模式特别适合输入类别很清楚的系统。它不是让一个主代理边聊边决定而是先做一次路由判断再把任务发给一个或多个专门代理。官方对它的定义很清楚先做 routing / classification调用零个、一个或多个专门代理最后把结果综合成一个答案它最适合什么领域边界清楚比如 GitHub、Notion、Slack、数据库、代码仓库你需要并行查询多个来源你希望路由逻辑更显式、更容易替换成规则或轻量模型LangGraph 里单路由和并行 fan-out 的写法分别对应Command和Send。并行版思路很简单from typing import TypedDict from langgraph.types import Send class RouterState(TypedDict): query: str def classify_query(query: str) - list[dict[str, str]]: Return a list like [{agent: github_agent, query: ...}]. ... def route_query(state: RouterState): classifications classify_query(state[query]) return [ Send(item[agent], {query: item[query]}) for item in classifications ]这个模式和subagents很像但不要混掉router更像一次显式的前置分类步骤subagents则是主代理在持续对话里动态决定调用谁官方还专门提醒了router的两种形态stateless router每次请求都重新路由不保留会话状态stateful router需要显式持久化上下文真实项目里一个很好用的折中方案是把无状态 router 封装成一个工具再交给会话型 agent 去调用。这样记忆由外层 agent 负责router 本身保持简单。3.7custom workflow标准模式不够时直接上 LangGraph如果你看到这里已经觉得我这个系统既有检索、又有审批、还要并行、还要失败重试、还要分支和循环好像哪种模式单独都不够。那就对了这正是custom workflow的适用范围。官方对它的定义非常直接用 LangGraph 自己定义执行图把确定性逻辑和 agent 行为混在同一个工作流里。它适合什么标准模式已经装不下真实业务你需要分支、循环、并行、人工中断、审批、回滚某些步骤必须是确定性代码某些步骤才交给模型最关键的一点是LangChain agent 可以直接作为 LangGraph 的一个节点来调用。from typing import TypedDict from langchain.agents import create_agent from langgraph.graph import StateGraph, START, END class WorkflowState(TypedDict): question: str documents: list[str] answer: str agent create_agent( modelopenai:gpt-5.4, tools[], ) def retrieve(state: WorkflowState) - dict: docs retriever.invoke(state[question]) return {documents: docs} def answer(state: WorkflowState) - dict: result agent.invoke( { messages: [ { role: user, content: f问题{state[question]}\n\n参考资料{state[documents]}, } ] } ) return {answer: result[messages][-1].content} workflow ( StateGraph(WorkflowState) .add_node(retrieve, retrieve) .add_node(answer, answer) .add_edge(START, retrieve) .add_edge(retrieve, answer) .add_edge(answer, END) .compile() )这个例子已经说明了custom workflow的价值retrieve是确定性节点answer是 agent 节点状态通过图中的结构化字段传递从官方文档的角度看router本身就是一种custom workflow。真正的分界线不是有没有多个 agent而是你是不是需要自己掌控整张执行图。3.8 怎么选模式官方文档还做了性能对比这里不需要死记数字但要记住结论单次 one-shot 请求handoffs、skills、router往往比subagents少一次协调开销重复请求handoffs和skills更容易复用当前状态或已加载技能多领域并行任务subagents和router更有优势因为它们更适合并行和上下文隔离把它翻译成开发决策就是你要中央调度 强隔离选subagents你要当前角色直接和用户继续聊 阶段切换选handoffs你要一个主 agent 按需加载专长选skills你要显式分类 并行派发多个领域选router你要完全控制分支、循环、人工环节和确定性步骤选custom workflow3.9 什么时候该用 Multi-agent多代理不是默认选项而是解决特定问题的手段。适合用 Multi-agent 的场景任务类型差异大需要不同专业角色单个 Agent 上下文过载需要隔离不同团队要独立维护不同能力需要明确的职责边界和审计追踪不适合用 Multi-agent 的场景任务相对简单单 Agent 能搞定上下文长度可控不需要拆分团队规模小维护成本考虑刚开始探索先验证核心逻辑建议先从单 Agent 开始遇到问题再考虑拆分。4. 总结LangChain 全景地图现在把上下篇的内容收成一张完整的开发地图。4.1 核心能力回顾模块职责关键对象核心组件让 Agent 跑起来模型、消息、装配入口、流式观察、结构化输出model、messages、agent、streaming、structured output工具系统让 Agent 能行动并把很多高级能力重新拉回同一条主轴Tool、ToolRuntime、Command、MCP中间件与控制系统让 Agent 可控、可治理、可上线middleware、runtime、context engineering记忆系统让 Agent 在当前线程和跨线程都能保留有效状态checkpointer、storeRAG / 知识接入让外部知识在需要的时候进入系统retrieval、vector storeMulti-agent在单代理装不下时做职责拆分和上下文隔离handoff、subagents、router4.2 总结所以真正应该记住的不是某个 API 名字而是这句话LangChain 不是调用大模型的工具箱而是组织 Agent 系统的框架。LangChain 的核心价值在于它把 Agent 的执行过程工程化了用核心组件搭起骨架用工具系统赋予行动能力用中间件实现控制和治理用记忆系统保留状态和经验用RAG接入外部知识用Multi-agent实现协作和分工当你用这个视角回看官方文档时原本零散的页面就会重新拼成一张清楚的图。参考文档Short-term MemoryLong-term MemoryMCPRetrievalMulti-agentMiddleware OverviewBuilt-in MiddlewareRuntimeContext Engineering