ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

LangChain 多智能体架构选型指北:Subagents 与 Router 配置骨架怎么搭

LangChain 多智能体架构选型指北:Subagents 与 Router 配置骨架怎么搭 1. 从一次“路由跑偏”说起为什么要在本地先做架构选型LangChain 的多智能体Multi-Agent这两年热度很高但真正落到代码里最先卡住人的往往不是模型能力而是架构选型。我见过不少团队一上来就堆四五个 Agent结果一个简单请求要绕三四次模型调用延迟翻倍、token 账单也翻倍。问题不在模型在于没搞清楚 Subagents子智能体和 Router路由器到底该选哪个。这篇就聚焦这两条最常被拿来对比的路线Subagents 是集中式编排一个主管 Agent 把子智能体当工具调用子智能体无状态、上下文隔离强Router 是并行调度先对输入分类再并行分发给专门 Agent最后综合结果。两者都能做多领域任务但调用次数、token 消耗、状态管理完全不同。适合谁看需要在本地快速验证选型的开发者手里已经有一个统一 Key/API 通道想用最小成本跑通一次真实的多智能体路由调用再决定往哪个方向搭骨架。下面我会给出可复制的config.toml与settings.json并演示一次完整的路由调用最后把常见报错逐个拆掉。2. TaoToken 前置把统一 Key 和 API 通道准备好多智能体选型验证最怕环境折腾。你要同时调多个模型主管用强模型、子智能体用轻模型如果每个模型单独配 Key、单独改 base_url光环境就能耗掉半天。我的做法是走一个统一通道所有模型请求都从同一个入口出切换模型只改一个字段。TaoToken 在这里的角色就是统一 Key/API 通道官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。你只需要在控制台生成一个 Key后面 LangChain 里所有 ChatModel 都指向它。具体操作路径先在控制台创建 Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 生成后复制保存。然后到 API Keys 页面确认权限地址 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 确保这个 Key 对你要用的模型都有调用权限。注意Key 只显示一次复制后立刻存进本地.env别直接写进代码提交到仓库。环境变量这样设后面config.toml和settings.json都读它export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你更习惯用.env文件配合python-dotenv写成TAOTOKEN_API_KEYsk-你的key TAOTOKEN_BASE_URLhttps://taotoken.net/api这一步做完模型通道就统一了。接下来不管主管 Agent 用哪个模型、子智能体用哪个模型都从这一个 base_url 走选型验证时你只需要关心架构逻辑不用再管鉴权。3. 可复制配置config.toml 与 settings.json 骨架多智能体项目最容易乱的就是配置分散。我习惯把模型与通道配置放config.toml把Agent 角色与路由规则放settings.json职责分开改架构时只动一个文件。3.1 config.toml模型与通道# config.toml [provider] name taotoken base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY [models.supervisor] model claude-opus-4 temperature 0.2 max_tokens 4096 [models.subagent_fast] model claude-sonnet-4 temperature 0.0 max_tokens 2048 [models.router] model claude-sonnet-4 temperature 0.0 max_tokens 1024 [runtime] max_concurrency 4 request_timeout 60这里supervisor是 Subagents 模式里的主管subagent_fast是子智能体router是 Router 模式里的分类器。三个角色共用同一个base_url和api_key_env这就是统一通道的价值——换模型只改model字段。3.2 settings.jsonAgent 角色与路由规则{ architecture: router, agents: { python_expert: { model_ref: subagent_fast, system: 你是 Python Web 开发专家只回答 Python 相关问题。, tools: [search_docs] }, js_expert: { model_ref: subagent_fast, system: 你是 JavaScript/Node 专家只回答 JS 相关问题。, tools: [search_docs] }, rust_expert: { model_ref: subagent_fast, system: 你是 Rust 专家只回答 Rust 相关问题。, tools: [search_docs] } }, router: { model_ref: router, routes: [python_expert, js_expert, rust_expert], fallback: python_expert, parallel: true }, subagents: { supervisor_ref: supervisor, children: [python_expert, js_expert, rust_expert], stateless_children: true } }architecture字段就是选型开关填router走并行调度填subagents走集中编排。parallel: true是 Router 的关键它决定多个专家 Agent 是否并行执行。stateless_children: true是 Subagents 的关键子智能体不保留历史保证上下文隔离。提示先用router跑通再切subagents对比这样你能直观看到调用次数和 token 的差异。4. 跑通一次多智能体路由调用配置就绪后用 LangChain 把骨架接起来。下面这段代码读config.toml和settings.json构建一个 Router 模式的多智能体系统并跑一次多领域查询。import json import tomllib import os from langchain_openai import ChatOpenAI from langchain_core.messages import SystemMessage, HumanMessage with open(config.toml, rb) as f: cfg tomllib.load(f) with open(settings.json, r, encodingutf-8) as f: settings json.load(f) provider cfg[provider] base_url provider[base_url] api_key os.environ[provider[api_key_env]] def build_model(model_ref: str) - ChatOpenAI: m cfg[models][model_ref] return ChatOpenAI( modelm[model], temperaturem[temperature], max_tokensm[max_tokens], base_urlbase_url, api_keyapi_key, ) router_model build_model(settings[router][model_ref]) expert_models { name: build_model(agent[model_ref]) for name, agent in settings[agents].items() } def route_query(query: str) - list[str]: routes settings[router][routes] prompt ( f从以下路由中选择最相关的可多选用逗号分隔只输出路由名{routes}\n f用户问题{query} ) resp router_model.invoke([HumanMessage(contentprompt)]) picked [r.strip() for r in resp.content.split(,) if r.strip() in routes] return picked or [settings[router][fallback]] def call_expert(name: str, query: str) - str: agent settings[agents][name] model expert_models[name] resp model.invoke([ SystemMessage(contentagent[system]), HumanMessage(contentquery), ]) return f[{name}] {resp.content} def run_router(query: str) - str: picked route_query(query) results [call_expert(name, query) for name in picked] return \n\n.join(results) if __name__ __main__: q 比较 Python、JavaScript 和 Rust 用于 Web 开发的优劣 print(run_router(q))运行python router_demo.py成功时你会看到类似输出内容因模型而异[python_expert] Python 在 Web 开发中生态成熟Django/Flask/FastAPI 覆盖从快速原型到高并发服务…… [js_expert] JavaScript 凭借 Node.js 实现前后端同构npm 生态庞大适合 I/O 密集型场景…… [rust_expert] Rust 在 Web 开发中以 Actix/Axum 提供接近 C 的性能和内存安全适合高性能网关……这次调用里Router 先做了一次分类1 次模型调用然后并行分发给三个专家3 次调用总共 4 次。如果你把settings.json的architecture改成subagents主管会先决定调用哪些子智能体子智能体返回结果后再由主管综合多一次汇总调用——这就是 Subagents 的“额外一次模型调用”开销。想直接对比模型输出差异可以在模型对话页面手动试几次地址 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 把同样的 query 丢进去看不同模型的路由判断倾向。5. 本篇常见错排查5.1 报错401 Unauthorized或invalid api key最常见。先确认TAOTOKEN_API_KEY真的被读到了python -c import os; print(os.environ.get(TAOTOKEN_API_KEY)[:8])如果打印为空说明.env没加载。用python-dotenv的话记得在入口文件顶部加load_dotenv()。另外确认 Key 没有多余空格复制时容易带上换行。5.2 报错model not found或路由返回空config.toml里的model字段必须和通道支持的模型名一致。如果你不确定可用模型去文档页核对地址 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。路由返回空通常是分类器输出格式不对route_query里已经做了in routes过滤如果模型返回了带解释的长句就会被过滤掉此时会走fallback。可以把temperature设为 0 提高稳定性。5.3 Router 没有并行耗时很长检查settings.json里parallel是否为true以及你的执行代码是否真的并发。上面示例用的是顺序for循环要真正并行得换成asyncio.gather或线程池import asyncio async def call_expert_async(name, query): return await asyncio.to_thread(call_expert, name, query) async def run_router_parallel(query): picked route_query(query) results await asyncio.gather(*[call_expert_async(n, query) for n in picked]) return \n\n.join(results)5.4 Subagents 模式下子智能体“记住了”上一轮这是stateless_children没生效。Subagents 的核心就是子智能体无状态每次调用都要重新构造消息列表不要把历史messages传进去。如果你发现子智能体引用了上一轮内容检查是不是复用了同一个ChatOpenAI实例并传了累积的 history。5.5 长任务编码场景该选哪个如果你验证下来发现是长期编码、Agent 反复迭代的场景Router 的无状态反而会导致重复路由开销。这种更适合走 Coding Plan 路线地址 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它针对长会话和代码迭代做了优化比每次重新路由更省。6. 选型结论与下一步回到选型本身把上面的实测对照成一张表维度SubagentsRouter控制方式集中式主管编排分布式分类后并行子智能体状态无状态上下文隔离强通常无状态按请求独立单次请求调用数多一次汇总调用分类 并行专家重复请求每次成本一致有重复路由开销多领域并行支持支持且更自然适合场景需集中控制、上下文隔离多垂直领域、并行查询综合判断方法很简单需要集中工作流控制、子智能体不直接和用户对话选 Subagents有多个独立知识域、要并行查询再综合选 Router。单领域任务别急着上多智能体先加工具、优化提示词真遇到上下文或协作瓶颈再升级。下一步建议你直接把settings.json的architecture在router和subagents之间切换用同一个 query 各跑三次记录调用次数和耗时。想更深入看接入细节文档页有完整的参数说明https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。选型不是拍脑袋是跑出来的数据说话。
返回列表