0. 开篇:Agent 不是"会聊天的模型",而是"会干活的系统"
普通 LLM 调用是一问一答:你把问题给它,它把答案还给你,结束。但真实任务往往不是一次问答能解决的——"帮我查一下杭州明天天气,如果下雨就给我的团队发封邮件改期",这需要查天气 → 判断 → 发邮件三步,中间还要根据第一步的结果决定第二步怎么做。Agent(智能体)就是为这种"多步、依赖反馈、需要外部能力"的任务而生的系统。

本讲义的一句话主线:
create_agent把「模型 + 工具 + 提示词」编译成一个会自己循环的状态图。你只要理解三件事——它怎么循环(1.3)、怎么调(3)、怎么加能力(4/5/6/7),就能写出生产可用的 Agent。
1. 理解 Agents
1.1 什么是 Agent?
官方定义非常直白:"An agent is a model that can call tools, observe their results, and decide what to do next."——Agent 是一个能够调用工具、观察结果、并自行决定下一步的模型。
拆开来看,Agent 由三个动词构成闭环:

Agent 循环的完整流程(以"查天气 + 发邮件"为例)
注意关键分支:模型自己决定"再调一个工具"还是"给最终答案"——这就是 Agent 与普通链路的本质区别

1.2 Agent 与普通 LLM 调用的区别

