主题:LangChain 1.0 全新 Agent 框架、
create_agent的模型接入、工具接入(内置/自定义)、ReAct 循环、记忆管理关键词:Agent Runtime / LangGraph / Tools / Tool Calling / ReAct Loop / Checkpointer / thread_id
0. 总览:LangChain 1.0 的 Agent 发生了什么变化?
LangChain 1.0 最大的变化之一:Agent 体系被"重做"并"统一"。
-
从"碎片化 Agent" → "统一 create_agent API"
-
0.x 时代:各种 Agent 创建函数分散(不同范式不同入口),学习与维护成本高。
-
1.0 时代:官方主推统一入口
create_agent(...),把 Agent 的创建方式"收敛"为一个更统一、可插拔的框架。
-
-
从"链式脚本" → "Agent Runtime(运行时)"
- Agent 不只是模型调用脚本,而更像一个可持续运行、能维护状态、能调度工具、能循环推理的"运行体"。
-
底层以 LangGraph 为核心
- 1.0 开始 LangGraph 更像"底座":用图结构组织 Agent 的节点与边(推理、工具调用、状态更新等),使 Agent 更可控、更工程化。
1. LangChain 1.0 最大更新:全新 Agent 框架介绍
1.1 Agent API "大一统":统一为 create_agent
LangChain 1.0 把 Agent 的核心创建方式统一到:
create_agent(model=..., tools=[...], system_prompt=..., checkpointer=...)
相比过去"要记住不同 Agent 工厂函数/不同范式",1.0 的目标是:
-
接口统一:减少分支、降低心智负担
-
可插拔:模型/工具/记忆都可以灵活替换
-
可扩展:更适合工程化与生产落地
1.2 create_agent 极简调用流程(核心代码骨架)
Notebook 给出的最小创建流程:模型 + 工具 + system_prompt → agent
python
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
from langchain_community.tools.tavily_search import TavilySearchResults
web_search = TavilySearchResults(max_results=2)
model = ChatDeepSeek(model="deepseek-chat")
agent = create_agent(
model=model,
tools=[web_search],
system_prompt="你是一名多才多艺的智能助手,可以调用工具帮助用户解决问题。"
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "请帮我查询2024年诺贝尔物理学奖得主是谁?"}]}
)
要点:
-
输入输出遵循 messages 结构(类似 Chat Completions 的对话消息)
-
Agent 内部会根据需要决定是否调用工具,并把工具结果纳入后续推理
1.3 底层架构:LangGraph 作为 Agent Runtime 的支撑
从 1.0 开始:
-
Agent 不再是"线性链式执行"
-
而是"图结构运行"(节点/边/状态)
带来典型优势:
-
接口统一,降低心智负担:开发者更少关心内部差异
-
跨生态兼容增强:更容易与不同模型/工具体系对接
-
工程化增强:状态管理、循环控制、可观察性更自然
1.4 与 Agents SDK / ADK 的关系(笔记观点)
Notebook 提到:LangChain 1.0 的 create_agent() 在形式上与某些 Agent SDK 风格接近:
"传入模型 + 工具 + 说明 → 返回可交互 Agent 实例"。
2. create_agent API:模型接入方法(静态 / 动态)
2.1 Agent Loop(智能体循环)的核心理解
Agent 并非"一次模型调用结束",而是一个循环结构(Agent Loop):
-
模型读入当前上下文(messages + 状态)
-
推理是否要调用工具
-
调用工具、获得 observation(工具返回)
-
结合 observation 再推理
-
不断迭代,直到满足停止条件(给出最终回答)
2.2 两种模型接入模式
A) 静态模型(Static Model)
特点:模型固定,适合快速 demo 与多数稳定生产场景。
方式 1:直接传字符串(框架自动映射/补全标识的思路)
- 你只需要传一个模型名,LangChain 会推断完整标识(Notebook 举了 deepseek 的例子)。
方式 2:先实例化模型对象,再传入
python
model = ChatDeepSeek(model="deepseek-chat")
agent = create_agent(model=model, tools=[...])
B) 动态模型(Dynamic Model)
特点:可根据上下文/阶段切换模型(成本与效果平衡)
-
例如:
-
对话初期用小模型省钱
-
推理变复杂再切到强模型
-
Notebook 更强调概念与价值:动态模型更适合"复杂任务与成本优化"。
3. create_agent 接入内置工具与 Agent 创建流程
3.1 为什么工具接入是 Agent 的关键?
Notebook 直接点明:
-
如果只是模型调用,用
model.invoke就够了 -
要做 Agent(能行动、能执行任务)就必须接入工具 Tools
3.2 LangChain 常见内置工具类型(Notebook 表格总结)
| 领域 | 工具示例 | 功能说明 |
|---|---|---|
| 搜索与检索 | DuckDuckGo / Brave / Bing | 联网问答、检索网页摘要与链接 |
| 网页浏览提取 | Playwright / Selenium | 自动化访问、抓取文本、截图等 |
| 生产力集成 | Slack / Jira / Google Drive | 读写消息、工单、文档、文件检索 |
| 数据库与向量检索 | SQLDatabase / Faiss/Chroma/Milvus | SQL 查询、向量相似检索(RAG) |
| 代码与终端执行 | Python REPL / Shell / Requests | 运行代码、执行命令、发 HTTP 请求 |
| 多模态 | DALL·E / Image Search / Whisper | 文生图、图片搜索、语音转文本 |
| 知识检索增强 | VectorStoreRetriever / MultiQuery | 文档片段检索、多查询扩展 |
| 云与 AI 服务 | OpenAI/Azure Functions / Anthropic | 调用函数、工具调用能力集成 |
| 文件与数据处理 | CSV Toolkit / Pandas DF Tool | 表格分析、过滤、统计等 |
示例中重点演示:TavilySearchResults(联网搜索工具)
3.3 内置工具示例:Tavily 搜索工具
初始化工具并直接调用工具:
python
from langchain_community.tools.tavily_search import TavilySearchResults
web_search = TavilySearchResults(max_results=2)
web_search.invoke("请问截至目前,2025年诺贝尔奖颁发了几个?")
3.4 把内置工具接入 Agent(完整流程)
python
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
from langchain_community.tools.tavily_search import TavilySearchResults
web_search = TavilySearchResults(max_results=2)
model = ChatDeepSeek(model="deepseek-chat")
agent = create_agent(
model=model,
tools=[web_search],
system_prompt="你是一名多才多艺的智能助手,可以调用工具帮助用户解决问题。"
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "请帮我查询2024年诺贝尔物理学奖得主是谁?"}]}
)
3.5 result["messages"]:理解 Agent 的"过程输出"
Notebook 后面逐个查看了:
-
result['messages'] -
len(result['messages']) -
result['messages'][0/1/2/3]
这暗示一个重要点:
-
Agent 输出不仅有最终回答,还可能包含:
-
用户输入消息
-
模型的中间响应
-
工具调用请求(tool call)
-
工具返回(observation)
-
最终总结回答
-
调试 Agent 时,messages 是最关键的可观察对象。
4. create_agent 接入自定义工具 & ReAct 循环介绍
4.1 自定义工具的本质
工具 = 一个可被 Agent 调用的函数(带清晰输入输出约束)
Notebook 给了两个工具案例:
-
get_weather(loc):调用 OpenWeather API 查天气 -
write_file(content):写入本地文件
4.2 自定义工具示例 1:天气查询(requests 调 API)
(原始函数版本)
python
def get_weather(loc):
url = "https://api.openweathermap.org/data/2.5/weather"
params = {
"q": loc,
"appid": os.getenv("OPENWEATHER_API_KEY"),
"units": "metric",
"lang": "zh_cn"
}
response = requests.get(url, params=params)
data = response.json()
return json.dumps(data)
关键点:
-
通过环境变量读取
OPENWEATHER_API_KEY -
返回 JSON(字符串化)作为工具输出,便于模型消费
4.3 用 @tool 把函数"工具化"
LangChain 需要知道:
-
这个函数可以被工具调用
-
其参数与返回值是什么
Notebook 的做法:
python
from langchain.tools import tool
@tool
def get_weather(loc):
...
4.4 自定义工具示例 2:写文件工具(强调健壮性)
python
@tool
def write_file(content: str) -> str:
try:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"output_{timestamp}.txt"
with open(filename, "w", encoding="utf-8") as f:
f.write(content)
abs_path = os.path.abspath(filename)
return f"✅ 已成功写入本地文件:{abs_path}"
except Exception as e:
return f"❌ 文件写入失败:{str(e)}"
这里有个工程细节非常重要(Notebook 特意标注 ✅):
- 先定义 filename/timestamp,避免异常路径下变量未绑定
4.5 把多个自定义工具接入 Agent,并触发"多步任务"
python
agent = create_agent(
model=model,
tools=[get_weather, write_file],
system_prompt="你是一名多才多艺的智能助手,可以调用工具帮助用户解决问题。"
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "请帮我查询天津、石家庄、上海等地天气,并写入本地文件。"}]}
)
这类任务通常会触发典型的 ReAct / Agent Loop:
-
先规划:要查多个城市
-
多次调用 get_weather
-
汇总成一段内容
-
调用 write_file 写入落盘
-
最后把结果路径/摘要回复用户
4.6 ReAct 循环(你需要把它当成"运行机制"而不是"提示词技巧")
虽然 Notebook 没把 ReAct 展开成公式,但从"工具调用 + observation + 再推理"的 messages 过程可以直接理解:
-
Reason(推理):决定下一步做什么
-
Act(行动):调用哪个工具、传什么参数
-
Observe(观察):读取工具返回
-
循环直到完成目标
5. create_agent 记忆管理(Memory / Checkpointer)
5.1 为什么需要记忆?
真实 Agent 场景里必须解决:
-
多轮对话上下文
-
状态持久化(同一会话 thread)
-
多用户/多线程隔离
Notebook 用 LangGraph 的 checkpointer 做记忆保存。
5.2 InMemorySaver:最小可用的"内存型 checkpoint"
python
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
tools = [get_weather]
agent = create_agent(model=model, tools=tools, checkpointer=checkpointer)
要点:
-
checkpointer负责保存/恢复状态 -
InMemorySaver 适合 demo(进程重启就没了),生产一般换持久化实现
5.3 用 thread_id 区分会话(同一 thread 才能"记得你")
同一 thread:记忆生效
python
config = {"configurable": {"thread_id": "1"}}
response = agent.invoke(
{"messages": [{"role": "user", "content": "你好,我叫陈明,好久不见!"}]},
config
)
response = agent.invoke(
{"messages": [{"role": "user", "content": "你好,请问你还记得我叫什么名字么?"}]},
config
)
并可读取当前线程状态:
python
latest = agent.get_state(config)
不同 thread:重新开一段新对话(记忆隔离)
python
config2 = {"configurable": {"thread_id": "2"}}
response2 = agent.invoke(
{"messages": [{"role": "user", "content": "你好,你还记得我叫什么名字么?"}]},
config2
)
核心结论:
-
thread_id 是"记忆作用域"的关键开关
-
同 thread = 共享记忆;不同 thread = 互相隔离
6. 开发清单(按 Notebook 流程提炼)
-
准备环境变量
- 模型 key / 工具 key(如 OpenWeather、Tavily 等)
-
选择模型接入方式
-
静态模型(简单稳定)
-
动态模型(成本/能力自适应)
-
-
准备工具
-
先用内置工具验证流程(如 Tavily)
-
再写自定义工具(用
@tool包装)
-
-
创建 Agent
create_agent(model, tools, system_prompt, checkpointer)
-
调试与可观察性
- 重点看
result["messages"]的全过程
- 重点看
-
上线前补齐记忆/状态
checkpointer+thread_id做多轮会话隔离与记忆