乐于分享
好东西不私藏

Claude Code源码系列:4、3-关键功能模块-Agent系统

Claude Code源码系列:4、3-关键功能模块-Agent系统

本文对 Claude Code 项目中的 Agent 系统进行庖丁解牛式的源码拆解,揭示其核心架构、执行流程、权限隔离机制以及 Prompt Cache 共享策略。


1. 概述与核心架构 (Overview)

1.1 一句话定义

Agent 系统是 Claude Code 中用于创建、管理和执行子代理 (Subagent) 的核心基础设施,它允许主代理将复杂任务委托给具有特定工具权限、系统提示和执行上下文的子代理来完成。

1.2 核心组件清单

Agent 系统由以下核心组件构成:

  1. AgentDefinition – Agent 定义类型系统,描述 Agent 的类型、工具权限、系统提示等元数据
  2. AgentTool – 工具入口,定义 Agent 工具的 schema 和调用逻辑
  3. runAgent – 执行引擎,核心的 AsyncGenerator 函数,驱动 Agent 的 query 循环
  4. resolveAgentTools – 工具解析器,根据 Agent 定义过滤和组装可用工具池
  5. createSubagentContext – 上下文隔离器,创建子 Agent 的独立执行上下文
  6. filterToolsForAgent – 工具过滤器,实现三层权限控制架构
  7. ForkSubagent – Fork 机制,实现 Prompt Cache 共享的高效子代理创建

1.3 目录结构概览

src/tools/AgentTool/├── AgentTool.tsx          # 主入口:工具定义、schema、调用路由├── runAgent.ts            # 执行引擎:AsyncGenerator query 循环├── loadAgentsDir.ts       # Agent 定义:类型系统、解析逻辑├── agentToolUtils.ts      # 辅助函数:工具解析、结果处理、生命周期├── forkSubagent.ts        # Fork 机制:prompt cache 共享实现├── builtInAgents.ts       # 内置 Agent 注册表├── constants.ts           # 常量定义 (工具名等)├── prompt.ts              # Agent 工具提示生成├── agentMemory.ts         # Agent 内存系统├── agentColorManager.ts   # 颜色管理 (UI 显示)├── UI.tsx                 # UI 渲染组件└── built-in/              # 内置 Agent 实现目录    ├── generalPurposeAgent.ts   # 全功能 Agent    ├── exploreAgent.ts          # 探索 Agent (只读)    ├── planAgent.ts             # 规划 Agent    ├── verificationAgent.ts     # 验证 Agent    ├── claudeCodeGuideAgent.ts  # Claude Code 指南 Agent    └── statuslineSetup.ts       # 状态栏设置 Agent

2. 核心模块源码拆解 (Core Implementation)

2.1 AgentDefinition 类型系统

AgentDefinition 是 Agent 系统的核心类型定义,描述了一个 Agent 的完整元数据。

// 文件路径: src/tools/AgentTool/loadAgentsDir.ts// 行号: 105-166// ===== 基础类型:所有 Agent 共享的字段 =====export type BaseAgentDefinition = {  agentType: string// Agent 类型名称 (如 "Explore", "Plan")  whenToUse: string// 使用场景描述 (展示给调用方)  tools?: string[]; // 工具白名单 (如 ["Bash", "Read"])  disallowedTools?: string[]; // 工具黑名单  skills?: string[]; // 预加载的技能名称 (slash commands)  mcpServers?: AgentMcpServerSpec[]; // Agent 特定的 MCP 服务器配置  hooks?: HooksSettings; // Session-scoped hooks (生命周期钩子)  color?: AgentColorName; // UI 显示颜色  model?: string// 模型配置 ('inherit' | 'sonnet' | 'opus' | 'haiku')  effort?: EffortValue; // 思考努力级别  permissionMode?: PermissionMode; // 权限模式覆盖  maxTurns?: number// 最大回合数限制  omitClaudeMd?: boolean// 是否省略 CLAUDE.md (节省 token)  background?: boolean// 是否强制后台运行  isolation?: "worktree" | "remote"// 隔离模式  memory?: AgentMemoryScope; // 持久化内存范围 ('user' | 'project' | 'local')  requiredMcpServers?: string[]; // 必需的 MCP 服务器模式  initialPrompt?: string// 预置到第一个 user turn 的内容  criticalSystemReminder_EXPERIMENTAL?: string// 每个 user turn 重新注入的提醒};// ===== 内置 Agent 定义 =====export type BuiltInAgentDefinition = BaseAgentDefinition & {  source: "built-in";  baseDir: "built-in";  callback?: () => void// Agent 完成后执行的回调  getSystemPrompt: (params: {    toolUseContext: Pick<ToolUseContext, "options">;  }) => string// 动态生成系统提示};// ===== 自定义 Agent (用户/项目/策略配置) =====export type CustomAgentDefinition = BaseAgentDefinition & {  getSystemPrompt: () => string// 静态系统提示  source: SettingSource; // 'userSettings' | 'projectSettings' | 'policySettings' | 'flagSettings'  filename?: string;  baseDir?: string;};// ===== 插件 Agent =====export type PluginAgentDefinition = BaseAgentDefinition & {  getSystemPrompt: () => string;  source: "plugin";  plugin: string// 插件名称  filename?: string;};// ===== 联合类型 =====export type AgentDefinition =  | BuiltInAgentDefinition  | CustomAgentDefinition  | PluginAgentDefinition;

核心执行流解析:

  1. 类型分层设计BaseAgentDefinition 作为基础层,定义所有 Agent 共享的字段;三种派生类型分别处理内置、自定义和插件场景

  2. source 字段的作用:标识 Agent 的来源,用于权限判断(如 isSourceAdminTrusted 检查)

  3. getSystemPrompt 的两种形态

    • 内置 Agent 使用动态生成函数,接收 toolUseContext 参数
    • 自定义/插件 Agent 使用静态闭包函数
  4. omitClaudeMd 优化:只读 Agent (Explore, Plan) 省略 CLAUDE.md 内容,节省约 5-15 Gtok/周


2.2 AgentTool 工具入口

AgentTool 是 Agent 系统的入口工具,定义了调用 Agent 的 schema 和核心路由逻辑。