判断标准:如果任务的步骤数量或步骤内容,在看到前面步骤的结果之前无法确定,就需要 Agent。反之——"把这段英文翻译成中文"——用普通调用即可,套 Agent 只会增加延迟和成本。
1.3 Agent 的核心组件
create_agent 把下面这些零件组装成一个状态图。理解每个零件的作用,你就掌握了全部调参空间。
| 组件 | 对应参数 | 作用与要点 |
|---|---|---|
| 模型 Model | model 必填 | Agent 的"大脑"。传字符串("openai:gpt-5.5")或模型对象(ChatOpenAI(...))。必须支持工具调用,否则无法形成循环。 |
| 工具 Tools | tools | Agent 的"手脚"。@tool 函数、BaseTool 实例或 dict。框架内部自动 bind_tools,你不要自己绑。为空则退化为纯模型节点,没有循环。 |
| 系统提示词 | system_prompt | Agent 的"人设与规矩"。字符串或 SystemMessage,每次调用模型时被放在消息列表最前面。实践中几乎必设。 |
| 中间件 Middleware | middleware | Agent 的"拦截器"。在模型调用前/后、工具调用前后插入逻辑:重试、摘要、PII 脱敏、人在回路、动态模型切换等。 |
| 结构化输出 | response_format | 约束最终答案的形状。可为 ToolStrategy / ProviderStrategy / 裸 Schema 类型。结果在 result["structured_response"]。 |
| 状态 State | state_schema | 默认 AgentState 只有 messages(+ structured_response)。需要额外字段就扩展它。 |
| 运行时上下文 | context_schema | 每次调用传入的不可变数据(user_id、租户信息)。不随 checkpoint 持久化,工具通过 ToolRuntime 读取。 |
| 短期记忆 | checkpointer | 按 thread_id 持久化会话。没有它,Agent 每次调用都是全新会话;有了它,多轮对话自动续接。 |
| 长期记忆 | store | 跨会话(跨 thread_id)持久化的知识库,如用户画像、历史偏好。 |
| 名称 | name | 图/智能体的名字。出现在 LangSmith trace 中,多智能体场景用于标识身份。 |
| 中断 | interrupt_before / interrupt_after | 在指定节点前/后暂停,实现人工审批等人机协同。 |
AgentState:Agent 的"记忆载体"长什么样
# 默认情况下,Agent 的状态就是一个消息列表(外加结构化输出字段)
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages] # ← 核心:只追加,不覆盖
structured_response: ResponseT | None # ← 配了 response_format 才有
jump_to: str | None # ← 中间件可用来跳转节点
# 需要额外字段?继承扩展即可
class CustomState(AgentState):
user_name: str
tool_call_count: int # ⚠ 会被并发工具调用争抢,建议配 reducer
agent = create_agent(model="openai:gpt-5.5", tools=tools, state_schema=CustomState)
为什么"消息列表"就是状态?因为
add_messagesreducer 保证每一步都只追加不修改:用户的提问、模型的思考、工具调用请求、工具返回结果、最终答案,全部按顺序留在列表里。这意味着——Agent 做的每一件事都可审计,你能完整复现模型当时看到了什么。这是相比黑盒 Agent 框架的最大优势。
1.4 Agent 创建与调用
在 v1 之前,LangChain 里"造一个 Agent"的方式多到让人困惑。下面这些 API 全部已弃用,多数已移入 langchain-classic。认识它们,是为了能识别过时教程。
# ===== ① 史前时代:initialize_agent + AgentType 枚举 =====
from langchain.agents import initialize_agent, AgentType
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
agent.run("今天杭州天气如何?") # ← 字符串进、字符串出,无状态管理
# ===== ② AgentExecutor 时代:手工拼 prompt + agent + executor =====
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
MessagesPlaceholder("chat_history"),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"), # ← 这个"草稿本"是最大的坑
])
agent = create_openai_tools_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
executor.invoke({"input": "...", "chat_history": []})
# ===== ③ 过渡期:langgraph.prebuilt.create_react_agent =====
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(model, tools, prompt="...", checkpointer=MemorySaver())
agent.invoke({"messages": [...]})
老 API 的四个硬伤:
① 三件套拼装——prompt / agent / executor 要手工对齐,
agent_scratchpad占位符漏了就报错;② 输入键不统一——
.run(str)vs.invoke({"input":..., "chat_history":...})vs{"messages":[...]};③ 记忆靠外挂——
ConversationBufferMemory等一堆 Memory 类,与图状态割裂;④ 类型众多——
ZERO_SHOT_REACT_DESCRIPTION、OPENAI_FUNCTIONS、STRUCTURED_CHAT… 选错就是踩坑。
1.4.2 全新的调用
from langchain.agents import create_agent
def check_weather(location: str) -> str:
"""Return the weather forecast for the specified location."""
return f"It's always sunny in {location}"
# 一次调用,全部搞定:模型 + 工具 + 提示词 → 编译好的图
graph = create_agent(
model="anthropic:claude-sonnet-4-5-20250929",
tools=[check_weather],
system_prompt="You are a helpful assistant",
)
inputs = {"messages": [{"role": "user", "content": "what is the weather in sf"}]}
for chunk in graph.stream(inputs, stream_mode="updates"):
print(chunk)
新旧对照:一张表看清迁移
| 维度 | ❌ 旧(v0 / 0.x) | ✅ 新(v1) |
|---|---|---|
| 创建入口 | initialize_agent / create_openai_tools_agent + AgentExecutor / create_react_agent | create_agent(...) —— 一个函数搞定 |
| 输入格式 | .run("字符串") 或 {"input","chat_history","agent_scratchpad"} | {"messages": [...]} —— 统一消息列表 |
| 工具绑定 | 传给 executor,prompt 里还要留 agent_scratchpad | create_agent 内部自动 bind_tools,你只需传列表 |
| 记忆 | ConversationBufferMemory / SummaryMemory … | checkpointer + thread_id(短期)、store(长期) |
| 返回值 | {"output": "字符串"} 中间步骤不可见 | 完整 messages 轨迹 + 可选 structured_response |
| 扩展能力 | 改 executor 参数、自定义 agent 类 | middleware(重试/摘要/脱敏/人在回路…) |
| 底层 | 自研循环逻辑 | LangGraph 状态图,可渐进下沉到 StateGraph |
识别过时教程的黄金标准(背下来):
- 出现
AgentExecutor/initialize_agent/agent.run(...)→ 2023 年的材料- 出现
ConversationBufferMemory/agent_scratchpad→ 2023–2024 年的材料- 出现
from langgraph.prebuilt import create_react_agent作为主推方案 → 2024 年过渡期材料- 用
from langchain.agents import create_agent且传{"messages": [...]}→ 符合 v1
create_agent 完整签名
def create_agent(
model: str | BaseChatModel, # ① 模型:字符串 or 实例
tools: Sequence[BaseTool | Callable | dict] | None = None, # ② 工具列表
*,
system_prompt: str | SystemMessage | None = None, # ③ 系统提示词
middleware: Sequence[AgentMiddleware] = (), # ④ 中间件
response_format: ResponseFormat | type | dict | None = None, # ⑤ 结构化输出
state_schema: type[AgentState] | None = None, # ⑥ 自定义状态
context_schema: type[ContextT] | None = None, # ⑦ 运行时上下文
checkpointer: Checkpointer | None = None, # ⑧ 短期记忆
store: BaseStore | None = None, # ⑨ 长期记忆
interrupt_before: list[str] | None = None, # ⑩ 节点前中断
interrupt_after: list[str] | None = None, # 节点后中断
debug: bool = False, # 调试开关
name: str | None = None, # ⑪ 图/智能体名称
cache: BaseCache | None = None, # 节点结果缓存
transformers: Sequence[TransformerFactory] | None = None,
) -> CompiledStateGraph[AgentState[ResponseT], ContextT, ...]
返回值是
CompiledStateGraph——它同时是一个标准 Runnable,所以invoke/stream/ainvoke/astream/batch全都能用,与 LangChain 其他组件无缝组合。
213

被折叠的 条评论
为什么被折叠?



