Claude Code Agent 实现原理深度剖析

声明 :本文源码标注的文件路径均来自 src/src/ 目录,为 Claude Code v2.1.88 反编译后的 TypeScript 源码,供学习与研究参考。


一、引言:从一个工具到一整个 Agent 系统

Claude Code 是 Anthropic 官方的 CLI 编程助手,它不仅是一个增强版的 REPL(Read-Eval-Print Loop),更是一个完整的 Agent 系统------它能够自主规划、调用工具、记忆上下文,并在多轮交互中持续推进复杂任务。

理解 Claude Code 的 Agent 实现原理,本质上是理解以下几个核心子系统的设计哲学与工程实践:

  • Agent 核心循环:消息如何驱动一轮又一轮的推理与执行
  • Tool 系统:工具的定义、执行与并发控制
  • 多 Agent 编排:子 Agent 与协调者模式的实现
  • 记忆与上下文管理:如何在有限上下文窗口内维护长期知识
  • 安全与权限体系:如何在开放能力的同时保障系统安全
  • Hooks 扩展机制:如何让用户干预 Agent 的每一步行为

本文将逐一展开,结合源码文件路径,帮助你在阅读后能够自行深入对应模块继续研究。


二、整体架构:从入口到 Agent 核心循环

2.1 程序入口与初始化

Claude Code 的入口由 src/src/entrypoints/cli.tsx 统一分发,根据命令行参数路由到不同模式(普通对话、Agent SDK、后台任务等)。真正的全局初始化在 src/src/entrypoints/init.ts 中完成,依次完成配置加载、网络初始化、遥测注册与清理函数注册。

src/src/main.tsx 中,我们可以看到完整的启动流水线:

typescript 复制代码
// src/src/main.tsx(约第 50-80 行,简化摘录)
loadGrowthBookFeatureFlags();  // 特性开关(实验性功能)
loadModels();                  // 模型列表加载
loadPlugins();                 // 插件系统初始化
loadSkills();                  // 技能(Slash Commands)加载
loadAgents();                  // 自定义 Agent 定义加载
startMcpServers();             // MCP(Model Context Protocol)服务器启动
renderREPL();                  // 渲染主 REPL 界面

整个过程是同步串行的,每个步骤失败都会阻断后续流程,这与 Agent 系统对运行环境健壮性要求高的特点一致。

2.2 Agent 核心循环:query() 与 queryLoop()

源码文件src/src/query.ts

Agent 的核心是一个 while(true) 无限循环,由 query() 函数驱动。query() 是一个 AsyncGenerator,每次 yield 出一个流式事件(文本、思考过程、工具调用、工具结果等),直到遇到终止条件。

整个循环的状态机如下:

typescript 复制代码
// src/src/query.ts - State 类型定义(简化)
type State = {
  messages: Message[]           // 消息历史
  toolUseContext: ToolUseContext // 工具执行上下文
  autoCompactTracking: AutoCompactTrackingState | undefined // 自动压缩追踪
  maxOutputTokensRecoveryCount: number  // max_tokens 恢复计数
  turnCount: number             // 当前轮次
  transition: Continue | undefined  // 继续指令
  // ...
}

每轮迭代经过以下阶段:

vbnet 复制代码
构建请求
  └─ system prompt(静态缓存部分 + 动态部分)
  └─ messages(带 cache breakpoints)
  └─ tools(Schema 转换后)

调用 API(流式)
  └─ message_start → content_block_start → content_block_delta → message_stop

处理响应块
  ├─ text 块 → 展示给用户
  ├─ thinking 块 → 展示推理过程
  └─ tool_use 块 → 交给 StreamingToolExecutor 执行

后处理
  ├─ 自动压缩(auto-compact)当上下文接近窗口上限
  ├─ Token 预算检查
  ├─ Stop Hooks 执行
  └─ 记忆预取(memory prefetch)

2.3 API 流式处理与容错

源码文件src/src/services/api/claude.ts

Claude Code 默认使用 SSE(Server-Sent Events)流式调用 Anthropic API,逐事件(event-by-event)处理,灵活性极高。核心处理流程为:

