拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LangChain 框架升级:DeepAgents 来袭,Cursor、Claude 助力规划与文件管理新高度!

LangChain 框架升级:DeepAgents 来袭,Cursor、Claude 助力规划与文件管理新高度! 1. 从 ReAct 到 DeepAgents规划与文件管理到底解决了什么如果你最近在 LangChain 生态里折腾 Agent大概率会有一种感觉ReAct 那套「思考—选工具—执行」的循环写个 demo 很爽一旦任务变成「先查资料、再整理成文档、中间还要记住上次结论」上下文就开始爆炸。模型要么忘了前面查过什么要么把一大堆中间结果全塞进对话历史token 烧得飞快最后还给你一个似是而非的答案。DeepAgents 这个包就是冲着这些痛点来的。它在 LangChain / LangGraph 之上补了三块能力一是内置write_todos工具让 Agent 把复杂任务拆成离散步骤并跟踪进度二是一整套文件系统工具ls、read_file、write_file、edit_file、glob、grep把大块上下文卸载到「文件」里而不是全堆在消息窗口三是子代理subagent机制用task工具生成专门的下游代理做上下文隔离。再配合 LangGraph 的 Store 做跨线程长期记忆一个能规划、能读写文件、能记住事的 Agent 骨架就成型了。这篇文章面向的是已经在用 LangChain 写 Agent、但被上下文和任务编排卡住的开发者。我会从环境准备讲到 Agent 任务编排的完整链路给出可复制的配置骨架以及一套统一的 Key / API 通道配置方式让你不用在多个模型供应商之间来回切换。Cursor 和 Claude 在这里的角色一个是帮你快速改配置和调试代码一个是作为规划能力较强的模型后端。下面直接进入实操。2. 前置准备环境、依赖与统一 API 通道2.1 安装与版本确认DeepAgents 的安装确实简单一行命令pip install deepagents但别急着跑先把依赖版本对齐。DeepAgents 依赖 LangChain 和 LangGraph 的较新版本如果你环境里是老的langchain0.1.x会出现create_deep_agent导入失败或者 backend 接口对不上的问题。建议单独建虚拟环境python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -U deepagents langchain langgraph langchain-community装完确认一下python -c import deepagents; print(deepagents.__version__)能打印出版本号就说明基础依赖没问题。2.2 用 TaoToken 统一 Key 与 API 通道实际开发里最烦的一件事是主 Agent 想用 Claude 做规划子代理想用国产模型省钱搜索工具又要另一个 Key。每个供应商一套 base_url、一套鉴权配置散落在各处换环境就崩。我的做法是把模型调用统一走一个兼容 OpenAI 协议的通道。TaoToken 提供的就是这样一个入口官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。你只需要在环境变量里配一个 Key 和一个 base_url模型名按需切换即可。在项目根目录建一个.env# .env TAOTOKEN_API_KEYsk-你的key TAOTOKEN_BASE_URLhttps://taotoken.net/apiKey 的获取在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。拿到之后不要硬编码进代码用python-dotenv读取。注意.env一定要加进.gitignore我见过太多把 Key 提交到公开仓库的案例清理起来很麻烦。2.3 Cursor 与 Claude 的协作定位Cursor 在这里不是运行时依赖而是你的开发环境。它的价值在于改settings.json、调 backend 路由、看 Agent 执行日志时能直接在编辑器里让 AI 帮你补全和解释。Claude 则作为规划能力较强的模型后端适合放在主 Agent 位置处理任务分解。两者一个管「写代码」一个管「跑规划」分工清晰。3. 可复制配置settings.json 与 config.toml 骨架3.1 Cursor 的 settings.json 片段如果你用 Cursor 开发这个项目可以在.cursor/settings.json里加一些项目级配置让编辑器理解你的 Python 环境和环境变量{ python.defaultInterpreterPath: ${workspaceFolder}/venv/bin/python, python.envFile: ${workspaceFolder}/.env, editor.formatOnSave: true, files.exclude: { **/__pycache__: true, **/local_file_path: false }, terminal.integrated.env.linux: { PYTHONPATH: ${workspaceFolder} } }files.exclude里特意把local_file_path设为false是因为后面 FilesystemBackend 会把 Agent 写的文件落到这个目录你需要能在侧边栏直接看到它方便验证文件读写是否生效。3.2 config.toml 骨架有些团队习惯用 TOML 管理模型和 backend 配置避免代码里散落魔法字符串。建一个config.toml[model] provider openai-compatible base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY main_model claude-sonnet-4-5-20250929 sub_model glm-4.5 temperature 0.5 [backend] default filesystem root_dir local_file_path virtual_mode true [backend.routes] /memories/ store [store] type in_memory [agent] recursion_limit 1000 debug true这份配置对应的是「主 Agent 用 Claude 做规划、子代理用 GLM 省钱、文件默认落本地、/memories/路径走 Store 持久化」的组合。下面代码里我会用os.environ直接读你可以按需替换成tomllib解析。3.3 模型初始化走统一通道关键点在于用ChatOpenAI兼容接口指向 TaoToken 的 base_url而不是给每个供应商写一套import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI load_dotenv() def create_main_model(): return ChatOpenAI( modelclaude-sonnet-4-5-20250929, api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], temperature0.5, ) def create_sub_model(): return ChatOpenAI( modelglm-4.5, api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], temperature0.5, )这样主模型和子模型共用一套鉴权切换模型只改model字段。如果你更习惯用ChatZhipuAI这类原生 SDK也可以但那样就得维护两套 Key统一通道的意义就没了。4. 核心链路backend 路由、子代理与中断控制4.1 文件系统 backend 的四种形态DeepAgents 的 backend 决定了「文件」到底存在哪。理解这四种形态是配好 Agent 的前提Backend存储位置生命周期典型用途StateBackendAgent State单次线程临时中间结果优化上下文FilesystemBackend本地磁盘目录长期保存生成的文档、代码文件StoreBackendLangGraph Store跨线程长期记忆如用户偏好CompositeBackend路由组合混合默认本地特定路径走 Store最常用的是CompositeBackend默认写本地磁盘但/memories/前缀的路径路由到 Store实现跨线程持久化。配置如下from pathlib import Path from deepagents.backends import CompositeBackend, FilesystemBackend, StoreBackend def make_backend(runtime): base_dir Path(__file__).parent / local_file_path return CompositeBackend( defaultFilesystemBackend(root_dirstr(base_dir), virtual_modeTrue), routes{ /memories/: StoreBackend(runtime) } )virtual_modeTrue会限制 Agent 只能在这个根目录下操作避免它乱写系统路径。这个参数建议一直开着。4.2 子代理定义与 CompiledSubAgent子代理的标准格式包含name、description、system_prompt、toolsmodel可选覆盖travel_advice { name: 旅游建议师, description: 根据天气情况给出适合旅游的建议, system_prompt: 你是一个旅游建议大师能够根据城市的天气给出对应的旅游攻略, tools: [], model: create_sub_model(), }如果你已经有用 LangGraph 搭好的 Agent 图可以直接用CompiledSubAgent包进来复用from deepagents import CompiledSubAgent from langchain.agents import create_agent custom_graph create_agent( modelcreate_sub_model(), toolsspecialized_tools, promptYou are a specialized agent for data analysis... ) custom_subagent CompiledSubAgent( namedata-analyzer, descriptionSpecialized agent for complex data analysis tasks, runnablecustom_graph )这样你之前写的图不用重写直接作为子代理挂到主 Agent 上。4.3 人机交互interrupt_on 与恢复涉及删除文件、发邮件这类敏感操作必须加人工审批。interrupt_on接收一个工具名到中断配置的字典from langgraph.checkpoint.memory import MemorySaver checkpointer MemorySaver() agent create_deep_agent( modelcreate_main_model(), tools[delete_file, read_file, send_email], interrupt_on{ delete_file: True, read_file: False, send_email: {allowed_decisions: [approve, reject]}, }, checkpointercheckpointer, )True表示允许批准、编辑、拒绝三种决策False表示不中断字典形式可以精确控制允许哪些决策。触发中断后Agent 会暂停并返回控制权你检查中断信息后用Command(resume...)恢复result agent.invoke( {messages: [{role: user, content: Delete the file temp.txt}]}, configconfig ) if result.get(__interrupt__): decisions [{type: approve}] result agent.invoke( Command(resume{decisions: decisions}), configconfig ) print(result[messages][-1][content])注意恢复时必须用同一个config否则 checkpointer 找不到对应的线程状态。子代理可以有自己的interrupt_on会覆盖主代理的设置这点在调试权限问题时容易踩坑。5. 验证请求规划与文件读写是否真的生效5.1 完整可运行示例把上面的片段拼起来写一个天气分析 Agent验证规划、搜索、子代理、文件写入四条链路import os import logging from typing import Literal from pathlib import Path from dotenv import load_dotenv from tavily import TavilyClient from deepagents import create_deep_agent from deepagents.backends import CompositeBackend, FilesystemBackend, StoreBackend from langgraph.store.memory import InMemoryStore from langchain_core.messages import HumanMessage load_dotenv() logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) def internet_search( query: str, max_results: int 5, topic: Literal[general, news, finance] general, include_raw_content: bool False, ): Run a web search tavily_client TavilyClient(api_keyos.environ[TAVILY_API_KEY]) return tavily_client.search( query, max_resultsmax_results, include_raw_contentinclude_raw_content, topictopic, ) SYSTEM_PROMPT 你是一个助手。 你的任务是帮助用户分析天气信息使用 search 工具搜索相关信息。 你有一个旅游建议师可以协助你做旅游攻略。 工作流程 1. 理解用户要分析的天气信息是哪个城市 2. 使用 search 搜索该城市的相关信息 3. 基于搜索结果和旅游建议师的建议提供清晰的结论 注意 - 把结论保存成 /consultion 下面的 Markdown 文件 - 把搜索信息保存到 /memories/search_info.md 中方便下次调用 main_tools [internet_search] def make_backend(runtime): base_dir Path(__file__).parent / local_file_path return CompositeBackend( defaultFilesystemBackend(root_dirstr(base_dir), virtual_modeTrue), routes{/memories/: StoreBackend(runtime)} ) travel_advice { name: 旅游建议师, description: 根据天气情况给出适合旅游的建议, system_prompt: 你是一个旅游建议大师能够根据城市的天气给出对应的旅游攻略, tools: [], model: create_sub_model(), } store InMemoryStore() agent create_deep_agent( modelcreate_main_model(), toolsmain_tools, backendmake_backend, system_promptSYSTEM_PROMPT, subagents[travel_advice], debugTrue, storestore, ).with_config({recursion_limit: 1000}) if __name__ __main__: import asyncio async def test_agent(): query 依次搜索青岛 济南的天气 result await agent.ainvoke({messages: [HumanMessage(contentquery)]}) if result and messages in result: print(分析结果, result[messages][-1].content) asyncio.run(test_agent())5.2 观察规划是否生效跑起来后debugTrue会打印执行过程。你要重点看两件事第一模型有没有调用write_todos。正常情况下它会先生成一个任务列表每项包含content要做的事和status初始为pending。执行到某一项时状态变成in_process完成后改成completed同时把下一项置为in_process。如果你看到它跳过write_todos直接调搜索说明系统提示里任务拆解的引导不够或者模型规划能力偏弱。第二子代理有没有被触发。当搜索到城市天气后主 Agent 应该通过task工具调用「旅游建议师」。日志里会出现子代理的调用记录返回的旅游建议会作为工具结果回到主 Agent。5.3 验证文件读写跑完后去项目目录看local_file_path/ls -R local_file_path/你应该能看到consultion/目录下的 Markdown 结论文件以及memories/search_info.md。前者走的是 FilesystemBackend落在本地磁盘后者走 StoreBackend存在内存 Store 里换成 Redis 或 Postgres 就能持久化。如果local_file_path是空的先检查make_backend里的base_dir路径是否正确再看 Agent 日志里有没有write_file调用。有时候模型会「说」它写了文件但实际没调工具这种幻觉要靠日志识别。6. 本篇常见错排查导入报错cannot import name create_deep_agent九成是版本问题。先pip show deepagents看版本再确认langchain和langgraph是不是被其他依赖降级了。建议在干净虚拟环境里重装。backend 报runtime相关错误make_backend接收的是runtime参数不是self。如果你从旧示例里抄了self.runtime.state.get(files, {})这种写法在 DeepAgents 里要改成通过 backend 接口访问。StateBackend 的文件存在 Agent State 的files字段里仅单线程有效。子代理不触发检查description是不是「以行动为导向」。主 Agent 靠这个描述决定何时委托如果写得太泛比如「一个助手」它不会调。改成「根据天气情况给出适合旅游的建议」这种具体描述触发率明显提升。中断后恢复失败最常见的原因是恢复时没传同一个config或者checkpointer没配。interrupt_on必须配合checkpointer使用否则中断信息无处保存。文件写到了意料之外的位置virtual_modeTrue时Agent 看到的路径是虚拟的实际映射到root_dir。如果它写/consultion/xxx.md实际落在local_file_path/consultion/xxx.md。别去系统根目录找。模型调用 401 或超时先确认.env里的TAOTOKEN_API_KEY和TAOTOKEN_BASE_URL都读到了可以在代码里print(os.environ.get(TAOTOKEN_BASE_URL))验证。base_url 结尾不要多加/v1按文档给的地址填。7. 继续深入把链路跑通之后做什么到这一步你已经有了一个能规划、能读写文件、能调子代理、能人工审批的 Agent 骨架。接下来可以往三个方向走一是把InMemoryStore换成 Redis 或 Postgres让/memories/真正跨会话持久化二是给子代理配上各自的工具集做更细的职责隔离三是把interrupt_on用在你自己的敏感工具上比如数据库写操作。如果你在接入过程中遇到模型通道配置的问题可以直接用模型对话页面快速验证 Key 是否可用https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。需要长期跑编码类 Agent、对调用量有要求的可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入细节和参数说明都在文档里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。最后留一个我踩过的坑调试阶段把recursion_limit设大一点比如 1000否则复杂任务跑到一半会抛递归上限错误而那个报错信息不会告诉你到底是哪一步循环了排查起来很费劲。
返回列表