Claude Code 中的 Harness:从受控工具循环到生产级 Agent 运行时
模型能力决定 Agent 的能力上限,Harness 决定系统能否安全、稳定、低成本地触达这个上限。

摘要
Claude Code 经常被简单理解为“一个可以读写代码、调用 Shell 的 Claude 客户端”,但这种描述忽略了它最有价值的部分:包裹在模型之外的 Agent Harness。
Anthropic 官方将 Claude Code 描述为运行在终端、IDE、桌面端和浏览器中的 Agentic Coding Tool。它能够读取代码库、编辑文件、运行命令、调用外部工具,并通过“收集上下文—执行动作—验证结果”的循环持续工作。官方文档进一步明确指出:Claude Code 是包裹 Claude 模型的 Agentic Harness,负责提供工具、上下文管理和执行环境。1
而社区项目 how-claude-code-works 则基于源码快照、二进制字符串、抓包与黑盒测试,对这一 Harness 做了更细粒度的工程分析,包括双层生成器运行时、工具流式预执行、渐进式上下文压缩、权限状态机、长期记忆、子 Agent 隔离与可观测性等。2
本文不讨论 Claude 模型内部的 Transformer、训练方法或推理机制,而是聚焦以下问题:
- Claude Code 的 Harness 由哪些层组成?
- 模型决策与确定性运行时如何分工?
- 为什么它不是一个简单的 ReAct Demo?
- 上下文、工具、权限、记忆与多 Agent 如何形成统一系统?
- 哪些结论得到官方文档确认,哪些来自社区源码分析或黑盒推断?
- 这些设计对企业级 Agent Harness 有什么可复用价值?
1. 证据边界:先区分官方事实、源码分析与工程推断
在深入架构之前,必须明确材料的可信边界。
1.1 三类证据
| 证据等级 | 来源 | 适合支撑的结论 |
|---|---|---|
| A:官方确认 | Claude Code 官方文档、Claude Platform 官方文档 | 产品行为、权限模式、Sandbox、Memory、Skills、Subagents、MCP、OTel 等公开能力 |
| B:社区源码分析 | how-claude-code-works 对源码快照的走读 | 类、函数、状态字段、循环结构、工具调度和部分内部机制 |
| C:黑盒逆向与架构推断 | 二进制字符串、网络抓包、运行行为测试 | 新功能可能的实现方式、内部编排和未公开机制 |
社区仓库本身明确声明:它是独立教育性分析,不代表 Anthropic 官方设计,也不保证与 Claude Code 当前版本的真实内部实现完全一致。仓库前半部分主要基于一个历史源码快照,后续新能力则更多依赖黑盒实测和公开情报。2
因此,本文采用以下写法:
- “官方文档确认”:可以视为当前产品公开契约;
- “社区源码分析显示”:可以作为高价值工程参考,但不等同于官方承诺;
- “可推断”或“可能”:只作为架构解释,不写成确定事实。
1.2 为什么社区分析仍然有价值
官方文档通常回答“用户如何使用”,而源码分析更适合回答:
- 为什么要把会话管理和 Agent Loop 分成两层?
- 工具为什么需要并发安全语义?
- 为什么旧工具输出要先裁剪,再做全局摘要?
- 为什么 Permission 不能只是一个确认弹窗?
- 为什么多 Agent 必须优先做上下文和文件系统隔离?
- 为什么错误恢复应该是状态转移,而不是统一重试?
这类问题决定了一个 Agent 能否从 Demo 演进为生产系统。
2. Harness 到底是什么
在 Agent 语境中,Harness 不是某个单一模块,也不是一个 Prompt 模板。
可以把它定义为:
Harness 是包裹在模型之外、负责上下文、能力、执行、状态、权限、恢复、预算和观测的确定性工程系统。
模型擅长:
- 理解模糊目标;
- 阅读代码和错误信息;
- 推断下一步行动;
- 在新观察出现后调整方案;
- 生成代码、计划和解释。
Harness 负责:
- 模型能看到哪些信息;
- 模型能调用哪些工具;
- 工具参数是否有效;
- 动作是否被授权;
- 哪些工具可以并行;
- 失败后应该重试、压缩、降级还是停止;
- 会话如何恢复;
- 费用、轮数和 Token 如何限制;
- 整个过程如何回放和审计。
二者的边界可以概括为:
模型:下一步“应该做什么”Harness:这一步“能不能做、怎样做、失败后怎么办”Anthropic 官方在 “How Claude Code works” 中将其核心循环概括为:
Gather context → Take action → Verify results → Repeat并指出 Claude Code 的 Agentic Loop 由“负责推理的模型”和“负责行动的工具”共同驱动,Claude Code 则作为 Harness 提供工具、上下文管理与执行环境。1
3. Claude Code Harness 的总体分层
从生产级 Agent 架构角度,可以把 Claude Code 抽象成以下结构:
交互与接入层 ↓会话生命周期层 ↓Agent Runtime / 状态机 ↓上下文编译与模型调用 ↓工具执行与结果回注 ↓恢复、继续或终止同时,四个横切平面贯穿整个链路:
能力平面:Tools / Skills / MCP / Subagents状态平面:State / Session / Transcript / Memory / Task治理平面:Permissions / Hooks / Sandbox / HITL观测平面:Metrics / Events / Trace / Transcript3.1 接入层
Claude Code 当前提供终端、IDE、桌面端、Web、CI/CD 和 Agent SDK 等多种界面。官方文档强调,不同界面共享相同的底层 Agentic Loop,变化的主要是交互方式和代码实际运行的位置。31
接入层负责把用户请求转换为统一任务输入,并附加:
- 当前工作目录;
- Git 状态;
- 会话 ID;
- 权限模式;
- CLI 或 SDK 配置;
- 附件和文件引用;
- 最大轮数和成本限制;
- 中断信号。
3.2 会话生命周期层
这一层负责:
- 接收和规范化用户输入;
- 管理多轮消息;
- 处理斜杠命令;
- 保存本地 Transcript;
- 恢复、继续或 Fork 会话;
- 跟踪 Token、成本和轮次;
- 将内部事件转换为终端或 SDK 输出。
官方文档确认 Claude Code 会把会话写入本地 JSONL,从而支持恢复、回退和 Fork。1
社区源码分析进一步将这层对应到 QueryEngine:它更关注一次用户交互是否成功、消息如何持久化、花费多少预算以及最终结果如何组装。4
3.3 Agent Runtime 层
这一层是真正的 Agent Loop:
准备上下文→ 调用模型→ 解析工具请求→ 执行工具→ 回注结果→ 判断继续或结束3.4 能力层
能力并不只包括文件读写和 Bash,还包括:
- 内置工具;
- MCP 工具;
- Skills;
- Subagents;
- Agent Teams;
- Hooks;
- Web 和代码智能插件。
官方把这些能力区分为不同扩展机制:CLAUDE.md 提供常驻上下文,Skills 提供按需工作流,Subagents 提供隔离执行,MCP 连接外部系统,Hooks 提供确定性事件自动化。5
3.5 治理层
Claude Code 可以直接在真实开发环境中产生副作用,因此必须有:
- 细粒度工具权限;
- Allow / Ask / Deny 规则;
- 不同 Permission Mode;
- 受保护路径;
- Hooks;
- Sandbox;
- 用户审批;
- 企业级 Managed Settings;
- 审计事件。
官方文档把 Permissions 与 Sandboxing 定义为互补安全层:前者控制允许做什么,后者从操作系统层限制 Bash 实际能访问什么。67
4. 双层运行时:会话引擎与 Agent 状态机分离
社区源码分析中最值得学习的设计之一,是将 Claude Code 运行时拆为两层:
QueryEngine:会话生命周期query():单次 Agent 执行循环
4.1 QueryEngine 解决什么问题
QueryEngine 关注的是“这一轮用户交互”:
- 输入是什么;
- 是否是本地命令;
- 系统提示词和记忆如何初始化;
- 消息是否持久化;
- 最大轮数和预算是否超限;
- 工具权限是否被拒绝;
- 最终输出是否有效;
- SDK 应返回哪些结构化元数据。
它类似于应用服务层或会话级 Runtime。
4.2 query() 解决什么问题
query() 关注的是一次 Agent Loop 内部的执行:
- 上下文是否需要压缩;
- 当前应该调用哪个模型;
- 流式响应里是否出现工具调用;
- 工具是否已经执行完成;
- Tool Result 如何注入;
- 是否进入下一轮;
- 是否因为 Token、Hook、预算或错误进入恢复路径。
它类似于 Agent 状态机或执行内核。
4.3 为什么要分两层
如果把所有逻辑都塞进一个循环,会形成以下耦合:
输入解析+ 会话持久化+ Prompt 构建+ 模型重试+ 工具调度+ 权限等待+ Token 统计+ UI 输出+ 最终结果提取这会导致:
- 很难对循环本身做单元测试;
- 无法复用到 Headless 或 SDK;
- 会话恢复和单轮执行相互污染;
- 错误恢复路径难以表达;
- UI 状态和核心 Runtime 紧密耦合。
双层架构把“对话外壳”和“执行内核”分开,使 CLI、SDK 和其他界面都能复用同一个 Agent Runtime。
4.4 这与 LangGraph 有什么不同
LangGraph 使用显式的:
State + Node + Edge + Reducer + CheckpointClaude Code 的社区分析则显示,它更接近手写的:
State + while/continue + Transition + Async Generator二者都在解决同一个问题:如何把非确定性模型调用约束在一个可追踪的状态机中。
差别在于:
- LangGraph 把控制流外显为图;
- Claude Code 把控制流编码在专用 Runtime 中;
- LangGraph 更通用;
- Claude Code 更贴近 Coding Agent 的具体工作负载,因此可以做更激进的定制优化。
5. 受控工具循环:为什么它不只是 ReAct