// 文件路径: src/tools/AgentTool/AgentTool.tsx// 行号: 196-258 (工具定义部分)// ===== Input 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("Optional model override"),    run_in_background: z      .boolean()      .optional()      .describe("Set to true to run in background"),  }),);// ===== Full 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 for teammate"),  });return baseInputSchema()    .merge(multiAgentInputSchema)    .extend({      isolation: z.enum(["worktree""remote"]).optional(),      cwd: z.string().optional().describe("Absolute path override"),    });});// ===== Output Schema =====export const outputSchema = lazySchema(() => {const syncOutputSchema = agentToolResultSchema().extend({    status: z.literal("completed"),    prompt: z.string(),  });const asyncOutputSchema = z.object({    status: z.literal("async_launched"),    agentId: z.string(),    description: z.string(),    outputFile: z.string(),  });return z.union([syncOutputSchema, asyncOutputSchema]);});// ===== 工具构建 =====export const AgentTool = buildTool({  name: AGENT_TOOL_NAME, // "Agent"  aliases: [LEGACY_AGENT_TOOL_NAME], // "Task" (兼容旧名)  maxResultSizeChars: 100_000, // 最大结果字符数async prompt({ agents, tools, getToolPermissionContext, allowedAgentTypes }) {// 根据权限过滤 Agent 列表const filteredAgents = filterDeniedAgents(      agents,      toolPermissionContext,      AGENT_TOOL_NAME,    );return await getPrompt(filteredAgents, isCoordinator, allowedAgentTypes);  },async call(input, toolUseContext, canUseTool, assistantMessage, onProgress) {// 核心调用逻辑 (详见下文)  },});

核心执行流解析:

  1. Schema 懒加载:使用 lazySchema 避免模块加载时的循环依赖问题

  2. 多状态输出:输出 schema 包含 completed(同步完成)和 async_launched(后台启动)两种状态

  3. 别名兼容:保留 Task 作为别名,兼容旧版本 API


2.3 AgentTool.call() 核心路由逻辑

// 文件路径: src/tools/AgentTool/AgentTool.tsx// 行号: 239-356 (核心路由部分)async call({  prompt,  subagent_type,  description,  model: modelParam,  run_in_background,  name,  team_name,  mode: spawnMode,  isolation,  cwd}: AgentToolInput, toolUseContext, canUseTool, assistantMessage, onProgress) {const startTime = Date.now();const appState = toolUseContext.getAppState();const permissionMode = appState.toolPermissionContext.mode;const rootSetAppState = toolUseContext.setAppStateForTasks ?? toolUseContext.setAppState;// ===== Step 1: 多代理团队权限检查 =====if (team_name && !isAgentSwarmsEnabled()) {throw new Error('Agent Teams is not yet available on your plan.');  }// ===== Step 2: Teammate 嵌套禁止 =====const teamName = resolveTeamName({ team_name }, appState);if (isTeammate() && teamName && name) {throw new Error('Teammates cannot spawn other teammates — the team roster is flat.');  }// ===== Step 3: 多代理 spawn 路由 =====if (teamName && name) {const agentDef = subagent_type      ? toolUseContext.options.agentDefinitions.activeAgents.find(a => a.agentType === subagent_type)      : undefined;if (agentDef?.color) {      setAgentColor(subagent_type!, agentDef.color);    }const result = await spawnTeammate({      name,      prompt,      description,      team_name: teamName,      use_splitpane: true,      plan_mode_required: spawnMode === 'plan',      model: model ?? agentDef?.model,      agent_type: subagent_type,      invokingRequestId: assistantMessage?.requestId    }, toolUseContext);return { data: { status: 'teammate_spawned', prompt, ...result.data } };  }// ===== Step 4: Fork/常规 Agent 路由 =====// - subagent_type 有值: 使用指定的 Agent 类型// - subagent_type 无值 + Fork 开启: 进入 Fork 路径// - subagent_type 无值 + Fork 关闭: 默认 general-purposeconst effectiveType = subagent_type ?? (isForkSubagentEnabled() ? undefined : GENERAL_PURPOSE_AGENT.agentType);const isForkPath = effectiveType === undefined;// ===== Step 5: Fork 递归守卫 =====if (isForkPath) {if (toolUseContext.options.querySource === `agent:builtin:${FORK_AGENT.agentType}` ||        isInForkChild(toolUseContext.messages)) {throw new Error('Fork is not available inside a forked worker.');    }    selectedAgent = FORK_AGENT;  } else {// ===== Step 6: Agent 类型查找和权限过滤 =====const allAgents = toolUseContext.options.agentDefinitions.activeAgents;const { allowedAgentTypes } = toolUseContext.options.agentDefinitions;const agents = filterDeniedAgents(      allowedAgentTypes ? allAgents.filter(a => allowedAgentTypes.includes(a.agentType)) : allAgents,      appState.toolPermissionContext,      AGENT_TOOL_NAME    );const found = agents.find(agent => agent.agentType === effectiveType);if (!found) {// 检查是否被权限规则拒绝const agentExistsButDenied = allAgents.find(agent => agent.agentType === effectiveType);if (agentExistsButDenied) {const denyRule = getDenyRuleForAgent(appState.toolPermissionContext, AGENT_TOOL_NAME, effectiveType);throw new Error(`Agent type '${effectiveType}' has been denied by permission rule.`);      }throw new Error(`Agent type '${effectiveType}' not found.`);    }    selectedAgent = found;  }// ===== Step 7: 必需 MCP 服务器检查 =====if (selectedAgent.requiredMcpServers?.length) {// 等待 pending 服务器连接完成const MAX_WAIT_MS = 30_000;while (hasPendingRequiredServers && Date.now() < deadline) {await sleep(POLL_INTERVAL_MS);    }// 验证服务器有可用工具if (!hasRequiredMcpServers(selectedAgent, serversWithTools)) {throw new Error(`Agent '${selectedAgent.agentType}' requires MCP servers.`);    }  }// ... 后续执行逻辑}

核心执行流解析:

  1. 路由优先级:Teammate spawn > Fork path > 常规 Agent

  2. Fork 守卫机制:通过 querySource 和 isInForkChild 双重检查防止递归 fork

  3. 权限过滤链allowedAgentTypes → filterDeniedAgents → 最终可用 Agent 列表

  4. MCP 等待机制:对于 pending 状态的必需 MCP 服务器,最多等待 30 秒


2.4 runAgent 执行引擎

runAgent 是 Agent 执行的核心引擎,是一个 AsyncGenerator 函数。

