精读 LangChain 官方文档(六)Agent 篇:把模型调用升级为可治理的运行结构

精读 LangChain 官方文档(六)Agent 篇:把模型调用升级为可治理的运行结构
本文基于 LangChain Python 官方文档整理:
Agents:https://docs.langchain.com/oss/python/langchain/agents
Markdown 版本:https://docs.langchain.com/oss/python/langchain/agents.md
对应开源文档源码:
https://github.com/langchain-ai/docs/blob/main/src/oss/langchain/agents.mdx
学习智能体时,都是从从一个非常小的代码片段开始:给模型一段 prompt,然后拿到一段回答。这与真实得智能体开发还是有很大差距得得。
真实 Agent 场景里,问题很快会变成另一组工程问题:模型什么时候该调用工具?工具返回结果怎么重新进入上下文?同一用户的连续对话怎么恢复?结构化结果怎么校验?流式进度怎么展示?模型失败、工具超时、敏感信息和人工审批又应该放在哪里治理?
如果所有能力都塞进一段大 prompt,系统会很快失控。prompt 会越来越长,工具调用边界会越来越模糊,排查问题时也很难知道到底是模型、工具、状态还是上下文出了问题。
LangChain 的 Agents 文档要解决的正是这个抽象边界问题:不要只把 Agent 理解成“会调用工具的模型”,而要把它理解成一个围绕模型循环构建出来的可配置运行结构。
这篇文档的核心主线可以概括成一句话:
Agent = Model + Harness。模型负责推理与决策,Harness 负责在正确时间把正确上下文、工具、状态和治理能力交给模型。
也就是说,create_agent 不是一个简单的模型包装函数,而是把“模型调用工具直到任务完成”的循环,提升为一个可以配置、扩展、观测和治理的 Agent runtime structure。
先把这条主线拆开看:
model:决定 Agent 使用哪个推理核心。tools:决定 Agent 能采取哪些行动。system_prompt:决定 Agent 的角色、风格和边界。response_format:决定最终输出能否变成可校验结构。messages、thread_id、checkpointer:决定对话状态如何进入运行时。context_schema、context:决定每次运行的业务上下文如何传入工具和中间件。middleware:决定执行环境、上下文治理、委派、重试、安全和人工介入如何组合进 Agent loop。
下面这张图先把 Agent = Model + Harness 的主线放在一起:

理解这条主线后,create_agent、model、tools、system_prompt、response_format、thread_id、context 和 middleware 就不再是散落参数,而是同一个 Agent 工程结构里的不同控制面。
1. Agent(智能体):从单次模型调用到任务循环
它解决的问题:Agent 解决的是“模型如何在一个任务里持续观察、决策、行动和收敛”,而不是只解决“一次模型调用怎么返回文本”。
官方文档对 Agent 的定义很简洁:Agent 是一个模型不断调用工具,直到任务完成的循环。这个定义里有三个关键词:
model:负责判断下一步该说什么、查什么、调什么工具。tools:让模型不只生成文本,还可以检索、查询、计算、写入或触发外部能力。loop:说明 Agent 不是单次调用,而是多轮状态推进。
示例:
import os
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="qwen3.7-max",
api_key=os.environ["QWEN_API_KEY"],
base_url=os.environ["QWEN_BASE_URL"],
)
agent = create_agent(
model=model,
tools=[],
system_prompt="你是一名中文技术助手,需要用简洁语言解释复杂概念。",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "请解释什么是 LangChain Agent"}]}
)
这里:
create_agent:创建 Agent 的入口函数。它把模型、工具、提示词和可选中间件组织成一个可运行结构。model:可以是模型标识字符串,也可以是已经初始化好的模型对象。这里用ChatOpenAI通过 OpenAI-compatible 协议调用qwen3.7-max。tools:工具列表。空列表表示这个 Agent 暂时只能回答,不能采取外部行动。system_prompt:系统提示词,负责给 Agent 设定长期稳定的行为边界。agent.invoke(...):执行一次 Agent 调用,输入更新到 Agent state 后,再由运行时推进。
业务场景:
在客服系统里,普通模型调用只能回答“订单状态可能在哪里查”。Agent 则可以先识别用户意图,再调用订单查询工具,拿到结果后继续判断是否需要退款、补发或人工介入。
最简记法:
普通模型调用回答一句话,Agent 在任务循环里不断决定下一步。
2. Harness(运行外壳):让模型在正确时间拿到正确上下文
它解决的问题:Harness 解决的是“模型周围那一整套运行支撑应该如何组织”。
如果只看模型本身,Agent 很容易被误解成“更长的 prompt”。但官方文档强调,Agent 的关键不是把所有说明写进 prompt,而是给模型一个 harness。
Harness 可以理解为模型外面的运行外壳,它包含:
- 模型本身。
- 系统提示词。
- 可调用工具。
- 消息和状态。
- 中间件。
- 检查点、上下文压缩、重试、安全、人工审批等运行能力。

