Claude Code CLI 源码分析 : 从 Prompt 架构到工业级 AI Agent缓存黑科技+自我进化+多Agent协作+遥测监控
Claude Code CLI 源码分析 : 从 Prompt 架构到工业级 AI Agent缓存黑科技+自我进化+多Agent协作+遥测监控
Claude Code CLI 源码分析 : 从 Prompt 架构到工业级 AI Agent缓存黑科技+自我进化+多Agent协作+遥测监控 Claude Code CLI 源码分析 : 从 Prompt 架构到工业级 AI Agent缓存黑科技+自我进化+多Agent协作+遥测监控 Modified April 2 虽然 Claude Code 收集了大量数据,但也有完整的隐私保护机制: 1. MCP 工具名归一化 外部用户的 MCP 工具名会被归一化为 mcp,不会暴露具体的工具名。 2. 模型名脱敏 外部用户的模型名会被归一化为 canonical 名或 other,不会暴露你用的是哪个具体的模型。 3. userId 哈希分桶 userId 会被哈希到 30 个 bucket,做基数限制。这样 Datadog 里不会有几百万个不同的 userId,降低了存储成本。 4. dev 版本号截断 开发版本的版本号会截断去掉 git sha,避免泄露内部构建信息。 5. 用户 prompt 默认 redacted OpenTelemetry 的链路追踪中,用户 prompt 默认是 redacted 的。需要设置 OTEL LOG USER PROMPTS=1 才会记录。 隐私控制:你可以关掉大部分 Claude Code 提供了六种隐私控制方式: 控制方式 DISABLE TELEMETRY=1 CLAUDE CODE DISABLE NONESSENTIAL TRAFFIC=1 CLAUDE CODE ATTRIBUTION HEADER=false Bedrock/Vertex/Foundry 模式 GrowthBook 远程 kill switch 工作区信任未建立 对应影响范围 关闭 Datadog + 1P + GrowthBook 关闭所有非必要网络(含遥测+自动更新) 关闭 API attribution header 自动关闭所有遥测 Anthropic 可单独杀 Datadog 或 1P sink 不发 GrowthBook + 不发 1P(直到信任) 关键点: • DISABLE TELEMETRY=1 可以关掉大部分遥测,但 API Header 仍然会发送(因为它嵌入 system prompt) • 如果你用 Bedrock/Vertex 等企业部署模式,所有遥测会自动关闭 • GrowthBook 有远程 kill switch,Anthropic 可以在服务端一键关闭某个 sink “换 IP 也没用”:完整的追踪链 即使你做了以下所有操作: • 换了 IP • 换了浏览器 • 清了 cookies • 重装了系统 以下标识符的组合仍然能把你关联起来: 核心标识符(任一都能唯一锁定): 1. deviceId — 存在 /.claude/.config.json,除非手动删除否则终身不变 2. accountUuid — OAuth 登录即绑定,删文件重登照样回来 3. organizationUuid — 同上 4. rh(仓库指纹) — 你的 git remote URL 哈希,绑定你工作的项目 环境指纹(交叉验证): 1. 终端类型(20+ 种检测)+ OS + 架构 2. 包管理器 + 运行时组合 3. 部署环境(30+ 种云平台) 4. Linux 发行版 + 内核版本 行为指纹: 1. fingerprint(每条消息的第 4/7/20 字符提取的哈希) 2. 完整的进程资源画像 这不是“隐私侵犯”,而是工业级产品的标准做法。 Google Analytics、Sentry、Datadog 都在做类似的事情。区别在于,Claude Code 把这套机制做得更完整、更可靠。 为什么要做得这么复杂? 因为 Claude Code 不是一个“玩具 Demo”,而是要支持数百万用户的生产级 AI Agent 平台。 没有完整的遥测体系,Anthropic 就无法回答以下问题: • 哪些功能在真实场景下有用? • 哪些场景会导致崩溃? • Compact 机制是否有效降低了成本? • 多 Agent 模式的资源占用是否可接受? • 某个 bug 是否只在特定环境下触发? 这套遥测体系不是“偷偷收集数据”,而是产品优化的反馈循环。 没有它,Claude Code 不可能做到今天的稳定性和性能。 十五、总结:这不是 Prompt 工程,是基础设施设计哲学 看完 Claude Code 的源码,最大的感受是:这不是 prompt 写得好不好的问题,而是整个系统架构为长对话、自主工作、持续进化优化到了极致。 三大支柱 1. 缓存架构 — 让无限上下文对话在商业上可行 两层缓存(静态/动态分离)+ 四层递进的 Compact 架构是整个系统的基石。 • 数百万用户共享同一份静态 prompt 缓存 • MicroCompact(轻量清理) → SessionMemoryCompact(精确切割) → Full Compact(Prompt Cache 共享) → PTL Retry(终极兜底) • 删除几百条消息后,响应速度还是那么快 • 长对话的成本大幅降低,产品才能规模化 没有这套机制,长对话的成本会让产品无法规模化。 2. 自我进化记忆 — 从“记录对话”到“学习知识” 三层记忆体系(Auto / Team / Agent Memory)+ Auto Dream(闭环自我进化)让 Agent 不仅能“记住”,还能“学习”和“进化”。 • 每 24 小时 + 累积 5 个会话后,自动反思 • 从日志和会话中提取新知识 • 合并、修正、去重,优化记忆结构 这是一个真正的自我进化系统,而不是简单的“记录对话”。 3. 多模式编排 — 从“被动响应”到“主动执行” Proactive 模式(焦点感知 + 定时唤醒 + Skill Discovery + Token Budget)+ 多 Agent 协作(Fork / Subagent / Swarm)让 Agent 从“工具”变成“同事”。 • 用户离开时,Agent 自主决策、直接提交代码 • 用户回来时,Agent 切换到协作模式,汇报进展 • 多个 Agent 通过邮箱系统协作,权限统一管理 虽然 Claude Code 收集了大量数据,但也有完整的隐私保护机制: 1. MCP 工具名归一化 外部用户的 MCP 工具名会被归一化为 mcp,不会暴露具体的工具名。 2. 模型名脱敏 外部用户的模型名会被归一化为 canonical 名或 other,不会暴露你用的是哪个具体的模型。 3. userId 哈希分桶 userId 会被哈希到 30 个 bucket,做基数限制。这样 Datadog 里不会有几百万个不同的 userId,降低了存储成本。 4. dev 版本号截断 开发版本的版本号会截断去掉 git sha,避免泄露内部构建信息。 5. 用户 prompt 默认 redacted OpenTelemetry 的链路追踪中,用户 prompt 默认是 redacted 的。需要设置 OTEL LOG USER PROMPTS=1 才会记录。 隐私控制:你可以关掉大部分 Claude Code 提供了六种隐私控制方式: 控制方式 DISABLE TELEMETRY=1 CLAUDE CODE DISABLE NONESSENTIAL TRAFFIC=1 CLAUDE CODE ATTRIBUTION HEADER=false Bedrock/Vertex/Foundry 模式 GrowthBook 远程 kill switch 工作区信任未建立 对应影响范围 关闭 Datadog + 1P + GrowthBook 关闭所有非必要网络(含遥测+自动更新) 关闭 API attribution header 自动关闭所有遥测 Anthropic 可单独杀 Datadog 或 1P sink 不发 GrowthBook + 不发 1P(直到信任) 关键点: • DISABLE TELEMETRY=1 可以关掉大部分遥测,但 API Header 仍然会发送(因为它嵌入 system prompt) • 如果你用 Bedrock/Vertex 等企业部署模式,所有遥测会自动关闭 • GrowthBook 有远程 kill switch,Anthropic 可以在服务端一键关闭某个 sink “换 IP 也没用”:完整的追踪链 即使你做了以下所有操作: • 换了 IP • 换了浏览器 • 清了 cookies • 重装了系统 以下标识符的组合仍然能把你关联起来: 核心标识符(任一都能唯一锁定): 1. deviceId — 存在 /.claude/.config.json,除非手动删除否则终身不变 2. accountUuid — OAuth 登录即绑定,删文件重登照样回来 3. organizationUuid — 同上 4. rh(仓库指纹) — 你的 git remote URL 哈希,绑定你工作的项目 环境指纹(交叉验证): 1. 终端类型(20+ 种检测)+ OS + 架构 2. 包管理器 + 运行时组合 3. 部署环境(30+ 种云平台) 4. Linux 发行版 + 内核版本 行为指纹: 1. fingerprint(每条消息的第 4/7/20 字符提取的哈希) 2. 完整的进程资源画像 这不是“隐私侵犯”,而是工业级产品的标准做法。 Google Analytics、Sentry、Datadog 都在做类似的事情。区别在于,Claude Code 把这套机制做得更完整、更可靠。 为什么要做得这么复杂? 因为 Claude Code 不是一个“玩具 Demo”,而是要支持数百万用户的生产级 AI Agent 平台。 没有完整的遥测体系,Anthropic 就无法回答以下问题: • 哪些功能在真实场景下有用? • 哪些场景会导致崩溃? • Compact 机制是否有效降低了成本? • 多 Agent 模式的资源占用是否可接受? • 某个 bug 是否只在特定环境下触发? 这套遥测体系不是“偷偷收集数据”,而是产品优化的反馈循环。 没有它,Claude Code 不可能做到今天的稳定性和性能。 十五、总结:这不是 Prompt 工程,是基础设施设计哲学 看完 Claude Code 的源码,最大的感受是:这不是 prompt 写得好不好的问题,而是整个系统架构为长对话、自主工作、持续进化优化到了极致。 三大支柱 1. 缓存架构 — 让无限上下文对话在商业上可行 两层缓存(静态/动态分离)+ 四层递进的 Compact 架构是整个系统的基石。 • 数百万用户共享同一份静态 prompt 缓存 • MicroCompact(轻量清理) → SessionMemoryCompact(精确切割) → Full Compact(Prompt Cache 共享) → PTL Retry(终极兜底) • 删除几百条消息后,响应速度还是那么快 • 长对话的成本大幅降低,产品才能规模化 没有这套机制,长对话的成本会让产品无法规模化。 2. 自我进化记忆 — 从“记录对话”到“学习知识” 三层记忆体系(Auto / Team / Agent Memory)+ Auto Dream(闭环自我进化)让 Agent 不仅能“记住”,还能“学习”和“进化”。 • 每 24 小时 + 累积 5 个会话后,自动反思 • 从日志和会话中提取新知识 • 合并、修正、去重,优化记忆结构 这是一个真正的自我进化系统,而不是简单的“记录对话”。 3. 多模式编排 — 从“被动响应”到“主动执行” Proactive 模式(焦点感知 + 定时唤醒 + Skill Discovery + Token Budget)+ 多 Agent 协作(Fork / Subagent / Swarm)让 Agent 从“工具”变成“同事”。 • 用户离开时,Agent 自主决策、直接提交代码 • 用户回来时,Agent 切换到协作模式,汇报进展 • 多个 Agent 通过邮箱系统协作,权限统一管理 • 自动发现相关技能,推送给模型调用 • 用 token 量驱动自主工作,“花 500K token” 就一直干到花完 这是一个真正的自主 Agent,而不是简单的“问答机器人”。 4. 安全分层 — 20+ 道检查流水线 Bash 安全分类器(2592 行)+ 沙箱执行 + 细粒度权限 + 网络隔离 + Commit 归属追踪。 • 20+ 道安全检查:Shell 元字符、命令替换、危险变量、花括号展开、反斜杠转义、引号反同步、控制字符、jq 系统函数、/proc 文件系统访问等 • Zsh 专属防御:zmodload、emulate、zpty、ztcp、zf rm 等危险命令 • 真实攻击案例防御:花括号展开绕过、反斜杠运算符绕过、引号反同步绕过 这是工业级 Agent 的安全基础设施。 设计哲学:Cache 感知 + 基础设施感知 Claude Code 的每个设计决策都在考虑两件事: 1. Cache 感知 • Fork 直接复制父级渲染后的 system prompt 字节,避免 Feature Flag 冷→热切换导致缓存失效 • Agent 根据缓存过期时间(5 分钟 TTL)决定 sleep 时长 • 连 Agent 的创建方式都要考虑缓存命中率 2. 基础设施感知 • Agent 感知缓存 TTL、token 预算、终端焦点状态 • 据此调整行为节奏,避免无效唤醒 • 让 Agent 理解基础设施的约束,而不是盲目执行 这才是工业级 AI Agent 和玩具 Demo 的区别。 对 OpenClaw 的启发 Claude Code 和 OpenClaw 走了完全不同的路: • Claude Code — 牺牲灵活性,换取极致的缓存效率 • OpenClaw — 牺牲缓存优化,换取极致的可定制性 两者没有绝对的好坏,而是针对不同约束条件做出的最优解。 OpenClaw 可以借鉴的: 1. 分层缓存 — Layer 1 6 用 global cache, Layer 7 8 用会话级缓存 2. Cache Edits — 给每个 tool result 加 cache reference,增量删除 3. 焦点感知 — 检测用户是否在看终端,动态调整 Agent 的自主程度 4. 基础设施感知 — 让 Agent 感知缓存 TTL、token 预算,据此调整行为节奏 OpenClaw 应该保留的: 1. 9 层架构 — 职责分离更清晰 2. Hook 系统 — 比 MCP Instructions 更强大 3. Skills Registry — 可扩展性更强 最后 Claude Code 的核心竞争力不是单个功能,而是这套缓存架构 + 自我进化记忆 + 多模式编排的完整基础设施。 特别是 cache edits 和分层缓存,是让无限上下文对话在商业上可行的关键。没有这套机制,长对话的成本会让产品无法规模化。 这才是工业级 AI Agent 的设计哲学。 未完待续 源码中还有很多值得深挖的系统,限于篇幅,留待下篇分析: • LSP 集成 — 内置 Language Server,实时诊断反馈 • MCP 完整架构 — OAuth 认证、XAA 动态发现、权限管理、channel allowlist • Hooks 系统 — 用户自定义钩子,工具执行前后注入逻辑 • Cron 定时任务 — Agent 定时执行任务,支持 timezone 转换 • Coordinator 调度 — 多 Agent 的任务调度层 • Plans 系统 — 从 plan 到 implementation 的执行框架 • Voice 语音模式 — 语音输入流式 STT、关键词提取 • MagicDocs — 文档自动检测和跟踪 • Code Indexing — 代码索引,可能用于语义搜索 • Session Restore — 会话恢复和断线重连 • Cost Tracker — 实时成本追踪 • Plugins 系统 — 插件安装、marketplace、git clone 隔离 • API 错误处理 — 错误分类、rate limit 处理、重试策略 这些系统同样体现了 Claude Code 的工程深度,值得深入单独成篇。 🔗 原文链接: https://x.com/servasyy ai/status/20... https://x.com/servasyy ai/status/20... 最近拿到了 Claude Code CLI 的源码。 之前写过 OpenClaw 的 9 层 Prompt 架构,当时就在想:Anthropic 这种量级的公司,他们会怎么设计 AI Agent? OpenClaw 的 9 层 Prompt 架构 看完源码才发现,这不是“Prompt 工程”那么简单,而是 缓存架构 + 自我进化记忆 + 多模式编排 的完整基础设施。 constants/prompts.ts 展示的是两层缓存架构,cache edits 实现的是增量删除机制,autoDream 构建的是自我进化的记忆系统,PROACTIVE 模式切换的是主动执行的编排逻辑。 这才是为什么 Claude Code 能支持无限长对话,为什么删除几百条消息后响应速度还是那么快,为什么 Agent 能从“记录对话”进化到“学习知识”。 这不是 prompt 写得好不好的问题,是整个系统架构为长对话、自主工作、持续进化优化到了极致。 一、System Prompt 的两层缓存架构:静态 vs 动态 大部分 AI 应用的 prompt 是一整块发给模型的。每次对话都要重发,浪费 token 也浪费钱。 Claude Code 把 prompt 切成两层: 核心设计 1. 静态前缀用 scope: 'global' Anthropic 后端跨用户、跨组织共享缓存。所有人的所有会话都复用同一份。这部分内容几乎不变: • 身份定义(Intro) • 系统规则(System) • 任务规范(Doing Tasks) • 操作安全(Actions) • 工具使用指南(Using Tools) • 风格要求(Tone & Style) • 效率要求(Output Efficiency) 2. 动态部分用 scope: null 每个会话独立,只在 /clear 或 /compact 时失效。包含会话特定的: • 会话指引(Session Guidance) • 记忆(Memory) • 环境信息(Env Info) • MCP 指令(MCP Instructions) • 语言偏好(Language) • 输出风格(Output Style) • 草稿本(Scratchpad) • Token 预算(Token Budget) 3. 分界线(BOUNDARY MARKER) 这是整个设计的关键。分界线确保动态部分变化时,静态部分的缓存不会失效。两者完全解耦。 • 静态部分大约 5 8K token,但可以跨所有用户共享 • 动态部分每次会话不同,通常也是 5 10K token • 分界线让两者解耦,动态变化不影响静态缓存 • 节省的不是绝对数量,而是 跨数百万用户共享这个乘数效应 缓存管理机制 动态部分不是每次重算,而是用 systemPromptSection() 注册 + memoize,只在 /clear 或 /compact 时清缓存。 例外:MCP Instructions 使用了 DANGEROUS uncachedSystemPromptSection,因为 MCP 服务器会中途连接/断开,需要实时更新。 效果 • Claude Code 启动几乎是瞬间的 • 新会话只需要发送动态部分 • 长对话的成本显著降低(短对话节省不明显) 二、四层递进的 Compact 架构:从轻量清理到全量压缩 Claude Code 的压缩不是单一机制,而是 四层递进的压缩策略 ,根据上下文压力逐级升级。 整体架构 Layer 1: MicroCompact + Cache Edits(黑科技) 这是 Anthropic API 的未公开功能,核心是 缓存不失效的增量删除 。 问题场景 长对话中,旧的 tool result(工具调用结果)会占满上下文。一个典型的长对话可能有 100K+ token 的 tool result。 传统做法有两种: 1. 直接删掉旧消息 → 整个 prompt cache 失效 → 下一轮全部重发 → 费用飙升($1+ 一轮)、延迟明显(5 10 秒) 2. 不删除 → 上下文溢出,对话中断 Prompt Cache 的工作原理:前缀完全匹配 为什么删除旧消息会导致缓存失效? 这是理解 Cache Edits 价值的关键。 Prompt Cache 的工作原理:前缀完全匹配 假设你的消息序列是这样的: [System Prompt] + [消息1] + [消息2] + [消息3] + [消息4] + [消息5] Claude 会把这整个序列缓存起来。下一轮对话,你发送: [System Prompt] + [消息1] + [消息2] + [消息3] + [消息4] + [消息5] + [消息6] Claude 发现前面的部分和缓存完全一致,直接复用缓存,只处理新的 【消息 6】。 但如果你删掉了消息 2: [System Prompt] + [消息1] + [消息3] + [消息4] + [消息5] + [消息6] Claude 发现从消息 1 之后,序列就对不上了: • 缓存里是:【消息 1】 + 【消息 2】 + 【消息 3】…… • 你发的是:【消息 1】 + 【消息 3】 + 【消息 4】…… 结果:缓存失效,整个序列需要重新处理。 这就像从书架上抽掉一本书,书的顺序变了,别人来找书时发现对不上,要重新整理书架。 Cache Edits 的解法 不修改本地消息,在 API 层发送删除指令: 工作原理(3 步) 1. 给每个块贴上 ID 每个 tool result 发送时带上 cache reference: tool use id,就像给缓存中的每个块贴上条形码。 目的:方便后续通过 ID 引用这些块。 2. 告诉服务端“跳过这些块” 通过 cache edits 发送删除指令,告诉服务端“把这些块标记为不可见”。 关键点: 数据还在缓存里,只是被标记为“跳过” 。本地消息也不动,只是在 API 层告诉服务端“别把这些块喂给模型”。 3. 保存标记指令,供后续请求使用 因为缓存里的原始数据还在(只是被标记为跳过),所以每一轮都需要重新发送 cache edits。 Claude Code 会把这个标记指令保存下来,自动在后续请求中附带,确保那些块持续被跳过。 效果 • 缓存前缀没变 → 下一轮还是命中 • 模型看到的上下文变短了 → 省 token • 原始数据还在服务端 → 只是被标记为“跳过” 什么时候会用 Cache Edits? Claude Code 有一个自动压缩机制叫 microCompactMessages(),当 tool result 太多时,会自动清理旧的。 但清理方式有两种,取决于缓存是否还热着: 场景 1:缓存已经过期了(超过 5 分钟) 直接删除旧 tool result 的内容,反正缓存已经失效了,删了也不影响。 场景 2:缓存还热着(5 分钟内) 用 Cache Edits 增量删除,保持缓存命中。 具体流程: 关键点:Cache Edits 只在缓存还热的时候用,这样才能保持缓存命中。 对比:传统方法 vs Cache Edits cache edits 的优势在于 只删 tool result 不动其他部分 ,而传统 compact 虽然 system prompt 部分仍能命中缓存,但 tool result 部分会失效,需要重发。 Layer 2: SessionMemoryCompact — 外科手术式的精确切割 当 MicroCompact 清理完 tool result 还不够时,就要动真格的了:切掉旧对话。 但这不是简单的“砍前半段”。Claude Code 的做法是 外科手术式的精确切割 ,确保不会把一个完整的交互拆散。 核心规则: • 保留最近 10K 40K token 的消息(根据上下文压力动态调整) • 用一条 Session Memory 替代旧对话(“之前我们讨论了……”) • 绝不拆散 tool use 和 tool result — 工具调用和结果必须成对出现 • 绝不拆散 thinking 块和同 message.id 的 tool use — 思考过程和执行动作必须在一起 message.id 为什么这样设计? 如果你把 tool use 留下但删掉 tool result,模型会以为工具调用还没执行完,陷入等待状态。如果你把 thinking 块删掉但留下 tool use,模型会不知道为什么要调用这个工具。 所以 Claude Code 的切割逻辑是: 从保留区的起点向后扩展,直到满足最小 token 数和最小消息数,并且不破坏任何完整的交互组 。 这是一个“宁可多留一点,也不能拆散”的保守策略,确保上下文的语义完整性。 Layer 3: Full Compact — 复用缓存的摘要魔法 当前两层都不够时,就要祭出大招了:Fork 一个 agent 做全量摘要。 但这里有个精妙的设计: 摘要 agent 的 system prompt + tools + model 和主对话完全一致 。 为什么?因为这样可以 直接命中主对话的 prompt cache ,大幅降低 token 成本。 工作流程: 为什么要自动注入文件和 Skills? 因为压缩后,模型会忘记之前读过哪些文件、激活过哪些技能。如果不自动恢复,下一轮对话模型会说“我需要先读取 xxx 文件”,浪费一轮交互。 自动注入的逻辑是: 把最近操作过的文件和技能重新喂给模型,但控制总量(文件 50K,Skills 25K),不会让上下文再次爆掉 。 这是一个“压缩后恢复”的闭环设计,确保模型不会因为压缩而丢失工作记忆。 Layer 4: PTL Retry — 最后的保险机制 即使是摘要请求本身,也可能触发 prompt too long。 这种情况通常发生在极端场景:对话历史太长,连摘要 agent 都塞不下。 Claude Code 的兜底策略是: 从头部砍掉最旧的消息组,砍到够为止 。 规则: • 每次最多砍 20% • 最多重试 3 次 • 砍的单位是“消息组”(user + assistant 成对删除),不会留下孤立的消息 这是最后的保险机制,确保即使在极端情况下(比如用户一次性粘贴了几十万 token 的日志),对话也能继续。 为什么不一开始就用这个策略? 因为这是最粗暴的方式,会丢失大量上下文。Claude Code 的设计哲学是: 能用轻量级方法解决的,就不用重量级方法 。只有前三层都不够时,才会启动这个终极兜底。 为什么需要四层? 这是 Claude Code 能支持无限上下文对话的关键基础设施之一。 三、Anthropic 员工用的是另一个版本 源码里有个彩蛋:USER TYPE === 'ant' 分支。 外部用户看到 Be concise 内部用户看到 • 完整的写作风格指南(400+ 字的 “Communicating with the user” 段落) • “不要写注释”的详细规则 • 验证 agent(VERIFICATION AGENT) • 数字化长度锚点:“工具间 ≤25 词,最终回复 ≤100 词” • 误报防御:“永远不要在测试失败时声称通过” 为什么这样设计? • Anthropic 内部用户需要更严格的输出控制 • 外部用户看到的是“简化版”,避免过度约束 • 这解释了为什么 Anthropic 员工用 Claude Code 的体验和我们不一样 编译时优化 实际实现通过 process.env. USER TYPE === 'ant' 在编译时做死代码消除,不是运行时判断: 这确保外部用户完全看不到内部版本的 prompt 内容。 四、Proactive 模式:用一套完全不同的 System Prompt 自主工作 普通的 Claude Code 是“被动响应”的:你输入,它回复。 但当激活 PROACTIVE 或 KAIROS 模式时,会切换到一套完全不同的 System Prompt,让 Agent 变成“自主工作”模式: Proactive Prompt 包含 • 自主身份 :“You are an autonomous agent……”(你是一个自主 Agent) • 定时唤醒 :tick 机制,不用等你输入,自己定时醒来干活 • 后台任务管理 :可以在后台执行长期任务 • 焦点感知 :知道你在不在看终端,动态调整行为 • 睡眠调度 :SleepTool 机制,合理安排工作和休眠 终端焦点感知:根据用户注意力动态调整自主程度 这是 Proactive 模式中最前瞻的设计。Agent 通过 terminalFocus 字段知道用户是否在看终端: Unfocused(用户离开): • 进入自主模式 • 主动做决定 • 直接提交代码 • 不需要等待确认 Focused(用户在看): • 进入协作模式 • 先问再做 • 等待用户反馈 • 保持交互式对话 这是一个非常聪明的设计: Agent 的自主程度不是固定的,而是根据用户的注意力动态调整 。当你专注工作时,Agent 安静地在后台干活;当你回来看终端时,Agent 立刻切换到协作模式,向你汇报进展并征求意见。 Token Budget:用 token 量驱动的自主工作 注意:Token Budget 不是 Proactive 专属功能, 普通模式也可以使用。但它确实是“自主工作”的一种驱动方式,所以放在这里介绍。 用户可以指定 token 预算,Agent 会持续工作直到接近预算: "+500k" → 500,000 tokens "+2m" → 2,000,000 tokens "use 1b tokens" → 1,000,000,000 tokens 闭环机制: 用户指定预算 → agent 持续工作 → 每轮检查进度 → 接近 90%?停止,报告完成 → 收益递减?停止(连续 3 轮增量 <500 token) → 未到 90%?注入 nudge 继续工作 关键设计: • System prompt 中的 token budget section 是缓存的(用了 “When the user specifies……” 条件句式,没有预算时是空操作,不破坏缓存) • 每轮对话结束后自动注入 nudge 消息:“Stopped at 72% of token target (360K / 500K). Keep working — do not summarize.” • 收益递减检测:连续 3 轮以上,且最近两轮增量都 <500 token,自动停止 这是一个用 token 量驱动的自主工作模式 — 用户说“花 500K token”,Agent 就一直干到花完为止。 从“被动响应”到“主动执行”的模式切换 这是 Claude Code 支持“自主 Agent”的基础,也是 OpenClaw 可以直接借鉴的设计。 五、Skill Discovery:技能自动发现与加载机制 Claude Code 有一个独立的 技能发现和加载系统 ,通过 EXPERIMENTAL SKILL SEARCH feature flag 控制。 注意:Skill Discovery 不是 Proactive 专属功能 ,它是一个独立的系统,普通模式和 Proactive 模式都可以使用。 三个层次 1. 自动发现(被动) 每轮对话自动运行 getTurnZeroSkillDiscovery(),扫描 .claude/skills/ 目录下的所有 SKILL.md,匹配关键词和描述,推送相关技能。 2. 主动搜索(DiscoverSkillsTool) 模型主动调用,搜索特定技能。用于“中途转向”或“非典型工作流”。已展示的技能自动过滤,不重复推荐。 3. 远程技能 通过 remoteSkillState + remoteSkillLoader 从远程加载技能。必须先通过 DiscoverSkills 发现,才能通过 SkillTool 执行。遥测追踪 was discovered 字段。 工作流程 用户发送消息 ↓ prefetch.ts — 扫描消息内容,匹配相关技能 ↓ 生成 skill discovery attachment "Skills relevant to your task: [skill1, skill2]" ↓ 注入到当轮对话的 attachment 中 ↓ 模型看到技能提示,调用 SkillTool 执行 与 Compact 的配合 压缩后 skill discovery attachment 会丢失,resetSentSkillNames() 会在下一轮重新推送,确保模型始终能看到相关技能。 这是一个智能的“技能推荐系统”,让 Agent 自动发现和加载最相关的能力。 六、与 OpenClaw 的架构对比:两种设计哲学 之前我写过一篇 OpenClaw 的 9 层 Prompt 架构详解,当时拆解的是 OpenClaw 如何通过精细分层来支持多场景定制。现在看完 Claude Code 的源码,发现两者走了完全不同的路。 OpenClaw 的 9 层 Prompt 架构详解 Claude Code:缓存优先 OpenClaw:组装优先 设计哲学的根本差异 Claude Code 的选择: • 牺牲灵活性,换取极致的缓存效率 • 适合 Anthropic 这种 Provider 深度定制的场景 • 数百万用户共享同一份静态 prompt,成本优势明显 OpenClaw 的选择: • 牺牲缓存优化,换取极致的可定制性 • 适合需要多场景、多身份、多协议的复杂系统 • 9 层架构让每个层次的职责清晰,便于扩展和调试 两者没有绝对的好坏,而是 针对不同约束条件做出的最优解 。 核心差异 1. Claude Code 更极致 • 缓存优化到极致(global cache + cache edits) • 成本和延迟控制得很好 • 适合 Anthropic 这种 Provider 深度定制 2. OpenClaw 更灵活 • 9 层架构职责分离更清晰 • Hook 系统比 MCP Instructions 更强大 • 支持更复杂的场景(Skills、协议规范、字符预算) 关键差异:systemPromptSection() 的缓存管理 Claude Code 还有一个核心机制: 动态部分不是每次重算,而是用 systemPromptSection() 注册 + memoize 。 为什么 MCP 是例外? • MCP 服务器会中途连接/断开 • 需要实时反映当前可用的 MCP 工具 • 不能缓存,否则会出现工具列表不同步 这个细节 OpenClaw 可以直接借鉴: • Layer 1 6 用 global cache • Layer 7 8 用 systemPromptSection() 做会话级缓存 • Layer 9 的实时上下文用 DANGEROUS uncached 如果 OpenClaw 要借鉴 Claude Code 1. 分层缓存 把 Layer 1 6(框