typescript 复制代码
// src/src/query.ts - 流式事件分发(概念性伪代码)
for await (const event of stream) {
  switch (event.type) {
    case 'message_start':
      // 初始化消息元数据
      break
    case 'content_block_start':
      if (event.content_block.type === 'tool_use') {
        // 新工具调用开始,推入 StreamingToolExecutor
        streamingExecutor.addTool(event.content_block, assistantMessage)
      }
      break
    case 'content_block_delta':
      if (event.delta.type === 'thinking_block' || event.delta.type === 'text_delta') {
        // 实时 yield 显示
        yield event.delta
      }
      break
    case 'message_stop':
      // 消息接收完毕,处理所有工具结果
      for await (const result of streamingExecutor.getRemainingResults()) {
        yield result
      }
      break
  }
}

当流式传输失败时,系统会降级为非流式调用 (最多一次),但代价是单次输出上限降至 64K tokens。如果遇到 max_output_tokens 错误,系统会依次尝试以下恢复策略:

  1. collapse_drain_retry --- 尝试压缩上下文重试
  2. reactive_compact_retry --- 响应式压缩重试
  3. max_output_tokens_escalate --- 扩大 max_tokens
  4. max_output_tokens_recovery --- 最多重试 3 次
  5. token_budget_continuation --- 在 token 预算内继续
typescript 复制代码
// src/src/query.ts - 恢复链(Recovery Chain)
const recoveryChain = [
  collapse_drain_retry,
  reactive_compact_retry,
  max_output_tokens_escalate,
  max_output_tokens_recovery,
  stop_hook_blocking,
  token_budget_continuation
]

三、Tool 系统:Agent 的四肢

3.1 统一的 Tool 接口定义

源码文件src/src/Tool.ts

Claude Code 定义了一个严格的 Tool 接口,每个工具都通过 buildTool() 工厂函数构建。以下是核心接口结构:

typescript 复制代码
// src/src/Tool.ts - Tool 接口核心字段
type Tool<Input, Output, P> = {
  name: string                          // 唯一标识符
  inputSchema: Input                    // Zod Schema,参数校验

  call(
    args: z.infer<Input>,               // 解析后的参数
    context: ToolUseContext,            // 执行上下文(大量注入依赖)
    canUseTool: CanUseToolFn,          // 权限检查函数
    parentMessage: AssistantMessage,   // 父消息(用于推理链溯源)
    onProgress?: ToolCallProgress<P>   // 进度回调(支持长时间操作)
  ): Promise<ToolResult<Output>>

  description(input?, options?): Promise<string>   // 工具描述(给模型看)
  prompt(options?): Promise<string>                 // 使用说明(给系统 prompt 用)

  // 执行属性(影响并发调度)
  isConcurrencySafe(input?): boolean   // true = 可并行,false = 独占
  isReadOnly(input?): boolean          // 只读 = 不修改系统状态
  isDestructive?(input?): boolean       // 破坏性标记

  // 权限
  checkPermissions(input, context): Promise<PermissionResult>

  // UI 渲染(React 组件,返回 Ink 兼容节点)
  renderToolUseMessage?(input, options): React.ReactNode
  renderToolResultMessage?(content, progressMessages, options): React.ReactNode
  renderGroupedToolUse?(toolUses[], options): React.ReactNode | null
}

buildTool() 工厂函数使用 TOOL_DEFAULTS 填充所有可选字段:

typescript 复制代码
// src/src/Tool.ts - 工厂默认值
const TOOL_DEFAULTS = {
  isEnabled: () => true,
  isConcurrencySafe: (_input?) => false,  // 默认非并发安全
  isReadOnly: (_input?) => false,
  checkPermissions: () => Promise.resolve({ behavior: 'allow', updatedInput: input }),
  // ...
}
export function buildTool<D extends AnyToolDef>(def: D): BuiltTool<D>

3.2 ToolUseContext:工具的"神经中枢"

源码文件src/src/Tool.tsToolUseContext 类型定义)

ToolUseContext 是一个约 150+ 字段的巨大对象,在每次工具调用时注入,为工具提供了 Agent 运行时的几乎所有上下文信息:

typescript 复制代码
// src/src/Tool.ts - ToolUseContext 核心字段概览
type ToolUseContext = {
  // 工具相关
  options: {
    tools: Tools                      // 可用工具池
    commands: Command[]               // 可用 Slash Commands
    thinkingConfig: ThinkingConfig     // 思考配置
    mcpClients: McpClientMap          // MCP 客户端
  }

  // 中断与取消
  abortController: AbortController     // 用户可随时取消

  // 文件状态
  readFileState: FileStateCache       // 文件读取缓存(避免重复读)

  // 状态管理
  getAppState: () => AppState         // Zustand 全局状态读取
  setAppState: (updater) => void       // 状态更新

  // Agent 追踪
  agentId?: string                     // 当前 Agent ID(多 Agent 时有用)
  queryTracking?: QueryTracking       // 当前查询追踪信息

  // 上下文压缩状态
  contentReplacementState: ContentReplacementState

  // 权限上下文
  permissionContext: PermissionContext
  // ... 150+ 字段
}

这种设计使得工具无需自行获取这些信息------所有依赖都通过 context 注入,符合**依赖注入(DI)**的设计原则,极大提升了工具的可测试性和可组合性。

3.3 工具执行管道:权限 → Hooks → 调用 → 后处理

源码文件

  • src/src/services/tools/toolExecution.ts
  • src/src/services/tools/toolHooks.ts

一次工具调用的完整管道如下:

scss 复制代码
Zod 输入校验
  → tool.validateInput()
  → runPreToolUseHooks()       // 执行 PreToolUse 钩子(可修改输入或阻断)
  → resolveHookPermissionDecision()  // 合并 Hook 和权限系统决策
  → canUseTool()               // 最终权限检查
  → tool.call()                // 执行工具核心逻辑
  → runPostToolUseHooks()     // 执行 PostToolUse 钩子(可触发后续行为)
  → (若出错) runPostToolUseFailureHooks()
typescript 复制代码
// src/src/services/tools/toolExecution.ts - 工具执行管道核心
async function checkPermissionsAndCallTool(
  tool, toolUseID, input, toolUseContext,
  canUseTool, assistantMessage, messageId, requestId,
  mcpServerType, mcpServerBaseUrl, onToolProgress
): Promise<MessageUpdateLazy[]> {
  // Step 1: Zod 校验
  const parseResult = tool.inputSchema.safeParse(input)

  // Step 2: PreToolUse Hooks(可阻断)
  const preHookResults = await runPreToolUseHooks(tool, input, toolUseContext)

  // Step 3: 权限决策
  const permissionResult = await resolveHookPermissionDecision(preHookResults, canUseTool)

  // Step 4: 执行工具(支持长时间操作的进度回调)
  const result = await tool.call(parseResult.data, context, canUseTool, ...)

  // Step 5: PostToolUse Hooks
  await runPostToolUseHooks(tool, result, toolUseContext)

  return [{ message: toolResultMessage }]
}

⚠️ 关键设计 :工具的输入参数是在一个克隆的副本 上运行 tool.backfillObservableInput(),这样 Hooks 和权限检查不会意外修改原始参数,从而保护 Prompt Cache 的完整性。

3.4 并发控制:谁可以并行,谁必须串行

源码文件src/src/services/tools/StreamingToolExecutor.ts

这是整个工具系统中设计最精妙的部分之一。StreamingToolExecutor 维护了一个工具状态机:

typescript 复制代码
// src/src/services/tools/StreamingToolExecutor.ts - 工具状态机
type TrackedTool = {
  id: string
  block: ToolUseBlock
  status: 'queued' | 'executing' | 'completed' | 'yielded'
  isConcurrencySafe: boolean
  promise?: Promise<void>
  results?: Message[]
  pendingProgress: Message[]    // 立即 yield 的进度消息
  contextModifiers?: Array<(context: ToolUseContext) => ToolUseContext>
}

// 并发判断逻辑
canExecuteTool(isConcurrencySafe: boolean): boolean {
  const executingTools = this.tools.filter(t => t.status === 'executing')
  return executingTools.length === 0 ||
    (isConcurrencySafe && executingTools.every(t => t.isConcurrencySafe))
  // 即:队列空闲时任何工具可执行;或者执行中只有并发安全工具时,新的并发安全工具可加入
}