// 文件路径: src/tools/AgentTool/runAgent.ts// 行号: 248-860export async functionrunAgent({  agentDefinition,  promptMessages,  toolUseContext,  canUseTool,  isAsync,  canShowPermissionPrompts,  forkContextMessages,  querySource,  override,  model,  maxTurns,  availableTools,  allowedTools,// ... 其他参数}: RunAgentParams): AsyncGenerator<Messagevoid{// ===== Step 1: 初始化 Agent ID 和 Context =====const agentId = override?.agentId ?? createAgentId();const appState = toolUseContext.getAppState();const permissionMode = appState.toolPermissionContext.mode;const rootSetAppState = toolUseContext.setAppStateForTasks ?? toolUseContext.setAppState;// ===== Step 2: 模型解析 =====const resolvedAgentModel = getAgentModel(    agentDefinition.model,    toolUseContext.options.mainLoopModel,    model,    permissionMode  );// ===== Step 3: 初始消息构建 =====const contextMessages: Message[] = forkContextMessages    ? filterIncompleteToolCalls(forkContextMessages)    : [];const initialMessages: Message[] = [...contextMessages, ...promptMessages];// ===== Step 4: 用户/系统上下文解析 =====const [baseUserContext, baseSystemContext] = await Promise.all([    override?.userContext ?? getUserContext(),    override?.systemContext ?? getSystemContext()  ]);// ===== Step 5: CLAUDE.md 省略优化 =====const shouldOmitClaudeMd =    agentDefinition.omitClaudeMd &&    !override?.userContext &&    getFeatureValue_CACHED_MAY_BE_STALE('tengu_slim_subagent_claudemd'true);const { claudeMd: _omittedClaudeMd, ...userContextNoClaudeMd } = baseUserContext;const resolvedUserContext = shouldOmitClaudeMd ? userContextNoClaudeMd : baseUserContext;// ===== Step 6: 权限上下文覆盖 =====const agentGetAppState = () => {const state = toolUseContext.getAppState();let toolPermissionContext = state.toolPermissionContext;// 覆盖 permissionMode (除非父级是 bypassPermissions/acceptEdits/auto)if (agentPermissionMode &&        state.toolPermissionContext.mode !== 'bypassPermissions' &&        state.toolPermissionContext.mode !== 'acceptEdits') {      toolPermissionContext = { ...toolPermissionContext, mode: agentPermissionMode };    }// 设置 shouldAvoidPermissionPrompts (异步 Agent 无法显示 UI)const shouldAvoidPrompts = canShowPermissionPrompts !== undefined      ? !canShowPermissionPrompts      : agentPermissionMode === 'bubble' ? false : isAsync;if (shouldAvoidPrompts) {      toolPermissionContext = {        ...toolPermissionContext,        shouldAvoidPermissionPrompts: true      };    }return { ...state, toolPermissionContext };  };// ===== Step 7: 工具池解析 =====const resolvedTools = useExactTools    ? availableTools    : resolveAgentTools(agentDefinition, availableTools, isAsync).resolvedTools;// ===== Step 8: 系统提示构建 =====const agentSystemPrompt = override?.systemPrompt    ? override.systemPrompt    : asSystemPrompt(await getAgentSystemPrompt(agentDefinition, toolUseContext, ...));// ===== Step 9: AbortController 配置 =====const agentAbortController = override?.abortController    ? override.abortController    : isAsync      ? new AbortController()  // 异步 Agent 使用独立 controller      : toolUseContext.abortController;  // 同步 Agent 共享父级 controller// ===== Step 10: SubagentStart Hooks 执行 =====const additionalContexts: string[] = [];for await (const hookResult of executeSubagentStartHooks(agentId, agentDefinition.agentType, ...)) {if (hookResult.additionalContexts?.length > 0) {      additionalContexts.push(...hookResult.additionalContexts);    }  }// ===== Step 11: Frontmatter Hooks 注册 =====if (agentDefinition.hooks && hooksAllowedForThisAgent) {    registerFrontmatterHooks(rootSetAppState, agentId, agentDefinition.hooks, ..., true);  }// ===== Step 12: Skills 预加载 =====const skillsToPreload = agentDefinition.skills ?? [];if (skillsToPreload.length > 0) {// 解析技能名称,加载内容,添加到 initialMessagesfor (const { skillName, skill, content } of loaded) {      initialMessages.push(createUserMessage({ content: [...], isMeta: true }));    }  }// ===== Step 13: MCP Servers 初始化 =====const { clients: mergedMcpClients, tools: agentMcpTools, cleanup: mcpCleanup } =await initializeAgentMcpServers(agentDefinition, toolUseContext.options.mcpClients);// 合并工具const allTools = agentMcpTools.length > 0    ? uniqBy([...resolvedTools, ...agentMcpTools], 'name')    : resolvedTools;// ===== Step 14: Subagent Context 创建 =====const agentToolUseContext = createSubagentContext(toolUseContext, {    options: agentOptions,    agentId,    agentType: agentDefinition.agentType,    messages: initialMessages,    readFileState: agentReadFileState,    abortController: agentAbortController,    getAppState: agentGetAppState,    shareSetAppState: !isAsync,    shareSetResponseLength: true  });// ===== Step 15: Query 循环 =====try {for await (const message of query({      messages: initialMessages,      systemPrompt: agentSystemPrompt,      userContext: resolvedUserContext,      systemContext: resolvedSystemContext,      canUseTool,      toolUseContext: agentToolUseContext,      querySource,      maxTurns: maxTurns ?? agentDefinition.maxTurns    })) {// 转发 stream_event 的 ttft 到父级 metricsif (message.type === 'stream_event' && message.event.type === 'message_start') {        toolUseContext.pushApiMetricsEntry?.(message.ttftMs);continue;      }// 处理 max_turns_reached 信号if (message.type === 'attachment' && message.attachment.type === 'max_turns_reached') {break;      }// 记录和 yield 可记录消息if (isRecordableMessage(message)) {await recordSidechainTranscript([message], agentId, lastRecordedUuid);yield message;      }    }// ===== Step 16: 内置 Agent callback =====if (isBuiltInAgent(agentDefinition) && agentDefinition.callback) {      agentDefinition.callback();    }  } finally {// ===== Step 17: 资源清理 =====await mcpCleanup();    clearSessionHooks(rootSetAppState, agentId);    cleanupAgentTracking(agentId);    agentToolUseContext.readFileState.clear();    initialMessages.length = 0;    unregisterPerfettoAgent(agentId);    clearAgentTranscriptSubdir(agentId);// 清理 todos 和 shell tasks    rootSetAppState(prev => { ...prev, todos });    killShellTasksForAgent(agentId, ...);  }}

核心执行流解析:

  1. 初始化阶段 (Steps 1-14):完整的 Agent 上下文构建,包括 ID、模型、消息、权限、工具、MCP、hooks 等

  2. Query 循环 (Step 15):调用核心 query() 函数,yield 消息给调用方

  3. 清理阶段 (Step 17):finally 块确保所有资源被正确释放

  4. 关键设计决策

    • 异步 Agent 使用独立的 AbortController,同步 Agent 共享父级
    • omitClaudeMd 优化为只读 Agent 节省大量 token
    • shouldAvoidPermissionPrompts 标志防止异步 Agent 弹出 UI

