ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

精读 LangChain 官方文档(一)Agents 篇:从 create_agent 看懂智能体的真实工作方式

精读 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 走向真实业务系统。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进