1. 多智能体跑着跑着就变笨,问题出在上下文膨胀
如果你正在用 LangChain 搭多智能体,大概率遇到过这种场景:主 Agent 一开始思路清晰,任务拆得明明白白,可当它连续调用几个子任务之后,回答开始跑偏,甚至把最初的目标都忘了。你去看它的上下文窗口,发现里面塞满了网页原始 HTML、失败重试日志、工具返回的中间态数据,真正有用的结论被挤到了角落。
这就是 Context Bloat,上下文膨胀。它不是一个玄学问题,而是多智能体架构里最典型的工程痛点。LangChain 发布的 Deep Agents 给出了一个很务实的解法:用 Subagents 做上下文隔离,用 Skills 做渐进式能力加载。主 Agent 只负责调度和汇总,脏活累活交给子智能体在自己的沙盒里干,干完只回传结论。
这篇文章我会带你从零跑通一个上下文可控的多智能体示例,同时把模型调用通道统一接到 TaoToken 上,避免你在多个模型供应商之间来回切换 Key 和 Base URL。适合已经了解 LangChain 基础、想进一步优化多智能体上下文管理的开发者。读完你能拿到一份可复制的 settings 配置、一套 Subagents + Skills 的代码骨架,以及一条可验证的调用链路。
2. 为什么 Subagents + Skills 能压住上下文,以及 TaoToken 前置准备
先说清楚 Deep Agents 到底解决了什么。传统多智能体写法里,一个主循环从头跑到尾,搜索、解析、计算、报错全在同一个上下文窗口里累积。假设你让 Agent 分析一只股票,它先搜了 20 条新闻,每条新闻的原始文本都进了上下文;然后算指标,工具返回的 JSON 也进了上下文;中间某次请求失败,错误堆栈又进了上下文。等到最后要输出结论时,模型面对的是一个被噪音填满的窗口,注意力被稀释,输出质量自然下降。
Deep Agents 的核心机制有两个。Subagents 让主 Agent 把任务委派给子智能体,子智能体拥有独立的上下文窗口。它在自己的窗口里可以搜 50 个网页、重试 10 次、翻遍文档,但返回给主 Agent 的只有一份总结报告。主 Agent 的上下文始终保持干净,只保留调度决策和最终结论。Skills 则是把工具定义和操作流程从 System Prompt 里抽出来,写成 SKILL.md 文件。Agent 初始只知道技能名称和简介,真正需要时才去读取详细步骤。这既省 Token,也让流程维护变成改 Markdown 而不是改代码。
在动手之前,你需要先准备好模型调用通道。多智能体场景下,主 Agent 和不同子智能体可能用不同模型,如果每个模型都去单独申请 Key、单独配 Base URL,管理成本很高。我建议统一走 TaoToken 的 API 通道,一个 Key 覆盖多个模型,Base URL 固定,切换模型只改 Model ID。
具体操作:访问 https://taotoken.net/api 获取 API Key,然后在控制台确认你要用的模型 ID。TaoToken 的接入文档在 https://taotoken.net/doc ,里面有各语言 SDK 的配置示例。如果你还没注册,可以先从官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 进入,完成账号创建后再去 API Keys 页面生成密钥。
这里有个细节要注意:Deep Agents 底层依赖 LangChain 的模型接口,所以你需要把 TaoToken 的 Base URL 和 Key 配到环境变量里,让 LangChain 能识别。推荐用.env文件管理,避免硬编码。
3. 可复制的 settings 配置与 Deep Agents 代码骨架
这一节是全文的核心,我会给出完整的配置文件片段和代码结构。你照着改路径和 Key 就能跑。
首先是环境变量配置。在项目根目录创建.env文件:
# .env TAOTOKEN_API_KEY=sk-your-token-here TAOTOKEN_BASE_URL=https://taotoken.net/api然后是 LangChain 侧的模型配置。Deep Agents 的create_deep_agent接受模型字符串,格式通常是provider:model。为了走 TaoToken 通道,我们需要在初始化时覆盖 Base URL。下面是一个可复制的 Python 配置片段:
# config.py import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI load_dotenv() def get_model(model_id: str = "claude-sonnet-4-5-20250929"): return ChatOpenAI( model=model_id, api_key=os.getenv("TAOTOKEN_API_KEY"), base_url=os.getenv("TAOTOKEN_BASE_URL"), temperature=0.2, )注意这里的base_url必须指向https://taotoken.net/api,不要带多余路径。Model ID 根据你在控制台看到的实际名称填写,比如claude-sonnet-4-5-20250929或gpt-4o。
接下来是 Skills 文件。Deep Agents 约定技能放在.deepagents/skills/目录下。我们创建一个量化分析流程的技能文件:
<!-- .deepagents/skills/finance/SKILL.md --> --- name: stock_analysis_pipeline description: 执行股票分析的标准作业流程 tags: [finance, trading] --- # 股票分析标准作业程序 当接收到分析某只股票的指令时,按顺序执行: 1. 搜集情报:调用 search_news 获取最近 24 小时关键消息。 2. 计算指标:调用 calculate_indicators 获取 RSI 和 MACD。 3. 风控审查:将情报和指标交给风控子智能体审核。 4. 最终决策:综合输出 Buy/Sell/Hold 建议。然后是子智能体和主智能体的定义。这里我把模型调用统一走上面配置的 TaoToken 通道:
# main.py from deepagents import create_deep_agent from deepagents.backends import FilesystemBackend from config import get_model def search_news(ticker: str): """搜索最近的市场新闻""" return f"Found 3 articles for {ticker}: AI demand strong; Earnings beat." def calculate_indicators(ticker: str): """计算技术指标""" return {"RSI": 65, "MA_200": "Bullish"} news_agent = { "name": "info_researcher", "description": "负责搜索互联网新闻和市场舆情。", "tools": [search_news], "model": get_model("gpt-4o"), } quant_agent = { "name": "math_wizard", "description": "负责计算技术指标,处理数字逻辑。", "tools": [calculate_indicators], "model": get_model("gpt-4o"), } risk_agent = { "name": "risk_manager", "description": "负责风险控制。RSI 超过 80 或有重大利空必须拒绝交易。", "system_prompt": "你是一个保守的风控官,宁可错过不可做错。", "model": get_model("claude-sonnet-4-5-20250929"), } agent = create_deep_agent( model=get_model("claude-sonnet-4-5-20250929"), subagents=[news_agent, quant_agent, risk_agent], backend=FilesystemBackend(root_dir="./"), skills=[".deepagents/skills/finance"], ) if __name__ == "__main__": user_input = "帮我分析一下 NVDA 现在能不能买?" response = agent.invoke({"messages": [{"role": "user", "content": user_input}]}) print(response.content)这段代码里,主 Agent 用 Claude 做调度,子智能体分别用不同模型处理各自擅长的任务。所有模型请求都通过 TaoToken 的 Base URL 发出,你只需要维护一个 API Key。
如果你用的是 Cline 或 Claude Code 这类工具做辅助开发,配置逻辑是一样的:Base URL 填https://taotoken.net/api,API Key 填 TaoToken 生成的密钥,Model ID 填控制台里对应的模型名称。这三件套缺一不可,尤其是 Model ID 必须和 TaoToken 支持的名称完全一致,否则会报模型不存在。
4. 验证多智能体调用链路是否跑通
配置写完之后,不要急着上复杂任务。先用一个最小请求验证通道是否通畅。
第一步,单独测试模型调用。写一个临时脚本:
from config import get_model llm = get_model("gpt-4o") resp = llm.invoke("用一句话说明什么是上下文膨胀") print(resp.content)如果这一步返回正常文本,说明 TaoToken 的 Key、Base URL、Model ID 三件套配置正确。如果报 401,检查 Key 是否复制完整;如果报 model not found,检查 Model ID 拼写。
第二步,验证 Skills 是否被正确加载。在main.py里加一行调试输出:
print("Loaded skills:", agent.skills)运行后应该能看到.deepagents/skills/finance这个路径。如果为空,检查FilesystemBackend的root_dir是否指向项目根目录,以及 SKILL.md 的 frontmatter 格式是否正确。
第三步,跑完整调用链路。执行python main.py,观察输出。预期流程是:主 Agent 读取 Skill 文件,识别出需要先搜集情报,于是派发info_researcher子智能体;子智能体调用search_news拿到新闻摘要后返回;主 Agent 再派发math_wizard计算指标;最后派发risk_manager做风控审查;主 Agent 汇总三者结论输出最终建议。
你可以在每个子智能体的工具函数里加一行print,确认它们确实被调用了。比如:
def search_news(ticker: str): print(f"[info_researcher] searching news for {ticker}") return f"Found 3 articles for {ticker}: AI demand strong; Earnings beat."如果运行后看到三行不同的子智能体日志,并且最终输出了包含 Buy/Sell/Hold 的建议,说明整条链路跑通了。这时候你再去检查主 Agent 的上下文,会发现里面只有调度记录和最终结论,没有原始新闻文本和中间计算数据,上下文膨胀问题被有效隔离。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
这一节整理我在调试过程中真实遇到过的几类报错,以及对应的排查路径。
401 Unauthorized:最常见的原因是 API Key 没有正确加载。检查.env文件是否在项目根目录,load_dotenv()是否在读取 Key 之前调用。另一个可能是 Key 复制时带了空格或换行,建议用print(os.getenv("TAOTOKEN_API_KEY")[:8])打印前几位确认。如果 Key 确认无误仍然 401,去 TaoToken 控制台的 API Keys 页面确认这个 Key 是否被禁用或过期。
local proxy failed / connection refused:这类报错通常出现在 Base URL 配置错误时。确认TAOTOKEN_BASE_URL的值是https://taotoken.net/api,不要写成https://taotoken.net/api/v1或其他路径。LangChain 的 OpenAI 兼容接口会自动拼接/chat/completions,你只需要提供到/api这一层。另外检查本地网络是否能正常访问该域名,可以用curl https://taotoken.net/api做连通性测试。
reading choices 报错 / KeyError: 'choices':这个报错说明请求返回的 JSON 结构里没有choices字段,通常是模型 ID 写错了,服务端返回了错误信息而不是正常的补全结果。解决方法是打印完整响应体:
import traceback try: resp = llm.invoke("test") except Exception as e: traceback.print_exc()根据错误信息里的提示修正 Model ID。TaoToken 控制台的模型列表里会显示可用模型名称,直接复制粘贴,不要手动拼写。
OAuth 相关报错:如果你在 Claude Code 或类似工具里看到 OAuth 认证失败,说明工具尝试走 Anthropic 官方 OAuth 流程而不是 API Key 通道。这时候需要检查工具的配置文件,确保它使用的是 API Key 模式。以 Claude Code 为例,检查~/.claude/settings.json或项目级.claude/settings.json,确认apiKey字段填的是 TaoToken 的 Key,baseUrl字段填的是https://taotoken.net/api。如果配置里同时存在 OAuth token 和 API Key,优先使用 API Key 并移除 OAuth 相关字段。
还有一个容易忽略的点:子智能体的model字段如果传的是字符串而不是ChatOpenAI实例,Deep Agents 可能会用默认的 OpenAI 客户端去请求,导致 Base URL 没有生效。确保每个子智能体的model都通过get_model()函数创建,这样 Base URL 和 Key 才会统一走 TaoToken 通道。
6. 把通道固定下来,让多智能体专注在业务逻辑上
跑通这个示例之后,你会发现 Deep Agents 的 Subagents + Skills 组合本质上是用工程化手段解决 LLM 应用的上下文管理问题。主 Agent 做路由和汇总,子智能体做具体执行,Skills 做流程编排。这套结构和你熟悉的微服务架构非常像,只是服务边界变成了上下文边界。
实际项目里,我建议把模型调用通道固定下来,不要让每个子智能体各自去配 Key 和 Base URL。统一走 TaoToken 的 API 通道,一个 Key 覆盖多个模型,切换模型只改 Model ID。这样你在调整子智能体分工时,不需要关心底层通道的差异,专注在 Skills 的流程设计和 Subagents 的职责划分上。
如果你需要长期跑编码类或 Agent 类任务,可以了解一下 Coding Plan,它适合高频调用的场景。日常验证模型效果,直接用模型对话页面就能快速测试。接入过程中遇到配置问题,接入文档里有各语言 SDK 的完整示例。把通道配好之后,剩下的就是不断调整子智能体的粒度和 Skills 的步骤,让整个多智能体系统在上下文可控的前提下稳定输出。