一个最小 ReAct Agent 通常可以写成:
while True: response = model(messages, tools)
if not response.tool_calls: return response.text
results = execute_tools(response.tool_calls) messages.extend(results)Claude Code 的语义骨架与此相似,但生产运行时还必须处理:
上下文预算提示缓存工具并发权限等待Hook 阻断输出 Token 截断API 重试用户中断大结果落盘会话恢复成本上限子 Agent 任务因此,更准确的抽象是:
Context Compile→ Model Decision→ Tool Admission→ Controlled Execution→ Observation Injection→ State Transition→ Recovery / Continue / Terminal5.1 模型控制语义,Runtime 控制状态
模型负责判断:
- 需要先读哪些文件;
- 应该搜索还是执行测试;
- 当前错误意味着什么;
- 下一步修改哪个位置;
- 是否已经完成任务。
Runtime 负责判断:
- 这个工具是否存在;
- 参数是否通过 Schema;
- 是否允许执行;
- 是否必须人工确认;
- 是否可以与其他工具并行;
- 是否超过最大轮数;
- 是否应该继续、恢复或终止。
这是“开放式推理”和“确定性执行”的核心分界。
5.2 错误应该被建模为状态转移
社区仓库分析出多个 Continue Site:正常工具续轮、上下文恢复、输出 Token 扩容、续写恢复、Stop Hook 阻止终止、Token 预算续跑等。4
这反映出一个生产级设计原则:
不同失败具有不同语义,不能全部交给统一重试器。
例如:
| 失败 | 合理处理 |
|---|---|
| API 暂时超时 | 指数退避重试 |
| 上下文超限 | 压缩后重试 |
| 输出 Token 用尽 | 提高上限或注入续写指令 |
| 用户拒绝权限 | 调整方案,不得原样重试 |
| 工具参数非法 | 把结构化错误回给模型修正 |
| 高风险动作 | 暂停等待人工 |
| 达到最大轮数 | 终止并返回不完整状态 |
统一 retry() 会掩盖这些差异,并可能制造死循环或重复副作用。
6. Async Generator:把 Token、工具和状态统一成事件流
社区源码分析认为,Claude Code 从模型 API 到终端 UI 广泛使用 async function* 异步生成器。8
其核心形态类似:
async function* query(): AsyncGenerator<RuntimeEvent, TerminalState> { yield { type: "message_delta", ... } yield { type: "tool_progress", ... } yield { type: "permission_request", ... } yield { type: "tool_result", ... }
return terminalState}
6.1 为什么不是普通 Promise
Promise 适合“一次调用、一次结果”:
request → await → resultAgent 任务却需要持续产生:
- 首 Token;
- 工具调用开始;
- 工具执行进度;
- 权限请求;
- 压缩边界;
- API 错误;
- 子任务通知;
- 最终结果。
如果使用 Promise,开发者往往需要额外维护:
- EventEmitter;
- 回调;
- 队列;
- AbortController;
- 完成状态;
- 错误通道。
异步生成器可以自然表达:
yield:中间事件return:最终状态throw:不可恢复异常6.2 流式不是 UI 特性,而是 Runtime 特性
很多系统只在最后一层做 Token Streaming:
模型完整生成 → 后端逐字切片 → 前端显示Claude Code 的思路更接近语义事件流:
模型事件工具事件权限事件恢复事件最终状态这样,终端、IDE、SDK 和观测系统可以消费同一条执行流。
6.3 取消和 Backpressure
异步生成器还天然有利于:
- 消费者处理速度控制;
- 用户中断;
- API Abort;
- 工具清理;
- 资源释放;
- 子任务取消。
对于长时间运行的 Agent,取消不是附加功能,而是 Runtime 的一等能力。
7. 上下文工程:每轮重新编译模型看到的世界
官方文档明确指出,Claude Code 的上下文窗口包含:
上下文不是“历史消息数组”,而是一个每轮重新生成的编译产物。