执行策略

  • 并发安全 的工具(如 ReadGlobGrep):最多 N 个同时执行(N 默认 10,可通过 CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY 配置)
  • 非并发安全 的工具(如 WriteBash):独占执行,形成"门锁"
  • 如果一个非并发安全工具启动,会等待所有当前执行中的工具完成后再开始

这种设计的好处是:模型可以一次性请求多个只读操作(如读取多个文件),它们会被并行高效地执行,而写操作和命令执行则保证串行以避免竞态条件。


四、工具注册与组装

源码文件src/src/tools.ts

Claude Code 有 43 个内置工具,分为多个类别:

类别 代表工具 源码文件
文件操作 FileReadTool, FileEditTool, FileWriteTool src/src/tools/FileReadTool/
搜索 GlobTool, GrepTool src/src/tools/GlobTool/
执行命令 BashTool, PowerShellTool, REPLTool src/src/tools/BashTool/
网络 WebFetchTool, WebSearchTool src/src/tools/WebFetchTool/
多 Agent AgentTool, SendMessageTool src/src/tools/AgentTool/
任务管理 TaskCreateTool, TaskUpdateTool, ... src/src/tools/TaskTool/
定时任务 CronCreateTool, CronDeleteTool, CronListTool src/src/tools/CronTool/
工作流 EnterPlanModeTool, ExitPlanModeTool, EnterWorktreeTool src/src/tools/PlanModeTool/
MCP MCPTool, ListMcpResourcesTool src/src/services/mcp/

工具组装的核心函数是 assembleToolPool(),它按以下顺序合并:

typescript 复制代码
// src/src/tools.ts - 工具组装逻辑
export function assembleToolPool(permissionContext, mcpTools): Tools {
  // 1. 获取所有内置工具(已按名称排序)
  const builtins = getAllBaseTools()

  // 2. MCP 工具排序
  const sortedMcpTools = [...mcpTools].sort((a, b) => a.name.localeCompare(b.name))

  // 3. 去重:内置工具优先
  const merged = [...builtins, ...sortedMcpTools]
  const deduplicated = uniqBy(merged, 'name')

  // 4. 内置工具形成连续前缀(用于 Prompt Cache 稳定性)
  return deduplicated
}

源码注src/src/tools.ts 中使用了 feature('COORDINATOR_MODE')feature('AGENT_TRIGGERS') 等编译时特性开关,配合 bun:bundlefeature() 宏实现死代码消除(Tree Shaking),确保不相关特性的代码不会进入最终产物。


五、多 Agent 系统:子 Agent 与协调者模式

5.1 子 Agent(AgentTool):Agent 递归嵌套

源码文件

  • src/src/tools/AgentTool/AgentTool.tsx
  • src/src/tools/AgentTool/runAgent.ts
  • src/src/utils/forkedAgent.ts

Claude Code 的 AgentTool 允许一个 Agent 在运行时动态创建子 Agent,每个子 Agent 有独立的消息历史、工具池和系统提示。

子 Agent 的输入 Schema 定义了它的元信息:

typescript 复制代码
// src/src/tools/AgentTool/AgentTool.tsx - 输入 Schema
const baseInputSchema = lazySchema(() => z.object({
  description: z.string(),      // 任务描述(显示用)
  prompt: z.string(),            // 子 Agent 的核心指令
  subagent_type: z.string().optional(),  // Agent 类型(general-purpose, explore 等)
  model: z.enum(['sonnet', 'opus', 'haiku']).optional(),  // 指定模型
  run_in_background: z.boolean().optional()  // 是否后台运行
}))

call() 方法中有四条 spawn 路径:

typescript 复制代码
// src/src/tools/AgentTool/AgentTool.tsx - call() 方法逻辑框架
async call(input, context, canUseTool, parentMessage, onProgress) {
  // 路径1: Teammate 模式(团队协作)
  if (input.team_name && input.name) {
    return spawnTeammate(input, context)
  }

  // 路径2: Fork 子 Agent(轻量级,共享父 prompt cache)
  if (effectiveType === undefined && isForkSubagentEnabled()) {
    return runForkedAgent(input, context, parentMessage)
  }

  // 路径3: 普通子 Agent(完全独立)
  const agentDef = resolveAgentDefinition(input)
  return runAgent(agentDef, input, context)

  // 路径4: 远程隔离(git worktree 或远程会话)
  if (input.isolation === 'remote') {
    return runRemoteIsolationAgent(input, context)
  }
}