3. 关键子模块/具体实现分析 (Sub-modules)

3.1 General Purpose Agent

// 文件路径: src/tools/AgentTool/built-in/generalPurposeAgent.ts// 行号: 1-35const SHARED_PREFIX = `You are an agent for Claude Code, Anthropic's official CLI for Claude.Given the user's message, you should use the tools available to complete the task.Complete the task fully—don't gold-plate, but don't leave it half-done.`;const SHARED_GUIDELINES = `Your strengths:- Searching for code, configurations, and patterns across large codebases- Analyzing multiple files to understand system architecture- Investigating complex questions that require exploring many files- Performing multi-step research tasksGuidelines:- For file searches: search broadly when you don't know where something lives.- NEVER create files unless they're absolutely necessary.- NEVER proactively create documentation files (*.md) or README files.`;functiongetGeneralPurposeSystemPrompt(): string{return `${SHARED_PREFIX} When you complete the task, respond with a concise report...${SHARED_GUIDELINES}`;}export const GENERAL_PURPOSE_AGENT: BuiltInAgentDefinition = {  agentType: "general-purpose",  whenToUse: "General-purpose agent for researching complex questions...",  tools: ["*"], // ===== 允许所有工具 =====  source: "built-in",  baseDir: "built-in",// model 留空 - 使用 getDefaultSubagentModel()  getSystemPrompt: getGeneralPurposeSystemPrompt,};

关键特性:

特性
说明
工具权限 tools: ['*']

 – 允许使用所有工具 (受三层过滤限制)
模型策略
不指定 model,使用默认子代理模型
核心职责
复杂研究、多文件分析、多步骤任务
行为准则
不创建不必要的文件,不主动创建文档
输出格式
简洁报告,覆盖完成的工作和关键发现

3.2 Explore Agent

// 文件路径: src/tools/AgentTool/built-in/exploreAgent.ts// 行号: 13-84functiongetExploreSystemPrompt(): string{const embedded = hasEmbeddedSearchTools();const globGuidance = embedded    ? `- Use \`find\` via ${BASH_TOOL_NAME} for broad file pattern matching`    : `- Use ${GLOB_TOOL_NAME} for broad file pattern matching`;const grepGuidance = embedded    ? `- Use \`grep\` via ${BASH_TOOL_NAME} for searching file contents`    : `- Use ${GREP_TOOL_NAME} for searching file contents`;return `You are a file search specialist for Claude Code...=== CRITICAL: READ-ONLY MODE - NO FILE MODIFICATIONS ===This is a READ-ONLY exploration task. You are STRICTLY PROHIBITED from:- Creating new files (no Write, touch, or file creation of any kind)- Modifying existing files (no Edit operations)- Deleting files (no rm or deletion)- Running ANY commands that change system stateYour strengths:- Rapidly finding files using glob patterns- Searching code and text with powerful regex patterns- Reading and analyzing file contentsGuidelines:${globGuidance}${grepGuidance}- Use ${FILE_READ_TOOL_NAME} when you know the specific file path- NEVER use ${BASH_TOOL_NAME} for: mkdir, touch, rm, cp, mv, npm install...NOTE: You are meant to be a fast agent that returns output as quickly as possible.- Make efficient use of tools- Spawn multiple parallel tool calls for grepping and reading files`;}export const EXPLORE_AGENT: BuiltInAgentDefinition = {  agentType: "Explore",  whenToUse: "Fast agent specialized for exploring codebases...",  disallowedTools: [    AGENT_TOOL_NAME, // ===== 禁止嵌套 Agent =====    EXIT_PLAN_MODE_TOOL_NAME, // ===== 禁止退出计划模式 =====    FILE_EDIT_TOOL_NAME, // ===== 禁止文件编辑 =====    FILE_WRITE_TOOL_NAME, // ===== 禁止文件写入 =====    NOTEBOOK_EDIT_TOOL_NAME, // ===== 禁止 Notebook 编辑 =====  ],  source: "built-in",  baseDir: "built-in",  model: process.env.USER_TYPE === "ant" ? "inherit" : "haiku"// ===== 外部用户使用 haiku =====  omitClaudeMd: true// ===== 省略 CLAUDE.md =====  getSystemPrompt: () => getExploreSystemPrompt(),};

关键特性:

特性
说明
只读模式
禁止所有文件修改操作 (Write, Edit, Delete)
禁止嵌套
禁止 Agent 工具,防止递归子代理
模型策略
Ant 用户继承父模型,外部用户使用 Haiku (更快、更便宜)
Token 优化 omitClaudeMd: true

 省略 CLAUDE.md,节省 5-15 Gtok/周
并行执行
系统提示鼓励并行工具调用以提高效率
搜索工具适配
根据 hasEmbeddedSearchTools() 调整搜索策略

3.3 Plan Agent

// 文件路径: src/tools/AgentTool/built-in/planAgent.ts// 行号: 14-93functiongetPlanV2SystemPrompt(): string{return `You are a software architect and planning specialist for Claude Code.Your role is to explore the codebase and design implementation plans.=== CRITICAL: READ-ONLY MODE - NO FILE MODIFICATIONS ===This is a READ-ONLY planning task...## Your Process1. **Understand Requirements**: Focus on the requirements provided...2. **Explore Thoroughly**:   - Read any files provided to you in the initial prompt   - Find existing patterns and conventions using ${searchToolsHint}   - Understand the current architecture   - Identify similar features as reference3. **Design Solution**:   - Create implementation approach based on your assigned perspective   - Consider trade-offs and architectural decisions4. **Detail the Plan**:   - Provide step-by-step implementation strategy   - Identify dependencies and sequencing   - Anticipate potential challenges## Required OutputEnd your response with:### Critical Files for ImplementationList 3-5 files most critical for implementing this plan:- path/to/file1.ts- path/to/file2.ts`;export const PLAN_AGENT: BuiltInAgentDefinition = {  agentType: 'Plan',  whenToUse: 'Software architect agent for designing implementation plans...',  disallowedTools: [    AGENT_TOOL_NAME,    EXIT_PLAN_MODE_TOOL_NAME,    FILE_EDIT_TOOL_NAME,    FILE_WRITE_TOOL_NAME,    NOTEBOOK_EDIT_TOOL_NAME,  ],  source: 'built-in',  tools: EXPLORE_AGENT.tools,  // ===== 继承 Explore Agent 的工具配置 =====  baseDir: 'built-in',  model: 'inherit',            // ===== 继承父模型 =====  omitClaudeMd: true,  getSystemPrompt: () => getPlanV2SystemPrompt(),};