示例:
agent = create_agent(
model=model,
tools=[],
system_prompt="你负责把用户问题拆解成可执行步骤,再给出中文回答。",
)
这里:
Agent = Model + Harness:模型不是全部,模型周围的工具、上下文和治理能力同样是 Agent 的一部分。Harness:不是一个必须显式实例化的类,而是官方文档用来解释create_agent所构建运行结构的心智模型。system_prompt、tools、middleware:都是 harness 的组成部分。
业务场景:
做企业知识库问答时,模型只负责理解问题和生成答案;harness 负责接入检索工具、控制上下文长度、加载用户权限、记录运行轨迹,并在高风险答案前触发人工确认。
最简记法:
Model 负责想,Harness 负责把能想、能查、能做、能管串起来。
3. create_agent(创建智能体):最小入口不是最小系统
它解决的问题:create_agent 解决的是“如何用一个统一入口创建可扩展 Agent”,而不是让你手写一套工具循环。
官方文档展示的最小形式非常短:
agent = create_agent(model=model, tools=tools)
但这行代码背后的意义并不小。它不是简单把 model 和 tools 存起来,而是创建了一个可以接受 state 更新、驱动模型调用、处理工具调用、返回结果并接入中间件的运行结构。

示例:
from langchain.agents import create_agent
from langchain.tools import tool
# 定义一个搜索工具,用于根据用户问题返回模拟检索结果
@tool
def search(query: str) -> str:
"""根据查询词搜索信息。"""
return f"查询词:{query};结果:这里是模拟搜索结果。"
agent = create_agent(
model=model,
tools=[search],
system_prompt="你是一名企业知识库助手,需要先查资料,再用中文回答。",
)
这里:
@tool:把普通 Python 函数声明成 LangChain 工具,使模型可以在需要时调用它。query:工具参数名,表示搜索关键词。参数名会进入工具 schema,模型会参考它生成工具调用参数。tools=[search]:把工具注册到 Agent harness 中。system_prompt:说明工具使用习惯,例如“先查资料,再回答”。
业务场景:
做售后助手时,可以把 search_order、query_refund_policy、create_ticket 这些函数都注册为工具。Agent 不再只回答“你可以联系客服”,而是能沿着业务流程推进。
最简记法:
create_agent 是 Agent 工程入口,不只是 model + tools 的字典拼装。
4. Model(模型):推理核心可以是字符串,也可以是实例
它解决的问题:model 解决的是“Agent 由哪个模型来进行推理和决策”。
官方文档里,model 可以传模型标识字符串,例如 "provider:model",也可以传已经初始化好的模型实例。为了便于在国内项目里落地,这里统一采用 OpenAI-compatible 的 ChatOpenAI 初始化方式。
示例:
import os
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="qwen3.7-max",
api_key=os.environ["QWEN_API_KEY"],
base_url=os.environ["QWEN_BASE_URL"],
temperature=0,
)
agent = create_agent(
model=model,
tools=[],
system_prompt="你是一名严谨的中文业务分析助手。",
)
这里:
ChatOpenAI:LangChain 的 OpenAI-compatible 聊天模型封装。model="qwen3.7-max":模型名称。这里用的是业务侧期望的模型名,而不是官方示例里的其他 provider 名称。api_key:API key,来自环境变量QWEN_API_KEY,不要写死在代码里。base_url:OpenAI-compatible 服务地址,来自环境变量QWEN_BASE_URL。temperature=0:降低随机性,适合业务分析、结构化输出和需要稳定复现的场景。
业务场景:
如果做财务、审批、合同问答这类系统,模型选择不只是“谁回答更聪明”,还要考虑输出稳定性、成本、延迟、上下文长度和内部合规要求。
最简记法:
model 是 Agent 的推理引擎,Harness 决定这个引擎怎么接入业务系统。
5. Tools(工具):让 Agent 从回答问题变成采取行动
它解决的问题:tools 解决的是“模型如何使用外部能力”,比如搜索、查库、算数、发起工单、读取文件或调用企业 API。
没有工具的 Agent 更像一个聊天模型;有工具的 Agent 才开始接近真实业务助手。
示例:
from langchain.tools import tool
# 查询订单状态,供 Agent 在用户询问订单进度时调用
@tool
def query_order_status(order_id: str) -> str:
"""根据订单号查询订单状态。"""
return f"订单 {order_id} 当前状态:已发货,预计明天送达。"
agent = create_agent(
model=model,
tools=[query_order_status],
system_prompt="你是一名售后客服助手。需要查询订单时,先调用工具,再回答用户。",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "帮我查一下订单 A10086 到哪了"}]}
)
这里:
query_order_status:工具函数名。函数名会影响模型理解工具用途,应该清晰、具体。order_id:工具参数名,表示订单号。真实系统里它通常会映射到数据库字段或接口参数。"""根据订单号查询订单状态。""":工具说明文本,模型会读它来判断何时调用工具。tools=[query_order_status]:把工具加入 Agent 可行动作集合。
业务场景:
在积分商城里,工具可以包括 query_points_balance、list_available_coupons、create_exchange_order。Agent 先查积分,再判断能否兑换,再生成下一步动作。
最简记法:
Tools 是 Agent 的手脚;没有工具,它多数时候只是在解释世界。
6. System prompt(系统提示词):不是堆规则,而是设定稳定边界
它解决的问题:system_prompt 解决的是“Agent 应该以什么身份、风格和原则完成任务”。
系统提示词适合放稳定规则,例如角色、语气、回答格式、工具使用原则和安全边界。不适合把每次调用才知道的用户 ID、订单号、权限、功能开关都写死进去;这些更适合通过 context 传入。
示例:
agent = create_agent(
model=model,
tools=[query_order_status],
system_prompt=(
"你是一名中文售后客服助手。"
"回答前先判断是否需要查询订单。"
"如果需要查询订单,必须先调用订单工具。"
"回答要简洁、准确,并说明下一步建议。"
),
)
这里:
system_prompt:系统提示词参数,负责控制 Agent 的长期行为。- “必须先调用订单工具”:这是工具使用策略,适合放在系统提示词里。
- “回答要简洁、准确”:这是输出风格约束。
业务场景:
客服 Agent、财务 Agent、代码助手和数据分析 Agent 的工具可能相似,但 system_prompt 会让它们呈现不同的职责边界。客服重视服务口径,财务重视审计准确性,代码助手重视可执行改动和测试。
最简记法:
system_prompt 定性格和边界,context 传当次运行的数据。
7. Structured output(结构化输出):让 Agent 结果进入业务系统
它解决的问题:response_format 解决的是“Agent 最终输出如何变成可校验、可入库、可被下游系统消费的数据”。
如果只返回自然语言,前端展示很方便,但业务系统很难稳定解析。结构化输出让 Agent 的最终结果符合一个 schema。
示例:
from pydantic import BaseModel, Field
class ServiceDecision(BaseModel):
summary: str = Field(description="给用户展示的中文结论")
needs_human: bool = Field(description="是否需要人工客服介入")
confidence: float = Field(description="判断置信度,范围从 0 到 1")
agent = create_agent(
model=model,
tools=[query_order_status],
response_format=ServiceDecision,
system_prompt="你是一名售后客服助手,需要给出可落库的处理结论。",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "订单 A10086 延迟了,我需要人工处理吗?"}]}
)
decision = result["structured_response"]
这里:
ServiceDecision:结构化输出 schema,用 Pydantic 描述返回字段。summary:给用户看的中文摘要。needs_human:布尔字段,表示是否需要人工介入。confidence:数值字段,表示模型判断的置信度。response_format=ServiceDecision:告诉 Agent 最终结果要符合这个 schema。structured_response:结果字典里的结构化返回键。下游可以直接读取它,而不是从一段文本里猜。
业务场景:
在工单系统里,Agent 可以返回 category、priority、needs_human、summary 等字段。这样自动分派、统计报表和人工复核都能基于稳定字段运行。
最简记法:
response_format 把“模型回答”变成“业务系统能接的结果”。
8. Invocation 与 thread_id(调用与会话):Agent 运行的是 State 更新
它解决的问题:Invocation 解决的是“如何把一次用户输入推进到 Agent state 里”,而 thread_id 解决的是“如何让多轮对话属于同一个会话”。
官方文档强调,调用 Agent 时传入的是对 state 的更新。所有 Agent state 里都包含一组消息,调用时把新的消息交给 Agent,再由运行时推进。

