🍇
Claude Code 源码拆解 harness 设计 - 全景解析 总结:Claude Code 的每一个子系统都在做同一件事,在概率性的模型周围,构建确定性的工程系统 模型可能输出错误参数,Zod schema 拦截它 模型可能执行危险的命令权限分类器阻止它 模型可能在长对话中迷失三级压缩流水线,为它清理上下文 模型可能在多 Agent 协作中被噪声污染 上下文隔离保护它 没有一行代码试图让模型变得更聪明 ,所有的工程投入都在让模型周围的系统变得更可靠 Claude Code 核心骨架 while 循环 + 一组工具(源码中称为Query Engine) Agent 的主循环控制流中没有 DAG 没有状态图,没有条件路由 ,看似简单但是包裹着精密的 harness 一整套系统 流程:根据用户的输入构建系统提示词,调用模型,模型说要工具就执行工具,把结果位回去,继续循环,直到模型给出最终回答或者触发预算上限 用户输入 构建系统提示词 调用模型 模型返回工具调用 执行工具 结果返回给模型 最终回答 or 预算上限 Harness 三层架构 第一层:上下文管理 - 解决模型能看到什么的问题 核心思想:上下文窗口越精简越好,关键不是模型上下文够不够,而是该不该装进去,根据不同程度的压缩任务使用不同成本的压缩策略 Claude Code 设计了一个三级压缩流水线来管理上下文窗口 微压缩 不调用模型,纯规则驱动 ,按工具类型白名单保留最近n个工具的结果,把更早的结果清理掉压缩的时候会考虑,如果清理掉会不会导致服务器的 KV cache 失效 调用 API 的时候 Anthropic 会把我们发过去的 prompt 前缀缓存在服务端,下次请求如果前缀相同不用重新处理(KV cache) 如果用户还在连续对话,服务端缓存还在 ,微压缩就会走更精细的路径,通过 cache editing api 告诉 服务端 把这几个工具结果删了但不动 prompt 前缀缓存继续有效 注意:为了保留 KV cache Claude Code 的实现是本地的 prompt 历史记录一个字都不改,将带有工具结果的prompt 完完整整的传递给服务端,先让KV cache命中,命中后传递给模型之前 服务端会将带有特定标签的内存块清理掉 ,从而实现保留KV cache 清理 上下文的效果 详解(缓存命中逻辑) 原封不动地发送,确保 100% 命中缓存 Claude Code 客户端发送请求时,历史的 messages 数组和上一次请求一模一样,包含原始的工具输出(此时缓存完美命中) 在 Payload 中注入“切除指令” 虽然文本内容没变,但 Claude Code 在构建 API 请求时,添加了两个新的参数 cache_reference:它会在需要删除的旧工具结果的 JSON 块上打上这个标记 cache_edits:在请求体中附带一个编辑指令,告诉服务器:“要干掉哪些 reference 块” 服务端的 GPU 显存切片 当显存已经加载了完整的 KV Cache 矩阵后,但在将其喂给模型开始预测下一个 Token 之前 Anthropic 的推理引擎它会读取 cache_edits 指令,直接在 GPU 的 KV Cache 矩阵中,把刚才标记的那些工具结果对应的 Token 内存块“物理挖掉”(类似于数组的 splice 操作) ,然后将剩余的上下文拼接在一起 源码中还包含 防循环依赖常量、防子 agent 污染全局状态 等设计 会话记忆压缩 它 不是把对话做摘要 而 是从对话中提取学到了什么,项目结构、用户偏好、任务进度 ,这些结构化的事实被持久化到本地的记忆目录中,提取的事实不是叙事 完整压缩 用一次独立的模型调用 ,把整段对话历史总结成一条精简的上下文边界消息,之前的消息从模型的prompt中移除,ui中保留完整的历史信息 总结:三个不同力度的问题,三种不同成本的解法,微压缩去除噪声、记忆压缩提取事实,完整压缩清理历史 工具加载和工具输出管理 Claude Code 内置了 80多个工具,不是一开始就全部塞进上下文,核心工具启动时加载,扩展工具按需加载(与 skills 渐进式理念保持一致) 每个工具用 Zod schema 定义输入参数,模型输出的 json,必须通过验证才能执行,如果工具输出太大系统不会直接截断,而是存到外部,给模型一个摘要加一个指针,让它按需取用 第二层:安全与约束 - 解决模型不能做什么的问题 核心思想:prompt中的规则是建议、代码中的规则是法律 有四个权限模式,从需要逐一确认到完全自动,每次调用都要过一个五步评估流水线 分类器的设计 第一层 Bash Classifier :纯规则匹配 ,分析命令内容,把只读命令自动归类为安全直接放行,无需调用模型 第二层 YOLO Classifier : 完整的 LLM-as-Judge 用一个独立的模型调用来审查主 Agent 的每一步操作 ,分为两个阶段 快速判断,只用一个 yes or no 来判断 ,如果是 no 则进入第二阶段 让模型做完整推理,再做判断,减少误杀 错误处理:宁可错杀,不可放过,解析失败、API错误、全部默认拦截 也就是生成和评估分离思想,主Agent 负责行动,分类器Agent评估该不该执行 源码中还有 bash 安全检查、防御 Zsh等号展开、Unicode 零宽空格注入、IFS空字节注入等等 hook 也属于代码中的规则法律 第三层:多Agent - 解决一个模型不够用怎么办的问题 核心思想:上下文隔离,但关键发现可以跨Agent流动 Claude Code 多agent系统叫 Swarm、主 Agent 叫 Leader 可以生成多个子 Agent 叫 Teammate 所有的 Teammate 跑在同一个运行时中,共享权限桥接,但上下文是隔离的,Leader 只能看到指令和最终结果,中间过程全部隔离 但光隔离还不够,源码中还有一个 team memory sync 机制,关键发现会同步回 Leader的记忆目录,其他 Teammate也能看到 还有一个 Coordinator mode 开启后 Claude code 变成纯粹的编排器,自己不干活只负责拆任务、派任务、收结果,system prompt中有一句 Do Not say based on your findings. Read the actual findings and specify exactly what to do. 不许偷懒委派 源码中存在,但还未发布的系统 投机执行 Speculation Claude 回答完问题后,在还没按回车之前,系统就已经在后台开始执行它预测你会做的下一步,所有写入重定向到沙箱,接受就合并,拒绝就丢弃,一次投机完成后就会立即开始下一轮 预测、执行、预测、执行 试图始终领先用户 KAIROS 永远在线的持久助手模式 系统按固定间隔向 Agent 发送 tick 提示,Agent自主决定要不要主动做点什么,有15秒阻塞预算的硬性约束,有自己的专属工具集 还配了一个叫 Dream的后台记忆整理引擎,空闲时自动整合和修剪记忆 白天主动,空闲时整理记忆 UltraPlan(目前已经对 Claude pro 用户开始测试) 将复杂的规划任务卸载到云端容器,运行 Opus 4.6,最长跑30分钟,浏览器实时观看和审批 和 Manus 的区别是, Manus把整个执行都放在云端,UltraPlan 只是在云端规划,实现仍在本地,规划需要深度思考但不需要本地文件系统,实现需要本地环境但不需要 30分钟推理,拆开放在各自最合适的地方运行 Claude Code 的源码证明了最强的编码Agent 核心竞争力不只是在模型,也在与Harness,模型是引擎 Harness是整辆车