关键特性:

特性
说明
架构规划
专注于实现计划设计,不执行实际修改
工具继承 tools: EXPLORE_AGENT.tools

 继承 Explore 的工具配置
模型策略 model: 'inherit'

 继承父代理模型
结构化输出
强制输出包含 “Critical Files for Implementation” 部分
过程导向
明确的四步流程:理解 → 探索 → 设计 → 详细计划

3.4 Fork Agent

// 文件路径: src/tools/AgentTool/forkSubagent.ts// 行号: 32-72/** * Fork subagent feature gate. * When enabled: * - `subagent_type` becomes optional on the Agent tool schema * - Omitting `subagent_type` triggers an implicit fork * - All agent spawns run in the background (async) * - `/fork <directive>` slash command is available */export functionisForkSubagentEnabled(): boolean{if (feature("FORK_SUBAGENT")) {if (isCoordinatorMode()) return false// ===== 与 coordinator 模式互斥 =====if (getIsNonInteractiveSession()) return false;return true;  }return false;}export const FORK_AGENT = {  agentType: FORK_SUBAGENT_TYPE, // 'fork'  whenToUse: "Implicit fork — inherits full conversation context...",  tools: ["*"],  maxTurns: 200,  model: "inherit"// ===== 继承父模型 (context length parity) =====  permissionMode: "bubble"// ===== 权限提示上浮到父终端 =====  source: "built-in",  baseDir: "built-in",  getSystemPrompt: () => ""// ===== 未使用:通过 override.systemPrompt 传递 =====} satisfies BuiltInAgentDefinition;/** * Guard against recursive forking. * Fork children keep the Agent tool in their pool for cache-identical tool defs. */export functionisInForkChild(messages: MessageType[]): boolean{return messages.some((m) => {if (m.type !== "user"return false;return m.message.content.some((block) =>        block.type === "text" &&        block.text.includes(`<${FORK_BOILERPLATE_TAG}>`),    );  });}

关键特性:

特性
说明
隐式触发
省略 subagent_type 时自动触发
Prompt Cache 共享
继承父 Agent 的 system prompt 实现字节级缓存共享
权限上浮 permissionMode: 'bubble'

 将权限提示发送到父终端
模型继承
保持与父 Agent 相同的模型以维持 context length
递归守卫
通过 isInForkChild 检测 fork boilerplate 防止嵌套
与 Coordinator 互斥
Coordinator 模式下 Fork 功能禁用

3.5 工具过滤机制

// 文件路径: src/tools/AgentTool/agentToolUtils.ts// 行号: 70-116export functionfilterToolsForAgent({  tools,  isBuiltIn,  isAsync = false,  permissionMode,}: FilterParams): Tools{return tools.filter((tool) => {// ===== Layer 1: MCP 工具豁免 =====if (tool.name.startsWith("mcp__")) {return true// 所有 Agent 都可以使用 MCP 工具    }// ===== Layer 2: Plan Mode ExitPlanMode 豁免 =====if (      toolMatchesName(tool, EXIT_PLAN_MODE_V2_TOOL_NAME) &&      permissionMode === "plan"    ) {return true// Plan mode Agent 可以退出计划模式    }// ===== Layer 3: 全局禁止工具 =====if (ALL_AGENT_DISALLOWED_TOOLS.has(tool.name)) {return false// TaskOutput, ExitPlanMode, AskUserQuestion 等禁止    }// ===== Layer 4: 自定义 Agent 禁止工具 =====if (!isBuiltIn && CUSTOM_AGENT_DISALLOWED_TOOLS.has(tool.name)) {return false// 自定义 Agent 有额外的工具限制    }// ===== Layer 5: 异步 Agent 工具限制 =====if (isAsync && !ASYNC_AGENT_ALLOWED_TOOLS.has(tool.name)) {// In-process teammates 有额外豁免if (isAgentSwarmsEnabled() && isInProcessTeammate()) {if (toolMatchesName(tool, AGENT_TOOL_NAME)) return true;if (IN_PROCESS_TEAMMATE_ALLOWED_TOOLS.has(tool.name)) return true;      }return false;    }return true;  });}

三层过滤架构解析:

┌─────────────────────────────────────────────────────────────────┐│  Layer 1: MCP 工具豁免                                           ││  → 所有 Agent 都可以使用 MCP 工具 (mcp__ 前缀)                    │├─────────────────────────────────────────────────────────────────┤│  Layer 2: 全局禁止工具 (ALL_AGENT_DISALLOWED_TOOLS)              ││  → TaskOutput, ExitPlanMode, AskUserQuestion, TaskStop          ││  → Agent (外部用户), Workflow                                    │├─────────────────────────────────────────────────────────────────┤│  Layer 3: 自定义 Agent 禁止工具 (CUSTOM_AGENT_DISALLOWED_TOOLS)  ││  → 继承 Layer 2 的所有工具                                       │├─────────────────────────────────────────────────────────────────┤│  Layer 4: Agent 特定配置 (tools / disallowedTools)               ││  → tools: ['*'] 或 tools: ['Bash''Read']                       ││  → disallowedTools: ['Agent''FileEdit']                        │├─────────────────────────────────────────────────────────────────┤│  Layer 5: 异步 Agent 工具限制 (ASYNC_AGENT_ALLOWED_TOOLS)        ││  → Read, Grep, Glob, Bash, Edit, Write 等基础工具                ││  → In-process teammates 有额外豁免                               │└─────────────────────────────────────────────────────────────────┘

4. 核心特殊机制深度剖析 (Deep Dive Mechanism)

4.1 Fork Subagent 的 Prompt Cache 共享机制

Fork Subagent 是 Agent 系统中最精巧的设计之一,其核心目标是实现 Prompt Cache 共享 —— 让多个子 Agent 能够共享父 Agent 的 API 请求前缀,从而大幅减少 token 消耗。

4.1.1 前置条件

  1. Feature Gate 开启feature('FORK_SUBAGENT') 返回 true
  2. 非 Coordinator 模式isCoordinatorMode() 返回 false
  3. 非非交互会话getIsNonInteractiveSession() 返回 false
  4. 省略 subagent_type:调用 Agent 工具时不指定 subagent_type

4.1.2 构建过程