示例:
from langchain_core.utils.uuid import uuid7
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
model=model,
tools=[],
checkpointer=InMemorySaver(),
system_prompt="你是一名中文对话助手,需要记住同一会话里的上下文。",
)
config = {"configurable": {"thread_id": str(uuid7())}}
result = agent.invoke(
{"messages": [{"role": "user", "content": "我正在比较两个智能客服方案"}]},
config=config,
)
follow_up = agent.invoke(
{"messages": [{"role": "user", "content": "刚才提到的第二个方案适合小团队吗?"}]},
config=config,
)
这里:
messages:Agent state 里的消息序列。每次调用通常追加新的用户消息。role:消息角色,例如user表示用户消息。content:消息内容。thread_id:会话标识,用来区分不同对话线程。configurable:运行配置中的可配置字段容器,thread_id放在这里。checkpointer=InMemorySaver():本地内存检查点,用来保存和恢复同一个thread_id下的对话状态。
业务场景:
用户在客服窗口里先问物流,再问“那可以改地址吗?”第二句话依赖第一轮上下文。没有 thread_id 和检查点,Agent 很难知道“那”指的是哪笔订单或哪段对话。
最简记法:
thread_id 管会话连续性,checkpointer 管状态能否被保存和恢复。
9. context_schema 与 context(运行上下文):把业务数据传给工具和中间件
它解决的问题:context 解决的是“每次运行才知道的业务数据如何进入 Agent”,例如用户 ID、租户 ID、权限、功能开关、渠道来源和 API 凭据引用。
这类数据不应该硬塞进 system_prompt。它们更适合作为结构化运行上下文传入,并通过 context_schema 描述形状。

