1. 为什么单 Agent 跑复杂任务总是卡住
我接过一个需求:用户管理页加批量导出,支持 CSV 和 Excel,后端记录导出日志。听起来不大,但拆开看至少涉及前端表格组件、导出按钮交互、后端导出接口、格式转换、日志存储五块。用单个 Claude Code 会话去推,过程基本是:先让它读项目结构,再写后端接口,然后切前端,联调报错回头改后端,改完发现日志格式和项目里已有的 winston 配置对不上,再补一轮。全程串行,每切一个技术栈,上下文就膨胀一圈,到后面它开始忘记前面定好的接口字段名。
这不是模型能力问题,是单会话上下文窗口的物理限制。一个窗口里塞进前端组件、后端路由、数据库模型、日志规范,关键约束很容易被挤出有效注意力范围。多 Subagents 协作要解决的就是这件事:把一个大任务拆成几个边界清晰的子任务,每个子代理只拿自己需要的那部分上下文,并行跑,最后由主代理汇总。
Claude Code 的 Subagents 机制允许你在settings.json里定义多个子代理,每个有独立的系统提示、工具权限和上下文范围。主代理根据任务描述决定调用哪个子代理、传什么上下文。适合谁?适合已经在用 Claude Code 做日常开发、任务开始跨文件跨层、感觉单会话越来越吃力的工程师。如果你还在单文件改改 bug,暂时用不上这套。
2. 前置准备:TaoToken 接入与 Claude Code 环境
Claude Code 本身是命令行工具,要让它跑起来并调用模型,需要一个稳定的 API 入口。我这边用的是 TaoToken 的接入方式,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 taotoken.net/api(这个地址不加 UTM 参数)。它的作用是给 Claude Code 提供一个兼容 Anthropic 协议的模型调用通道,你不需要在本地折腾模型部署,配好 key 和 base_url 就能用。
先拿到 API Key。登录后进控制台,在 API Keys 页面创建一个新 key,复制出来。这个 key 后面要写进环境变量,不要硬编码到 settings.json 里提交到仓库。
# 设置环境变量,写入你的 shell 配置文件 export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的key"如果你用的是 Claude Code 的 Anthropic 兼容模式,这两个变量它会自动读取。验证一下环境是否通了:
claude --version # 输出类似 1.x.x 即安装正常然后跑一个最小请求确认模型通道可用:
claude -p "回复 ok 两个字母即可"如果返回ok,说明 TaoToken 的通道和 Claude Code 已经打通。这一步没过,后面 Subagents 配置再对也跑不起来。踩过的坑是有人把 base_url 写成带路径的完整地址,结果 404,记住就是https://taotoken.net/api这个根。
3. settings.json 配置骨架:定义你的 Subagents
Claude Code 的 Subagents 配置放在项目根目录的.claude/settings.json里,或者用户级的~/.claude/settings.json。项目级配置会覆盖用户级,团队协作建议放项目级并提交到仓库,这样每个人拉下来行为一致。
配置的核心结构是agents字段,每个子代理是一个键值对。下面是我在批量导出这个场景里实际用的骨架,你可以直接复制改:
{ "agents": { "frontend-export": { "description": "负责前端导出按钮、格式选择与下载触发", "prompt": "你是前端子代理。只修改 src/pages/user 和 src/services/api.ts。任务:在用户管理页添加导出按钮,支持 CSV/Excel 选择,调用 POST /api/export,参数 { format: 'csv' | 'xlsx' },响应为 Blob 时触发下载。不要改动路由和其他页面。", "tools": ["Read", "Edit", "Write", "Bash"], "model": "claude-sonnet-4-20250514" }, "backend-export": { "description": "负责后端导出接口与格式转换", "prompt": "你是后端子代理。只修改 src/routes/export.ts 和 src/services/exportService.ts。任务:实现 POST /api/export,接收 { format },用已有 getUsers 查询数据,生成 CSV 或 XLSX,返回正确 Content-Type 的 Blob。接口契约:请求体 { format: 'csv' | 'xlsx' },响应二进制流。", "tools": ["Read", "Edit", "Write", "Bash"], "model": "claude-sonnet-4-20250514" }, "logging-agent": { "description": "负责导出日志记录,遵循项目 winston 规范", "prompt": "你是日志子代理。只关注 src/routes/export.ts 中的日志插入点和 src/config/logger.ts 的现有配置。任务:在导出接口成功返回前插入 winston 日志调用,记录 userId、format、记录数、时间戳。日志格式必须与项目现有 info 级别一致,不要新建日志文件。", "tools": ["Read", "Edit"], "model": "claude-sonnet-4-20250514" } } }几个关键点。description是给主代理看的,它靠这个判断什么时候该调用哪个子代理,写清楚职责边界。prompt是子代理的系统提示,这里要把范围锁死,明确写“只修改哪些文件”,否则子代理容易越界。tools控制权限,日志子代理只给 Read 和 Edit 就够了,不需要 Bash,减少误操作面。model可以按任务复杂度分配,简单任务用轻量模型省成本。
主代理的调度逻辑不需要你手写,Claude Code 会根据任务描述和子代理的 description 自动匹配。但你要在任务描述里给出足够信号,比如“这个任务涉及前端、后端和日志三块,请分派给对应子代理并行处理”。
4. 验证并行执行与结果汇总
配置写好后,怎么确认子代理真的在并行跑、结果有没有汇总对?分三步验证。
第一步,看启动日志。在 Claude Code 里发起任务时加上--verbose:
claude --verbose -p "在用户管理页增加批量导出功能,支持 CSV 和 Excel,后端新增导出接口用已有 getUsers 查询,并记录导出日志到数据库。涉及前端、后端、日志三块,请分派给对应子代理并行处理。"输出里会看到类似Dispatching to agent: frontend-export、Dispatching to agent: backend-export、Dispatching to agent: logging-agent的行,且时间戳接近,说明是并行触发而非串行等待。
第二步,检查各子代理的产出范围。任务结束后看 git diff:
git diff --stat预期是前端子代理只动了src/pages/user和src/services/api.ts,后端子代理只动了src/routes/export.ts和src/services/exportService.ts,日志子代理只在export.ts里插了日志行。如果某个子代理动了范围外的文件,说明 prompt 里的边界约束没生效,回去收紧。
第三步,验证接口契约一致性。这是最容易出问题的地方。前端子代理发的是{ format: 'xlsx' },后端子代理如果写成接收{ type: 'excel' },联调就炸。检查方法:
# 看前端调用处 grep -n "api/export" src/services/api.ts # 看后端接收处 grep -n "req.body" src/routes/export.ts两边的字段名和取值必须对齐。我在骨架的 prompt 里把契约写死成{ format: 'csv' | 'xlsx' },就是为了让两个子代理拿到同一份约定,减少这种不一致。
跑一次端到端测试确认功能通:
npm run test:e2e -- --grep "export"如果测试通过,且日志表里有新记录,说明三个子代理的产出汇总成功。
5. 常见报错与排查
子代理没被触发,主代理自己干了。原因通常是任务描述里没给分派信号,或者子代理的description写得太模糊。解决:在任务描述里显式说“分派给对应子代理”,并把 description 改成具体职责,比如“前端导出按钮相关”而不是“前端”。
报Agent not found。settings.json 的路径不对,或者 JSON 格式有误。Claude Code 读的是项目根目录.claude/settings.json,不是根目录直接放。用cat .claude/settings.json | python -m json.tool验证 JSON 合法性。
两个子代理改了同一文件冲突。比如后端和日志子代理都动export.ts。Claude Code 会尝试行级合并,但如果改的是同一段代码就会冲突。解决:在 prompt 里错开职责,后端子代理负责业务逻辑主体,日志子代理只负责在指定函数末尾插入日志调用,并明确“不要修改已有业务代码”。
子代理输出风格不一致。前端用了分号,后端没用,lint 报一堆。解决:在项目根放.eslintrc和.prettierrc,子代理的 prompt 里加一句“遵循项目根目录的 lint 和格式化配置”,整合后跑一次npm run lint --fix。
API 调用报 401 或 403。检查ANTHROPIC_API_KEY是否设置正确,以及 key 是否有对应模型的权限。TaoToken 控制台里可以看 key 的调用记录,如果请求根本没到,说明环境变量没被 Claude Code 读到,检查 shell 配置有没有 source。
并行执行变成串行。看 verbose 日志里各子代理的启动时间戳,如果间隔很大,可能是任务描述里隐含了依赖关系,主代理判断必须串行。解决:确认子任务之间没有数据依赖,如果有,就接受串行,或者把依赖部分抽出来先跑。
6. 把配置用起来:从骨架到日常
这套骨架跑通后,你可以按项目类型沉淀几套模板。全栈功能开发用前端+后端+日志三件套;重构任务用“分析子代理+执行子代理”两段式,先让分析子代理读代码出方案,再让执行子代理按方案改;测试补全用“测试生成子代理+断言校验子代理”并行。
长期做编码和 Agent 编排的话,Coding Plan 那边有更完整的额度方案,适合高频调用场景,地址在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。模型对话调试可以在 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 直接试,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,API Keys 管理在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 。Claude Code 的 Anthropic 兼容接入说明在 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 。
最后说一个实际经验:Subagents 的拆分粒度别太细。我一开始把日志拆成独立子代理,后来发现它和后端改同一文件,合并成本比省下的时间还高。现在我的做法是,改同一文件的逻辑尽量放一个子代理,跨文件的才拆并行。拆之前先问自己一句:这两个子任务如果由两个人同时做,会不会互相等对方?会等,就别拆。