0. 阅读说明与源码边界

Harness Engineering

0. 阅读说明与源码边界

0.1 源码位置

  • Claude Code:claude-code-complete-original 仓库;后文路径均相对该仓库根目录。
  • Codex:codex 仓库;后文路径均相对该仓库根目录。
  • DeepSeek Harness:/deepseek-harness 仓库;本次渗透式阅读以 47f943859b(0.1.0-rc.5)为证据基线,后文 packages/...、docs/...、examples/... 路径均相对该仓库根目录。
  • 岗位要求:Agent岗位HC梳理-技术要求分级.md。

Claude Code 目录是从发布包与 source map 还原的代码快照,部分重复的 src/cli/src/... 文件只是类型占位;本文优先引用包含实际实现的根 src/...。Codex 是 Rust 多 crate 工程,核心循环主要位于 codex-rs/core,长期记忆、沙箱、技能和追踪分别拆到独立 crate。DeepSeek Harness 是 TypeScript/pnpm monorepo,底层使用内置 Cordis 组装插件树;它处于开发者预览期,因此本文优先引用稳定职责、事件词汇和能力分层,不把当前包名视为永久兼容承诺。

0.2 工程结论的证据等级

  • 源码事实:能在本地源码中直接定位到结构、状态或控制流。
  • 架构推导:源码没有同名类,但可以从多个模块的协作关系得出,例如“SuperAgent 路由”。
  • 工程设计:岗位要求存在,但开源快照没有完整产品实现,需要给出合理设计,而不能冒充源码事实。

0.3 企业岗位能力优先级

优先级知识维度岗位侧原因
P0Harness、Runtime、Agent Loop、Tool Use、Context、Memory、可观测、权限、沙箱多数 Harness/架构岗位直接要求,决定系统能否生产化
P0MCP、Multi-Agent、Session/状态持久化多个岗位要求协议接入、子 Agent 编排、长任务恢复
P1Skill、Planning、长期/短期记忆、上下文压缩与窗口决定能力扩展、长程任务成功率与成本
P1Agent 交互体验、Prompt/Context Engineering前端、全栈、AI Native 岗位重点

0.4 源码阅读方法:从文件名定位到可验证调用链