示例:
from dataclasses import dataclass
from langchain.tools import ToolRuntime, tool
@dataclass
class RuntimeContext:
user_id: str
tenant_id: str
channel: str
# 根据运行上下文读取当前用户的积分余额
@tool
def query_points(runtime: ToolRuntime[RuntimeContext]) -> str:
"""查询当前用户的积分余额。"""
user_id = runtime.context.user_id
tenant_id = runtime.context.tenant_id
return f"租户 {tenant_id} 下,用户 {user_id} 当前积分余额为 1200。"
agent = create_agent(
model=model,
tools=[query_points],
context_schema=RuntimeContext,
system_prompt="你是一名积分商城助手,需要根据用户上下文回答问题。",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "我现在有多少积分?"}]},
context=RuntimeContext(
user_id="user-123",
tenant_id="mall-a",
channel="mobile-app",
),
)
这里:
RuntimeContext:运行上下文的数据结构,描述本次运行可用的业务字段。user_id:用户标识。tenant_id:租户或组织标识,多租户系统里很常见。channel:请求来源渠道,例如小程序、App、Web 或企业微信。context_schema=RuntimeContext:告诉 Agent 运行上下文的类型。context=RuntimeContext(...):本次调用真实传入的上下文数据。runtime.context:工具或中间件读取运行上下文的位置。
业务场景:
做 SaaS 客服 Agent 时,同一句“帮我查订单”,不同租户、不同用户、不同渠道对应的权限和数据范围都不同。context 让这些业务条件以结构化方式进入运行时。
最简记法:
thread_id 是会话身份,context 是本次运行的业务身份。
10. Streaming(流式反馈):让长任务不再像黑箱
它解决的问题:Streaming 解决的是“Agent 多步执行时,用户和系统如何看到中间进度”。
如果 Agent 要查资料、调用工具、分析结果、再生成答案,只等最终结果会让用户觉得系统卡住了。流式反馈可以让前端展示中间消息、工具调用和状态变化。

