什么是 Sub-Agent
当我们给 Claude Code 一个复杂任务时,它有时候会”分身”——创建一个或多个 Sub-Agent(子代理)来并行处理不同的子任务。
比如你说:
帮我重构 src/components/ 下的所有组件,统一使用新的设计系统
Claude Code 可能会:
- 主 Agent 分析任务,拆分为多个子任务
- 创建 Sub-Agent A 处理 Header 组件
- 创建 Sub-Agent B 处理 Footer 组件
- 创建 Sub-Agent C 处理 Sidebar 组件
- 主 Agent 汇总结果,确保一致性
这就是 Sub-Agent 模式——分而治之。
Sub-Agent 的触发条件
Claude Code 不是每次都会使用 Sub-Agent。它会根据任务的特征来决定:
| 条件 | 是否触发 Sub-Agent | 原因 |
|---|---|---|
| 修改单个文件 | 否 | 任务简单,不需要拆分 |
| 修改多个独立文件 | 可能 | 文件之间无依赖,可以并行 |
| 跨目录的大规模重构 | 是 | 任务复杂,需要分工 |
| 需要多种专业知识 | 是 | 不同子任务需要不同”专家” |
| 简单问答 | 否 | 不涉及工具调用 |
观察 Sub-Agent 的创建
在 Claude Code 的输出中,你会看到类似这样的提示:
正在分析任务...
创建子任务 1: 重构 Header 组件
创建子任务 2: 重构 Footer 组件
创建子任务 3: 重构 Sidebar 组件
并行执行中...
Sub-Agent 的工作原理
架构概览
┌─────────────────────────────────────────┐
│ 主 Agent (Orchestrator) │
│ │
│ 1. 接收用户任务 │
│ 2. 分析和拆分任务 │
│ 3. 分配给 Sub-Agent │
│ 4. 收集和整合结果 │
│ 5. 返回最终结果 │
└──────────┬──────────┬──────────┬────────┘
│ │ │
┌─────▼─────┐ ┌──▼──────┐ ┌▼─────────┐
│ Sub-Agent │ │Sub-Agent│ │Sub-Agent │
│ A │ │ B │ │ C │
│ │ │ │ │ │
│ 处理任务1 │ │处理任务2│ │ 处理任务3│
└───────────┘ └─────────┘ └──────────┘
上下文隔离
每个 Sub-Agent 有自己独立的上下文:
- 独立的对话历史
- 独立的工具调用
- 独立的文件操作
这意味着 Sub-Agent A 修改的文件不会影响 Sub-Agent B 的读取——除非主 Agent 协调它们。
结果汇总
Sub-Agent 完成后,主 Agent 会:
- 收集所有 Sub-Agent 的输出
- 检查是否有冲突(比如两个 Sub-Agent 修改了同一个文件)
- 解决冲突
- 整合结果
- 做最终验证
任务分解模式
模式 1:按文件分解
最常见的模式——每个 Sub-Agent 处理一个或一组文件:
重构 src/components/ 下的所有组件
分解为:
- Sub-Agent 1:
Header.astro,Navigation.astro - Sub-Agent 2:
Footer.astro,SocialLinks.astro - Sub-Agent 3:
Sidebar.astro,TableOfContents.astro
模式 2:按职责分解
不同 Sub-Agent 负责不同的职责:
给项目添加完整的测试覆盖
分解为:
- Sub-Agent 1: 单元测试(工具函数)
- Sub-Agent 2: 组件测试(React/Astro 组件)
- Sub-Agent 3: 集成测试(API 端点)
模式 3:按阶段分解
虽然不是并行的,但可以按阶段分工:
将项目从 JavaScript 迁移到 TypeScript
分解为:
- 阶段 1 Sub-Agent: 添加 TypeScript 配置
- 阶段 2 Sub-Agent: 转换工具函数
- 阶段 3 Sub-Agent: 转换组件
- 阶段 4 Sub-Agent: 修复类型错误
模式 4:按专业领域分解
优化应用的整体性能
分解为:
- Sub-Agent 1(前端专家): 优化渲染性能、减少 bundle 大小
- Sub-Agent 2(后端专家): 优化 API 响应时间、数据库查询
- Sub-Agent 3(基础设施专家): 优化缓存策略、CDN 配置
实战示例
示例 1:多文件重构
把 src/utils/ 下所有的 CommonJS 模块转换为 ES Modules
Claude Code 的执行过程:
主 Agent: 扫描 src/utils/ 目录,发现 8 个 CommonJS 文件
Sub-Agent 1: 转换 format.js, date.js
- require() → import
- module.exports → export
- 更新文件扩展名
Sub-Agent 2: 转换 api.js, http.js
- 同上
- 处理动态 require
Sub-Agent 3: 转换 config.js, env.js, logger.js, helpers.js
- 同上
主 Agent: 汇总结果
- 检查所有 import 路径是否正确
- 运行 npm run build 验证
- 运行 npm test 确认功能正常
示例 2:全栈功能开发
添加用户搜索功能,包括前端搜索框、后端 API 和数据库查询
主 Agent: 分析需求,设计接口
Sub-Agent 1 (后端):
- 创建 src/api/routes/search.ts
- 实现全文搜索查询
- 添加分页支持
Sub-Agent 2 (前端):
- 创建 src/components/SearchBar.tsx
- 实现实时搜索(debounce)
- 添加搜索结果展示
Sub-Agent 3 (测试):
- 编写 API 测试
- 编写组件测试
- 编写 E2E 测试
主 Agent: 整合
- 确保前后端接口一致
- 运行所有测试
- 输出功能摘要
示例 3:代码审查
审查 PR #42 的所有变更
主 Agent: 获取 PR diff,分析变更范围
Sub-Agent 1 (安全审查):
- 检查是否有安全漏洞
- 检查敏感信息泄露
- 检查权限控制
Sub-Agent 2 (质量审查):
- 检查代码风格
- 检查类型安全
- 检查错误处理
Sub-Agent 3 (性能审查):
- 检查算法复杂度
- 检查内存使用
- 检查数据库查询效率
主 Agent: 汇总审查报告
- 合并所有发现
- 按严重程度排序
- 生成统一的审查报告
使用 SDK 编排 Sub-Agent
通过 Claude Code SDK,我们可以手动编排 Sub-Agent 模式:
基础编排
import { claude } from "@anthropic-ai/claude-code";
async function parallelRefactor(files: string[]) {
// 将文件分组
const chunkSize = 3;
const chunks: string[][] = [];
for (let i = 0; i < files.length; i += chunkSize) {
chunks.push(files.slice(i, i + chunkSize));
}
// 并行处理每组文件
const results = await Promise.all(
chunks.map((chunk, index) =>
claude(
`重构以下文件,使用新的设计系统:
${chunk.join(", ")}
规则:
- 使用 Tailwind CSS 替换内联样式
- 使用新的 Button, Card, Input 组件
- 保持功能不变`,
{
cwd: process.cwd(),
allowedTools: ["Read", "Write", "Edit"],
timeout: 60000,
}
)
)
);
// 汇总结果
console.log(`完成 ${files.length} 个文件的重构`);
results.forEach((r, i) => {
console.log(`组 ${i + 1}: ${r.text.substring(0, 100)}...`);
});
}
// 使用
await parallelRefactor([
"src/components/Header.tsx",
"src/components/Footer.tsx",
"src/components/Sidebar.tsx",
"src/components/Card.tsx",
"src/components/Button.tsx",
"src/components/Modal.tsx",
]);
带协调的编排
import { claude, Conversation } from "@anthropic-ai/claude-code";
async function coordinatedRefactor() {
// 第一步:分析和规划(主 Agent)
const plan = await claude(
`分析 src/components/ 目录,列出所有需要重构的组件,
以 JSON 格式返回:
{
"groups": [
{ "name": "导航组件", "files": ["Header.tsx", "Nav.tsx"] },
...
],
"sharedChanges": ["需要统一修改的内容"]
}`,
{
cwd: process.cwd(),
allowedTools: ["Read", "Glob", "Grep"],
}
);
const { groups, sharedChanges } = JSON.parse(plan.text);
// 第二步:并行重构(Sub-Agents)
const results = await Promise.all(
groups.map((group: { name: string; files: string[] }) =>
claude(
`重构 ${group.name}:${group.files.join(", ")}
统一变更要求:
${sharedChanges.join("\n")}
完成后列出所有修改的文件和变更摘要。`,
{
cwd: process.cwd(),
allowedTools: ["Read", "Write", "Edit"],
timeout: 120000,
}
)
)
);
// 第三步:验证和整合(主 Agent)
const validation = await claude(
`刚刚完成了以下组件的重构:
${groups.map((g: { name: string }) => g.name).join(", ")}
请执行以下验证:
1. 运行 npx tsc --noEmit 检查类型
2. 运行 npm run lint 检查代码风格
3. 运行 npm test 确认功能正常
4. 检查组件之间的接口是否一致
报告验证结果。`,
{
cwd: process.cwd(),
allowedTools: ["Read", "Bash", "Glob", "Grep"],
timeout: 60000,
}
);
console.log("验证结果:", validation.text);
}
专家模式编排
import { claude } from "@anthropic-ai/claude-code";
interface ExpertReview {
expert: string;
systemPrompt: string;
focus: string;
}
async function expertReview(targetPath: string) {
const experts: ExpertReview[] = [
{
expert: "安全专家",
systemPrompt: "你是一个应用安全专家,专注于发现安全漏洞",
focus: "安全漏洞、注入攻击、认证问题、敏感信息泄露",
},
{
expert: "性能专家",
systemPrompt: "你是一个性能优化专家,专注于代码效率",
focus: "算法复杂度、内存泄漏、不必要的计算、缓存策略",
},
{
expert: "架构专家",
systemPrompt: "你是一个软件架构师,专注于代码结构和设计模式",
focus: "设计模式、模块耦合、代码复用、可扩展性",
},
];
// 并行执行专家审查
const reviews = await Promise.all(
experts.map((expert) =>
claude(
`审查 ${targetPath},重点关注:${expert.focus}
以 JSON 格式返回:
{
"expert": "${expert.expert}",
"findings": [
{
"severity": "high|medium|low",
"file": "文件路径",
"line": 行号,
"issue": "问题描述",
"suggestion": "改进建议"
}
],
"score": 1-10
}`,
{
cwd: process.cwd(),
systemPrompt: expert.systemPrompt,
allowedTools: ["Read", "Glob", "Grep"],
timeout: 60000,
}
)
)
);
// 汇总报告
const allFindings = reviews.flatMap((r) => {
try {
return JSON.parse(r.text).findings;
} catch {
return [];
}
});
// 按严重程度排序
allFindings.sort((a: any, b: any) => {
const order = { high: 0, medium: 1, low: 2 };
return (order[a.severity as keyof typeof order] || 2) -
(order[b.severity as keyof typeof order] || 2);
});
console.log(`\n审查完成,共发现 ${allFindings.length} 个问题:`);
console.log(`- 高严重度: ${allFindings.filter((f: any) => f.severity === "high").length}`);
console.log(`- 中严重度: ${allFindings.filter((f: any) => f.severity === "medium").length}`);
console.log(`- 低严重度: ${allFindings.filter((f: any) => f.severity === "low").length}`);
return allFindings;
}
// 使用
await expertReview("src/");
监控 Sub-Agent
进度追踪
import { claude } from "@anthropic-ai/claude-code";
async function trackedParallelExecution(tasks: string[]) {
const total = tasks.length;
let completed = 0;
const results = await Promise.all(
tasks.map(async (task, index) => {
console.log(`[${index + 1}/${total}] 开始: ${task}`);
const result = await claude(task, {
cwd: process.cwd(),
onProgress: (event) => {
if (event.type === "tool_use") {
console.log(` [${index + 1}] 使用工具: ${event.tool}`);
}
},
});
completed++;
console.log(`[${completed}/${total}] 完成: ${task}`);
return result;
})
);
return results;
}
错误处理
async function resilientParallelExecution(tasks: string[]) {
const results = await Promise.allSettled(
tasks.map((task) =>
claude(task, {
cwd: process.cwd(),
timeout: 60000,
})
)
);
const succeeded = results.filter((r) => r.status === "fulfilled");
const failed = results.filter((r) => r.status === "rejected");
console.log(`成功: ${succeeded.length}, 失败: ${failed.length}`);
// 重试失败的任务
if (failed.length > 0) {
console.log("重试失败的任务...");
const retryTasks = failed.map((_, i) => tasks[results.indexOf(failed[i])]);
// 串行重试,避免并发问题
for (const task of retryTasks) {
try {
await claude(task, { cwd: process.cwd(), timeout: 120000 });
console.log(`重试成功: ${task.substring(0, 50)}...`);
} catch (error) {
console.error(`重试失败: ${task.substring(0, 50)}...`);
}
}
}
}
最佳实践
1. 任务粒度要合适
太粗的任务拆分不够,太细的任务开销太大:
// 太粗:一个 Sub-Agent 处理太多文件
await claude("重构 src/ 下所有 200 个文件");
// 太细:每个文件一个 Sub-Agent,开销太大
files.forEach(f => claude(`重构 ${f}`));
// 合适:按逻辑分组,每组 3-5 个文件
const groups = chunkByModule(files, 5);
await Promise.all(groups.map(g => claude(`重构 ${g.join(", ")}`)));
2. 避免 Sub-Agent 之间的冲突
// 不好:两个 Sub-Agent 可能修改同一个文件
await Promise.all([
claude("优化 src/utils/index.ts 的导出"),
claude("给 src/utils/index.ts 添加新函数"),
]);
// 好:确保 Sub-Agent 操作不同的文件
await Promise.all([
claude("优化 src/utils/format.ts"),
claude("优化 src/utils/date.ts"),
]);
3. 共享上下文通过参数传递
// 先获取共享信息
const designSystem = await claude("读取 src/design-system/tokens.ts 的内容");
// 然后传递给每个 Sub-Agent
await Promise.all(
components.map(comp =>
claude(`使用以下设计系统 Token 重构 ${comp}:
${designSystem.text}`)
)
);
4. 始终做最终验证
// 并行执行
await Promise.all(subTasks.map(t => claude(t)));
// 最终验证(串行)
await claude("运行 npm run build && npm test,确认所有修改没有破坏功能");
Sub-Agent 模式是 Claude Code 处理复杂任务的秘密武器。理解它的工作原理,学会手动编排,你就能把一个小时的串行工作压缩到几分钟的并行执行。分而治之,不仅是算法的智慧,也是 AI 协作的智慧。
相关文章
评论
加载中...
评论
加载中...