# 第二阶段 · 模块二 · 第五节:子代理系统
Claude Code 如何实现子代理?AgentTool 的工作原理是什么?Fork 子代理是什么?LocalAgentTask 如何管理子代理的生命周期?子代理与主代理如何通信?
Claude Code 全局架构
┌─────────────────────────────────────────────────────────────────────┐
│ 工具层(tools/) │
│ │
│ 子代理系统 ← 本节 │
│ ├── AgentTool │
│ ├── forkSubagent.ts │
│ ├── LocalAgentTask │
│ └── 并行执行 │
└─────────────────────────────────────────────────────────────────────┘
源码位置:`src/tools/AgentTool/`
子代理(Subagent)是 Claude Code 中用于并行处理复杂任务的机制。主代理可以启动一个或多个子代理来同时执行多个任务。
┌─────────────────────────────────────────────────────────────────────┐
│ 主代理 (Main Agent) │
│ │
│ ├─ 启动子代理 A ──> 并行执行任务 A │
│ ├─ 启动子代理 B ──> 并行执行任务 B │
│ └─ 启动子代理 C ──> 并行执行任务 C │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 子代理 vs 工具 │
│ │
│ 工具(Tool) │
│ - 单次调用 │
│ - 无状态 │
│ - 同步执行 │
│ │
│ 子代理(Subagent) │
│ - 独立会话 │
│ - 有状态 │
│ - 可异步执行 │
│ - 支持复杂逻辑 │
└─────────────────────────────────────────────────────────────────────┘
问 1:什么时候应该使用子代理?
// 使用子代理的场景:
// 1. 并行任务
// - 多个独立任务可同时执行
// - 任务间无依赖
// 2. 复杂推理
// - 子任务需要独立思考
// - 主任务等待子结果
// 3. 隔离执行
// - 需要独立上下文
// - 避免干扰主会话
源码位置:`src/tools/AgentTool/AgentTool.tsx`
// 基础输入 Schema
const baseInputSchema = lazySchema(() => z.object({
description: z.string().describe('A short (3-5 word) description of the task'),
prompt: z.string().describe('The task for the agent to perform'),
subagent_type: z.string().optional().describe('The type of specialized agent to use'),
model: z.enum(['sonnet', 'opus', 'haiku']).optional().describe('Model override'),
run_in_background: z.boolean().optional().describe('Run in background')
}))
// 完整 Schema(含多代理参数)
const fullInputSchema = lazySchema(() => {
const multiAgentInputSchema = z.object({
name: z.string().optional().describe('Name for the spawned agent'),
team_name: z.string().optional().describe('Team name for spawning'),
mode: permissionModeSchema().optional().describe('Permission mode'),
})
return baseInputSchema().merge(multiAgentInputSchema).extend({
isolation: z.enum(['worktree', 'remote']).optional().describe('Isolation mode'),
cwd: z.string().optional().describe('Working directory override')
})
})
源码位置:`src/tools/AgentTool/builtInAgents.ts`
// 内置代理列表
const agents: AgentDefinition[] = [
GENERAL_PURPOSE_AGENT,
STATUSLINE_SETUP_AGENT,
EXPLORE_AGENT, // 如果启用
PLAN_AGENT, // 如果启用
VERIFICATION_AGENT, // GrowthBook 门控
CLAUDE_CODE_GUIDE_AGENT, // 非 SDK 入口点
]
// 代理启用检查
export function areExplorePlanAgentsEnabled(): boolean {
if (feature('BUILTIN_EXPLORE_PLAN_AGENTS')) {
return getFeatureValue_CACHED_MAY_BE_STALE('tengu_amber_stoat', true)
}
return false
}
| 参数 | 类型 | 说明 |
| description | string | 简短任务描述(3-5词) |
| prompt | string | 详细任务指令 |
| subagent_type | string | 专用代理类型 |
| model | enum | 模型选择(sonnet/opus/haiku) |
| run_in_background | boolean | 是否后台运行 |
| name | string | 子代理名称(可选) |
| team_name | string | 团队名称(可选) |
| isolation | enum | 隔离模式(worktree/remote) |
| cwd | string | 工作目录覆盖(可选) |
源码位置:`src/tools/AgentTool/forkSubagent.ts`
Fork 子代理是一种隐式子代理机制,当省略 `subagent_type` 且实验启用时触发。
// Fork Subagent 功能门控
export function isForkSubagentEnabled(): boolean {
if (feature('FORK_SUBAGENT')) {
if (isCoordinatorMode()) return false // 与协调模式互斥
if (getIsNonInteractiveSession()) return false // 非交互模式禁用
return true
}
return false
}
┌─────────────────────────────────────────────────────────────────────┐
│ Fork 触发条件 │
│ │
│ 1. feature('FORK_SUBAGENT') 启用 │
│ 2. 非协调模式 │
│ 3. 非 SDK/非交互模式 │
│ 4. 省略 subagent_type 参数 │
└─────────────────────────────────────────────────────────────────────┘
// Fork 专用代理定义
export const FORK_AGENT = {
agentType: FORK_SUBAGENT_TYPE, // 'fork'
whenToUse: 'Implicit fork — inherits full conversation context. Not selectable via subagent_type',
tools: ['*'], // 接收父代理的精确工具池
maxTurns: 200,
model: 'inherit', // 继承父模型,保持上下文长度一致
permissionMode: 'bubble', // 权限提示冒泡到父终端
source: 'built-in',
baseDir: 'built-in',
getSystemPrompt: () => '', // 未使用,通过 override 传递
}
// Fork 的关键特性:
// 1. 隐式继承
// - 子代理继承父代理的完整对话上下文
// - 不需要指定 subagent_type
// 2. 工具池精确匹配
// - tools: ['*'] 表示接收父代理的精确工具池
// - 保证 API 前缀的缓存一致性
// 3. 权限冒泡
// - permissionMode: 'bubble'
// - 子代理的权限提示显示在父终端
// 4. 模型继承
// - model: 'inherit'
// - 保持与父代理相同的上下文长度
// 5. 系统提示传递
// - 通过 override.systemPrompt 传递
// - 避免重新调用 getSystemPrompt() 导致缓存不命中
// 防止递归 Fork
export function isInForkChild(messages: MessageType[]): boolean {
return messages.some(m => {
if (m.type !== 'user') return false
// 检查是否存在 Fork 标记
// Fork 子代理保留 Agent tool 在工具池中
// 所以通过检测 FORK_BOILERPLATE_TAG 防止递归
})
}
源码位置:`src/tasks/LocalAgentTask/LocalAgentTask.tsx`
export type LocalAgentTaskState = TaskStateBase & {
type: 'local_agent';
agentId: string;
prompt: string;
selectedAgent?: AgentDefinition;
agentType: string;
model?: string;
status: 'pending' | 'running' | 'completed' | 'failed';
result?: string;
error?: string;
}
┌─────────────────────────────────────────────────────────────────────┐
│ 任务状态流转 │
│ │
│ pending ──► running ──► completed │
│ │ │ │
│ │ ▼ │
│ └──────► failed │
└─────────────────────────────────────────────────────────────────────┘
// 注册异步任务
async function registerAsyncAgent(
agentId: string,
task: LocalAgentTask
): Promise<void> {
// 1. 创建任务记录
// 2. 启动任务执行
// 3. 注册回调
}
// 完成任务
function completeAsyncAgent(
agentId: string,
result: string
): void {
// 1. 更新任务状态
// 2. 通知主代理
// 3. 清理资源
}
// 终止任务
function killAsyncAgent(agentId: string): void {
// 1. 停止执行
// 2. 清理资源
// 3. 更新状态
}
// 子代理执行流程
async function executeSubagent(input: SubagentInput): Promise<string> {
// 1. 验证输入
const validated = inputSchema.parse(input)
// 2. 创建任务
const taskId = await createTask(validated)
// 3. 执行任务
if (validated.run_in_background) {
// 后台执行
registerAsyncAgent(taskId, task)
return `Task ${taskId} started in background`
} else {
// 同步执行
return await runAgent(task)
}
}
// 后台执行模式
// 自动后台任务阈值
const PROGRESS_THRESHOLD_MS = 2000; // 2秒后显示后台提示
// 1. 启动后台任务
const taskId = await spawnBackgroundTask({
prompt: '分析代码库...',
isolation: 'worktree'
})
// 2. 轮询状态
const status = await getTaskStatus(taskId)
// 3. 获取结果
const result = await getTaskResult(taskId)
问 1:子代理如何与主代理通信?
// 通信方式:
// 1. 同步返回
// - 子代理完成后直接返回结果
// - 主代理等待
// 2. 异步回调
// - 注册回调函数
// - 任务完成时自动调用
// 3. 共享状态
// - 通过共享存储通信
// - 支持复杂交互
// worktree 隔离模式
interface WorktreeIsolation {
type: 'worktree';
baseDir: string;
worktreeName: string;
}
// 创建隔离工作目录
async function createWorktreeIsolation(
prompt: string
): Promise<WorktreeIsolation> {
// 1. 创建 git worktree
const worktree = await git.worktree('add', generateWorktreeName())
// 2. 初始化子代理环境
await initAgentEnvironment(worktree.path)
return { type: 'worktree', ...worktree }
}
// remote 隔离模式
interface RemoteIsolation {
type: 'remote';
host: string;
sessionId: string;
}
// 使用远程会话
async function createRemoteIsolation(
prompt: string
): Promise<RemoteIsolation> {
// 1. 建立远程连接
const connection = await connectToRemote(host)
// 2. 创建新会话
const session = await connection.createSession()
return { type: 'remote', host, sessionId: session.id }
}
源码位置:`src/tools/AgentTool/built-in/`
// 内置代理
GENERAL_PURPOSE_AGENT // 通用代理
STATUSLINE_SETUP_AGENT // 状态栏设置代理
EXPLORE_AGENT // 代码探索代理
PLAN_AGENT // 计划代理
VERIFICATION_AGENT // 验证代理(GrowthBook 门控)
CLAUDE_CODE_GUIDE_AGENT // Claude Code 指南代理
// 创建自定义代理
const customAgent = {
name: 'MyAgent',
description: '自定义代理',
systemPrompt: '你的专属提示词...'
}
// 注册代理
registerAgent(customAgent)
// 使用
const result = await runAgent({
prompt: '任务描述',
subagent_type: 'MyAgent'
})
答案:
// 限制:
// 1. 数量限制
// - 同时运行的子代理数量有限
// - 避免资源耗尽
// 2. 上下文限制
// - 子代理上下文独立
// - 共享数据需要额外处理
// 3. 通信限制
// - 主代理和子代理通信有延迟
// - 不适合实时交互
// 4. Fork 递归限制
// - Fork 子代理中不能再 Fork
// - 防止无限递归
答案:
// 普通子代理:
// - 需要指定 subagent_type
// - 显式创建
// - 可选择不同类型的代理
// Fork 子代理:
// - 省略 subagent_type 隐式触发
// - 继承父代理完整上下文
// - 工具池与父代理完全一致
// - 更轻量、更快
答案:
// 递归 Fork 问题:
// 问题:Fork 子代理内部如果再调用子代理,会导致无限递归
// 解决:isInForkChild() 检测
function isInForkChild(messages: Message[]): boolean {
// 检查对话历史中是否存在 Fork 标记
return messages.some(m => {
if (m.type !== 'user') return false
// 检测 FORK_BOILERPLATE_TAG
return m.content.includes('[Fork Agent]')
})
}
// 使用:
if (isInForkChild(messages)) {
throw new Error('Cannot fork within a forked subagent')
}
答案:
// 权限冒泡模型 (permissionMode: 'bubble'):
// 设计考虑:
// 1. 权限继承
// - 子代理继承父代理权限
// - 但写操作需要确认
// 2. 权限隔离
// - 某些敏感操作不允许子代理执行
// - 需要父代理直接处理
// 3. 权限提升
// - 紧急情况下可以提升权限
// - 但需要审计追踪
| 资源 | 说明 |
| `src/tools/AgentTool/AgentTool.tsx` | 子代理工具入口 |
| `src/tools/AgentTool/forkSubagent.ts` | Fork 子代理实现 |
| `src/tools/AgentTool/builtInAgents.ts` | 内置代理 |
| `src/tasks/LocalAgentTask/LocalAgentTask.tsx` | 状态管理 |
下一节我们将进入 Agent Swarms 多代理团队:
- TeamCreateTool
- 多代理协作
- 团队通信机制