示例:
from langchain.messages import AIMessage, HumanMessage
stream = agent.stream_events(
{"messages": [{"role": "user", "content": "请搜索 AI 新闻并总结重点"}]},
version="v3",
)
for snapshot in stream.values:
latest_message = snapshot["messages"][-1]
if latest_message.content:
if isinstance(latest_message, HumanMessage):
print(f"用户:{latest_message.content}")
elif isinstance(latest_message, AIMessage):
print(f"智能体:{latest_message.content}")
elif latest_message.tool_calls:
tool_names = [tool_call["name"] for tool_call in latest_message.tool_calls]
print(f"正在调用工具:{tool_names}")
这里:
agent.stream_events(...):启动事件流。version="v3":使用新版事件流协议。stream.values:观察每一步 state 快照。snapshot["messages"]:当前状态里的消息列表。latest_message.tool_calls:模型准备调用的工具列表。
业务场景:
数据分析 Agent 可能要读取文件、清洗数据、跑统计、生成图表。前端可以用 streaming 展示“正在读取数据”“正在分析字段”“正在生成报告”,而不是让用户盯着一个转圈动画。
最简记法:
invoke 适合拿最终结果,streaming 适合看运行过程。
11. Middleware(中间件):Agent loop 的可组合治理层
它解决的问题:middleware 解决的是“如何在不重写 Agent loop 的情况下,给 Agent 加上额外运行能力”。
官方文档强调,create_agent 是高度可扩展的,扩展原语就是 middleware。每个 middleware 处理一个关注点,并在 Agent loop 的合适位置介入。

