1. 从单模型 LLM 调用到多智能体:为什么你的 Agent 总是半路翻车
如果你已经用 OpenAI SDK 或 LangChain 跑通过一个能调工具的 LLM,大概率遇到过这种场景:让它调研一个主题并写份报告,前两轮搜索还挺像样,第三轮开始它就"忘了"最初的任务目标,或者把前面搜到的资料张冠李戴。这不是模型变笨了,而是单模型 LLM 调用的工程天花板到了。
单模型 LLM 调用的本质是"一问一答加工具循环":你给模型一段系统提示,挂几个工具,模型决定调哪个、拿到结果再决定下一步。这个模式在任务步骤少于五步、上下文不超过窗口三分之一时非常好用。可一旦任务变成"先规划、再分头调研、汇总、写稿、自查"这种多阶段结构,问题就集中爆发:上下文窗口被中间结果塞满、单一角色注意力被稀释、没有全局计划导致走一步看一步。
DeepAgents 框架正是冲着这些痛点来的。它是 LangChain 官方生态里对"深度代理"理念的工程化落地,内置了任务规划(write_todos)、虚拟文件系统、子代理生成(task 工具)和长期记忆四套机制。简单说,它把"规划—执行—反馈—迭代"这个闭环从你手写的 while 循环里抽出来,变成框架级能力。
这篇文章面向需要在本地快速验证 Agent 编排的开发者。我会先讲清楚从 LLM 到 DeepAgents 的工程化路径,然后给出用 TaoToken 统一 Key 打通整条调用链的可复制配置,最后跑一次端到端验证,把框架分层和调用链路的衔接方式讲透。你不需要有 LangGraph 经验,但最好跑通过一次基础的 Function Calling。
2. TaoToken 前置准备:一个 Key 打通多智能体调用链
多智能体框架最烦人的地方在于:主代理、子代理、规划模型、审核模型可能配了不同的 Key 和 Base URL,调试时一个 401 就要翻半天配置文件。TaoToken 在这里的价值就是统一入口——一个 API Key、一个 Base URL,主代理和所有子代理共用同一套凭证,调用链路上不会因为凭证不一致而断掉。
TaoToken 是一个兼容 OpenAI 接口规范的模型调用服务,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api 。它适合谁?适合正在本地验证 Agent 编排、又不想在多个模型供应商之间来回切换凭证的开发者。DeepAgents 底层走的是 LangChain 的 ChatModel 抽象,只要模型服务兼容 OpenAI 协议,就能直接接进来。
你需要准备三样东西:一个 TaoToken API Key、确认要用的 Model ID、以及 DeepAgents 的运行环境。Key 在控制台的 API Keys 页面创建,地址是 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 。创建后复制保存,页面只显示一次。
Model ID 这块要注意:DeepAgents 的主代理和子代理可以指定不同模型。规划类任务用推理强一点的模型,检索摘要类子代理用快而便宜的模型,成本能压下来不少。具体有哪些 Model ID 可用,在模型对话页面能直接看到并试跑,地址 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite 。
环境准备就三步。第一,Python 3.10 以上,建议用虚拟环境隔离。第二,安装 deepagents 和 langchain 相关包。第三,把 Key 写进环境变量,别硬编码在代码里。安装命令如下:
python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install -U deepagents langchain langchain-openai装完后验证一下版本,deepagents 依赖 langchain v1 和 langgraph,版本不匹配会在导入时报错:
pip show deepagents langchain langgraph | grep -E "Name|Version"这里有个前置认知要建立:DeepAgents 不是替代 LangChain,而是站在它上面。langchain-core 提供 BaseChatModel 等抽象,langgraph 提供有状态图运行时,langchain 提供 create_agent 这类高阶 API,deepagents 再把规划、文件系统、子代理打包成 create_deep_agent。你配的 TaoToken Key 最终是通过 langchain-openai 的 ChatOpenAI 类注入到最底层的,所以只要这一层通了,上面三层全通。
3. 可复制配置:DeepAgents 接入 TaoToken 的完整片段
这一节给你可以直接抄的配置。核心思路是用 ChatOpenAI 指向 TaoToken 的 Base URL,然后把这个模型实例传给 create_deep_agent。先建一个.env文件放凭证:
# .env TAOTOKEN_API_KEY=sk-你的key TAOTOKEN_BASE_URL=https://taotoken.net/api然后是主程序agent_demo.py。注意 base_url 要带/v1还是不带,取决于 SDK 版本,langchain-openai 的 ChatOpenAI 内部会拼/chat/completions,所以 base_url 填https://taotoken.net/api即可:
import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from deepagents import create_deep_agent load_dotenv() # 统一模型入口:主代理和子代理共用同一套凭证 def build_model(model_id: str, temperature: float = 0.0): return ChatOpenAI( model=model_id, api_key=os.environ["TAOTOKEN_API_KEY"], base_url=os.environ["TAOTOKEN_BASE_URL"], temperature=temperature, ) # 主代理用推理强的模型 main_model = build_model("你的主模型ModelID") # 子代理用快而便宜的模型,成本能压下来 sub_model = build_model("你的子模型ModelID") agent = create_deep_agent( model=main_model, subagents=[ { "name": "researcher", "description": "负责联网检索和资料摘要", "model": sub_model, "tools": [], } ], )如果你更习惯用 TOML 管理配置,可以建一个config.toml,把模型 ID 和参数抽出来:
[main] model_id = "你的主模型ModelID" temperature = 0.0 [subagent.researcher] model_id = "你的子模型ModelID" temperature = 0.2然后在 Python 里用tomllib读取。这样做的好处是换模型不用改代码,改配置就行。实测下来,把主代理和子代理的模型分开配,一次深度调研任务的成本能降三到四成,因为子代理的检索摘要调用次数远多于主代理的规划调用。
关于 Model ID 的填写,有个坑要提前说:不同模型对temperature的接受范围不一样,有的推理模型只接受默认值。如果你在调用时收到参数校验错误,先把 temperature 去掉再试。另外create_deep_agent的subagents参数里,每个子代理的tools列表如果留空,它会继承主代理的工具集;如果你想让子代理只能用特定工具,就在这里显式列出。
配置写完后,先别急着跑完整任务,用一段最小代码验证模型连通性:
resp = main_model.invoke("回复两个字:通了") print(resp.content)这一步能过,说明 TaoToken 的 Key、Base URL、Model ID 三件套都对,后面 DeepAgents 的报错就基本与凭证无关了。
4. 端到端验证:跑一次带子代理的调研任务
配置通了之后,跑一个能体现 DeepAgents 分层结构的任务。我选的是"调研两个技术框架并写对比报告",因为它天然需要规划、分头检索、汇总三个环节,正好把 write_todos、task 子代理、文件系统三套机制都触发一遍。
完整调用代码如下:
from deepagents import create_deep_agent from langchain_openai import ChatOpenAI import os model = ChatOpenAI( model="你的主模型ModelID", api_key=os.environ["TAOTOKEN_API_KEY"], base_url=os.environ["TAOTOKEN_BASE_URL"], ) agent = create_deep_agent( model=model, subagents=[ { "name": "researcher", "description": "负责检索指定主题的资料并输出要点摘要", "model": model, } ], ) result = agent.invoke({ "messages": [ { "role": "user", "content": "调研 LangGraph 和 AutoGen 两个框架的定位差异,写一份 500 字对比报告,先列计划再执行。", } ] }) for msg in result["messages"]: print(type(msg).__name__, ":", getattr(msg, "content", "")[:200])跑起来后,你会看到消息序列里出现几类关键节点。第一类是主代理发起的write_todos工具调用,参数里是一个待办列表,比如"调研 LangGraph""调研 AutoGen""对比分析""写报告"。第二类是task工具调用,主代理把两个调研方向分别委派给 researcher 子代理。第三类是子代理内部的搜索和write_file调用,把大段资料落盘成langgraph_notes.md和autogen_notes.md。最后主代理用read_file取回笔记,综合成报告。
这里的关键观察点是上下文隔离。子代理内部可能发起了十几次检索调用,但这些中间消息都留在子代理自己的上下文里,回流给主代理的只有一条精炼的 ToolMessage。主代理的上下文因此保持干净,不会因为检索结果太多而"忘记"最初的任务。这就是 DeepAgents 相比手写单模型循环的核心优势。
成功结果的判断标准有三个:一是消息序列里能看到write_todos的调用记录,说明规划机制生效;二是能看到task工具被调用且子代理返回了摘要,说明子代理委派生效;三是最终 AI 消息里有一份结构完整的对比报告,而不是零散的资料堆砌。三个都满足,说明从 TaoToken 到 DeepAgents 的整条调用链是通的。
如果你想更直观地看调用链,可以在创建 agent 时打开流式输出,或者用 LangGraph 的 checkpointer 把每一步状态存下来回放。不过对第一次验证来说,打印消息序列已经够用了。
5. 常见报错排查:401、local proxy failed 与 reading choices
这一节按真实报错来。多智能体调用链比单模型调用长,出错点也多,但绝大多数集中在凭证、网络和响应解析三类。
401 Unauthorized。这是最常见的。原因通常是 Key 没读到、Key 失效、或者 Base URL 拼错。先检查.env有没有被load_dotenv()正确加载,可以在代码里打印os.environ.get("TAOTOKEN_API_KEY")[:8]确认前几位。如果 Key 读到了还报 401,去控制台确认 Key 是否被删除或过期。Base URL 这块,https://taotoken.net/api结尾不要多加斜杠,也不要自己拼/v1,让 SDK 处理。
local proxy failed / connection error。这类报错说明请求根本没发出去,通常是本地网络环境或代理配置问题。检查你的运行环境有没有设置HTTP_PROXY、HTTPS_PROXY环境变量,如果有但代理不可用,请求会卡在这里。可以先在终端用 curl 直接测一下端点连通性:
curl -s -o /dev/null -w "%{http_code}" https://taotoken.net/api/models \ -H "Authorization: Bearer $TAOTOKEN_API_KEY"返回 200 说明网络通,问题在代码层;返回其他码再针对性排查。
reading choices / KeyError 'choices'。这个报错出现在响应解析阶段,说明服务返回的 JSON 结构里没有choices字段。常见原因是 Model ID 填错了,服务返回了一个错误对象而不是正常的补全结果。解决办法是先把 Model ID 换成确认可用的,在模型对话页面试跑一次拿到正确的 ID。另一个原因是流式和非流式模式混用,DeepAgents 默认走非流式,如果你手动改了streaming=True又没处理流式响应,也会解析失败。
OAuth / authentication 相关报错。如果你之前配过 Claude Code 或 Codex 的凭证,环境里可能残留了ANTHROPIC_API_KEY或OPENAI_API_KEY,langchain-openai 在某些版本下会优先读环境变量而不是你传的api_key参数。解决办法是在创建 ChatOpenAI 时显式传api_key,或者临时清掉冲突的环境变量。
子代理不触发。任务跑了但没看到task调用,通常是子代理的description写得太模糊,主代理判断不出该委派给谁。把 description 写具体,比如"负责联网检索指定主题并输出不超过 300 字的要点摘要",触发率会明显提升。
上下文溢出。如果任务跑到一半报 token 超限,说明文件系统机制没生效。检查你的提示词里有没有引导模型"把大段资料写入文件",DeepAgents 的内置提示会做这件事,但如果你覆盖了系统提示,可能把这个引导弄丢了。
排查顺序建议从下往上:先 curl 测端点,再测单模型 invoke,再跑单代理任务,最后跑多代理任务。这样能把问题定位在具体哪一层。
6. 把统一 Key 用起来:从验证到长期编码
走到这里,你已经跑通了一条从 TaoToken 统一 Key 到 DeepAgents 多智能体框架的完整调用链。回顾一下分层:langchain-core 提供模型和工具的抽象契约,langgraph 提供有状态图运行时,langchain 提供 create_agent 这类高阶封装,deepagents 把规划、文件系统、子代理、长期记忆打包成开箱即用的 create_deep_agent。你的 TaoToken Key 通过 langchain-openai 的 ChatOpenAI 注入最底层,上面三层全部复用同一套凭证。
这套结构的好处是,你换模型只需要改一个 Model ID,不用动任何编排代码。主代理用推理强的模型做规划,子代理用快而便宜的模型做检索,成本和质量能同时兼顾。
如果你打算把这条链路用到日常编码或长期运行的 Agent 上,建议下一步做两件事。一是把配置抽成独立的 settings 文件,主代理、子代理、审核代理各自指定模型,方便按任务类型调优。二是接上 LangGraph 的 checkpointer,让长任务支持中断恢复,这样即使某一步失败也不用从头跑。
需要长期跑编码类 Agent 的,可以看下 Coding Plan 的额度方案,地址 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有各语言 SDK 的完整示例。如果你用的是 Claude Code 做本地开发,Anthropic 兼容接入的说明在 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude_code&utm_campaign=rewrite 。
最后留一个实操建议:多智能体任务调试时,先把子代理数量压到一个,跑通再加。子代理一多,调用链变长,出错时定位成本会指数上升。等单子代理稳定了,再按"检索、分析、审核"的角色逐步拆分,这样每一步的上下文隔离效果都能单独验证。