7.1 三类上下文
稳定前缀
适合长期保持不变:
- 核心 System Prompt;
- 通用行为规则;
- 安全指令;
- 稳定的工具定义;
- 输出格式约束。
会话级动态上下文
变化频率中等:
- 当前目录;
- Git 状态;
- CLAUDE.md;
- 路径级 Rules;
- 用户配置;
- 已发现 Skills;
- MCP 服务器信息;
- Auto Memory 索引。
快速增长的工作历史
每轮都会增长:
- 用户消息;
- Assistant 消息;
- Tool Use;
- Tool Result;
- 文件全文;
- Shell 输出;
- 子 Agent 摘要;
- 动态附件。
7.2 缓存感知的内容排序
Anthropic 的 Prompt Caching 以完整前缀为缓存对象,并按照:
tools → system → messages形成层级。缓存命中要求被缓存前缀完全一致,工具顺序、System 内容或早期消息变化都可能导致缓存失效。1011
这解释了为什么一个成熟 Harness 会:
- 把稳定内容放在前部;
- 避免在 System Prompt 中插入时间戳等高频变化字段;
- 保持工具排序稳定;
- 将动态信息放在后部;
- 对不常用工具使用延迟加载;
- 对会话历史使用增量缓存。
这不是简单的 Token 省钱,而是同时优化:
- 首 Token 延迟;
- 输入成本;
- 速率限制;
- 长会话吞吐。
7.3 CLAUDE.md 为什么不是硬配置
官方当前文档说明,CLAUDE.md 会以用户消息形式进入上下文,而不是成为不可覆盖的系统配置。Claude 会尽力遵循,但不保证严格执行。12
因此:
CLAUDE.md = 行为上下文不是权限系统不是策略引擎不是安全边界真正需要强制执行的规则应该放在:
- Permission Deny;
- Hooks;
- Sandbox;
- CI;
- Policy Engine;
- 静态分析;
- 代码审查。
7.4 渐进式压缩
官方确认 Claude Code 在上下文接近上限时,会优先清理旧工具输出,再在需要时对对话进行摘要;如果压缩后立即再次溢出,还会停止反复压缩,避免 Thrashing。1
社区仓库进一步将其拆成更细的流水线:
Tool Result Budget→ History Snip→ Microcompact→ Context Collapse→ Autocompact其中的核心思想是:
- 先使用本地、低成本、可逆的压缩;
- 再对局部结果做裁剪;
- 再生成只读折叠视图;
- 最后才调用模型做全局摘要。
这比“一满就总结全部历史”更稳健,因为全局摘要会:
- 增加一次模型延迟;
- 消耗 Token;
- 丢失细节;
- 可能改变早期指令语义;
- 造成摘要漂移。
7.5 Tool Search 与延迟加载
官方 MCP 文档说明,Claude Code 默认支持 Tool Search:MCP 工具定义可以延迟加载,启动时只让模型看到工具名称,真正需要时再加载完整 Schema。13
Anthropic 的 Tool Use + Prompt Caching 文档进一步说明,延迟工具不会插入稳定的 System 前缀,而是在发现后以 tool_reference 追加到历史中,因此不会破坏已有前缀缓存。11
这是一个非常重要的可扩展性设计:
能力数量可以很大≠每轮都把所有能力 Schema 塞给模型8. 工具系统:能力、权限、并发和 UI 的统一协议
Claude Code 的所有真实行动都应经过 Tool:
- 文件读取;
- 文件编辑;
- Shell;
- 搜索;
- Web;
- MCP;
- Skills;
- 子 Agent;
- 用户询问;
- 任务管理。
官方工具文档明确列出了内置工具,并允许通过 Permission Rules、Hooks、Subagents 和 MCP 对其进行控制和扩展。14
社区源码分析则把 Tool 抽象为一个包含多种行为语义的对象,而不是简单函数。15

