第 10 章 · SubAgent 协作
04 · 编排与串行执行
Orchestrator 按顺序执行子任务,把前置结果传递给后续 subagent。
Orchestrator 的职责
Orchestrator 是子任务的调度中心。它不执行具体任务——它负责把任务分发给 subagent,并管理任务间的信息流。
在 src/subagent/orchestrator.ts 中:
export class Orchestrator {
private model: Model;
private tools: Tool[];
async execute(tasks: SubTask[], workingDir: string): Promise<SubAgentResult[]> {
const results: SubAgentResult[] = [];
for (const task of tasks) {
const previousContext = results.length > 0
? this.formatPreviousResults(results) : "";
const taskWithContext = previousContext
? `${task.task}\n\n## 前置任务的结果\n\n${previousContext}`
: task.task;
const subAgent = new SubAgent(this.model, this.tools, task.role);
const result = await subAgent.execute(taskWithContext, workingDir);
results.push(result);
}
return results;
}
}串行而非并行
当前实现是串行执行——一个接一个。这不是技术限制,而是设计选择:
为什么串行?
- 避免文件冲突。 两个 editor subagent 同时修改同一个文件,会产生冲突。串行执行让后一个 subagent 能看到前一个的修改。
- 信息依赖。 editor 需要 explorer 收集的信息。reviewer 需要看到 editor 的修改。串行保证信息按正确的顺序流动。
- 简单可靠。 并行需要处理并发、冲突、超时等复杂问题。教学项目优先选择简单。
什么时候可以并行?
如果多个 explorer 搜索不同的内容(一个搜测试文件、一个搜配置文件),可以并行。但这需要更复杂的编排逻辑,留作后续优化。
delegate_tasks 工具
subagent 系统通过一个工具暴露给主 agent——delegate_tasks。主 agent 的模型在分析任务后,可以决定是否委托:
{
"name": "delegate_tasks",
"description": "将复杂任务拆分后委托给子 agent 执行...",
"parameters": {
"type": "object",
"properties": {
"tasks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"task": { "type": "string", "description": "子任务描述" },
"role": { "type": "string", "enum": ["explorer", "editor", "reviewer"] }
}
}
}
}
}
}模型看到这个工具后,在遇到复杂任务时,可以主动调用它。调用时传入子任务列表,每个子任务指定角色。工具返回所有子任务的汇总结果。
模型自己决定何时 delegate。 这比硬编码规则更灵活——简单任务模型直接用内置工具完成,复杂任务模型自己拆分并委托。
执行统计
每个 subagent 返回独立的统计数据:
interface SubAgentResult {
answer: string;
role: SubAgentRole;
task: string;
stats: {
modelCalls: number;
toolCallCount: number;
};
}主 agent 可以统计总消耗:所有 subagent 的 modelCalls 和 toolCallCount 之和。这帮助用户理解多 agent 协作的成本。
版本更新
main.ts 的版本号从 v0.9.0 升级到 v0.10.0。
加上之前章节的测试,整个项目现在有 179 个测试用例。
登录以继续阅读
解锁完整文档、代码示例及更多高级功能。