异步 vs 同步执行 :如果 shouldRunAsync 为 true(后台运行、协调者模式、强制异步等),Agent 在后台线程中执行,主 Agent 不会等待结果:

typescript 复制代码
// src/src/tools/AgentTool/AgentTool.tsx - 异步循环
while (true) {
  const result = await Promise.race([
    agentIterator.next(),        // Agent 迭代器下一步
    backgroundPromise            // 超时自动后台化
  ])

  if (result.done) {
    finalizeAgentTool(agentMessages, agentId, metadata)
    break
  }

  // 支持用户中断后自动后台化
  if (userInterrupted) {
    await agentIterator.return(undefined)
    continueInBackground(agentIterator)
    break
  }
}

5.2 Fork 子 Agent:共享 Prompt Cache 的轻量方案

源码文件src/src/utils/forkedAgent.ts

Fork 子 Agent 是 Claude Code 的一个高阶优化 :普通子 Agent 会创建一个完全新的 API 会话,但 Fork Agent 通过 createSubagentContext() 确保父子 Agent 共享相同的缓存参数(如 cache_control 字段),使得 API 能够命中跨会话的 Prompt Cache,大幅降低 token 消耗和响应延迟。

typescript 复制代码
// src/src/utils/forkedAgent.ts - 核心函数
export function createSubagentContext(
  parentParams: AnthropicMessageParam[],
  parentSystemPrompt: SystemPrompt,
  childSystemPrompt: SystemPrompt
): SubagentContext {
  // 确保 cache 的边界点(cache breakpoint)一致
  return {
    sharedCacheParams: extractCacheParams(parentParams),
    childSystemPromptHash: hashSystemPrompt(childSystemPrompt)
  }
}

5.3 协调者模式(Coordinator Mode):多 Agent 协作编排

源码文件src/src/coordinator/coordinatorMode.ts

协调者模式是 Claude Code 的多 Agent 生产级方案:主 Agent(协调者)负责任务分解、派发和结果综合,多个工作 Agent 并行执行子任务。

协调者模式的核心是继续 vs 派发决策矩阵

场景 决策 原因
研究结果刚好是要编辑的文件 继续(SendMessageTool) Worker 有文件上下文和清晰计划
研究广泛但实现范围窄 派发新 Agent(AgentTool) 避免探索噪声
修正失败或扩展近期工作 继续(SendMessageTool) Worker 有错误上下文
验证他人代码 派发新 Agent(AgentTool) 全新视角,无实现偏见
完全无关的任务 派发新 Agent(AgentTool) 无可复用上下文

协调者的系统提示约为 370 行(src/src/coordinator/coordinatorMode.ts),明确定义了 Research → Synthesis → Implementation → Verification 四个阶段的工作流程和工具使用规则。


六、记忆与上下文管理

6.1 记忆层次架构

Claude Code 实现了多层次的记忆系统:

scss 复制代码
┌─────────────────────────────────────────┐
│  长期记忆 (Long-term Memory)              │
│  · CLAUDE.md 文件 (memdir 系统)            │
│  · 自定义 Agent 定义 (.claude/agents/)     │
│  · Team Memory (团队共享知识)               │
├─────────────────────────────────────────┤
│  会话记忆 (Session Memory)                 │
│  · SessionMemory 服务(后台子 Agent 维护)  │
│  · 自动记录对话中的关键信息到 .md 文件        │
├─────────────────────────────────────────┤
│  工作记忆 (Working Memory)                │
│  · messages[] 数组(LLM 可见)              │
│  · ToolUseContext 中的 readFileState 等    │
├─────────────────────────────────────────┤
│  上下文压缩 (Context Compaction)            │
│  · 自动压缩(auto-compact)触发时由子 Agent │
│    生成摘要,替换旧消息段落                   │
└─────────────────────────────────────────┘

源码文件

  • src/src/memdir/memdir.ts --- 记忆目录管理
  • src/src/memdir/findRelevantMemories.ts --- 上下文相关记忆检索
  • src/src/services/SessionMemory/sessionMemory.ts --- 会话记忆(后台 Agent 维护)
  • src/src/services/extractMemories/ --- 记忆提取服务