8.1 一个生产级 Tool 应包含什么
一个成熟工具接口至少应表达:
interface Tool<Input, Output> { name: string description: string inputSchema: Schema<Input>
call(input: Input, context: ToolContext): Promise<Output>
isReadOnly(input: Input): boolean isDestructive(input: Input): boolean isConcurrencySafe(input: Input): boolean
validateInput(input: Input): ValidationResult checkPermissions(input: Input, context: ToolContext): PermissionResult
maxResultSize: number interruptBehavior(): InterruptPolicy}这意味着 Tool 同时是:
能力描述+ 参数协议+ 执行函数+ 风险声明+ 并发声明+ 权限入口+ 中断语义+ 结果格式8.2 为什么安全属性必须贴近工具
如果风险属性放在外部配置:
{ "Edit": { "readOnly": false }, "Grep": { "readOnly": true }}工具实现变化后,配置可能没有同步。
而如果工具自己实现:
isReadOnly(input)isDestructive(input)isConcurrencySafe(input)安全语义与具体输入和实现绑定,能够处理:
- 同一个 Bash Tool 中既有只读命令,也有破坏性命令;
- 同一个文件工具对不同路径风险不同;
- 某些操作只在特定环境可并发;
- 某些参数组合必须升级审批。
8.3 Fail-Closed:默认走保守路径
社区仓库分析的一个优秀设计是:
- 新工具默认不可并发;
- 默认不视为只读;
- 默认不能自动批准;
- 只有显式声明后才放宽。
这是一种 Fail-Closed 设计:
未知能力 → 保守处理而不是未知能力 → 默认放行在 Agent 工具生态快速扩展时,这一点非常关键。
8.4 流式工具预执行
社区源码分析指出,Claude Code 可能在模型流式输出期间,一旦某个完整 tool_use 块被解析出来,就立即把它送入执行队列,而不是等待整个模型响应结束。4
时间线从:
[模型完整生成][工具1][工具2][工具3]变成:
[模型持续生成................] [工具1] [工具2] [工具3]工具延迟可以被隐藏在模型生成窗口中。
8.5 并发必须由工具语义决定
正确的并发规则不是:
所有 Tool Call 都丢进线程池而是:
Read / Grep / Glob→ 通常可并行
Edit / Write / Bash / Deploy→ 默认串行或独占
具有依赖关系的命令→ 失败时取消兄弟任务工程上可以将工具状态建模为:
queued → executing → completed → yielded并保证:
- 并发安全工具可以共存;
- 非并发安全工具独占执行;
- 结果按原始 Tool Call 关联;
- 中断和错误可以传递;
- 最终回注顺序可控。
9. 安全:不是一个 Guardrail,而是纵深治理体系

