1. 为什么 DeepAgents 项目一到配置环节就卡住
如果你最近在折腾 LangChain 的 DeepAgents,大概率会遇到一个很具体的场景:本地 demo 跑通了,但一旦要接多个模型、多个子智能体、多个工具,配置就开始失控。主智能体用 Claude,评审子智能体想换 Haiku 省成本,数据子智能体又想走本地 Ollama,结果 API Key 散落在.env、os.environ、代码硬编码里,换台机器就得重新配一遍。
DeepAgents 本身是 LangChain 生态里一个把「规划工具 + 子智能体 + 虚拟文件系统 + 详细提示词」四件事做成通用能力的 Python 包,它底层就是一个 LangGraph 图,所以流式、HITL、记忆、Studio 这些能力都能直接用。但正因为灵活,配置层没有一个统一入口时,工业级落地就会变成「能跑但不敢改」。
这篇要解决的就是这个配置环节:用一份可复制的config.toml骨架,把多模型 Key 收敛到 TaoToken 统一通道,让主智能体和各个子智能体通过同一套 API 入口调用不同模型,本地启动一次跑通全栈链路。适合已经写过create_deep_agent入门示例、准备往生产环境推的开发者。
2. TaoToken 统一 Key 通道:DeepAgents 多模型配置的前置准备
DeepAgents 的模型配置支持传任意 LangChain 模型对象,也支持给子智能体单独指定model_settings。这意味着一个项目里可能同时出现 Anthropic、OpenAI、本地 Ollama 等多种模型来源。如果每个来源都单独维护 Key 和 base_url,配置复杂度会随子智能体数量线性增长。
TaoToken 在这里的角色是一个统一的 API 通道:你只需要申请一个 Key,通过https://taotoken.net/api这个入口,就能在同一个 base_url 下调用不同厂商的模型。对 DeepAgents 来说,好处是config.toml里只需要维护一份凭证,子智能体切换模型时只改模型名,不改接入层。
前置准备分三步:
第一步,注册并登录 TaoToken 控制台,地址是https://taotoken.net/api-keys,在 API Keys 页面创建一个新 Key。建议按项目命名,比如deepagents-prod,方便后续轮换。
第二步,确认你要用的模型在通道里可用。DeepAgents 默认模型是claude-sonnet-4-20250514,如果你打算给评审子智能体用claude-3-5-haiku-20241022,这两个都可以在模型对话页面先验证一下连通性,地址是https://taotoken.net/models。
第三步,把 Key 写进环境变量,不要写进代码。Linux/macOS 下:
export TAOTOKEN_API_KEY="sk-你的key"Windows PowerShell:
$env:TAOTOKEN_API_KEY="sk-你的key"注意:环境变量名建议统一用
TAOTOKEN_API_KEY,后面config.toml里通过${TAOTOKEN_API_KEY}引用,这样本地和 CI 环境可以用同一份配置文件。
3. config.toml 骨架与 DeepAgents 接入代码
这一节是全文的核心。我把它拆成「配置文件」和「加载代码」两部分,你可以直接复制后改模型名。
3.1 config.toml 完整骨架
# config.toml # DeepAgents 工业级配置骨架 [provider] name = "taotoken" base_url = "https://taotoken.net/api" api_key = "${TAOTOKEN_API_KEY}" [models.default] model = "claude-sonnet-4-20250514" temperature = 0.2 max_tokens = 8192 [models.critique] model = "claude-3-5-haiku-20241022" temperature = 0 max_tokens = 4096 [models.local] model = "ollama:gpt-oss:20b" temperature = 0.3 [agent] builtin_tools = ["write_todos", "write_file", "read_file", "ls", "edit_file"] max_iterations = 25 [subagents.research] name = "research-agent" description = "Used to research more in depth questions" model_ref = "default" [subagents.critique] name = "critique-agent" description = "Critique the final report" model_ref = "critique"这份骨架的设计思路是:[provider]段只维护一份接入信息,[models.*]段用逻辑名引用模型,[subagents.*]段通过model_ref指向逻辑名。这样换模型时只改[models.*],子智能体定义不动。
3.2 加载 config.toml 并构建 DeepAgents
import os import tomllib from deepagents import create_deep_agent from langchain.chat_models import init_chat_model with open("config.toml", "rb") as f: cfg = tomllib.load(f) provider = cfg["provider"] api_key = os.environ.get("TAOTOKEN_API_KEY") if not api_key: raise RuntimeError("TAOTOKEN_API_KEY 未设置") def build_model(model_ref: str): m = cfg["models"][model_ref] return init_chat_model( model=m["model"], temperature=m.get("temperature", 0.2), max_tokens=m.get("max_tokens", 8192), api_key=api_key, base_url=provider["base_url"], ) default_model = build_model("default") subagents = [] for key, sub in cfg.get("subagents", {}).items(): subagents.append({ "name": sub["name"], "description": sub["description"], "prompt": f"You are the {sub['name']}. Focus on your specialty.", "model_settings": { "model": cfg["models"][sub["model_ref"]]["model"], "temperature": cfg["models"][sub["model_ref"]].get("temperature", 0.2), }, }) def internet_search(query: str, max_results: int = 5): """Run a web search""" return {"query": query, "results": []} agent = create_deep_agent( tools=[internet_search], instructions="You are an expert researcher. Plan first, then execute.", model=default_model, subagents=subagents, builtin_tools=cfg["agent"]["builtin_tools"], )这里有个关键点:init_chat_model的base_url参数指向 TaoToken 的 API 入口,api_key从环境变量读取。这样主智能体和子智能体都走同一条通道,但模型名可以不同。
3.3 子智能体独立模型设置
如果你不想在config.toml里维护model_settings,也可以直接在代码里给某个子智能体单独指定:
critique_sub_agent = { "name": "critique-agent", "description": "Critique the final report", "prompt": "You are a tough editor.", "model_settings": { "model": "claude-3-5-haiku-20241022", "temperature": 0, "max_tokens": 8192, }, }两种方式效果一样,区别是配置化后可以在不改代码的情况下调整模型,适合工业级部署。
4. 本地启动验证:一次跑通全栈链路
配置写完后,不要急着上生产,先在本地做一次完整验证。验证目标是:主智能体能规划、能调用工具、能把任务分派给子智能体、子智能体用独立模型返回结果。
4.1 最小验证脚本
result = agent.invoke({ "messages": [ {"role": "user", "content": "调研 LangGraph 的核心能力,并给出一份简短报告"} ] }) for msg in result["messages"]: print(msg.type, ":", msg.content[:200])预期输出里应该能看到write_todos产生的待办列表、internet_search的调用记录,以及最终的报告内容。如果子智能体被触发,还会看到research-agent或critique-agent的中间消息。
4.2 验证模型通道是否生效
单独测一下 TaoToken 通道的连通性,避免把配置问题误判成 DeepAgents 问题:
from langchain.chat_models import init_chat_model test_model = init_chat_model( model="claude-3-5-haiku-20241022", api_key=os.environ["TAOTOKEN_API_KEY"], base_url="https://taotoken.net/api", ) print(test_model.invoke("ping").content)如果这一步返回正常,说明 Key 和 base_url 没问题,问题就在 DeepAgents 的配置层。
4.3 验证 HITL 拦截
DeepAgents 支持给工具加人工审批。验证时可以用interrupt_config拦截write_file:
from langgraph.checkpoint.memory import InMemorySaver agent = create_deep_agent( tools=[internet_search], instructions="...", model=default_model, subagents=subagents, checkpointer=InMemorySaver(), interrupt_config={"write_file": {"allow_accept": True, "allow_edit": True}}, )启动后如果write_file被拦截并等待输入,说明 HITL 链路正常。当前一次只能拦截一个并行工具调用,这点在排障时要注意。
5. 本篇常见错排查
配置环节的报错大多集中在 Key、base_url、模型名三处。下面是我实际遇到过的几类。
报错一:AuthenticationError或 401。先检查TAOTOKEN_API_KEY是否在当前 shell 生效,echo $TAOTOKEN_API_KEY确认。如果用了config.toml的${TAOTOKEN_API_KEY}写法,注意 tomllib 不会自动展开环境变量,需要在代码里手动替换,或者直接用os.environ读取。
报错二:model not found。DeepAgents 默认模型是claude-sonnet-4-20250514,如果你在config.toml里写了一个通道不支持的模型名,会在第一次 invoke 时报错。建议先在模型对话页面确认模型可用,再写进配置。
报错三:子智能体没有按预期模型执行。检查model_settings里的model字段是否和[models.*]段一致。如果子智能体定义里同时有model_ref和model_settings,以model_settings为准。
报错四:builtin_tools精简后文件系统不可用。如果你把builtin_tools设成["write_todos"],那write_file、read_file、ls、edit_file都不会注册,子智能体读写文件时会报工具不存在。工业级场景建议保留全部五个。
报错五:本地 Ollama 模型走 TaoToken 通道失败。ollama:gpt-oss:20b这类本地模型不应该走 TaoToken 的 base_url,它需要本地 Ollama 服务。正确做法是给本地模型单独建一个 provider 段,或者在代码里用init_chat_model(model="ollama:...")不传 base_url。
提示:排障时优先用最小脚本单独测模型通道,再测 DeepAgents 配置,最后测子智能体分派。分层定位比一次性跑全链路快得多。
6. 把配置收敛成一份可维护的骨架
走到这里,你应该已经有一份能跑的config.toml和对应的加载代码。工业级落地的关键不是一次跑通,而是后续换模型、加子智能体、调参数时不用动代码。
我的建议是:[provider]段永远只保留一份接入信息,所有模型通过[models.*]逻辑名引用,子智能体通过model_ref指向逻辑名。这样新增一个子智能体只需要在config.toml里加两段,代码零改动。
如果你准备把 DeepAgents 推到长期运行的编码或 Agent 场景,可以进一步了解 Coding Plan 的接入方式,地址是https://taotoken.net/coding-plan。需要看完整 API 文档的话,接入文档在https://taotoken.net/doc。配置跑通后,下一步就是把这套骨架接进你的 CI,让每次部署都从同一份config.toml构建智能体。