6.2 自动上下文压缩(Auto-Compact)

源码文件src/src/query.tsautoCompactTracking 相关逻辑)

当上下文接近模型窗口上限时,系统会触发自动压缩流程:

typescript 复制代码
// src/src/query.ts - 压缩决策逻辑(概念性)
async function maybeCompact(state: State): Promise<State> {
  const contextUsage = calculateContextUsage(state.messages, state.systemPrompt)
  const windowLimit = getModelWindowLimit(state.model)

  if (contextUsage / windowLimit > 0.85) {  // 85% 阈值
    // 创建一个压缩子 Agent,输入为即将被压缩的消息
    // 子 Agent 输出一个摘要,然后替换原始消息范围
    const summary = await runCompactAgent(state.messages, state.toolUseContext)
    return {
      ...state,
      messages: replaceWithSummary(state.messages, summary),
      autoCompactTracking: { ... }  // 记录压缩历史,避免重复压缩
    }
  }
  return state
}

七、Hook 扩展机制

源码文件

  • src/src/utils/hooks/execAgentHook.ts
  • src/src/utils/hooks/execPromptHook.ts
  • src/src/utils/hooks/execHttpHook.ts
  • src/src/services/tools/toolHooks.ts

Claude Code 提供了一个强大的 Hook 系统,允许用户在 Agent 运行的各个阶段拦截和干预行为。目前支持三种 Hook 类型:

Hook 类型 执行时机 可干预内容
PreToolUse 工具执行前 修改输入参数、阻断执行
PostToolUse 工具执行后 记录日志、触发后续 Agent
Stop Agent 轮次结束 发送通知、持久化数据

Hook 可以由多种机制触发:

typescript 复制代码
// Hook 触发类型
type HookExecutionType =
  | { type: 'command', command: string }      // 执行 Shell 命令
  | { type: 'agent', prompt: string }         // 运行一个 Agent
  | { type: 'prompt', template: string }       // 渲染提示模板
  | { type: 'http', url: string, method: string, body: object }  // 发送 HTTP 请求

PreToolUse Hook 的返回值会与权限系统决策合并(resolveHookPermissionDecision),形成一个统一的允许/拒绝/需确认决策。


八、安全与权限体系

源码文件

  • src/src/utils/permissions/permissions.ts --- 核心权限引擎
  • src/src/utils/permissions/filesystem.ts --- 文件系统权限规则
  • src/src/tools/BashTool/bashSecurity.ts --- Bash 危险命令检测
  • src/src/utils/bash/bashParser.ts --- Bash AST 解析器(130KB)
  • src/src/hooks/useCanUseTool.tsx --- 交互模式权限决策流程

Claude Code 实现了多层安全防御

  1. 工具级权限checkPermissions 方法):每个工具自行定义敏感操作的条件
  2. Bash 命令 AST 分析 :将 Bash 命令解析为 AST,检测危险模式(如 rm -rf /、重定向到系统文件等)
  3. 权限模式(Permission Modes)
    • default:询问用户
    • plan:需要明确批准
    • bypass:允许所有
    • auto:由 YOLO 分类器自动决策
  4. 沙箱执行src/src/utils/sandbox/sandbox-adapter.ts 支持在受限环境中执行危险操作
typescript 复制代码
// src/src/hooks/useCanUseTool.tsx - 权限决策流程(简化)
async function useCanUseTool(toolName, input, context): Promise<PermissionResult> {
  const tool = findToolByName(availableTools, toolName)

  // 1. 工具自身权限检查
  const toolPermission = await tool.checkPermissions(input, context)
  if (toolPermission.behavior !== 'allow') return toolPermission

  // 2. 全局权限规则检查(filesystem.ts 中的路径规则)
  const globalPermission = await checkGlobalPermissionRules(toolName, input)
  if (globalPermission.behavior !== 'allow') return globalPermission

  // 3. Bash 特殊检测(若为 BashTool)
  if (toolName === 'Bash') {
    const bashAnalysis = parseBashCommand(input.command)
    const dangerLevel = detectDangerousPatterns(bashAnalysis)
    if (dangerLevel > context.permissionMode.threshold) {
      return { behavior: 'block', reason: 'Dangerous pattern detected' }
    }
  }

  return { behavior: 'allow' }
}

