1. 从 LangChain 手写规划到 DeepAgent 原生 write_todos
如果你用 LangChain 搭过稍微复杂一点的智能体,大概率经历过这个阶段:为了让模型把「先查资料、再写代码、最后跑测试」这件事拆清楚,你得在提示词里反复强调「请先列出步骤」「每完成一步标记状态」,然后自己解析模型返回的文本,判断它到底做没做完。LangGraph 好一些,它给了你状态图和检查点,但 Plan→Execute→Review 这几个节点还是得自己画,边和条件路由也得自己连。多智能体就更麻烦,create_agent 拼来拼去,上下文隔离和通信全靠自觉。
DeepAgent 想解决的就是这一层「工程胶水」。它把自己定位成 LangChain + LangGraph 之上的生产级 Harness,核心卖点之一是原生write_todos工具:主 Agent 拿到任务后,直接调用这个工具做结构化拆解,生成带状态的待办列表,执行过程中持续更新进度,失败可回溯、可动态调整。另一个卖点是分层子 Agent——声明式、编译式、异步三类 SubAgent,主 Agent 负责规划和协调,子 Agent 负责专业执行,天然支持并行。
这条链路每一步都在调模型:拆解要调、子 Agent 执行要调、结果汇总还要调。Token 就是在这里被消耗的。所以模型接入层怎么配,直接决定了你跑长任务时顺不顺、贵不贵。这篇就按「主 Agent 触发一次 write_todos 拆解、子 Agent 并行返回结果」这条最小可用链路,把模型接入改走 TaoToken 的完整配置写清楚,配通之后再叠加沙箱、长期记忆和 DeltaChannel 检查点,模型侧不用再换 Key。
2. 前置准备:TaoToken 的 Key 与 Base URL 怎么拿
TaoToken 在这套架构里只做一件事:给模型通道发 Key 和 Base URL。它不参与 write_todos 的拆解逻辑,也不碰 VFS、沙箱和三层记忆。你可以把它理解成模型调用的统一入口,DeepAgent 底层那份 LangChain 模型配置指向它就行。
第一步,打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 注册账号。注册流程很常规,邮箱加密码,收个验证邮件就完事。
第二步,进控制台创建 API Key。地址是 https://taotoken.net/console ,登录后在 API Keys 页面点新建,复制出来的 Key 一般形如sk-开头的一长串。这个 Key 只显示一次,建议先存到本地环境变量文件里,别直接硬编码进代码。
第三步,记下 Base URL:https://taotoken.net/api。注意这里不带/v1,也不加任何 UTM 参数。很多 LangChain 的 OpenAI 兼容配置默认会拼/v1/chat/completions,如果你把 Base URL 写成带/v1的,最终路径就会变成/v1/v1/...,直接 404。这个坑后面排障章节会再展开。
如果你只是想先验证模型通不通,可以走模型对话页面 https://taotoken.net/models 快速试一句;如果是要长期跑编码类 Agent,可以了解下 Coding Plan https://taotoken.net/coding-plan ;接入细节和参数说明在文档 https://taotoken.net/doc ,Key 管理在 https://taotoken.net/api-keys 。这些入口按需用,核心还是下面这份配置。
3. 可复制配置:把 Key 和 Base URL 写进 DeepAgent 的模型层
DeepAgent 底层还是 LangChain 的模型抽象,所以配置点就在你初始化 ChatModel 的那一处。下面用 OpenAI 兼容接口举例,因为 TaoToken 的 Base URL 就是按这个协议暴露的。
先设置环境变量,避免 Key 泄漏到代码仓库:
export TAOTOKEN_API_KEY="sk-你的Key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"然后在 Python 里初始化模型层:
import os from langchain_openai import ChatOpenAI llm = ChatOpenAI( model="gpt-4o-mini", # 按你实际要用的模型名填 api_key=os.environ["TAOTOKEN_API_KEY"], base_url=os.environ["TAOTOKEN_BASE_URL"], temperature=0.2, timeout=120, max_retries=2, )这里有几个参数值得说清楚。base_url一定是不带/v1的裸域名加/api,LangChain 的 OpenAI 客户端会自己补路径。timeout建议给到 120 秒以上,因为 write_todos 拆解和子 Agent 执行都是长响应,默认 60 秒容易在复杂任务上超时。max_retries给 2 次,网络抖动时能自动重试,但别给太多,否则失败任务会拖很久。
接下来把这份 llm 传给 DeepAgent 的主 Agent。假设你已经按官方方式创建了主 Agent,配置大致是这样:
from deepagents import create_deep_agent agent = create_deep_agent( model=llm, tools=[], # 主 Agent 主要靠 write_todos 规划 system_prompt="你是一个规划型主 Agent,负责拆解任务并协调子 Agent。", )子 Agent 的模型可以复用同一个 llm 实例,也可以按角色单独配。声明式 SubAgent 的配置里带上 name、description、tools 就够了:
from deepagents import SubAgent researcher = SubAgent( name="researcher", description="负责资料检索与信息汇总", system_prompt="你只做检索和摘要,不写最终代码。", tools=[search_tool], model=llm, ) coder = SubAgent( name="coder", description="负责根据需求编写和修改代码", system_prompt="你只写代码,写完给出文件路径。", tools=[write_file_tool, edit_file_tool], model=llm, )主 Agent 拿到任务后会调write_todos生成待办,然后按 description 把子任务分派给 researcher 和 coder。两个子 Agent 之间没有直接通信,上下文是隔离的,结果通过主 Agent 汇总。这就是「主 Agent 规划、子 Agent 执行」的基本形态。
4. 验证请求:跑通一次 write_todos 拆解与子 Agent 并行
配置写完,先别急着上复杂任务。用一句中等复杂度的话验证链路:
result = agent.invoke({ "messages": [ {"role": "user", "content": "帮我调研一下 Python 异步编程的三种主流写法,并给出一个对比表格。"} ] }) print(result)预期你会看到主 Agent 先输出一段规划,内部触发write_todos,生成类似这样的结构化待办:
{ "todos": [ {"id": 1, "task": "检索 asyncio 基础用法", "status": "pending"}, {"id": 2, "task": "检索 async/await 语法要点", "status": "pending"}, {"id": 3, "task": "检索多线程与异步的边界", "status": "pending"}, {"id": 4, "task": "汇总生成对比表格", "status": "pending"} ] }然后 researcher 子 Agent 被触发,并行去处理前三个检索任务,状态从 pending 变成 in_progress 再到 completed。最后主 Agent 汇总,输出对比表格。
如果你在日志里看到子 Agent 的调用是交错出现的,说明并行生效了。如果是一个接一个串行,检查一下你用的是不是异步 AsyncSubAgent,或者主 Agent 的分派逻辑有没有被 system_prompt 限制成串行。
验证通过后,再按原文思路叠加沙箱执行、三层记忆和 DeltaChannel 检查点。这些能力都在 DeepAgent 内部,模型侧不用动,Key 和 Base URL 保持上面那份配置即可。
5. 本篇常见错排查
报错一:404 Not Found,路径里出现/v1/v1/。这是最常见的。原因就是 Base URL 写成了https://taotoken.net/api/v1。改成https://taotoken.net/api即可,不要带/v1。
报错二:401 Unauthorized。检查 Key 有没有复制完整,前后有没有多余空格。环境变量方式读取时,确认os.environ["TAOTOKEN_API_KEY"]真的取到了值,可以在初始化前 print 一下长度。
报错三:write_todos 不触发,主 Agent 直接开始回答。多半是 system_prompt 没强调规划职责,或者模型本身对工具调用支持弱。把 system_prompt 改成明确要求「先调用 write_todos 拆解,再分派子 Agent」,并确认你选的模型支持 function calling。
报错四:子 Agent 并行变串行。检查子 Agent 类型。声明式 SubAgent 默认按主 Agent 分派顺序执行,要真正并行得用异步 AsyncSubAgent,或者在主 Agent 层用异步调用方式触发多个子任务。
报错五:长任务跑到一半超时。把timeout调到 180 甚至 300 秒,同时确认max_retries不要设成 0。如果还是断,看看是不是单次 write_todos 拆出的待办太多,可以限制单次拆解的任务数量。
报错六:上下文溢出。这是没启用 VFS 或自动摘要时的典型问题。确认 DeepAgent 的 VFS 后端配好了,大文本走文件读写而不是全塞对话窗口。三层记忆和自动摘要开启后,长会话会稳定很多。
6. 配通之后:模型侧不用再换 Key
把上面这份配置跑通,你拿到的是一个可用的最小链路:主 Agent 触发 write_todos 拆解,子 Agent 并行执行并返回结果。TaoToken 在这里只负责模型通道的 Key 和 Base URL,拆解逻辑、VFS、沙箱、记忆这些都不归它管,也不该归它管。
后续你要加沙箱执行代码,就在 DeepAgent 的 execute 工具上配隔离后端;要加长期记忆,就接三层记忆的存储;要压缩长会话检查点,就开 DeltaChannel。这些叠加过程中,模型层那份ChatOpenAI配置不用动,Key 和 Base URL 保持https://taotoken.net/api就行。
如果你跑的是长期编码类 Agent,建议顺手看下 Coding Plan https://taotoken.net/coding-plan ,额度模型和按量计费的取舍在那里讲得比较清楚。接入过程中遇到路径或鉴权问题,文档 https://taotoken.net/doc 里有参数对照,Key 的轮换和权限管理在 https://taotoken.net/api-keys 。先把这条最小链路跑稳,再往上叠能力,比一上来就堆全套配置要省心得多。