Claude Code 在用户真实机器上运行 Shell,因此面临:
- 模型误操作;
- Prompt Injection;
- 恶意仓库配置;
- 路径越界;
- 命令注入;
- 凭据泄漏;
- 远程系统副作用;
- 子 Agent 权限洗白;
- 自动化疲劳导致的盲目批准。
9.1 官方确认的安全主线
官方文档确认了以下机制:
9.2 Permissions 与 Sandbox 的分工
Permission:决定 Agent 是否被允许尝试某项动作
Sandbox:即使动作已经执行,也限制进程实际能访问的文件和网络例如:
Deny Rule 阻止 Bash 尝试读取 ~/.ssh+Sandbox 从 OS 层禁止进程访问 ~/.ssh即使 Prompt Injection 绕过了模型的行为判断,操作系统边界仍然存在。
9.3 社区总结的七层纵深防御
社区仓库把安全进一步归纳为:
- 工作区信任;
- 权限模式;
- Allow / Deny / Ask 规则;
- Bash 语法与静态风险分析;
- 工具级输入和路径检查;
- Sandbox 与 Worktree 隔离;
- 用户确认。18
其中,AST 分析和具体静态检查数量属于社区源码分析结论,不应视为官方长期稳定接口;但“多种不同技术共同防守”的思想值得复用。
9.4 为什么 Prompt 不能成为安全边界
Prompt 可以告诉模型:
不要执行危险命令修改前先读取文件高风险操作先询问但 Prompt 可能因为以下原因失效:
- 模型理解错误;
- 上下文污染;
- Prompt Injection;
- 长对话压缩;
- 指令冲突;
- 工具描述不清;
- 新模型行为变化。
因此安全必须落在确定性层:
Prompt:降低危险请求发生概率Schema:阻止畸形参数Permission:决定是否授权Hook:执行组织级策略Sandbox:限制实际能力HITL:对高风险动作最终裁决Audit:记录发生了什么9.5 Checkpoint 只覆盖可逆的本地变化
官方说明 Claude Code 会在文件编辑前保存快照,支持本地回退;但数据库写入、部署、发送消息、Git Push 等远程副作用无法通过文件 Checkpoint 撤销。1
因此高风险工具必须额外具备:
- 幂等键;
- Dry Run;
- 审批;
- 前置条件;
- 后置状态校验;
- 补偿动作;
- 审计日志。
10. Hooks:把必须执行的策略从模型判断中移出
官方 Hooks 文档将 Hook 定义为在会话事件发生时自动执行的 Shell、HTTP、Prompt、MCP Tool 或 Agent 处理器。它们可以:19
- 在工具执行前阻断危险动作;
- 修改输入;
- 记录审计日志;
- 在编辑后运行格式化;
- 在停止前执行验证;
- 发送通知;
- 要求人工审批;
- 管理会话资源。
10.1 Skill 与 Hook 的根本区别
Skill:把一套知识或流程交给模型使用模型仍然决定如何执行
Hook:当事件匹配时确定性触发不依赖模型记得执行例如:
“修改后最好运行 ESLint”→ 写在 Skill 中,属于软指导
“每次 Edit 后必须运行 ESLint”→ 使用 PostToolUse Hook,属于硬流程10.2 Hook 是 Agent Runtime 的中间件
可以把 Hook 看成:
Agent Middleware / Interceptor它适合实现:
- 安全策略;
- 审计;
- 输入清洗;
- 组织级合规;
- 工具结果后处理;
- 生命周期通知;
- 自定义审批。
但 Hook 本身也可能执行代码,因此:
- 项目级 Hook 必须受工作区信任保护;
- Hook 超时不能拖死主流程;
- Hook 输出要经过 Schema 校验;
- Hook 失败要区分阻断错误和非阻断错误;
- Hook 也要被观测和审计。
11. Memory:区分常驻指令、自动记忆和当前状态