九、Build 系统与特性开关

源码文件

  • src/src/tools.tsfeature() 调用处)
  • src/src/main.tsx(特性加载处)
  • 项目根目录 package.json

Claude Code 使用 Bun 作为构建工具,通过 bun:bundlefeature() 宏实现编译时特性开关

typescript 复制代码
// src/src/tools.ts - 编译时特性开关示例
if (feature('COORDINATOR_MODE')) {
  // 只有开启协调者模式编译标志,才包含相关代码
  const { CoordinatorMode } = require('./coordinator/coordinatorMode')
}

if (feature('AGENT_TRIGGERS')) {
  // 定时任务和远程触发工具
  const { CronTool, RemoteTriggerTool } = require('./tools/CronTool')
}

这种设计带来了显著的好处:

  • 用户编译的产物只包含其开启的功能代码,体积最小化
  • 不同部署环境(Ant 用户 vs 普通用户)可以有不同的功能子集
  • 实验性功能(如 KAIROSVOICE_MODE)可以在不重新编译的情况下通过配置切换

十、QueryEngine:面向 SDK 的高级抽象

源码文件src/src/QueryEngine.ts

QueryEnginequery() 函数的高级封装,专为 SDK/Headless 模式设计。它将 Agent 的核心能力以类形式暴露:

typescript 复制代码
// src/src/QueryEngine.ts - 核心 API
export class QueryEngine {
  constructor(config: QueryEngineConfig)

  // 提交用户消息,返回流式结果
  async *submitMessage(
    prompt: string | ContentBlockParam[],
    options?: { uuid?: string; isMeta?: boolean }
  ): AsyncGenerator<SDKMessage, void, unknown>

  interrupt(): void        // 中断当前 Agent
  getMessages(): readonly Message[]   // 获取消息历史
  getReadFileState(): FileStateCache   // 获取文件状态
  getSessionId(): string   // 会话 ID
  setModel(model: string): void  // 动态切换模型
}

在 SDK 模式下,Agent 的所有能力都可以通过 submitMessage() 调用,Agent 的循环、工具执行、权限处理对外部完全透明。Claude Code 的 /v1/agents/v1/sessions API 底层正是基于 QueryEngine 实现。


十一、整体架构图

scss 复制代码
┌──────────────────────────────────────────────────────────┐
│                      main.tsx                             │
│  (GrowthBook → Models → Plugins → Skills → Agents → MCP)   │
└──────────────────────────┬───────────────────────────────┘
                           │
                           ▼
┌──────────────────────────────────────────────────────────┐
│                  QueryEngine / query()                    │
│           ┌──────────────────────────────┐               │
│           │   while(true) Agent Loop     │               │
│           │  ① 构建请求 (System+Msgs+Tools) │              │
│           │  ② 调用 API (Streaming)        │              │
│           │  ③ 分发事件                    │              │
│           │    ├─ text → UI 展示           │              │
│           │    ├─ thinking → 推理展示      │              │
│           │    └─ tool_use → 工具执行器    │              │
│           │  ④ 工具执行管道                 │              │
│           │     ├─ PreToolUse Hooks       │              │
│           │     ├─ Permission Check       │              │
│           │     ├─ tool.call()           │              │
│           │     └─ PostToolUse Hooks     │              │
│           │  ⑤ Auto-Compact / 后处理       │              │
│           └──────────────────────────────┘               │
└──────────────────────────┬───────────────────────────────┘
                           │
        ┌──────────────────┼──────────────────┐
        ▼                  ▼                  ▼
┌───────────────┐  ┌──────────────┐  ┌──────────────────┐
│ Tool Pool      │  │ AgentTool    │  │ CoordinatorMode   │
│ (43 built-in  │  │ (子Agent递归) │  │ (多Agent编排)      │
│  + MCP tools)  │  │              │  │                   │
│               │  │ ├─ runAgent   │  │  Coordinator      │
│ Streaming     │  │ ├─ ForkAgent  │  │    ├─ Worker A    │
│ Executor      │  │ ├─ Teammate   │  │    ├─ Worker B    │
│ (并发/串行控制) │  │ └─ RemoteISO │  │    └─ Worker C    │
└───────────────┘  └──────────────┘  └──────────────────┘
        │                  │                  │
        ▼                  ▼                  ▼
