Claude Code源码系列:4、3-关键功能模块-Agent系统
本文对 Claude Code 项目中的 Agent 系统进行庖丁解牛式的源码拆解,揭示其核心架构、执行流程、权限隔离机制以及 Prompt Cache 共享策略。
1. 概述与核心架构 (Overview)
1.1 一句话定义
Agent 系统是 Claude Code 中用于创建、管理和执行子代理 (Subagent) 的核心基础设施,它允许主代理将复杂任务委托给具有特定工具权限、系统提示和执行上下文的子代理来完成。
1.2 核心组件清单
Agent 系统由以下核心组件构成:
-
AgentDefinition– Agent 定义类型系统,描述 Agent 的类型、工具权限、系统提示等元数据 -
AgentTool– 工具入口,定义 Agent 工具的 schema 和调用逻辑 -
runAgent– 执行引擎,核心的AsyncGenerator函数,驱动 Agent 的 query 循环 -
resolveAgentTools– 工具解析器,根据 Agent 定义过滤和组装可用工具池 -
createSubagentContext– 上下文隔离器,创建子 Agent 的独立执行上下文 -
filterToolsForAgent– 工具过滤器,实现三层权限控制架构 -
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;
核心执行流解析:
-
类型分层设计:
BaseAgentDefinition作为基础层,定义所有 Agent 共享的字段;三种派生类型分别处理内置、自定义和插件场景 -
source字段的作用:标识 Agent 的来源,用于权限判断(如isSourceAdminTrusted检查) -
getSystemPrompt的两种形态: -
内置 Agent 使用动态生成函数,接收 toolUseContext参数 -
自定义/插件 Agent 使用静态闭包函数 -
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) {// 核心调用逻辑 (详见下文) },});
核心执行流解析:
-
Schema 懒加载:使用
lazySchema避免模块加载时的循环依赖问题 -
多状态输出:输出 schema 包含
completed(同步完成)和async_launched(后台启动)两种状态 -
别名兼容:保留
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.`); } }// ... 后续执行逻辑}
核心执行流解析:
-
路由优先级:Teammate spawn > Fork path > 常规 Agent
-
Fork 守卫机制:通过
querySource和isInForkChild双重检查防止递归 fork -
权限过滤链:
allowedAgentTypes→filterDeniedAgents→ 最终可用 Agent 列表 -
MCP 等待机制:对于 pending 状态的必需 MCP 服务器,最多等待 30 秒
2.4 runAgent 执行引擎
runAgent 是 Agent 执行的核心引擎,是一个 AsyncGenerator 函数。
// 文件路径: src/tools/AgentTool/runAgent.ts// 行号: 248-860export async function* runAgent({ agentDefinition, promptMessages, toolUseContext, canUseTool, isAsync, canShowPermissionPrompts, forkContextMessages, querySource, override, model, maxTurns, availableTools, allowedTools,// ... 其他参数}: RunAgentParams): AsyncGenerator<Message, void> {// ===== 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, ...); }}
核心执行流解析:
-
初始化阶段 (Steps 1-14):完整的 Agent 上下文构建,包括 ID、模型、消息、权限、工具、MCP、hooks 等
-
Query 循环 (Step 15):调用核心
query()函数,yield 消息给调用方 -
清理阶段 (Step 17):finally 块确保所有资源被正确释放
-
关键设计决策:
-
异步 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: ['*']
|
| 模型策略 |
|
| 核心职责 |
|
| 行为准则 |
|
| 输出格式 |
|
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(),};
关键特性:
|
|
|
|---|---|
| 只读模式 |
|
| 禁止嵌套 |
Agent 工具,防止递归子代理 |
| 模型策略 |
|
| Token 优化 | omitClaudeMd: true
|
| 并行执行 |
|
| 搜索工具适配 |
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
|
| 模型策略 | model: 'inherit'
|
| 结构化输出 |
|
| 过程导向 |
|
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 共享 |
|
| 权限上浮 | permissionMode: 'bubble'
|
| 模型继承 |
|
| 递归守卫 |
isInForkChild 检测 fork boilerplate 防止嵌套 |
| 与 Coordinator 互斥 |
|
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 前置条件
-
Feature Gate 开启: feature('FORK_SUBAGENT')返回 true -
非 Coordinator 模式: isCoordinatorMode()返回 false -
非非交互会话: getIsNonInteractiveSession()返回 false -
省略 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 上下文消息};
关键设计决策解析:
-
占位符统一:所有 fork children 使用相同的
FORK_PLACEHOLDER_RESULT文本,只有最后的 directive 不同 -
字节级匹配:通过继承父级的
systemPrompt、tools、model确保 API 请求前缀字节级一致 -
thinking config 继承:通过
useExactTools传递toolUseContext.options.thinkingConfig,因为 thinking 配置也是 cache key 的一部分 -
递归守卫:
<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() |
|
| 文件状态缓存 | createFileStateCacheWithSizeLimit() |
|
| AbortController | new AbortController()
|
|
| MCP Clients | initializeAgentMcpServers() |
|
| Subagent Context | createSubagentContext() |
|
| Hooks 注册 | registerFrontmatterHooks() |
|
| Transcript 目录 | setAgentTranscriptSubdir() |
|
5.2 Agent 清理阶段
清理阶段在 finally 块中执行,确保所有资源被正确释放:
// 文件路径: src/tools/AgentTool/runAgent.ts// 行号: 817-858} finally {// ===== 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, ...); }}
防内存泄漏要点:
-
MCP Cleanup 区分:只清理 inline 定义的服务器,引用的服务器通过 memoization 共享
-
Todos 清理:防止每个 subagent 的 todos key 成为永久性 leak
-
Shell Tasks:后台 shell 任务必须在 Agent 结束时终止,否则会成为 zombie 进程
-
消息数组清空:
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 分析:
|
|
|
|
|
|---|---|---|---|
| 完全隔离 |
|
|
|
| 共享 AppState |
|
|
|
| Bubble Mode |
|
|
|
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 }}
关键设计决策:
-
System Prompt 继承:Fork child 使用父级的
renderedSystemPrompt而非重新生成,避免 GrowthBook cold→warm 状态变化导致的 divergence -
工具池精确匹配:通过
useExactTools标志传递父级的完整工具池,而非经过resolveAgentTools过滤 -
Thinking Config 继承:Fork children 继承父级的
thinkingConfig,因为 budget_tokens 也是 cache key -
占位符统一:所有 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;constagentMessages: MessageType[] = [];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 |
|
AgentTool
inputSchema, outputSchema |
src/tools/AgentTool/runAgent.ts |
|
runAgent()
|
src/tools/AgentTool/loadAgentsDir.ts |
|
AgentDefinition
BaseAgentDefinition |
src/tools/AgentTool/agentToolUtils.ts |
|
resolveAgentTools()
filterToolsForAgent() |
src/tools/AgentTool/forkSubagent.ts |
|
buildForkedMessages()
FORK_AGENT |
src/tools/AgentTool/built-in/generalPurposeAgent.ts |
|
GENERAL_PURPOSE_AGENT |
src/tools/AgentTool/built-in/exploreAgent.ts |
|
EXPLORE_AGENT |
src/tools/AgentTool/built-in/planAgent.ts |
|
PLAN_AGENT |
src/tools/AgentTool/builtInAgents.ts |
|
getBuiltInAgents() |
src/tools/AgentTool/constants.ts |
|
AGENT_TOOL_NAME
ONE_SHOT_BUILTIN_AGENT_TYPES |
src/utils/forkedAgent.ts |
|
createSubagentContext()
runForkedAgent() |
src/constants/tools.ts |
|
ALL_AGENT_DISALLOWED_TOOLS
ASYNC_AGENT_ALLOWED_TOOLS |
src/tasks/LocalAgentTask/LocalAgentTask.tsx |
|
LocalAgentTaskState
registerAsyncAgent() |
src/utils/model/agent.ts |
|
getAgentModel()
AgentModelAlias |
src/tools.ts |
|
assembleToolPool()
getAllBaseTools() |
7.2 核心设计哲学总结
Agent 系统的设计哲学可以概括为 “隔离、高效、可控” 三个核心原则:
-
隔离性:每个子 Agent 都有独立的执行上下文、文件状态缓存和 AbortController,防止对父级状态的意外干扰。三层工具过滤架构确保子 Agent 的操作不会超出预期范围。
-
高效性:Fork Subagent 机制通过继承父级的 system prompt、工具池和 thinking config,实现了 Prompt Cache 共享,大幅减少 API token 消耗。
omitClaudeMd优化为只读 Agent 节省约 5-15 Gtok/周。 -
可控性:完整的生命周期管理,从初始化阶段分配 MCP servers、hooks、transcript 目录,到清理阶段释放所有资源,防止内存泄漏和 zombie 进程。异步 Agent 的
shouldAvoidPermissionPrompts标志确保无法弹出 UI,避免阻塞主线程。
Agent 系统不仅是 Claude Code 中任务委托的基础设施,更体现了在 AI Agent 架构中如何平衡 灵活性 与 安全性、效率 与 可观测性 的设计智慧。
夜雨聆风