官方当前文档区分两类跨会话知识:12
| 机制 | 谁写 | 适合存什么 | 加载方式 |
|---|---|---|---|
| CLAUDE.md | 用户或团队 | 编码规范、工作流、项目架构、长期规则 | 每次会话加载 |
| Auto Memory | Claude | 发现的构建命令、调试经验、偏好和模式 | 索引常驻,主题文件按需读取 |
11.1 State 与 Memory 不是一回事
State:当前任务正在发生什么
Memory:未来会话可能复用什么例如:
当前测试失败 3 个→ State / Transcript
用户偏好所有 API 使用 Result 类型→ CLAUDE.md 或 Memory
当前正在编辑 auth.ts→ State
项目测试命令为 pnpm test→ CLAUDE.md 或 Auto Memory当前任务状态必须来自权威 Runtime,不能依赖模型“记住”。
11.2 MEMORY.md 是索引,不是数据库正文
官方文档说明,Auto Memory 目录包含:
MEMORY.mddebugging.mdapi-conventions.md...每次会话只加载 MEMORY.md 的前 200 行或 25KB,详细主题文件按需读取。12
这体现了两级结构:
常驻索引→ 告诉模型有哪些记忆
主题文件→ 真正需要时再加载它本质上是在管理:
召回能力与上下文成本之间的平衡11.3 “只记不可推导信息”应作为设计原则,而非绝对事实
社区仓库提出一个很有价值的原则:
尽量只保存不能从代码、Git 和文档重新推导的信息。20
这个原则可以防止记忆漂移。例如:
“认证模块位于 src/auth”代码重构后可能过期,重新搜索代码更可靠。
不过官方 Auto Memory 示例包含构建命令、架构笔记和调试经验,其中一部分理论上也能从项目中重新推导。因此,更准确的工程建议是:
权威事实优先实时读取;只有在重新推导成本高、语义隐含或来自用户反馈时,才进入长期记忆。11.4 记忆写入必须有 Policy
企业 Agent 不应让模型随意写长期记忆。需要判断:
- 是否稳定;
- 是否有未来价值;
- 是否包含敏感信息;
- 是否能从权威源重新获取;
- 是否需要用户确认;
- 是否有时效;
- 是否与旧记忆冲突;
- 是否需要记录来源和时间。
推荐结构:
type: feedbacksource: user_explicitcreated_at: 2026-07-24confidence: highexpires_at: null12. Skills:按需加载的行为包与工作流模板
官方将 Skill 定义为一个以 SKILL.md 为核心的能力包,可以包含:
- 描述;
- 使用条件;
- Prompt;
- 工具白名单;
- Supporting Files;
- 动态上下文;
- 子 Agent 执行配置;
- 调用控制。21
12.1 Skill 适合解决什么
当某段 CLAUDE.md 逐渐变成:
- 多步骤流程;
- 检查清单;
- 大型参考文档;
- 特定任务模板;
- 可重复执行的操作说明;
就应该移入 Skill。
因为:
CLAUDE.md:每轮都加载Skill:只在需要时加载12.2 Skill 的渐进披露
官方文档说明,模型可调用 Skill 时,启动阶段通常只加载名称和描述,完整正文在 Skill 被使用时才进入上下文。219
这是一种 Progressive Disclosure:
先暴露能力目录→ 模型发现匹配能力→ 再加载完整操作手册它让系统能拥有大量技能,而不让每轮上下文爆炸。
12.3 Description 就是语义路由接口
模型是否自动选择 Skill,主要依赖:
- 用户请求;
- 当前上下文;
- Skill 的名称和描述。
因此 Description 不是普通文案,而是能力路由的核心协议。
好的描述应包含:
什么时候使用什么时候不要使用输入需要什么会产生什么结果有何风险或限制12.4 Skill 不是强制策略
Skill 进入模型上下文后,仍属于模型可解释的软指令。
如果流程必须每次执行,应使用 Hook、Workflow 或代码状态机,而不是依赖 Skill。
13. MCP:统一外部能力,但不能跳过 Harness 治理
官方将 MCP 定义为连接 AI 应用与工具、数据源和服务的开放协议。Claude Code 可以通过 MCP 接入数据库、Issue Tracker、监控系统、设计平台和内部 API。13
13.1 MCP 解决的是能力互操作,不是自动安全
MCP 提供:
- 工具发现;
- Schema;
- Resources;
- Prompts;
- Transport;
- OAuth;
- 动态能力更新。
但 MCP 工具仍必须进入 Claude Code 的:
Tool Search→ Tool Registry→ Permission→ Hook→ Execution→ Result Processing外部工具不能因为是 MCP 就绕过安全层。
13.2 MCP Tool Search 的架构价值
当工具数量从 10 个增长到 1000 个时,直接加载所有 Schema 会带来:
- Context 爆炸;
- Prompt Cache 失效;
- 工具选择准确率下降;
- 首次请求延迟升高;
- 无关能力干扰。
官方 Tool Search 采用:
启动只加载名称→ 需要时搜索→ 按需加载完整工具定义这使 Capability Registry 可以扩展,而不把复杂度全部转嫁给模型上下文。13
13.3 大结果必须外部化
MCP、Shell、搜索和数据库查询都可能返回巨大结果。
成熟 Harness 应支持:
小结果 → 直接回注中结果 → 截断 + 摘要大结果 → 落盘 / 对象存储 + 返回引用模型需要全文时再分块读取,而不是把 100K 字符一次塞入上下文。
14. 多 Agent:核心不是角色数量,而是隔离与治理
官方 Subagent 文档强调,每个 Subagent 都拥有:22
- 独立上下文窗口;
- 自定义 System Prompt;
- 特定工具权限;
- 独立 Permission;
- 可选择不同模型;
- 完成后只向主会话返回摘要。