可以把 middleware 理解成 Agent runtime 的插件层。常见类别包括:
| 类别 | 中文理解 | 典型能力 |
|---|---|---|
| Execution environment | 执行环境 | 文件系统、沙箱、代码执行、工具工作区 |
| Context management | 上下文管理 | 摘要压缩、记忆、技能、prompt caching |
| Planning and delegation | 规划与委派 | 待办列表、子智能体、并行任务 |
| Fault tolerance | 容错 | 模型重试、工具重试、fallback、调用限制 |
| Guardrails | 安全护栏 | PII 检测、内容策略、输入输出治理 |
| Steering | 人工引导 | 高风险动作前暂停、审批、编辑、拒绝 |
示例:
from langchain.agents.middleware import ModelRetryMiddleware, ToolRetryMiddleware
agent = create_agent(
model=model,
tools=[query_order_status],
middleware=[
ModelRetryMiddleware(max_retries=3),
ToolRetryMiddleware(max_retries=2),
],
system_prompt="你是一名售后客服助手,需要稳定处理订单问题。",
)
这里:
middleware:中间件列表,按配置组合进 Agent harness。ModelRetryMiddleware:模型调用失败时的重试中间件。ToolRetryMiddleware:工具调用失败时的重试中间件。max_retries:最大重试次数,属于运行可靠性参数。
业务场景:
生产环境里,模型 API 可能限流,订单查询 API 可能超时,用户输入可能包含敏感信息。把这些治理能力放进 middleware,比把所有异常处理写散在工具函数里更清楚。
最简记法:
middleware 是 Agent loop 的治理插槽,每个插槽只处理一个关注点。
12. Execution environment 与 Context management(执行环境与上下文治理)
它解决的问题:
执行环境解决“Agent 能在哪里工作”,上下文治理解决“Agent 如何在有限上下文窗口里保持任务连续性”。
官方文档把 execution environment 描述为工具、文件系统、沙箱和代码执行。它让 Agent 不只在聊天窗口里回答,而是有一个可以读写、执行和迭代的工作区。
同时,Agent 运行越久,上下文窗口越容易被消息、工具结果和中间步骤填满。上下文治理需要摘要压缩、长期记忆、技能按需加载等能力。
示例:
from deepagents.backends import StateBackend
from deepagents.middleware import (
FilesystemMiddleware,
MemoryMiddleware,
SkillsMiddleware,
SummarizationMiddleware,
)
backend = StateBackend()
agent = create_agent(
model=model,
tools=[query_order_status],
middleware=[
FilesystemMiddleware(backend=backend),
SummarizationMiddleware(model=model, backend=backend),
MemoryMiddleware(backend=backend, sources=["./AGENTS.md"]),
SkillsMiddleware(backend=backend, sources=["./skills/"]),
],
system_prompt="你是一名能处理长任务的中文业务助手。",
)
这里:
StateBackend:状态后端,用于给部分 deepagents middleware 提供共享存储。FilesystemMiddleware:提供文件系统能力,让 Agent 可以围绕文件工作。SummarizationMiddleware:在上下文膨胀时压缩历史。MemoryMiddleware:加载持久记忆或项目规则。SkillsMiddleware:按需加载技能,避免一开始把所有领域知识塞进上下文。sources:资源来源路径,例如./AGENTS.md或./skills/。
业务场景:
一个投标方案生成 Agent 可能要读取客户资料、生成多版方案、对比报价、保存中间文件、复用公司写作规范。执行环境负责“能工作”,上下文治理负责“长任务不失忆”。
最简记法:
执行环境给 Agent 工作台,上下文治理让 Agent 长时间工作不散架。
13. Planning and delegation(规划与委派):让复杂任务从单脑袋变成可分工
它解决的问题:Planning and delegation 解决的是“复杂任务如何拆分、跟踪和交给子智能体处理”。
当任务超过一个上下文窗口,或者需要多个专业视角时,让一个 Agent 从头扛到尾会很吃力。官方文档把待办列表和子智能体归到这个能力区:主 Agent 负责任务协调,子 Agent 在隔离上下文里完成专门工作。
示例:
from deepagents.backends import StateBackend
from deepagents.middleware import FilesystemMiddleware
from deepagents.middleware.subagents import SubAgentMiddleware
from langchain.agents.middleware import TodoListMiddleware
backend = StateBackend()
agent = create_agent(
model=model,
tools=[search],
name="research_coordinator",
middleware=[
FilesystemMiddleware(backend=backend),
TodoListMiddleware(),
SubAgentMiddleware(
backend=backend,
subagents=[
{
"name": "researcher",
"description": "搜索资料并返回结构化中文摘要。",
"system_prompt": "请使用搜索工具调研问题,并用中文总结关键证据。",
"tools": [search],
"model": model,
"middleware": [],
}
],
),
],
)
这里:
TodoListMiddleware:让 Agent 维护任务待办列表,适合长任务。SubAgentMiddleware:配置子智能体。subagents:子智能体配置列表。name:Agent 名称。在多智能体或子图场景里,它可以作为节点标识。description:子智能体能力描述,帮助主 Agent 判断什么时候委派给它。system_prompt:子智能体自己的系统提示词。
业务场景:
做行业研究报告时,主 Agent 可以负责框架和质量控制;子 Agent 分别调研竞品、政策、技术架构和成本测算。这样主 Agent 的上下文更干净,也更容易追踪各部分来源。
最简记法:
TodoList 管任务拆解,SubAgent 管专业分工,name 管多 Agent 里的身份。
14. Fault tolerance、Guardrails 与 Steering(可靠性、安全与人工介入)
它解决的问题:
这三个能力解决的是“Agent 进入生产环境后,如何在失败、安全和高风险动作面前可控”。
生产系统里的 Agent 不可能只面对理想输入。它会遇到模型超时、工具报错、接口限流、敏感信息、高影响操作和用户越权请求。官方文档把这些能力放在 harness 配置里,就是提醒我们:Agent 的核心不只是会做事,还要能被治理。

