精读 LangChain 官方文档(一)Agents 篇:从 create_agent 看懂智能体的真实工作方式
精读 LangChain 官方文档(一)Agents 篇:从create_agent看懂智能体的真实工作方式
本文基于 LangChain 官方文档 Agents 页面整理:
https://docs.langchain.com/oss/python/langchain/agents
对应开源文档 MDX:
https://github.com/langchain-ai/docs/edit/main/src/oss/langchain/agents.mdx
如果你刚开始看 LangChain 的 Agent 文档,很容易被一堆词绕进去:model、tools、system_prompt、response_format、thread_id、middleware、checkpointer、stream。
但这篇官方文档真正想讲的主线其实很清楚:
Agent 不是“会思考的模型本身”,而是“模型 + 运行外壳”。
官方用一句话概括:Agent = Model + Harness。
其中Model是会生成、推理、决定下一步的模型;Harness是包在模型外面的执行环境,负责把正确上下文、工具、提示词、状态、约束和中间件,在正确时机交给模型。
换句话说,Agent 的关键不只是“模型聪不聪明”,而是你有没有给它设计一个可靠的工作台。
1. Agent(智能体)到底解决什么问题
它解决的问题:
让模型不再只是一次性回答,而是可以在“思考 -> 调工具 -> 观察结果 -> 继续决策”的循环里完成任务。
普通聊天模型通常是:
用户提问 -> 模型回答Agent 更像是:
用户任务 -> 模型判断 -> 调用工具 -> 拿到结果 -> 继续判断 -> 最终回答官方文档开头说,Agent 是一个模型循环调用工具,直到给定任务完成。这里的重点是“循环”和“工具”。
示例:
fromlangchain.agentsimportcreate_agent agent=create_agent("openai:gpt-5.4",tools=tools)这里:
create_agent:LangChain 提供的 Agent 创建函数,用来组装模型、工具、提示词、中间件等能力。"openai:gpt-5.4":模型标识符,格式通常是provider:model,其中provider表示模型服务提供方,model表示具体模型名。tools:传给 Agent 的工具集合,模型可以根据任务决定是否调用这些工具。
业务场景:
比如一个“订单售后助手”,不能只靠模型猜答案。它需要查订单、查物流、判断退款规则、生成回复话术。Agent 就是把模型和这些能力组织到一起。
最简记法:
Agent = 让模型带着工具循环做事。
2. Harness(运行外壳)为什么比模型本身更重要
它解决的问题:
把模型需要的上下文、工具、规则、状态和控制逻辑,在合适的时间送到模型面前。
官方文档把 Agent 拆成Model + Harness。这个Harness可以理解为“运行外壳”或“任务工作台”。
它包括:
model:真正负责生成和推理的模型。tools:模型可以调用的外部能力。system_prompt:约束模型行为的系统提示词。middleware:插入 Agent 循环的可组合扩展能力。state:Agent 运行过程中的消息、工具调用和中间结果。checkpointer:保存和恢复对话状态的检查点能力。
示例:
fromlangchain.agentsimportcreate_agent agent=create_agent(model="openai:gpt-5.4",tools=tools,system_prompt="你是一名企业知识库助手。回答要简洁、准确,并说明依据。",)这里:
model:指定 Agent 使用哪个模型。tools:定义模型可以调哪些工具。system_prompt:系统提示词,决定 Agent 的角色、语气、边界和输出要求。
业务场景:
一个客服 Agent 如果没有system_prompt,它可能回答得很随意;如果没有工具,它查不到订单;如果没有状态,它记不住上下文;如果没有中间件,它很难做安全审查和人工审批。
最简记法:
模型负责思考,Harness 负责把任务现场搭起来。
3. Model(模型):Agent 的推理发动机
它解决的问题:
告诉 Agent 用哪个模型来理解任务、生成回复、决定是否调用工具。
LangChain 的create_agent可以接收模型标识符字符串,也可以接收已经初始化好的模型实例。
示例:
fromlangchain.agentsimportcreate_agent agent=create_agent(model="openai:gpt-5.4",tools=[],)这里:
model:可以写成"provider:model"。例如"openai:gpt-5.4"表示 OpenAI 供应商下的某个模型。tools=[]:表示当前 Agent 暂时没有外部工具,只依赖模型直接回答。
如果你的模型服务是 OpenAI 兼容接口,也可以先初始化模型对象,再交给 Agent。下面是常见写法:
importosfromlangchain.agentsimportcreate_agentfromlangchain_openaiimportChatOpenAI model=ChatOpenAI(model="qwen-plus",api_key=os.getenv("QWEN_API_KEY"),base_url=os.getenv("QWEN_BASE_URL"),)agent=create_agent(model=model,tools=[],)这里:
ChatOpenAI:LangChain 的聊天模型客户端类,常用于 OpenAI 或 OpenAI 兼容服务。model="qwen-plus":具体模型名称,实际值要按你的服务商配置。api_key:接口密钥,示例中从环境变量QWEN_API_KEY读取,避免把真实密钥写进代码。base_url:OpenAI 兼容接口地址,示例中从环境变量QWEN_BASE_URL读取。
业务场景:
如果你在企业内部做 AI 助手,通常不会把模型配置写死。更常见的是后端根据环境变量、租户配置或成本策略选择模型。
最简记法:model决定 Agent 的脑子是谁。
4. Tools(工具):让模型从“会说”变成“会做”
它解决的问题:
把搜索、查库、调用接口、读写文件等外部能力暴露给模型,让模型在需要时调用。
官方示例中,工具可以是 Python callable、LangChain tool 或工具字典。最常见的是用@tool装饰一个函数。
示例:
fromlangchain.agentsimportcreate_agentfromlangchain.toolsimporttool# 定义一个搜索工具,供 Agent 在需要外部信息时调用。@tooldefsearch(query:str)->str:"""根据查询词搜索信息,并返回简短结果。"""returnf"搜索结果:{query}"agent=create_agent(model="openai:gpt-5.4",tools=[search],)这里:
@tool:把普通 Python 函数包装成 LangChain 工具,让 Agent 能识别和调用。search:工具函数名。函数名会影响模型理解这个工具的用途,建议命名清楚。query:工具参数,表示搜索关键词。tools=[search]:把工具注册到 Agent。
业务场景:
电商客服 Agent 可以有get_order_status(order_id)、query_refund_policy(product_id)、create_after_sales_ticket(user_id, order_id)等工具。模型负责判断什么时候调,工具负责做真实动作。
最简记法:
工具是 Agent 的手,模型是 Agent 的脑。
5. System Prompt(系统提示词):给 Agent 立规矩
它解决的问题:
让 Agent 明确自己的角色、回答风格、业务边界和安全约束。
system_prompt可以是字符串,也可以是SystemMessage。如果提示词需要根据运行时动态变化,官方建议使用middleware。
示例:
agent=create_agent(model="openai:gpt-5.4",tools=tools,system_prompt=("你是一名售后客服助手。""回答要先核对订单信息,再解释处理规则。""遇到退款、补偿、改地址等高影响操作时,必须提示需要人工确认。"),)这里:
system_prompt:系统级提示词,优先级高于普通用户消息。tools=tools:让提示词约束工具使用方式,例如“先查订单再回答”。
业务场景:
同样是一个搜索工具,用在“技术客服”里要给出处和排查步骤;用在“销售顾问”里要强调产品价值;用在“法务助手”里要加免责声明和人工复核。
最简记法:system_prompt是 Agent 的工作守则。
6. Structured Output(结构化输出):让结果能被程序接住
它解决的问题:
把 Agent 的自然语言回答变成可校验的数据结构,方便后端继续处理。
官方文档使用response_format=指定结构化输出 Schema。Python 中常见做法是定义一个 PydanticBaseModel。
示例:
frompydanticimportBaseModelfromlangchain.agentsimportcreate_agentclassAnswer(BaseModel):summary:strconfidence:floatagent=create_agent(model="openai:gpt-5.4",tools=tools,response_format=Answer,)result=agent.invoke({"messages":[{"role":"user","content":"请总结一下人工智能的发展趋势"}]})structured_answer=result["structured_response"]这里:
Answer:结构化输出模型,定义 Agent 最终输出应该包含哪些字段。summary:摘要字段,类型是字符串。confidence:置信度字段,类型是浮点数。response_format=Answer:要求 Agent 输出能被Answer校验的结构。result["structured_response"]:LangChain 返回结果里的结构化响应字段。
业务场景:
如果你做“工单自动分流”,就不能只要一段话。你可能需要:
category:工单类别。priority:优先级。summary:摘要。need_human:是否需要人工介入。
这些字段后续要写数据库、触发工作流、推送给运营人员,所以必须稳定。
最简记法:
自然语言给人看,结构化输出给系统用。
7. Name(名称):把 Agent 放进多智能体系统
它解决的问题:
给 Agent 一个可识别的节点名称,方便它作为子图或多智能体系统的一部分被引用。
官方文档里name是可选字段。当 Agent 被嵌入到 multi-agent 系统中时,这个名字会作为节点名使用。
示例:
agent=create_agent(model="openai:gpt-5.4",tools=tools,name="research_assistant",)这里:
name:Agent 名称。建议用清晰的英文标识,例如research_assistant、order_agent、refund_agent。research_assistant:示例名称,表示这个 Agent 主要负责研究和检索。
业务场景:
一个企业 AI 系统可以拆成多个 Agent:
router_agent:判断用户意图。order_agent:处理订单查询。refund_agent:处理退款判断。knowledge_agent:查询知识库。
有了name,系统编排和日志追踪会更清楚。
最简记法:name是 Agent 在复杂系统里的工牌。
8. Invocation(调用):用messages和thread_id驱动 Agent
它解决的问题:
把用户输入作为状态更新传给 Agent,并用thread_id维持同一段对话的历史。
LangChain Agent 继承了 LangGraph 的状态模型。官方文档强调:调用 Agent 时,传入的是对State的一次更新。所有 Agent 的状态里都包含一组messages。
示例:
fromlangchain.agentsimportcreate_agentfromlangchain_core.utils.uuidimportuuid7fromlanggraph.checkpoint.memoryimportInMemorySaver agent=create_agent(model="google_genai:gemini-3.5-flash",tools=[],checkpointer=InMemorySaver(),)config={"configurable":{"thread_id":str(uuid7())}}result=agent.invoke({"messages":[{"role":"user","content":"请查询上海今天的天气"}]},config=config,)result=agent.invoke({"messages":[{"role":"user","content":"那明天呢?"}]},config=config,)这里:
agent.invoke(...):同步调用 Agent,返回最终结果。messages:消息列表。每条消息通常包含role和content。role:消息角色,例如user表示用户,assistant表示模型助手。content:消息内容。config:调用配置。configurable:LangGraph/LangChain 中可配置参数的承载位置。thread_id:对话线程 ID,用来区分不同会话。checkpointer=InMemorySaver():本地内存检查点,用来保存和恢复对话状态。
注意:
如果要用thread_id持久化对话历史,Agent 必须配置checkpointer。在本地示例里可以用InMemorySaver(),生产环境通常需要更可靠的存储方案。
业务场景:
一个客服会话里,用户先问“我的订单到哪了”,后面又问“可以改地址吗”。如果两次调用没有复用同一个thread_id,Agent 就不知道“它”指的是哪个订单。
最简记法:thread_id管一段对话,messages送一轮输入。
9. Context(运行时上下文):把用户、密钥和开关传给工具
它解决的问题:
把每次运行才知道的数据传给工具和中间件,而不是写死在全局变量里。
官方文档区分了两个概念:
thread_id:负责对话历史和检查点。context:负责当前这次调用的运行时数据,例如用户 ID、API key、功能开关。
示例:
fromdataclassesimportdataclassfromlangchain.agentsimportcreate_agentfromlangchain_core.utils.uuidimportuuid7fromlanggraph.checkpoint.memoryimportInMemorySaver@dataclassclassContext:user_id:stragent=create_agent(model="google_genai:gemini-3.5-flash",tools=[],context_schema=Context,checkpointer=InMemorySaver(),)result=agent.invoke({"messages":[{"role":"user","content":"请查询我的待处理工单"}]},config={"configurable":{"thread_id":str(uuid7())}},context=Context(user_id="user-123"),)这里:
Context:定义运行时上下文的数据结构。user_id:用户 ID,用于工具判断当前用户身份或查询权限内数据。context_schema=Context:告诉 Agent 这次运行的上下文长什么样。context=Context(user_id="user-123"):真正传入本次调用的上下文对象。
业务场景:
用户 A 和用户 B 都问“我的订单”。工具必须知道当前请求属于哪个用户,否则就有数据泄露风险。context就是把“当前用户是谁”传进工具和中间件的地方。
最简记法:thread_id记住聊天,context记住这次是谁在用。
10. Streaming(流式输出):让用户看见 Agent 正在做什么
它解决的问题:
当 Agent 要执行多步任务时,不等全部完成才返回,而是把中间状态流式吐出来。
如果 Agent 需要搜索、调用接口、分析多份文件,最终结果可能要等很久。agent.stream(...)可以让前端看到中间进度,例如“正在调用搜索工具”“正在整理结果”。
示例:
fromlangchain.messagesimportAIMessage,HumanMessageforchunkinagent.stream({"messages":[{"role":"user","content":"请搜索 AI 新闻并总结重点"}]},stream_mode="values",):latest_message=chunk["messages"][-1]iflatest_message.content:ifisinstance(latest_message,HumanMessage):print(f"用户:{latest_message.content}")elifisinstance(latest_message,AIMessage):print(f"Agent:{latest_message.content}")eliflatest_message.tool_calls:print(f"正在调用工具:{[tc['name']fortcinlatest_message.tool_calls]}")这里:
agent.stream(...):流式调用 Agent。stream_mode="values":返回每一步完整状态值。chunk:流式返回的一段状态。latest_message:当前状态中的最新消息。tool_calls:模型决定调用的工具列表。
业务场景:
一个“研报生成助手”可能要搜索资料、读取文件、提取表格、生成摘要。前端如果只显示转圈,用户会焦虑;如果能显示“正在检索资料”“正在调用工具”“正在生成摘要”,体验会好很多。
最简记法:invoke等最终答案,stream看过程。
11. Middleware(中间件):扩展 Agent 的标准方式
它解决的问题:
把文件系统、记忆、总结、子智能体、重试、安全规则、人工审批等能力,以可组合方式插入 Agent 循环。
官方文档说,create_agent是高度可扩展的。middleware是定制 Agent 的基础原语:每个中间件只处理一个关注点,在正确时机接入 Agent 循环,并且可以自由组合。
示例:
fromlangchain.agentsimportcreate_agentfromdeepagents.backendsimportStateBackendfromdeepagents.middlewareimportFilesystemMiddleware agent=create_agent(model="anthropic:claude-sonnet-4-6",tools=[search],middleware=[FilesystemMiddleware(backend=StateBackend()),],)这里:
middleware:中间件列表。FilesystemMiddleware:文件系统中间件,让 Agent 可以跨轮次读写文件。StateBackend:状态后端,用来保存中间件需要的状态数据。
业务场景:
一个长任务 Agent 要写文件、记住项目规则、拆分任务、调用子 Agent、失败后重试。如果这些逻辑都塞进提示词,会非常脆弱;中间件可以把它们变成工程能力。
最简记法:
提示词管行为倾向,中间件管工程能力。
12. Context Management(上下文管理):别让上下文窗口被塞爆
它解决的问题:
随着 Agent 执行时间变长,历史消息、工具结果和中间步骤会越来越多,最终挤爆上下文窗口。
官方文档给出的上下文管理方向包括:
SummarizationMiddleware:在上下文过长之前压缩历史。MemoryMiddleware:加载长期记忆或项目规则。SkillsMiddleware:按需暴露领域技能,而不是一次性把所有知识塞进上下文。FilesystemMiddleware:让文件成为跨轮次的工作空间。
示例:
fromdeepagents.backendsimportStateBackendfromdeepagents.middlewareimport(FilesystemMiddleware,MemoryMiddleware,SkillsMiddleware,SummarizationMiddleware,)backend=StateBackend()model="anthropic:claude-sonnet-4-6"agent=create_agent(model=model,tools=[search],middleware=[FilesystemMiddleware(backend=backend),SummarizationMiddleware(model=model,backend=backend),MemoryMiddleware(backend=backend,sources=["./AGENTS.md"]),SkillsMiddleware(backend=backend,sources=["./skills/"]),],)这里:
backend:中间件共享的状态后端。sources=["./AGENTS.md"]:记忆来源文件,常用于放项目规则、编码规范和业务约束。sources=["./skills/"]:技能目录,按需加载专业工作流。
业务场景:
如果你让 Agent 连续处理一个大型代码仓库,它会遇到上下文窗口限制。更稳的做法是:规则放记忆,专业流程放技能,历史过程做摘要,文件内容放工作区。
最简记法:
上下文管理不是“塞更多”,而是“该记的记,该压的压,该按需取的按需取”。
13. Planning and Delegation(规划与委派):让复杂任务拆开跑
它解决的问题:
当任务太复杂时,让主 Agent 负责协调,把搜索、分析、写作、代码检查等子任务委派给子 Agent。
官方文档把SubAgentMiddleware放在 “Planning and delegation” 里。它的意义是:主 Agent 不必把所有细节都塞进自己的上下文,而是把任务拆给隔离的子 Agent。
示例:
fromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportTodoListMiddlewarefromdeepagents.backendsimportStateBackendfromdeepagents.middlewareimportFilesystemMiddlewarefromdeepagents.middleware.subagentsimportSubAgentMiddlewarefromlangchain.toolsimporttool# 定义一个检索工具,供主 Agent 或子 Agent 查询资料。@tooldefsearch(query:str)->str:"""根据查询词搜索资料,并返回结构化摘要。"""returnf"搜索结果:{query}"backend=StateBackend()agent=create_agent(model="google_genai:gemini-3.5-flash",tools=[search],middleware=[FilesystemMiddleware(backend=backend),TodoListMiddleware(),SubAgentMiddleware(backend=backend,subagents=[{"name":"researcher","description":"负责检索资料并返回结构化摘要。","system_prompt":"使用搜索工具调研问题,并总结关键结论。","tools":[search],"model":"anthropic:claude-sonnet-4-6","middleware":[],}],),],)这里:
TodoListMiddleware:待办事项中间件,帮助 Agent 显式规划任务。SubAgentMiddleware:子智能体中间件。subagents:子 Agent 配置列表。description:对子 Agent 能力的描述,帮助主 Agent 判断何时委派。system_prompt:子 Agent 自己的系统提示词。
业务场景:
一个“技术方案生成 Agent”可以把任务拆成:资料检索、竞品分析、架构设计、成本估算、风险检查。主 Agent 负责总控,子 Agent 负责专项。
最简记法:
主 Agent 管路线,子 Agent 做专项。
14. Fault Tolerance、Guardrails、Steering(可靠性、安全和人工控制)
它解决的问题:
让 Agent 在生产环境里不只是“能跑”,还要能抗失败、守规则、关键动作可审批。
官方文档把这几类能力放在中间件生态中:
- Fault tolerance:故障容错,例如模型重试、工具重试、调用限制。
- Guardrails:安全护栏,例如个人信息检测、内容策略控制。
- Steering:人工引导,例如在写文件、发消息、扣费等高影响动作前暂停等待审批。
示例一:重试中间件。
fromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportModelRetryMiddleware,ToolRetryMiddleware agent=create_agent(model="google_genai:gemini-3.5-flash",tools=[search],middleware=[ModelRetryMiddleware(max_retries=3),ToolRetryMiddleware(max_retries=2),],)这里:
ModelRetryMiddleware(max_retries=3):模型调用失败时最多重试 3 次。ToolRetryMiddleware(max_retries=2):工具调用失败时最多重试 2 次。
示例二:敏感信息护栏。
fromlangchain.agents.middlewareimportPIIMiddleware agent=create_agent(model="google_genai:gemini-3.5-flash",tools=[search],middleware=[PIIMiddleware("email"),],)这里:
PIIMiddleware("email"):对电子邮箱等个人敏感信息进行检测或处理。PII:Personally Identifiable Information,个人可识别信息。
示例三:人工审批。
fromlangchain.agents.middlewareimportHumanInTheLoopMiddleware agent=create_agent(model="google_genai:gemini-3.5-flash",tools=[search],middleware=[HumanInTheLoopMiddleware(interrupt_on={"write_file":True}),],)这里:
HumanInTheLoopMiddleware:人工介入中间件。interrupt_on={"write_file": True}:当 Agent 要执行write_file这类高影响动作时暂停,等待人工确认。
业务场景:
如果 Agent 只是总结文章,风险较低;如果它要自动发邮件、改数据库、写文件、下单、退款,就必须有重试、审计、权限校验和人工审批。
最简记法:
生产级 Agent = 能恢复、守边界、关键动作有人看。
15. 一句话总结:从“模型应用”走向“Agent 工程”
这篇官方文档最重要的不是某一个 API,而是一个工程视角:
| 层次 | 关键对象 | 解决的问题 |
|---|---|---|
| 推理层 | model | 用哪个模型理解和生成 |
| 行动层 | tools | 能调用哪些外部能力 |
| 规则层 | system_prompt | 按什么角色和边界工作 |
| 输出层 | response_format | 结果能不能被程序稳定接住 |
| 状态层 | messages、thread_id、checkpointer | 能不能延续对话和恢复上下文 |
| 运行层 | context | 当前用户、密钥、开关如何传入 |
| 扩展层 | middleware | 如何加入记忆、文件系统、重试、安全、人工审批 |
如果只记一句话:
LangChain Agent 的核心不是“让模型自由发挥”,而是用create_agent把模型、工具、上下文、状态和中间件组装成一个可控的任务执行系统。
下一篇如果继续精读 LangChain,我建议看Tools或Structured output。因为这两个主题决定了 Agent 能不能从 demo 走向真实业务系统。