// 文件路径: src/tools/AgentTool/forkSubagent.ts// 行号: 107-169/** * Build the forked conversation messages for the child agent. * * For prompt cache sharing, all fork children must produce byte-identical * API request prefixes. This function: * 1. Keeps the full parent assistant message (all tool_use blocks, thinking, text) * 2. Builds a single user message with tool_results for every tool_use block *    using an identical placeholder, then appends a per-child directive text block */export functionbuildForkedMessages(  directive: string,  assistantMessage: AssistantMessage,): MessageType[] {// ===== Step 1: 克隆父 Assistant 消息 (保持所有 content blocks) =====const fullAssistantMessage: AssistantMessage = {    ...assistantMessage,    uuid: randomUUID(),    message: {      ...assistantMessage.message,      content: [...assistantMessage.message.content], // 浅拷贝所有 blocks    },  };// ===== Step 2: 收集所有 tool_use blocks =====const toolUseBlocks = assistantMessage.message.content.filter(    (block): block is BetaToolUseBlock => block.type === "tool_use",  );if (toolUseBlocks.length === 0) {// 无 tool_use 时,直接返回指令消息return [      createUserMessage({        content: [{ type"text", text: buildChildMessage(directive) }],      }),    ];  }// ===== Step 3: 构建占位符 tool_results (所有使用相同文本) =====const FORK_PLACEHOLDER_RESULT = "Fork started — processing in background";const toolResultBlocks = toolUseBlocks.map((block) => ({type"tool_result" as const,    tool_use_id: block.id,    content: [{ type"text" as const, text: FORK_PLACEHOLDER_RESULT }],  }));// ===== Step 4: 构建用户消息 (占位符 results + 子 Agent 指令) =====const toolResultMessage = createUserMessage({    content: [      ...toolResultBlocks,      { type"text" as const, text: buildChildMessage(directive) },    ],  });// ===== Result: [assistant(all_tool_uses), user(placeholder_results..., directive)] =====return [fullAssistantMessage, toolResultMessage];}/** * 子 Agent 指令构建 - 包含严格的执行规则 */export functionbuildChildMessage(directive: string): string{return `<${FORK_BOILERPLATE_TAG}>STOP. READ THIS FIRST.You are a forked worker process. You are NOT the main agent.RULES (non-negotiable):1. Your system prompt says "default to forking." IGNORE IT — that's for the parent.2. Do NOT converse, ask questions, or suggest next steps3. USE your tools directly: Bash, Read, Write, etc.4. If you modify files, commit your changes before reporting5. Keep your report under 500 wordsOutput format:  Scope: <echo back your assigned scope>  Result: <the answer or key findings>  Key files: <relevant file paths>  Files changed: <list with commit hash></${FORK_BOILERPLATE_TAG}>${FORK_DIRECTIVE_PREFIX}${directive}`;}

4.1.3 特定模板和数据结构

CacheSafeParams 类型

// 文件路径: src/utils/forkedAgent.ts// 行号: 56-68/** * Parameters that must be identical between the fork and parent API requests * to share the parent's prompt cache. The Anthropic API cache key is composed of: * system prompt, tools, model, messages (prefix), and thinking config. */exporttype CacheSafeParams = {  systemPrompt: SystemPrompt; // 系统提示 - 必须匹配父级  userContext: { [k: string]: string }; // 用户上下文  systemContext: { [k: string]: string }; // 系统上下文  toolUseContext: ToolUseContext; // 工具上下文 (包含 tools, model)  forkContextMessages: Message[]; // Fork 上下文消息};

关键设计决策解析:

  1. 占位符统一:所有 fork children 使用相同的 FORK_PLACEHOLDER_RESULT 文本,只有最后的 directive 不同

  2. 字节级匹配:通过继承父级的 systemPrompttoolsmodel 确保 API 请求前缀字节级一致

  3. thinking config 继承:通过 useExactTools 传递 toolUseContext.options.thinkingConfig,因为 thinking 配置也是 cache key 的一部分

  4. 递归守卫<FORK_BOILERPLATE_TAG> 标记防止在 fork child 中再次 fork


5. 生命周期与资源管理 (Lifecycle)

5.1 Agent 初始化阶段

Agent 的初始化阶段涉及多个资源的分配和配置:

// 文件路径: src/tools/AgentTool/runAgent.ts// 初始化阶段核心步骤汇总// ===== 1. Agent ID 生成 =====const agentId = override?.agentId ?? createAgentId();// ===== 2. 模型解析 =====const resolvedAgentModel = getAgentModel(agentDefinition.model, ...);// ===== 3. 文件状态缓存创建 =====const agentReadFileState = forkContextMessages !== undefined  ? cloneFileStateCache(toolUseContext.readFileState)  // Fork: 克隆父级缓存  : createFileStateCacheWithSizeLimit(READ_FILE_STATE_CACHE_SIZE);  // 新建缓存// ===== 4. AbortController 配置 =====const agentAbortController = override?.abortController  ?? (isAsync ? new AbortController() : toolUseContext.abortController);// ===== 5. MCP Servers 初始化 =====const { clients: mergedMcpClients, tools: agentMcpTools, cleanup: mcpCleanup } =await initializeAgentMcpServers(agentDefinition, toolUseContext.options.mcpClients);// ===== 6. Subagent Context 创建 =====const agentToolUseContext = createSubagentContext(toolUseContext, {  options: agentOptions,  agentId,  agentType: agentDefinition.agentType,  messages: initialMessages,  readFileState: agentReadFileState,  abortController: agentAbortController,  getAppState: agentGetAppState,  shareSetAppState: !isAsync,  shareSetResponseLength: true,});

分配的资源清单:

资源类型
分配方式
说明
Agent ID createAgentId()
UUID 格式,用于追踪和日志
文件状态缓存 createFileStateCacheWithSizeLimit()
有大小限制的 LRU 缓存
AbortController new AbortController()

 (异步) 或继承 (同步)
控制执行终止
MCP Clients initializeAgentMcpServers()
Agent 特定的 MCP 服务器连接
Subagent Context createSubagentContext()
隔离的执行上下文
Hooks 注册 registerFrontmatterHooks()
Session-scoped hooks
Transcript 目录 setAgentTranscriptSubdir()
侧链 transcript 存储路径

5.2 Agent 清理阶段

清理阶段在 finally 块中执行,确保所有资源被正确释放:

// 文件路径: src/tools/AgentTool/runAgent.ts// 行号: 817-858finally {// ===== 1. MCP Servers 清理 =====await mcpCleanup();// 只清理 inline 定义的服务器,引用的服务器保持连接// ===== 2. Session Hooks 清理 =====if (agentDefinition.hooks) {    clearSessionHooks(rootSetAppState, agentId);  }// ===== 3. Prompt Cache Tracking 清理 =====if (feature('PROMPT_CACHE_BREAK_DETECTION')) {    cleanupAgentTracking(agentId);  }// ===== 4. 文件状态缓存释放 =====  agentToolUseContext.readFileState.clear();// ===== 5. Fork Context Messages 释放 =====  initialMessages.length = 0;// ===== 6. Perfetto Agent Registry 清理 =====  unregisterPerfettoAgent(agentId);// ===== 7. Transcript Subdir 映射清理 =====  clearAgentTranscriptSubdir(agentId);// ===== 8. Todos 清理 =====  rootSetAppState(prev => {if (!(agentId in prev.todos)) return prev;const { [agentId]: _removed, ...todos } = prev.todos;return { ...prev, todos };  });// 防止 whale sessions 中 hundreds of agents 留下 orphaned keys// ===== 9. Shell Tasks 清理 =====  killShellTasksForAgent(agentId, toolUseContext.getAppState, rootSetAppState);// 防止 run_in_background shell loops 成为 PPID=1 zombie// ===== 10. Monitor MCP Tasks 清理 =====if (feature('MONITOR_TOOL')) {    mcpMod.killMonitorMcpTasksForAgent(agentId, ...);  }}

防内存泄漏要点:

  1. MCP Cleanup 区分:只清理 inline 定义的服务器,引用的服务器通过 memoization 共享

  2. Todos 清理:防止每个 subagent 的 todos key 成为永久性 leak

  3. Shell Tasks:后台 shell 任务必须在 Agent 结束时终止,否则会成为 zombie 进程

  4. 消息数组清空initialMessages.length = 0 释放内存引用


6. 关键设计模式与架构权衡 (Design Patterns & Trade-offs)

6.1 权限隔离模式

Agent 系统实现了严格的权限隔离,确保子 Agent 的操作不会超出预期范围:

// 文件路径: src/utils/forkedAgent.ts// 行号: 345-462export functioncreateSubagentContext(  parentContext: ToolUseContext,  overrides?: SubagentContextOverrides,): ToolUseContext{// ===== 1. AbortController 隔离 =====const abortController =    overrides?.abortController ??    (overrides?.shareAbortController      ? parentContext.abortController      : createChildAbortController(parentContext.abortController));// 默认创建子 controller,父级 abort 会传播但子级独立// ===== 2. getAppState 包装 =====const getAppState: ToolUseContext["getAppState"] = overrides?.getAppState    ? overrides.getAppState    : overrides?.shareAbortController      ? parentContext.getAppState      : () => {const state = parentContext.getAppState();if (state.toolPermissionContext.shouldAvoidPermissionPrompts) {return state;          }return {            ...state,            toolPermissionContext: {              ...state.toolPermissionContext,              shouldAvoidPermissionPrompts: true// ===== 设置避免权限提示标志 =====            },          };        };return {// ===== 3. Mutable State 克隆 =====    readFileState: cloneFileStateCache(      overrides?.readFileState ?? parentContext.readFileState,    ),    nestedMemoryAttachmentTriggers: new Set<string>(), // ===== 新建集合 =====    loadedNestedMemoryPaths: new Set<string>(),    dynamicSkillDirTriggers: new Set<string>(),    discoveredSkillNames: new Set<string>(),    toolDecisions: undefined,// ===== 4. Content Replacement State 克隆 =====    contentReplacementState:      overrides?.contentReplacementState ??      (parentContext.contentReplacementState        ? cloneContentReplacementState(parentContext.contentReplacementState)        : undefined),// ===== 5. Mutation Callbacks 默认 no-op =====    setAppState: overrides?.shareSetAppState      ? parentContext.setAppState      : () => {},    setInProgressToolUseIDs: () => {},    setResponseLength: overrides?.shareSetResponseLength      ? parentContext.setResponseLength      : () => {},    updateFileHistoryState: () => {},    addNotification: undefined// ===== 子 Agent 无法控制父级 UI =====    setToolJSX: undefined,    setStreamMode: undefined,// ===== 6. 新的 Query Tracking Chain =====    queryTracking: {      chainId: randomUUID(),      depth: (parentContext.queryTracking?.depth ?? -1) + 1,    },  };}

Trade-off 分析:

方案
优点
缺点
采用情况
完全隔离
安全性高,无干扰
无法共享进度、状态
异步 Agent
共享 AppState
可以更新共享状态
可能产生竞争
同步 Agent
Bubble Mode
权限提示可见
需要 UI 交互
Fork children

6.2 Prompt Cache 共享策略

Fork Subagent 的设计是为了最大化 Prompt Cache 命中率:

Cache Key 组成:

API Cache Key = {  system_prompt: string,  tools: Tool[],  model: string,  messages_prefix: Message[],  thinking_config: { type, budget_tokens }}

关键设计决策:

  1. System Prompt 继承:Fork child 使用父级的 renderedSystemPrompt 而非重新生成,避免 GrowthBook cold→warm 状态变化导致的 divergence

  2. 工具池精确匹配:通过 useExactTools 标志传递父级的完整工具池,而非经过 resolveAgentTools 过滤

  3. Thinking Config 继承:Fork children 继承父级的 thinkingConfig,因为 budget_tokens 也是 cache key

  4. 占位符统一:所有 fork children 的 tool_result 使用相同的 placeholder 文本

Trade-off:

  • 优点:大幅减少 token 消耗,多个 fork children 共享同一个 cache prefix
  • 缺点:fork children 无法有定制化的 system prompt 或工具集

6.3 工具池组装策略

Agent 的工具池经过精心设计的组装流程:

// 文件路径: src/tools.ts (核心工具组装)// 工具池组装的完整流程// ===== Step 1: 获取基础工具 =====export functiongetAllBaseTools(): Tools{return [    AgentTool,    BashTool,    ReadTool,// ... other built-in tools    ...cronTools,    ...(isAgentSwarmsEnabled()      ? [getTeamCreateTool(), getTeamDeleteTool()]      : []),  ];}// ===== Step 2: 组装工具池 =====export functionassembleToolPool(  permissionContext: ToolPermissionContext,  mcpTools: Tools,): Tools{// 获取内置工具const builtInTools = getTools(permissionContext);// 合并 MCP 工具const allTools = [...builtInTools, ...mcpTools];// 应用 deny rulesreturn filterToolsByDenyRules(allTools, permissionContext);}// ===== Step 3: Agent 特定过滤 =====// 在 runAgent.ts 中调用const resolvedTools = useExactTools  ? availableTools // Fork: 直接使用父级工具池  : resolveAgentTools(agentDefinition, availableTools, isAsync).resolvedTools;// resolveAgentTools 内部调用 filterToolsForAgentconst filteredAvailableTools = isMainThread  ? availableTools  : filterToolsForAgent({      tools: availableTools,      isBuiltIn: source === "built-in",      isAsync,      permissionMode,    });

组装流程图:

getAllBaseTools() → getTools(permissionContext) → assembleToolPool()    │                      │                            │    │                      │                            ├─ 合并 MCP tools    │                      │                            ├─ 应用 deny rules    │                      │                            └─ Deduplication    │                      │                            │    └──────────────────────┴────────────────────────────┘                              │                              ↓                      availableTools (传递给 runAgent)                              │                              ↓                      resolveAgentTools()                              │                              ├─ filterToolsForAgent() (三层过滤)                              ├─ 应用 agent.disallowedTools                              ├─ 应用 agent.tools whitelist                              │                              ↓                      resolvedTools (Agent 可用工具池)

6.4 异步执行模式

Agent 支持同步和异步两种执行模式:

同步模式:

  • Agent 在主线程执行,共享父级的 AbortController
  • 可以实时 yield 消息给调用方
  • shareSetAppState: true 可以更新共享状态

异步模式:

  • Agent 在后台执行,使用独立的 AbortController
  • 通过 runAsyncAgentLifecycle 管理
  • 通过 enqueueAgentNotification 通知完成
  • shouldAvoidPermissionPrompts: true 自动拒绝权限提示
// 文件路径: src/tools/AgentTool/agentToolUtils.ts// 行号: 508-686export async functionrunAsyncAgentLifecycle({  taskId,  abortController,  makeStream,  metadata,  description,  toolUseContext,  rootSetAppState,  agentIdForCleanup,  enableSummarization,}: AsyncAgentParams): Promise<void{let stopSummarization: (() => void) | undefined;constagentMessagesMessageType[] = [];try {consttracker = createProgressTracker();constonCacheSafeParams = enableSummarization      ? (params: CacheSafeParams) => {const { stop } = startAgentSummarization(taskId, ...);          stopSummarization = stop;        }      : undefined;// ===== 执行 stream =====for await (const message of makeStream(onCacheSafeParams)) {      agentMessages.push(message);// ===== 实时更新 UI (如果 retain) =====      rootSetAppState(prev => {const t = prev.tasks[taskId];if (!isLocalAgentTask(t) || !t.retain) return prev;return {          ...prev,          tasks: { ...prev.tasks, [taskId]: { ...t, messages: [...base, message] } },        };      });// ===== 更新进度 =====      updateProgressFromMessage(tracker, message, ...);      updateAsyncAgentProgress(taskId, getProgressUpdate(tracker), rootSetAppState);    }// ===== 完成 =====const agentResult = finalizeAgentTool(agentMessages, taskId, metadata);    completeAsyncAgent(agentResult, rootSetAppState);// ===== Classifier handoff =====if (feature('TRANSCRIPT_CLASSIFIER')) {const handoffWarning = await classifyHandoffIfNeeded(...);if (handoffWarning) finalMessage = `${handoffWarning}\n\n${finalMessage}`;    }// ===== 通知 =====    enqueueAgentNotification({      taskId,      description,      status: 'completed',      finalMessage,      usage: { totalTokens, toolUses, durationMs },    });  } catch (error) {if (error instanceof AbortError) {// ===== 用户终止 =====      killAsyncAgent(taskId, rootSetAppState);const partialResult = extractPartialResult(agentMessages);      enqueueAgentNotification({ status: 'killed', finalMessage: partialResult });    } else {// ===== 错误 =====      failAsyncAgent(taskId, errorMessage(error), rootSetAppState);      enqueueAgentNotification({ status: 'failed', error: errorMessage(error) });    }  } finally {    clearInvokedSkillsForAgent(agentIdForCleanup);    clearDumpState(agentIdForCleanup);  }}

7. 总结与相关文件索引 (Summary & File Index)

7.1 关键文件索引表

文件路径
功能描述
核心类型/函数
src/tools/AgentTool/AgentTool.tsx
Agent 工具入口定义
AgentTool

inputSchemaoutputSchema
src/tools/AgentTool/runAgent.ts
Agent 执行引擎
runAgent()

 AsyncGenerator
src/tools/AgentTool/loadAgentsDir.ts
Agent 定义类型系统
AgentDefinition

BaseAgentDefinition
src/tools/AgentTool/agentToolUtils.ts
工具解析和生命周期辅助
resolveAgentTools()

filterToolsForAgent()
src/tools/AgentTool/forkSubagent.ts
Fork 子 Agent 机制
buildForkedMessages()

FORK_AGENT
src/tools/AgentTool/built-in/generalPurposeAgent.ts
全功能 Agent 定义
GENERAL_PURPOSE_AGENT
src/tools/AgentTool/built-in/exploreAgent.ts
探索 Agent 定义
EXPLORE_AGENT
src/tools/AgentTool/built-in/planAgent.ts
规划 Agent 定义
PLAN_AGENT
src/tools/AgentTool/builtInAgents.ts
内置 Agent 注册表
getBuiltInAgents()
src/tools/AgentTool/constants.ts
常量定义
AGENT_TOOL_NAME

ONE_SHOT_BUILTIN_AGENT_TYPES
src/utils/forkedAgent.ts
Forked agent 执行和上下文创建
createSubagentContext()

runForkedAgent()
src/constants/tools.ts
工具权限常量
ALL_AGENT_DISALLOWED_TOOLS

ASYNC_AGENT_ALLOWED_TOOLS
src/tasks/LocalAgentTask/LocalAgentTask.tsx
Agent 任务状态管理
LocalAgentTaskState

registerAsyncAgent()
src/utils/model/agent.ts
Agent 模型配置
getAgentModel()

AgentModelAlias
src/tools.ts
核心工具组装
assembleToolPool()

getAllBaseTools()

7.2 核心设计哲学总结

Agent 系统的设计哲学可以概括为 “隔离、高效、可控” 三个核心原则:

  1. 隔离性:每个子 Agent 都有独立的执行上下文、文件状态缓存和 AbortController,防止对父级状态的意外干扰。三层工具过滤架构确保子 Agent 的操作不会超出预期范围。

  2. 高效性:Fork Subagent 机制通过继承父级的 system prompt、工具池和 thinking config,实现了 Prompt Cache 共享,大幅减少 API token 消耗。omitClaudeMd 优化为只读 Agent 节省约 5-15 Gtok/周。

  3. 可控性:完整的生命周期管理,从初始化阶段分配 MCP servers、hooks、transcript 目录,到清理阶段释放所有资源,防止内存泄漏和 zombie 进程。异步 Agent 的 shouldAvoidPermissionPrompts 标志确保无法弹出 UI,避免阻塞主线程。

Agent 系统不仅是 Claude Code 中任务委托的基础设施,更体现了在 AI Agent 架构中如何平衡 灵活性 与 安全性效率 与 可观测性 的设计智慧。