14.1 为什么 Subagent 要独立上下文
一个搜索型子任务可能产生:
- 数十个文件内容;
- 大量日志;
- 中间假设;
- 无关搜索结果。
如果全部进入主上下文,会造成:
- 主任务被噪声污染;
- Token 费用上升;
- 压缩提前触发;
- 关键指令被稀释;
- 后续推理注意力分散。
Subagent 用自己的上下文处理这些材料,只返回结论,相当于一种“语义 Map-Reduce”。
14.2 工具隔离比角色 Prompt 更重要
只给角色名字:
你是安全专家并不能构成真正隔离。
更重要的是:
Explore Agent→ 只读工具→ 快速模型→ 独立上下文
Plan Agent→ 只读工具→ 强推理模型→ 结构化计划
Implementation Agent→ Edit / Bash→ 更严格 Permission→ Worktree 隔离这体现最小权限原则。
14.3 文件系统隔离
并行 Agent 如果共享同一工作区,可能同时修改同一文件。
可选策略:
- 文件所有权分区;
- 乐观锁;
- Patch 合并;
- Git Worktree;
- 独立容器;
- 最终 Integrator 统一合并。
官方文档把 Worktree 作为并行会话隔离方式;社区仓库也将 Worktree 视为多 Agent 避免代码冲突的重要手段。2324
14.4 从模型编排到确定性编排
少量任务可以让模型动态决定:
派谁何时派如何汇总但规模扩大后会遇到:
- 重复派发;
- 并发失控;
- 等待屏障不合理;
- 中间格式不稳定;
- 无法断点续跑;
- 成本不可预测。
社区仓库对 Dynamic Workflow 的黑盒分析提出一种值得关注的模式:由主模型生成确定性脚本,再由 Runtime 执行 agent()、pipeline()、parallel() 和 Schema 校验。25
该结论属于黑盒逆向,不应视为官方稳定接口,但它揭示了一条普遍规律:
开放探索留给 Agent大规模编排交给确定性 Runtime推荐演进路径:
小任务:单 Agent独立副任务:Subagent多 Worker 并行:Coordinator / Team大批量任务:Deterministic Workflow + Agent Workers15. 可观测性:把一次 Agent 任务做成 EXPLAIN