阅读两套源码时不要从类名猜架构,而应固定追踪五个问题:入口是谁、状态归谁、外部副作用在哪里发生、事实在哪里持久化、失败后从哪里恢复。

  • Claude Code:先从 query.ts/QueryEngine.ts 找模型循环,再沿 ToolUse 进入 toolOrchestration.ts → toolExecution.ts → 具体 Tool;状态侧沿 sessionStorage.ts/conversationRecovery.ts,安全侧沿 permissions/* → sandbox-adapter.ts,最后用 UI/Telemetry 文件确认用户可见投影。源码快照中存在 src/cli/src/... 等类型占位,必须优先打开含真实函数体的根 src/...。
  • Codex:从 core/src/tasks/regular.rs 进入 session/turn.rs,再沿 run_sampling_request → ToolRouter/Handler → sandboxing;Conversation Item 与协议 Event 分别追到 state.history/Rollout 和事件通道。跨 crate 类型要继续追到 protocol/skills/sandboxing/otel,不能只看调用端 trait。
  • DeepSeek Harness:先从 packages/bundle/base/cordis.patch.yml 和 packages/boot/app-boot/src/profile.ts 确认实际组装,再沿 core/agent-loop/src/agent.ts → core/tools/src/index.ts → 能力 Consumer/Provider 追控制流;状态侧沿 core/session → session-persistence → session-projection,安全侧沿 user-approval/sandbox-policy → fs-sandbox/bash-sandbox → sandbox-local。每个能力都要同时确认 Service Definition、Provider 和 Consumer,只看某个 ctx 服务定义不能证明产品已组装该能力。
  • 验证顺序:先确认数据结构,再确认创建点和消费点,最后确认异常/取消分支。只有定义没有调用可能是 Stub;只有 Feature 名没有启用路径不能视为默认能力。
  • 引用原则:工程分析中优先引用“稳定职责 + 调用链”,行号只用于现场核查。源码版本变化后行号会漂移,但 Session → Turn → Step → ToolCall 等领域关系和安全不变量更稳定。

建议为每个结论保留一条最短证据链,例如:模型产生 ToolUse → Schema 校验 → Hook → 权限 → 沙箱 → ToolResult → Rollout。如果无法把结论落到至少两个相邻环节,就应降级为架构推导而不是源码事实。

源码阅读最终要还原的不是“有哪些文件”,而是三个互相约束的模型:领域模型解释 Session、Turn、Step、ToolCall 等对象分别拥有哪段状态;控制模型解释正常、重试、取消、压缩和恢复怎样迁移;信任模型解释模型、外部工具、Hook、MCP、子 Agent 与 OS 各自能提出什么、又由谁强制执行。后续每章都按这三个模型展开,因此同一段源码可能同时出现在 Runtime、Session 和可观测章节,但解释角度不同。

0.5 术语使用约定

本文优先使用容易理解的中文。确实属于工程领域的固定术语,在第一次出现时说明含义:

  • 终态(terminal state):状态机中不会再回到运行阶段的最终状态,例如完成、失败或取消。
  • Turn 与 Step:Turn 是围绕一次用户目标展开的完整执行过程;Step 是其中一次“构建上下文并调用模型”的步骤。一个 Turn 通常包含多个 Step。
  • Runtime(运行时 / 执行内核):程序真正运行期间,负责把静态配置和模型输出变成受控执行过程的系统组件。本文单独写 Runtime 时,默认指 Agent Runtime:它接收 Turn,驱动一个或多个 Step,协调 Context 构建、模型调用、ToolCall、权限、沙箱、状态持久化、预算、取消、重试和停止判断。模型只提出“回答或执行什么”,Runtime 决定“当前能否执行、怎样执行、结果保存在哪里、失败后如何恢复、何时结束”,因此 Runtime 不是模型本身,也不只是一个工具执行器。若写 Sandbox / Exec Runtime,特指真正运行命令或代码并强制资源隔离的执行环境;若写 MCP Runtime,特指管理 MCP Server 连接、工具目录及当前可用连接快照的子系统。
  • 快照(snapshot):某一时刻固定下来的状态副本,用来保证一次判断和执行看到相同数据。
  • 投影(projection):根据事件记录计算出的查询或展示视图;它可以重新生成,不是原始记录。
  • 幂等(idempotency):同一个请求重复执行,不会产生额外副作用。
  • 原子操作(atomic operation):一组更新要么全部成功,要么完全不生效,其他线程或恢复过程看不到只完成一半的中间状态。
  • 检查点(checkpoint):保存到持久化存储中的恢复位置;重启后可从这里继续,而不必从头执行。
  • 背压(backpressure):生产事件的一方过快时,由队列上限、暂停读取或丢弃低价值进度等方式保护消费方。
  • 熔断(circuit breaker):外部服务连续失败时暂时停止调用,等待恢复后再试,避免故障持续拖慢整个 Agent Loop。
  • 执行产物(Artifact):计划文件、代码补丁、完整日志、图片等需要独立保存,并通过 ID 或路径引用的结果。
  • 来源记录(provenance):记录一条信息来自哪个会话、工具或文件,以及经过了哪些提取、摘要或合并步骤。
  • 事件游标(event cursor)与递增事件序号(ordinal):前者表示客户端已收到哪个位置,后者表示事件在会话中的稳定顺序,两者共同支持断线续传。
  • 检查与执行之间发生变化的问题(TOCTOU):系统完成权限检查后,真正执行前,路径、工作目录或目标对象发生变化,导致实际动作不再是刚才批准的动作。
  • Rollout / Transcript:按发生顺序保存的会话与执行记录,用于恢复、回放和审计;本文在解释原理时统称“原始事件记录”。
  • 租约(lease)与防过期令牌(fencing token):租约限制 Worker 的执行时间;防过期令牌用于拒绝租约已经失效的旧 Worker 提交结果。
  • 控制面与执行面:控制面决定允许做什么,执行面负责真正执行并强制限制。

本文不使用含义不清的自造简称。凡是可以直接说明动作或状态的地方,统一写成“创建 Turn 并先持久化”“持久化事件记录”“连接版本”“不破坏调用配对的切分位置”和“缩小到最小权限范围”等直白表达。

0.6 先看全局:用一条 Agent Loop 主线理解全书

第一次阅读不需要立刻记住所有模块。先抓住一条主线:用户提出目标,Runtime 为本次 Step 构建 Context,模型决定回答或调用工具;工具经过权限与沙箱执行,结果先持久化,再进入下一次 Step;直到系统验证任务完成,Turn 才能结束。 Memory、Skill、MCP、Planning、Multi-Agent、安全和可观测都服务于这条主线。

图表加载中…

这张图先建立五个关键认识:

  1. Harness 是外壳:它把 Runtime、Context、工具、安全、状态和观测组合成可运行系统。
  2. Agent Loop 是主链:一次 Turn 可以包含多次 Step;每次工具结果都可能触发下一次模型采样。
  3. 模型只有提议权:模型不能直接操作文件、网络或进程,副作用必须经过权限和沙箱。
  4. Context 是本轮输入,不是全部 Memory:Context Builder 从历史、Skill、Memory 和环境中选择有限内容发送给模型。
  5. 恢复依赖持久化事件:ToolCall、ToolResult、审批和计划版本必须有稳定 ID,进程重启后才能判断从哪里继续。

0.6.1 一次 Turn 的精简流程

图表加载中…

上下文压缩通常发生在“准备下一次模型采样”之前:当前历史可能尚未超限,但加上新的用户输入、工具结果、环境变化和工具 Schema 后,预计输入将接近窗口上限。第 9、10 章解释具体触发条件,第 25.5 节给出完整流程图。

0.6.2 建议学习顺序

学习阶段建议章节需要回答的问题
先掌握主链1 → 2 → 4 → 14 → 17Harness 如何围绕 Session、Turn、Step 和 ToolCall 运行?
再理解模型看到什么11 → 12 → 10 → 9 → 5 → 7 → 8 → 15Prompt、Context、窗口、压缩、Skill 和 Memory 如何协作?
再理解复杂任务16 → 3 → 6计划如何变成任务,子 Agent 如何协作,MCP 如何提供外部工具?
再补生产边界19 → 20 → 13 → 18权限和沙箱如何限制副作用,用户如何观察和控制,系统如何定位问题?
最后做系统设计23 → 24 → 25如何把正常流程、异常恢复、安全和质量闭环串成完整架构?
专项学习 Harness 优化26如何用 Trace、Eval、留出集和回归门禁提高固定模型的复杂任务成功率?
专项渗透 DeepSeek Harness27,再回到 1–20 章各自的 DeepSeek 映射一切皆插件如何落到组装、日志、能力 seam、安全和界面?
按需查证与备考21、22到哪里找源码证据,哪些知识需要优先掌握?

推荐采用“两遍地图法”:开始学习时只看本节的精简地图,知道每章处于 Agent Loop 的哪个位置;学完专题后再回到第 25 章,用全景架构图、端到端时序图、状态恢复图、Context–Memory 图、安全执行图和 Multi-Agent 图检查知识是否真正连通;再用第 27 章的 DeepSeek Harness 实装检查每个抽象是否能落到真实插件、事件和持久化边界;最后阅读第 26 章,练习如何把一次真实失败转化成可验证的 Harness 改进。

0.6.3 核心对象如何组织

理解 Agent 系统最容易混淆的地方,是把 Session、Turn、Step、Task 和 Agent 都当成“任务”。它们实际处于不同维度:前三者描述一次会话怎样执行,Task 描述工作怎样拆分,Agent 描述由谁执行。

图表加载中…

需要记住四条边界:

  • Session 包含多个 Turn,Turn 包含多个 Step;工具结果通常结束一个 Step,但不一定结束 Turn。
  • ToolCall 属于某个 Step;Approval 和 ToolResult 必须通过同一个 call_id 与它关联。
  • Plan 与 Task 不等于模型历史;它们是可持久化、可验证的结构化工作状态。
  • Agent 是执行者,不是 Task 本身;任务可以更换负责人,Agent 退出也不代表任务已经完成。

0.6.4 六层架构与各层职责

图表加载中…

这不是严格的网络分层,而是职责分层。判断模块放在哪一层时,可问:它是在接收用户意图、控制流程、执行动作、提供能力、保存证据,还是强制资源边界?例如 Approval 属于控制层,Sandbox 属于基础设施强制边界;二者都与安全有关,但不能互相替代。

0.6.5 什么情况会进入特殊流程

图表加载中…

面对异常时,先判断事实状态,再选择动作:是否已经产生副作用、结果能否确认、操作是否幂等、策略是否允许重试、旧 Context 是否仍有效。不能只根据错误字符串决定“重试还是停止”。第 25 章会把这些判断展开成完整决策树。

最后更新 8/18/2026, 10:55:01 AM