┌──────────────────────────────────────────────────────────┐
│              ToolUseContext (150+ 字段依赖注入)            │
│  tools | abortController | readFileState | permissions   │
│  agentId | queryTracking | mcpClients | ...              │
└──────────────────────────────────────────────────────────┘
        │
        ▼
┌──────────────────────────────────────────────────────────┐
│ Memory System                                             │
│  CLAUDE.md (memdir) → SessionMemory → Auto-Compact       │
│  Hooks: PreToolUse | PostToolUse | Stop                  │
└──────────────────────────────────────────────────────────┘

十二、总结:核心设计哲学

纵观 Claude Code 的 Agent 实现,有几条贯穿始终的设计哲学值得学习:

  1. 一切皆 Generator :核心循环 query()AsyncGenerator,每个阶段的事件都可以被 yield 和实时处理,实现了真正的流式交互。

  2. 依赖注入替代全局状态ToolUseContext 统一注入所有上下文信息,工具不需要自行获取依赖,可测试性和可组合性极强。

  3. 并发安全分类 :通过 isConcurrencySafe 标记,Agent 可以一次性请求大量只读操作并高效并行执行,而写操作则保证串行安全。

  4. Prompt Cache 优先:无论是系统提示的静态部分缓存,还是工具池的连续前缀排序,还是 Fork Agent 的缓存参数共享,都在最大化利用 Anthropic 的 Prompt Cache 以降低成本和延迟。

  5. 可恢复的错误处理:Agent 循环永远不会因为一次错误就崩溃------它有一整套恢复链,从压缩重试到 token 上限扩容,确保长任务能够尽可能完成。

  6. 编译时 vs 运行时特性分离 :使用 feature() 宏在编译时实现特性开关,用户产物体积最小化,同时保留了运行时的灵活性。


延伸阅读建议(源码文件路径,供深入研究):

  • Agent 核心循环:src/src/query.ts
  • 工具框架:src/src/Tool.ts
  • 工具执行管道:src/src/services/tools/toolExecution.tssrc/src/services/tools/toolOrchestration.ts
  • 并发执行器:src/src/services/tools/StreamingToolExecutor.ts
  • 子 Agent 系统:src/src/tools/AgentTool/AgentTool.tsxsrc/src/utils/forkedAgent.ts
  • 协调者模式:src/src/coordinator/coordinatorMode.ts
  • SDK 封装:src/src/QueryEngine.ts
  • 权限系统:src/src/utils/permissions/permissions.ts
  • Hook 机制:src/src/services/tools/toolHooks.tssrc/src/utils/hooks/
  • 记忆系统:src/src/memdir/src/src/services/SessionMemory/
  • 工具注册:src/src/tools.ts
相关推荐
ZC跨境爬虫2 小时前
3D 地球卫星轨道可视化平台开发 Day5(简介接口对接+规划AI自动化卫星数据生成工作流)
前端·人工智能·3d·ai·自动化
星晨雪海2 小时前
若依框架原有页面功能进行了点位管理模块完整改造(3)
开发语言·前端·javascript
morethanilove2 小时前
新建vue3 + ts +vite 项目
前端·javascript·vue.js
不瘦80斤不改名2 小时前
深入理解 FastAPI 核心架构:依赖注入、分页机制与数据流转的底层逻辑
python·架构·fastapi
GISer_Jing2 小时前
微软AI战略全景:从基础设施到智能体生态
前端·人工智能·microsoft
发际线向北2 小时前
0x03 单元测试与Junit
前端·单元测试
忆往wu前2 小时前
搞懂 SPA 再学路由!Vue Router 从0到完善 + 嵌套路由一次性梳理
前端·vue.js
Aliex_git2 小时前
前端监控笔记(三)
前端·笔记·学习
M ? A2 小时前
Vue Suspense 组件在 React 中,VuReact 会如何实现?
前端·javascript·vue.js·经验分享·react.js·面试·vureact