官方 Claude Code 监控文档支持通过 OpenTelemetry 导出:
- Metrics;
- Events / Logs;
- 可选 Traces;
- 工具、权限、Hook 和 API 活动。26
同时,官方说明本地会话会保存为 JSONL Transcript,用于恢复、回放和 Fork。1
15.1 四种记录回答不同问题
Metrics:总账
回答:
- Token 用了多少;
- 成本是多少;
- 有多少会话;
- 修改了多少行;
- 创建了多少 Commit 和 PR。
Metrics 必须控制标签基数,不能把每个 Prompt ID 都作为维度。
Events:离散行为
回答:
- 哪个工具被调用;
- 是否成功;
- Permission 是允许还是拒绝;
- Hook 是否阻断;
- MCP 是否连接失败;
- API 最终是否重试耗尽。
Trace:因果链
回答:
- 哪个模型调用最慢;
- 工具执行耗时多少;
- 等待用户权限用了多久;
- 子 Agent 属于哪个父任务;
- 一次任务的调用树是什么。
Transcript:本地事实记录
回答:
- 会话发生过哪些消息;
- Tool Use 和 Tool Result 是什么;
- 如何 Resume;
- 从哪个节点 Fork;
- 压缩边界在哪里。
15.2 ID、树和聚合不能混为一谈
社区仓库对观测系统的一个优秀总结是:
离散事件用 ID 关联因果关系用 Span 树表达聚合指标拒绝高基数 ID这适用于任何 AgentOps 系统。
15.3 默认保护隐私
官方 OTel 文档说明:
- 用户 Prompt 默认不记录;
- Tool 参数默认不记录;
- Tool 内容默认不记录;
- 原始 API Body 默认不记录;
- 开启详细日志时可能暴露敏感数据,需要额外脱敏和后端治理。26
因此可观测性不是“记录越多越好”,而是:
可诊断性×隐私×成本×基数之间的平衡。
16. 性能优化:为什么 Claude Code 给人“很快”的感觉
用户感知速度不只由模型 Token/s 决定。
可以拆为:
首次可见反馈时间+ 模型首 Token+ 工具等待+ 上下文预处理+ UI 渲染+ 用户权限等待Claude Code 的 Harness 通过多种方式隐藏延迟。
16.1 全链路流式事件
模型开始生成后立即输出,不等待完整响应。
16.2 工具流式预执行
社区源码分析认为,完整工具块一旦解析完即可开始执行,将工具延迟覆盖在模型生成时间中。4
16.3 记忆与能力预取
与模型调用并行:
- Memory 召回;
- Skill 发现;
- MCP 连接;
- 工具准备;
- UI 初始化。
16.4 Prompt Cache
稳定的 Tool 和 System 前缀可以复用缓存,减少重复输入处理。官方 Prompt Caching 文档确认,缓存命中可以降低延迟、费用并改善速率限制利用率。10
16.5 延迟加载
不常用的:
- MCP 工具;
- Skill 正文;
- 观测 Exporter;
- 子 Agent 上下文;
- 大型参考资料;
不进入冷启动关键路径。
16.6 速度的真正公式
感知速度≈尽早反馈+ 并行隐藏等待+ 缓存稳定前缀+ 减少无效上下文+ 限制串行关键路径17. 可靠性:预算、恢复与终止条件
开放式 Agent 最大风险之一是“不知道什么时候停”。
一个生产 Harness 至少要限制:
{ "max_turns": 30, "max_tool_calls": 50, "max_parallel_tools": 8, "max_subagents": 10, "max_cost_usd": 5, "max_duration_seconds": 1800, "max_context_compactions": 3}官方 CLI 和 Agent SDK 提供最大轮数、权限模式、工具列表和成本控制等接口。2728
17.1 恢复不能制造重复副作用
如果模型调用后网络中断,不能简单重放所有工具。
副作用工具需要:
- Idempotency Key;
- Execution ID;
- 状态查询;
- Exactly-Once 的业务近似;
- 可补偿操作;
- Tool Result 持久化。
17.2 终止不是只看“模型不再调用工具”
还应该检查:
- 任务目标是否达成;
- 测试是否通过;
- 必要工具是否执行;
- 是否有未处理错误;
- 是否等待人工;
- 是否达到预算;
- 是否重复循环;
- 是否出现上下文 Thrashing。
17.3 Verifier 优先使用确定性信号
验证顺序建议:
测试 / 编译 / 数据库状态>静态规则 / Schema>专用判别器>通用 LLM 自我反思只要存在可执行标准,就不应让模型仅凭文本判断“完成了”。
18. Claude Code Harness 的关键设计原则
原则一:模型负责语义决策,代码负责硬约束
模型决定下一步应该做什么;Runtime 决定是否允许、如何执行、如何恢复。原则二:所有副作用必须经过 Tool
模型不能绕过能力接口直接操作真实世界。
原则三:上下文是编译产物
每轮都要选择、排序、压缩、隔离和缓存,而不是机械拼接历史。
原则四:工具应携带风险与并发语义
isReadOnly、isDestructive、isConcurrencySafe 应是一等属性。
原则五:默认保守
未知工具、未知路径、未知副作用和未知权限应进入更严格流程。
原则六:错误是状态转移
上下文超限、Token 截断、权限拒绝和工具失败不能走同一重试逻辑。
原则七:记忆不能替代权威数据源
代码读代码,Git 读 Git,业务状态查业务系统。
原则八:多 Agent 优先做隔离
独立上下文、最小工具、文件隔离、结构化结果比角色命名更重要。
原则九:规模越大,编排越应确定性化
小范围探索可由模型控制,大规模 fan-out 应由 Workflow Runtime 管理。
原则十:观测系统必须与隐私和成本共同设计
不是“全量记录一切”,而是按 Metrics、Events、Trace 和 Transcript 分层。
19. 从 Claude Code 抽象出的企业级 Harness 参考架构
Client / API / IDE / Chat ↓Session Gateway- auth / tenant / trace_id- input normalization- stream protocol ↓Context Compiler- system policy- conversation state- memory retrieval- RAG evidence- capability discovery- token budget ↓Agent Runtime- planner / router- model loop- transition state machine- max steps / cost / time ↓Tool Admission- registry- schema- permission- policy- HITL ↓Tool Executor- concurrency semantics- timeout / retry- idempotency- sandbox- result normalization ↓Verifier- postcondition- business state check- tests / rules ↓State / Checkpoint / Transcript ↓Metrics / Events / Trace / Eval19.1 哪些层可以交给框架
LangGraph、Temporal、Agent SDK 等框架可以帮助实现:
- 状态机;
- Checkpoint;
- 中断恢复;
- 节点执行;
- Streaming;
- 工具循环;
- 子图;
- Trace。
19.2 哪些问题框架不会替你解决
框架无法自动决定:
- 哪些工具是危险的;
- 哪些字段允许并发写;
- 哪些结果是权威事实;
- 哪些动作必须人工审批;
- 业务完成条件是什么;
- 哪些记忆应该持久化;
- 什么错误可以安全重试;
- 多 Agent 是否真的比单 Agent 更好。
Harness 的核心仍然是业务和系统设计。
20. 不应该照搬 Claude Code 的地方
Claude Code 是 Coding Agent,其工作负载有特殊性:
- 文件系统是主要工作空间;
- Git 提供天然版本控制;
- 测试和编译提供明确 Verifier;
- Shell 是通用能力入口;
- Worktree 可用于隔离;
- 大多数操作发生在本地环境。
企业业务 Agent 可能完全不同:
| Coding Agent | 企业业务 Agent |
|---|---|
| 文件编辑可本地回滚 | 订单、支付、消息可能不可逆 |
| Git 是权威历史 | 数据库和审计系统是权威历史 |
| 测试是主要验证器 | 业务规则和状态查询是验证器 |
| Worktree 隔离代码 | 租户、权限和事务隔离业务数据 |
| Shell 是通用工具 | 工具通常是受控业务 API |
| 用户是开发者 | 用户可能不理解技术风险 |
因此不能简单复制:
开放 Bash宽松自动审批模型自主决定所有步骤本地 Transcript 作为唯一状态应该抽取其原则,而不是复制具体实现。
21. 结论
Claude Code 的价值不只是“Claude 模型会写代码”,而是它构建了一套围绕模型的生产级执行系统。
可以用下面的公式概括:
Claude Code=LLM 决策循环× 上下文编译器× 统一工具协议× 流式执行引擎× 权限与沙箱× 恢复状态机× 记忆与技能× 隔离式多 Agent× 可观测运行时真正决定系统质量的边界是:
模型提出动作Harness 管理后果模型能力升级会提高推理和生成上限,但如果 Harness 缺少:
- 上下文治理;
- 工具 Schema;
- 权限;
- 并发控制;
- 状态持久化;
- 终止预算;
- 错误恢复;
- Verifier;
- 观测与评估;
Agent 仍然只能停留在 Demo。
Claude Code 给 Agent 工程最重要的启示不是“如何写一个更长的 Prompt”,而是:
把模型的不确定智能放进一个确定、可控、可恢复、可审计的运行环境中。