示例:
from langchain.agents.middleware import (
HumanInTheLoopMiddleware,
ModelRetryMiddleware,
PIIMiddleware,
ToolRetryMiddleware,
)
agent = create_agent(
model=model,
tools=[query_order_status],
middleware=[
ModelRetryMiddleware(max_retries=3),
ToolRetryMiddleware(max_retries=2),
PIIMiddleware("email"),
HumanInTheLoopMiddleware(interrupt_on={"create_refund": True}),
],
system_prompt="你是一名售后客服助手,高风险操作必须等待人工确认。",
)
这里:
ModelRetryMiddleware:模型调用失败时重试。ToolRetryMiddleware:工具调用失败时重试。PIIMiddleware("email"):对邮箱等个人信息进行治理。"email"表示要处理的 PII 类型。HumanInTheLoopMiddleware:在高风险工具调用前暂停,让人工审批、编辑或拒绝。interrupt_on:指定哪些工具或动作需要中断等待人工处理。create_refund:示例中的退款工具名。真实系统里它通常对应会产生资金或订单状态变化的动作。
业务场景:
普通查询可以自动完成,但退款、改地址、发券、删除数据、写入合同这类动作要进入人工审批。这样 Agent 既能提升效率,也不会把高风险动作完全交给模型自由执行。
最简记法:
可靠性靠 retry,合规靠 guardrails,高风险动作靠 human-in-the-loop。
15. 工程落地:读 Agent 文档时最该抓住的边界
它解决的问题:
这一节解决的是“读完 Agents 文档后,如何把它转成工程设计判断”。
不要把 create_agent 当成一个魔法函数,也不要把 Agent 当成一段超级 prompt。更稳的理解方式是:先确认 Agent loop 需要哪些控制面,再逐个选择参数和 middleware。
可以按下面这张表落到工程设计:
| 工程问题 | 对应能力 | 关键字段或函数 |
|---|---|---|
| 用哪个模型推理 | Model | model、ChatOpenAI、QWEN_API_KEY、QWEN_BASE_URL |
| 能调用哪些外部能力 | Tools | tools、@tool、函数名、参数名、工具说明 |
| 行为边界是什么 | System prompt | system_prompt |
| 输出能否入库 | Structured output | response_format、structured_response |
| 多轮对话如何恢复 | Invocation | messages、thread_id、checkpointer |
| 本次运行有哪些业务变量 | Runtime context | context_schema、context、runtime.context |
| 长任务如何显示进度 | Streaming | stream_events、version="v3"、stream.values |
| 生产治理怎么接入 | Middleware | middleware、retry、PII、human-in-the-loop |
| 复杂任务如何拆分 | Delegation | TodoListMiddleware、SubAgentMiddleware、name |
业务场景:
如果你在做企业智能客服,Agent 方案不应该只写“使用 LangChain + 大模型”。更准确的方案应该写清楚:模型选型、工具清单、订单/积分/工单 API、会话状态、用户上下文、结构化输出、流式进度、审计日志、敏感信息治理和人工审批边界。
最简记法:
Agent 不是模型增强版,而是围绕模型循环搭起来的运行时工程结构。
最后总结:从“会调工具”到“可运行、可治理、可扩展”
Agents 这篇官方文档真正重要的地方,不是告诉我们多写几个参数,而是给了一个更清晰的抽象层次:
Model -> Agent loop -> Harness -> Middleware ecosystem -> Production governance
最底层,模型负责理解和生成。
往上一层,Agent loop 让模型可以调用工具并持续推进任务。
再往上一层,Harness 把提示词、工具、状态、上下文和中间件组织起来。
到了生产层,middleware 让可靠性、安全、人工审批、上下文治理和任务委派成为可组合能力,而不是散落在业务代码里的临时补丁。
所以读 create_agent 时,不要只问“怎么创建一个 Agent”。更好的问题是:
我这个业务 Agent 需要哪些运行能力?
如果只是简单问答,model + system_prompt 可能够用。
如果要查业务数据,就要设计 tools。
如果要多轮对话,就要设计 thread_id 和 checkpointer。
如果要读取用户身份和租户权限,就要设计 context_schema。
如果要进入生产环境,就要设计 streaming、retry、guardrails、human-in-the-loop 和审计。
理解这一层后,再读后续的 Messages、Runtime、Tools、Middleware 和 Human-in-the-loop 文档时,它们就不再是分散 API,而是同一个 Agent harness 里的不同工程组件。
最简记法:
create_agent 把模型调用提升为可配置的 Agent harness;
middleware 再把 Agent harness 推向可治理的生产运行结构。
更多推荐


所有评论(0)