LangChain create_agent() 函数详解:从 Agent 原理到可运行的实战代码
搞 LLM 应用开发的人大概都有一段"配 Agent 配到头皮发麻"的经历:自己拼模型调用、工具循环、记忆、判断分支......代码越写越长,还容易各有各的写法。LangChain 的 create_agent() 就是为了终结这种混乱------它是 LangChain 现在最核心的 Agent 工厂函数,一个函数就能搭出一个完整的 Agent 图(StateGraph),把模型调用、工具执行、循环控制、状态管理全包在里面。
这篇文章带你从头把它搞懂:先厘清"Agent 到底是什么",再逐参数拆解 create_agent(),最后给出一套能直接跑起来的示例和进阶玩法。文中所有参数与用法以 LangChain 官方文档为准,标注来源,便于你对照查阅。
说明:写作时当前环境访问外部文档受限,本文参数细节以 LangChain 官方 Agents 文档与菜鸟教程
create_agent()参考页为准(来源见文末),如有新版差异请以官方 reference 为准。
一、先搞懂:Agent 到底是什么
1.1 Agent 的本质:Model + Harness
LangChain 官方对 Agent 的定义很精炼:
An agent is a model calling tools in a loop until a given task is complete. (Agent 是模型在一个循环里反复调用工具,直到某个任务完成。)
拆开看是两件事:
- Model(模型):负责"想",理解任务、决定下一步做什么。
- Harness(装配层/控制层):循环本身之外的一切------提示词、工具、中间件,以及决定"在什么时机给模型喂什么上下文"的逻辑。
所以官方一句话公式是:
ini
Agent = Model + Harness
Agent 的真正核心不是模型,而是 Harness。 模型再聪明,如果拿不到正确的上下文、不会用工具,也只是一块"会说话的 GPU"。
1.2 核心循环:Agent Loop
一个 Agent 的运行是一个循环,每一圈大致是:
markdown
模型思考 → 决定要不要调工具 → 调用工具拿到结果 → 把结果喂回模型 → 再思考......
↓
直到任务完成(或到达终止条件)
关键点在于:模型不是"一次回答"就结束,而是在循环里不断迭代 ,直到它判断任务完成。这个循环 + 状态管理,正是 create_agent() 帮你搭好的东西。
1.3 为什么需要 Harness
有人会问:我直接 bind 工具给模型调不行吗?可以,但只是"能用"。Harness 解决的问题是------在正确的时间,给模型送对上下文。
举个例子:一个带搜索、带记忆的 Agent,需要保证------
- 每轮调用前把历史对话 + 工具结果组装好送给模型;
- 工具返回后能解析并更新状态;
- 多轮之间能持久化,让 Agent 记得上下文;
- 该中断让人类审批的地方停下。
这些琐事如果手写,分散在各处很难维护。create_agent() 就是把这些"装配"逻辑一次打包。
1.4 一句话定位 create_agent()
create_agent() 是一个高度可配置的 Harness 工厂。它的最小用法只三行,却能生成一个完整的、带状态管理的可运行 Agent:
python
from langchain.agents import create_agent
agent = create_agent(model="google_genai:gemini-3.6-flash", tools=tools)
它返回一个编译好的图(CompiledStateGraph) ,你可以 invoke、stream、挂接 checkpointer,本质上是用 LangGraph 帮你搭好了 Agent 的骨架。
二、create_agent():一个函数搞定 Agent
2.1 函数签名与参数总览
create_agent() 的完整签名如下(基于 LangChain 官方 Agents 文档与菜鸟教程整理):
python
from langchain.agents import create_agent
agent = create_agent(
model, # str | BaseChatModel:语言模型
tools=None, # Sequence:工具列表
*,
system_prompt=None, # str | SystemMessage:系统提示
middleware=(), # Sequence[AgentMiddleware]:中间件列表
response_format=None, # ResponseFormat | type:结构化输出配置
state_schema=None, # type[AgentState]:自定义状态结构
context_schema=None, # type:运行时上下文结构
checkpointer=None, # Checkpointer:对话持久化
store=None, # BaseStore:跨会话存储
interrupt_before=None, # list[str]:在哪些节点前暂停
interrupt_after=None, # list[str]:在哪些节点后暂停
debug=False, # bool:是否输出详细日志
name=None, # str:Agent 名称
cache=None, # BaseCache:缓存配置
)
| 参数 | 类型 | 作用 |
|---|---|---|
model |
`str | BaseChatModel` |
tools |
Sequence |
工具列表,可空 |
system_prompt |
`str | SystemMessage` |
middleware |
Sequence[AgentMiddleware] |
中间件,扩展 Harness 能力 |
response_format |
`ResponseFormat | type` |
state_schema |
type[AgentState] |
自定义运行状态结构 |
context_schema |
type |
每次调用的运行时上下文结构 |
checkpointer |
Checkpointer |
会话/对话持久化 |
store |
BaseStore |
跨会话长期存储 |
interrupt_before |
list[str] |
在哪些节点前暂停 |
interrupt_after |
list[str] |
在哪些节点后暂停 |
debug |
bool |
是否输出详细日志 |
name |
str |
Agent 标识名 |
cache |
BaseCache |
缓存配置 |
2.2 返回值:CompiledStateGraph
create_agent() 返回一个 CompiledStateGraph(LangGraph 编译后的图对象)。它不是一个"函数",而是一个可执行的状态图,提供了多种运行方式:
| 方法 | 说明 | 适用场景 |
|---|---|---|
invoke(input, config) |
同步运行,等待完整结果 | 脚本、简单接口 |
ainvoke(input, config) |
异步运行,等待完整结果 | Web 服务 |
stream(input, config, stream_mode) |
同步流式运行 | 实时展示中间步骤 |
astream(input, config, stream_mode) |
异步流式运行 | WebSocket、SSE |
get_state(config) |
获取当前状态 | 查看/恢复对话状态 |
update_state(config, values) |
更新状态 | 手动修改对话状态 |
(注:官方文档还介绍了 stream_events,用于逐步展示工具调用与中间消息。)
三、核心参数逐个拆解
3.1 model:选模型
model 是三处必填参数中最关键的一个,接受两种形式:
方式 1:传字符串(最常用)
python
from langchain.agents import create_agent
agent = create_agent(
model="deepseek:deepseek-v4-flash",
system_prompt="你是菜鸟教程 RUNOOB 的助手",
)
create_agent() 内部会自动调用 init_chat_model() 处理字符串,帮你完成模型初始化、工具绑定、结构化输出等逻辑。
方式 2:传已构建好的模型实例
python
from langchain.chat_models import init_chat_model
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0.3, max_tokens=500)
agent = create_agent(
model=model,
system_prompt="你是菜鸟教程 RUNOOB 的助手",
)
适合你需要精细控制模型参数(temperature、max_tokens 等),或需要在 Agent 之外复用同一个模型实例的场景。
方式 3:传已绑定工具的模型实例
python
model_with_tools = init_chat_model("deepseek:deepseek-v4-flash").bind_tools([...])
agent = create_agent(model=model_with_tools)
这种方式不太常用------通常让 create_agent 自己管理工具绑定更省事。
推荐方式 1(传字符串)。
create_agent()内部会统一处理初始化、工具绑定、结构化输出等。方式 2 适合"同实例多处复用"的场景。
3.2 tools:工具列表(Agent 的"四肢")
tools 决定 Agent 能做什么。接受三种格式的工具,可混合:
格式 1:@tool 装饰的函数(最常用)
python
from langchain.tools import tool
@tool
def search_course(keyword: str) -> str:
"""搜索菜鸟教程课程"""
return f"搜索结果:{keyword} 相关课程"
格式 2:Pydantic BaseModel 类
python
from pydantic import BaseModel, Field
class WeatherQuery(BaseModel):
"""查询天气"""
city: str = Field(description="城市名称")
格式 3:工具字典(描述远程工具或内置工具)
python
mcp_tool = {
"type": "mcp",
"server_label": "weather_server",
"server_url": "https://weather.example.com/sse",
"allowed_tools": ["get_forecast"],
}
混合使用:
python
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[search_course, WeatherQuery, mcp_tool],
)
传
None或空列表表示 Agent 无工具可用,此时它就是一个纯粹的对话模型(等价于直接调模型)。
python
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=None,
system_prompt="你是菜鸟教程 RUNOOB 的助手",
)
result = agent.invoke({"messages": [HumanMessage(content="Python 适合零基础学习吗?")]})
print(result["messages"][-1].content)
3.3 system_prompt:系统提示(行为边界)
定义 Agent 的行为角色和约束规则,支持字符串和 SystemMessage 对象。
方式 1:字符串(简单直接)
python
agent = create_agent(
model="deepseek:deepseek-v4-flash",
system_prompt="你是菜鸟教程 RUNOOB 的学习顾问。回答要简洁,不超过 100 字。",
)
方式 2:SystemMessage 对象(可在多个 Agent 间复用)
python
from langchain.messages import SystemMessage
system_msg = SystemMessage(content="你是菜鸟教程 RUNOOB 的学习顾问。回答要简洁,不超过 100 字。")
agent = create_agent(
model="deepseek:deepseek-v4-flash",
system_prompt=system_msg,
)
system_prompt是可选的,但不传的话模型会以"通用助手"角色回答。有明确业务场景的应用,建议始终设置system_prompt来约束模型的行为边界。 若需要运行时动态生成提示,用 middleware(见第五节)。
3.4 state_schema / AgentState:自定义运行状态
默认的 AgentState 只包含 messages、jump_to(跳转)和 structured_response 等内置字段。内置字段的关键一个是:
| 字段 | 类型 | 说明 |
|---|---|---|
messages |
list[BaseMessage] |
当前线程的完整对话历史,只追加,不替换 |
AgentState 也是所有中间件钩子(before_model、after_model 等)的类型签名。钩子接收当前状态,返回要合并回去的更新字典。
如果你需要额外状态字段,可以子类化 AgentState 并通过 state_schema 传入。 下面这个例子给 Agent 加了"学习进度"的字段,并用 InjectedState 让工具直接读写状态:
python
from typing import Annotated
from typing_extensions import TypedDict
from langchain.agents import create_agent, AgentState
from langchain.tools import tool, InjectedState
from langchain.messages import HumanMessage
# 扩展 AgentState,添加自定义字段
class LearningAgentState(AgentState):
"""自定义状态,增加学习进度相关字段"""
user_level: str # 用户等级
completed_topics: list[str] # 已完成的主题列表
@tool
def track_progress(
topic: str,
state: Annotated[dict, InjectedState],
) -> str:
"""记录用户的学习进度。
Args:
topic: 刚学完的主题名称
"""
completed = state.get("completed_topics", [])
completed.append(topic)
return f"已记录学习进度。当前已完成 {len(completed)} 个主题:{', '.join(completed)}"
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[track_progress],
state_schema=LearningAgentState, # 使用自定义状态
system_prompt="你是菜鸟教程 RUNOOB 的学习助手。",
)
# 运行时需提供自定义状态的初始值
result = agent.invoke({
"messages": [HumanMessage(content="我学完了 Python 基础,帮我记录一下")],
"user_level": "入门",
"completed_topics": ["HTML 基础"],
})
print(f"用户等级: {result.get('user_level')}")
print(f"已完成主题: {result.get('completed_topics')}")
print(f"回复: {result['messages'][-1].content[:100]}")
运行结果:
less
用户等级: 入门
已完成主题: ['HTML 基础', 'Python 基础']
回复: 已记录学习进度。当前已完成 2 个主题:HTML 基础, Python 基础
为什么用 InjectedState? 它让工具函数能直接拿到并回写运行状态,不用把 state 显式传进工具参数里。这是 LangChain 处理"工具需要访问状态"的标准做法。
3.5 response_format:结构化输出
想让 Agent 返回校验过的结构化数据 ,而不是一段自由文本,就用 response_format 指定一个 Pydantic 模型或 ResponseFormat:
python
from pydantic import BaseModel
from langchain.agents import create_agent
class Answer(BaseModel):
summary: str
confidence: float
agent = create_agent(
model="google_genai:gemini-3.6-flash",
tools=tools,
response_format=Answer,
)
result = agent.invoke({"messages": [{"role": "user", "content": "Summarize AI trends"}]})
print(result["structured_response"]) # Answer(summary=..., confidence=...)
结果从 result["structured_response"] 取出,是一个校验过的、类型安全的模型实例。做数据管道、接后端接口时特别有用。
3.6 checkpointer / store:持久化与记忆
checkpointer(Checkpointer) :对话/会话持久化。配合thread_id,让 Agent 记住多轮对话、可中断恢复。
python
from langchain.agents import create_agent
from langchain_core.utils.uuid import uuid7
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
model="google_genai:gemini-3.6-flash",
tools=[],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": str(uuid7())}}
# 第一轮
result = agent.invoke(
{"messages": [{"role": "user", "content": "What's the weather in San Francisco?"}]},
config=config,
)
# 第二轮:复用同一 thread_id,延续历史
result = agent.invoke(
{"messages": [{"role": "user", "content": "What about tomorrow?"}]},
config=config,
)
thread_id 区分不同会话;复用同一个值即延续同一段历史。持久化历史需要配置 checkpointer ,本地可用 InMemorySaver(),生产环境(如 LangSmith 部署)会自动配置。
store(BaseStore):跨会话的长期存储(区别于 checkpointer 的单会话记忆)。用于存用户偏好、长期知识等。
3.7 context_schema:运行时上下文
thread_id 管"会话",context 管"单次运行"。 如果你想给工具/中间件传每次调用才会变的运行时数据(用户 ID、API key、feature flag 等),用 context_schema 定义其结构,用 runtime.context 访问:
python
from dataclasses import dataclass
from langchain.agents import create_agent
from langchain_core.utils.uuid import uuid7
from langgraph.checkpoint.memory import InMemorySaver
@dataclass
class Context:
user_id: str
agent = create_agent(
model="google_genai:gemini-3.6-flash",
tools=[],
context_schema=Context,
checkpointer=InMemorySaver(),
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What's the weather in San Francisco?"}]},
config={"configurable": {"thread_id": str(uuid7())}},
context=Context(user_id="user-123"),
)
3.8 其余可选参数
middleware:中间件列表,扩展 Harness 能力(详见第五节)。interrupt_before/interrupt_after:在指定节点前/后暂停,配合人机协同做审批。也可用HumanInTheLoopMiddleware。debug:输出详细日志,排查问题时开启。name:给 Agent 起名,多 Agent 系统里嵌入为子图时很有用。cache:缓存配置,减少重复调用、提升性能。
四、实战:从 0 到 1 的可运行示例
这一节把上面拆开的参数串成五个渐进场景,从最小可用到完整能力。
4.1 场景一:最小可用 Agent(无工具)
python
from langchain.agents import create_agent
from langchain.messages import HumanMessage
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=None,
system_prompt="你是菜鸟教程 RUNOOB 的助手。",
)
result = agent.invoke({"messages": [HumanMessage(content="Python 适合零基础学习吗?")]})
print(result["messages"][-1].content)
没有工具,Agent 退化为纯对话模型,适合验证模型和提示词。
4.2 场景二:带工具 + 自定义 system_prompt
python
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def search_course(keyword: str) -> str:
"""搜索菜鸟教程课程。"""
return f"搜索结果:{keyword} 相关课程"
@tool
def weather(city: str) -> str:
"""查询城市天气。"""
return f"{city} 当前晴,26℃"
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[search_course, weather],
system_prompt="你是学习助手。查课程用 search_course,查天气用 weather。",
)
result = agent.invoke({"messages": [HumanMessage(content="北京今天天气如何?")]})
print(result["messages"][-1].content)
✅ 成功标志 :Agent 自动选择了 weather 工具并返回对应结果。
4.3 场景三:自定义状态(扩展 AgentState)
复用第三节 3.4 的 LearningAgentState 例子,重点在于用 state_schema 注入自定义状态、用 InjectedState 让工具回写状态。
4.4 场景四:结构化输出
python
from pydantic import BaseModel
from langchain.agents import create_agent
class Summary(BaseModel):
topic: str
key_points: list[str]
confidence: float
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=None,
response_format=Summary,
system_prompt="把用户输入总结为结构化摘要。",
)
result = agent.invoke({"messages": [{"role": "user", "content": "介绍下分页查询"}]})
print(result["structured_response"]) # Summary(...)
✅ 成功标志 :structured_response 返回一个 Summary 实例,字段齐全且类型正确。
4.5 场景五:会话持久化
python
from langchain.agents import create_agent
from langchain_core.utils.uuid import uuid7
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": str(uuid7())}}
agent.invoke({"messages": [{"role": "user", "content": "我叫吴彦祖"}]}, config=config)
result = agent.invoke(
{"messages": [{"role": "user", "content": "我叫什么?"}]},
config=config,
)
print(result["messages"][-1].content) # 记得我叫吴彦祖
✅ 成功标志:第二轮回答了第一轮的信息------说明历史被正确记住。
五、进阶:中间件(Middleware)怎么用
create_agent 的可定制性主要来自 middleware(中间件) 。每块中间件只负责一个关注点,挂在 Agent 循环的正确时机,且可自由组合------只取当前需求需要的,跳过其余。
5.1 常用预制中间件
| 中间件 | 作用 | 典型场景 |
|---|---|---|
ModelRetryMiddleware |
模型调用自动重试 | 应对限流、超时、瞬时错误 |
ToolRetryMiddleware |
工具调用自动重试 | 工具不稳定、偶发失败 |
HumanInTheLoopMiddleware |
人机协同,指定工具前暂停审批 | 危险写操作、昂贵调用前人工确认 |
PIIMiddleware |
隐私护栏,脱敏/拦截敏感数据 | 合规要求,强制性策略 |
SummarizationMiddleware |
历史/上下文压缩 | 长上下文防溢出 |
MemoryMiddleware |
加载持久化指令 | 跨会话记忆 |
SkillsMiddleware |
按需加载领域知识 | 避免一次性全量加载 |
FilesystemMiddleware |
文件系统读写 | 跨轮次的文件工作区 |
TodoListMiddleware |
任务清单规划 | 多步复杂任务 |
SubAgentMiddleware |
子代理委托 | 复杂任务并行分解,主上下文保持干净 |
5.2 示例:重试 + 人机协同
python
from langchain.agents import create_agent
from langchain.agents.middleware import (
ModelRetryMiddleware,
ToolRetryMiddleware,
HumanInTheLoopMiddleware,
)
from langchain.tools import tool
@tool
def search(query: str) -> str:
"""搜索并返回简短摘要。"""
return f"Search results for: {query}"
agent = create_agent(
model="google_genai:gemini-3.6-flash",
tools=[search],
middleware=[
ModelRetryMiddleware(max_retries=3),
ToolRetryMiddleware(max_retries=2),
HumanInTheLoopMiddleware(interrupt_on={"write_file": True}),
],
)
5.3 示例:文件系统 + 记忆 + 技能(来自 deepagents)
python
from deepagents.backends import StateBackend
from deepagents.middleware import (
FilesystemMiddleware,
MemoryMiddleware,
SkillsMiddleware,
SummarizationMiddleware,
)
backend = StateBackend()
model = "google_genai:gemini-3.6-flash"
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/"]),
],
)
这个示例从
deepagents包导入,需要先pip install deepagents。
5.4 create_agent() vs create_deep_agent()
create_agent:需要你自己配置 Harness,灵活、可控,适合按需组装能力。create_deep_agent:基于create_agent构建,已预置常用能力(规划、文件系统工具、子代理、记忆等)。
官方建议:需要深度定制时用 create_agent;想要一个开箱即用、能力齐全的长任务 Agent(coding / research)时用 create_deep_agent。
六、总结:你真正需要记住的 N 件事
- Agent = Model + Harness。 模型负责思考,Harness 负责在正确时机喂正确上下文;
create_agent()就是帮你组装 Harness 的工厂函数。 create_agent()返回CompiledStateGraph,用invoke/stream/get_state等运行和查看状态。- 三件套必配:
model+tools+system_prompt。model推荐传字符串;tools可传@tool函数 / Pydantic 类 / 工具字典;system_prompt建议总是设置。 - 自定义状态用
state_schema+ 子类化AgentState+InjectedState,让工具直接读写运行状态。 - 结构化输出用
response_format,从result["structured_response"]拿校验过的对象。 - 会话记忆用
checkpointer+thread_id,跨会话长期记忆用store。 - 单次运行上下文用
context_schema+context,它和thread_id是两个维度。 - 扩展能力靠
middleware:重试、PII 护栏、人机协同、文件系统、子代理、记忆/技能,自由组合、按需取用。 - 深度定制用
create_agent,开箱即用选create_deep_agent。
验证清单
- 能用
from langchain.agents import create_agent成功导入 - 最小 Agent(
model+system_prompt,无工具)能invoke并拿到回复 - 加入
@tool工具后,Agent 能在循环中自动调用工具 - 扩展
AgentState+InjectedState后,工具能读写自定义状态字段 - 配置
response_format后,能从structured_response拿到类型安全对象 - 配置
checkpointer+thread_id后,第二轮能记住第一轮对话 - 用
stream(或stream_events)能实时看到中间步骤 / 工具调用 - 生产场景下,为关键调用配置了
ModelRetryMiddleware/ToolRetryMiddleware - 涉及敏感或破坏性操作时,加了
HumanInTheLoopMiddleware或interrupt_before/after
参考资源
- LangChain 官方 Agents 文档:docs.langchain.com/oss/python/...
- LangChain
create_agentAPI Reference:reference.langchain.com/python/lang... - 菜鸟教程
create_agent()参考页:www.runoob.com/langchain/l... - 模型配置与 init_chat_model:docs.langchain.com/oss/python/...
- 中间件(Middleware)文档:docs.langchain.com/oss/python/...
- Deep Agents 文档:docs.langchain.com/oss/python/...
注:本文撰写时环境中外网访问受限,文中参数与示例主要引用上述 LangChain 官方文档及菜鸟教程页面。为获得最准确的参数与版本信息,请以官方参考为准。