1. 为什么 deepagents 跑起来总在鉴权上翻车
deepagents 是 langchain-ai 团队基于 LangGraph 构建的智能体开发框架,核心卖点是让 Agent 能处理长周期、复杂任务:内置 write_todos 做任务分解,提供 ls/read_file/write_file 等文件系统工具管理上下文,还能通过 task 工具派生子代理隔离上下文。适合谁?适合已经在用 LangGraph、想快速搭一个"能规划、能记笔记、能派小弟"的深度智能体的开发者。
但真正落地时,很多人卡在第一步:模型鉴权。原因不复杂——deepagents 底层是 LangGraph,模型走的是 LangChain 的 ChatModel 体系,而 LangChain 读取密钥的方式有好几套:环境变量、显式传参、settings.json、.env 文件。你本地可能同时装了 OpenAI、Anthropic、Tavily 的 Key,环境变量互相覆盖,报错信息又只给你一句AuthenticationError或者model not found,根本看不出是哪一层配置没生效。
我试过在一台机器上同时跑三个 Agent 项目,结果 deepagents 一直报 401,排查半小时才发现是旧的OPENAI_API_KEY环境变量把新配置顶掉了。所以这篇不讲虚的,直接给你一份 settings.json 骨架,把 deepagents 的模型通道统一到 TaoToken,再配上逐步验证动作和报错对照表,让配置问题十分钟内定位。
2. TaoToken 前置:统一 Key 与 API 通道
TaoToken 在这里扮演的角色是"统一模型入口"。你不需要在 deepagents 里分别配 OpenAI、Anthropic 的 Key,而是把 base_url 指向 TaoToken 的 API 地址,用一个 Key 调用多个模型。这对 deepagents 特别有用,因为它的子代理可以指定不同模型(比如主代理用 claude-sonnet,子代理用 gpt-4o),如果每个模型都要单独配 Key,settings.json 会变得很乱。
先拿到你的 Key。访问控制台创建 API Key:
https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite创建后复制 Key,格式通常是sk-开头。API 基础地址是:
https://taotoken.net/api注意这个地址不带 UTM 参数,直接用于代码里的 base_url。如果你用的是 OpenAI 兼容协议,base_url 填https://taotoken.net/api/v1;如果走 Anthropic 协议,填https://taotoken.net/api。deepagents 默认走 LangChain 的init_chat_model,所以两种协议都支持,取决于你传的 model 前缀。
建议把 Key 存到环境变量,而不是硬编码在 settings.json 里。原因后面排错章节会讲——环境变量优先级最高,能覆盖掉配置文件里的旧值。
export TAOTOKEN_API_KEY="sk-你的key"Windows PowerShell 用:
$env:TAOTOKEN_API_KEY="sk-你的key"3. settings.json 可复制骨架
deepagents 本身没有强制的 settings.json 格式,但 LangChain 生态里常用一个统一的配置文件来管理模型、工具、子代理。下面这份骨架是我实测能跑通的版本,放在项目根目录,命名为settings.json。
{ "model": { "provider": "openai", "name": "gpt-4o", "base_url": "https://taotoken.net/api/v1", "api_key_env": "TAOTOKEN_API_KEY", "temperature": 0.2, "max_tokens": 4096 }, "subagents": [ { "name": "research-agent", "description": "用于深入研究问题", "system_prompt": "你是一位优秀的研究员,擅长拆解复杂问题并给出结构化结论。", "model": "openai:gpt-4o", "tools": ["internet_search"] }, { "name": "code-agent", "description": "用于代码生成与审查", "system_prompt": "你是一位资深 Python 工程师,输出可运行的代码。", "model": "anthropic:claude-sonnet-4-20250514", "tools": [] } ], "tools": { "internet_search": { "type": "tavily", "api_key_env": "TAVILY_API_KEY", "max_results": 5 } }, "runtime": { "verbose": true, "max_iterations": 25 } }几个关键点解释一下。base_url指向 TaoToken 的 OpenAI 兼容端点,这样 LangChain 的ChatOpenAI会直接把请求发到 TaoToken,而不是默认的 OpenAI 官方地址。api_key_env写的是环境变量名,不是 Key 本身,这样你可以把 settings.json 提交到 Git 而不泄露密钥。
子代理里的model字段用provider:name格式。deepagents 在创建子代理时会调用init_chat_model,这个函数识别前缀后自动选择对应的 ChatModel 类。但要注意:init_chat_model默认不会读你的 base_url,所以需要在代码里显式把 base_url 传进去,或者用环境变量OPENAI_API_BASE覆盖。
下面是配套的 Python 加载代码,放在agent.py:
import json import os from deepagents import create_deep_agent from langchain.chat_models import init_chat_model from tavily import TavilyClient # 读取 settings.json with open("settings.json", "r", encoding="utf-8") as f: settings = json.load(f) # 从环境变量取 Key api_key = os.environ.get(settings["model"]["api_key_env"]) if not api_key: raise RuntimeError("未找到 TAOTOKEN_API_KEY,请先 export") # 初始化主模型,显式传 base_url main_model = init_chat_model( model=settings["model"]["name"], model_provider=settings["model"]["provider"], api_key=api_key, base_url=settings["model"]["base_url"], temperature=settings["model"]["temperature"], max_tokens=settings["model"]["max_tokens"], ) # 初始化搜索工具 tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"]) def internet_search(query: str, max_results: int = 5): """执行网络搜索""" return tavily_client.search(query, max_results=max_results) # 组装子代理 subagents = [] for sub in settings["subagents"]: subagents.append({ "name": sub["name"], "description": sub["description"], "system_prompt": sub["system_prompt"], "model": sub["model"], "tools": [internet_search] if "internet_search" in sub["tools"] else [], }) # 创建深度代理 agent = create_deep_agent( model=main_model, tools=[internet_search], system_prompt="进行研究并撰写一份精炼的报告。", subagents=subagents, ) if __name__ == "__main__": result = agent.invoke({ "messages": [{"role": "user", "content": "什么是 LangGraph?"}] }) print(result["messages"][-1].content)这段代码的核心是init_chat_model显式接收base_url和api_key。如果你只依赖环境变量,LangChain 会去找OPENAI_API_KEY,而不是TAOTOKEN_API_KEY,这就是很多人报 401 的根因。
4. 验证请求与成功结果
配置写完,别急着跑完整 Agent,先做三层验证,逐层排除问题。
第一层:验证 TaoToken 通道本身通不通。用 curl 直接打 API:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 10 }'如果返回 JSON 里有choices字段,说明 Key 和通道都没问题。如果返回 401,检查 Key 是否复制完整;返回 404,检查 base_url 是否多了或少了/v1。
第二层:验证 LangChain 的 ChatModel 能调通。单独跑一段:
from langchain.chat_models import init_chat_model import os model = init_chat_model( model="gpt-4o", model_provider="openai", api_key=os.environ["TAOTOKEN_API_KEY"], base_url="https://taotoken.net/api/v1", ) resp = model.invoke("用一句话解释什么是智能体") print(resp.content)这一步能过,说明 LangChain 层没问题。如果报model not found,大概率是模型名写错了,TaoToken 的模型名要和官方一致,比如gpt-4o、claude-sonnet-4-20250514。
第三层:跑完整 deepagents。执行python agent.py,正常输出应该是一段关于 LangGraph 的解释文本。如果 Agent 启动了但中途卡住,看runtime.verbose打开的日志,通常会显示它在调用哪个工具、哪个子代理。
成功结果的特征:主代理先调用 write_todos 列出计划,然后可能派发 research-agent 子代理去搜索,最后汇总成报告。你会在终端看到类似Tool: write_todos、Subagent: research-agent的日志。
5. 本篇常见错排查
下面这张表覆盖了 deepagents 接入 TaoToken 时最高频的报错,按报错信息查即可。
| 报错信息 | 根因 | 修复动作 |
|---|---|---|
AuthenticationError: 401 | Key 未传或传错 | 检查TAOTOKEN_API_KEY是否 export,代码里是否显式传 api_key |
model not found | 模型名拼写错误 | 用gpt-4o而非gpt4o,Anthropic 模型带日期后缀 |
Connection error | base_url 写错 | OpenAI 协议用/api/v1,Anthropic 协议用/api |
KeyError: TAVILY_API_KEY | 搜索工具 Key 缺失 | 单独 export TAVILY_API_KEY,或先去掉搜索工具测试 |
| 子代理报 401 但主代理正常 | 子代理未继承 base_url | 子代理的 model 字段需在代码里统一注入 base_url |
max_iterations exceeded | Agent 循环调用工具 | 调大runtime.max_iterations,或检查工具返回值是否为空 |
| 环境变量覆盖配置 | 旧 Key 残留 | unset OPENAI_API_KEY后再跑,避免 LangChain 优先读旧变量 |
重点说两个坑。第一个是环境变量优先级:LangChain 的init_chat_model如果没收到显式 api_key,会按OPENAI_API_KEY→AZURE_OPENAI_API_KEY的顺序找。你机器上如果有旧的OPENAI_API_KEY,它会优先用那个,导致请求发到官方而不是 TaoToken。解决办法就是代码里显式传 api_key,别偷懒。
第二个是子代理的 base_url 继承问题。deepagents 在创建子代理时,如果子代理的 model 字段是字符串(如openai:gpt-4o),它会内部调用init_chat_model,这时候不会自动带上主代理的 base_url。所以要么在子代理配置里也写 base_url,要么在创建 Agent 前设置环境变量OPENAI_API_BASE=https://taotoken.net/api/v1,让所有 ChatModel 默认走这个地址。
export OPENAI_API_BASE="https://taotoken.net/api/v1"这个环境变量是 LangChain 识别的,设了之后所有 OpenAI 协议的模型都会走 TaoToken,省去逐个传参的麻烦。
6. 配置稳定后的下一步
settings.json 骨架跑通后,你可以把 Key 管理做得更干净:用.env文件配合python-dotenv,把TAOTOKEN_API_KEY、TAVILY_API_KEY都放进去,代码开头load_dotenv()一行搞定。这样换机器时只改.env,不动代码。
如果你打算长期跑编码类 Agent,或者让 deepagents 常驻做自动化任务,建议看一下 Coding Plan,它针对高频调用场景做了额度优化:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite需要管理多个项目的 Key、或者查看调用量时,去控制台:
https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite想快速验证某个模型在 TaoToken 上的表现,直接用模型对话页面试一句:
https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite接入文档里有各协议的完整参数说明,遇到 base_url 或模型名不确定时查这里:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite最后提醒一句:deepagents 的子代理模型可以混用,主代理用便宜的模型做规划,子代理用强模型做研究,这样成本可控。但每个模型的 base_url 都要确认走的是 TaoToken,别让某个子代理偷偷连了官方端点——那是最难排查的一类"部分请求失败"问题。