DeepSeek Harness 设计解析:从 Agent Harness 的六个关键决策讲起

Agent 声称任务完成,测试却没跑;长任务跑了一阵,开头的约束开始丢失;重开会话需要反复交代背景;想让它离线跑,又频繁卡在权限确认上。

本文沿用「How to Design an Agent Harness」(下文简称:Agent Harness 设计)中归纳的六个设计面,并以 DeepSeek Harness(dsh) 为工程样本,围绕这些问题展开:Loop 如何驱动、工具如何暴露、上下文如何组装、状态如何跨崩溃恢复、权限如何设防,以及任务如何验收。

Loop 决定任务如何持续运行

最基础的 Agent Loop 逻辑并不复杂:Harness 将任务与当前上下文提交给模型,模型返回工具调用,Harness 执行对应工具,再将结果放回上下文,驱动模型决定下一步。但进入长程任务以后,Harness 还需要在基础 Loop 之外管理完整的执行生命周期。

基础 Loop 之外,长程执行还需要处理四类问题:停止条件、异常结束、资源上限和运行记录。

首先需要明确停止规则,在执行前定义什么算完成。例如"测试全部通过且应用正常启动",不能只依赖"Agent 声明自己做完了"。

其次要预设异常分支:中途遇阻后,是携带失败信息重新启动,还是停止并等待人工介入,需要提前确定。

长任务还需要设置资源硬上限,例如限制执行轮次或实际运行时间,防止 Agent 长时间围绕同一个失败状态重复消耗 Token。对于无人值守任务,则需要保留可追溯的逐轮日志,记录每一轮发生了什么,否则执行偏离后很难回溯定位。

DeepSeek Harness 在系统层进一步拆开了这套执行生命周期。

在基础执行层,它将过程划分为轮次和步骤 :一个步骤对应一次模型请求以及这次请求触发的工具调用;一个轮次可以包含零个或多个步骤,由默认的 agent-loop 负责驱动。

在需要多轮持续推进的任务中,DeepSeek 提供了两套不同的执行机制:Goal Round 和 Ralph Run

Goal Round 会继续使用当前会话,因此可以保留已有的对话上下文;Ralph Run 则由多个独立的 Ralph round 组成,每一轮都会启动新的子 Agent,不继承父级会话的对话历史。不同轮次之间的信息,主要通过共享工作区和一份长度受限的结构化交接报告进行传递。

两套机制在上下文继承、状态传递和继续执行的授权方式上采用不同策略。 DeepSeek 没有把这些重复执行机制统一收进一个通用 Loop,而是让 Goal 和 Ralph 分别维护自己的生命周期,并建立在现有的 Agent、会话、工具和 Workflow 等能力之上。定时 /loop 或是定时执行则属于另一类机制,由调度器负责管理,不属于 Goal / Ralph 的生命周期。

目前 Goal 与 Ralph 已经提供轮次上限功能,但跨轮聚合的 Token、费用和总耗时等预算机制当前尚未实现。

长程 Agent 的 Loop 设计因此覆盖了停止条件、异常处理、上下文继承、继续执行的授权、资源边界和运行记录。重复调用模型只是其中最基础的一步。

工具设计决定 Agent 的行动空间

模型无法直接感知宿主机或后端基础设施,它所理解的"外部世界",由 Harness 暴露给它的工具 Schema 定义。工具的名称、功能描述、输入参数和返回结果,共同构成模型可以选择的行动空间。

工具接口主要需要处理四件事:控制暴露范围、设计错误反馈、减少能力歧义,以及规范命名与分组。

首先要避免全量前置加载。不要每轮都把所有工具描述塞进上下文,尤其挂载多个 MCP Server 后,大量静态描述会持续占用有效 Token。一个具体做法是把工具描述保存为可按需读取的文件,让 Agent 只加载当前任务需要的能力。

其次,错误信息也是接口的一部分 。相比只返回 invalid request 这类模糊错误,更有效的返回应该明确告诉模型哪个字段出错、合法输入是什么、下一步可以怎样修改。

还需要主动缩减工具列表。长期没有使用、职责重复或者名称高度相似的工具都会扩大模型的选择空间。工具的命名与分组同样会影响模型的选择行为,前缀、后缀和分类方式并不只是代码层面的命名问题。

DeepSeek Harness 的工具注册表将模型可见的 Schema 与运行时实现分开。模型请求收到的是经过筛选的工具 Schema;真正的 execute、超时设置、并发属性和 UI 展示逻辑等运行时信息不会发送给模型。工具还可以通过作用域配置 allow / deny,进一步限制当前 Agent 能看到哪些继承而来的能力。

Agent 预设则负责按会话组合工具、提示词和其他能力。其中与本文工具设计直接相关的三种内置模式是:

  • Minimal 模式只提供可保持会话状态的 Bash 和 str_replace_editor 两个工具;

  • Standard 模式提供文件编辑、Shell、文件与 Web 检索、Skills、Plan、Goals、子 Agent 和 Workflow 等完整的 Coding Agent 能力;

  • PTC 模式具备 Standard 的全部能力,但通过 Code Mode SDK 暴露工具,让模型可以使用一个 TypeScript 程序组合多步操作。

因此,Harness 中的工具设计可以拆成三个层次:系统拥有哪些能力、当前 Agent 可以看到哪些能力、这些能力以什么形式交给模型。

工具管理的目标,是根据任务控制 Agent 的行动空间,而不是默认把 Harness 已经接入的所有能力全部暴露给模型。

上下文管理决定模型当前看到什么

长上下文窗口扩大了单次推理能够容纳的信息量,但并未取消上下文管理的必要性。

随着任务深入,对话历史、工具返回、代码片段和运行日志持续累积,Harness 需要不断决定:哪些信息继续留在当前模型输入中,哪些历史可以压缩成摘要,哪些硬性约束不能在压缩过程中丢失。

长任务的上下文管理可以拆成四个动作:控制水位、按阶段切换、固定长期规则,以及在上下文被污染后主动重置。

首先是主动控制上下文水位。不要因为模型拥有很长的上下文窗口,就一直使用到理论极限。「Agent Harness 设计」给出的建议是,即使面对百万 Token 的上下文模型,也会在约 300K~400K Token 时考虑主动结束当前会话。这不是通用阈值,核心原则是主动控制上下文规模,而不是等到窗口溢出。

其次是按任务阶段切分上下文。例如调研完成后先沉淀为文档,再启动干净会话制定 Plan;Plan 完成后,用计划和必要材料进入实现阶段。跨阶段传递的是结构化产物,而不是未经整理的全部历史。

还需要区分事实与规则。探索过程中积累的事实可以被压缩,长期规则不能随普通历史一起消失。例如"不能操作生产环境""不能提交密钥""API 契约已经固定"等规则,可以写入 Agent 每次重置后重新读取的文件,并在系统提示词中重复强调。

如果早期错误假设已经进入上下文,并被后续推理持续当成既定事实,则需要识别上下文污染并主动重置。继续在同一个会话中追加信息可能只会放大偏差,此时应重新启动干净会话,再从外部状态恢复任务。

DeepSeek Harness 会在每次模型请求前重新构造模型可见输入。其中,系统提示词组装负责组合提示词片段、动态上下文、工具 Schema 等内容,会话日志则提供对话历史的来源。Agent 生命周期中的其他扩展点也可以影响当前请求最终看到的信息。

上下文压缩被设计成独立的可选能力,并没有固定写进 Agent Loop。当出现上下文压力或 context-overflow 时,系统可以选择一段模型当前可见的历史生成摘要,再用摘要替换模型后续看到的那部分内容。被替换的原始事件以及压缩过程本身的记录仍然保留在持久日志中。

这里存在两个不同层次:上下文决定模型当前看到什么,持久状态记录系统已经发生过什么。

上下文可以动态重组、分阶段重置和局部压缩;持久日志则负责保留执行历史,用于恢复和重建。

上下文窗口变长以后,Harness 仍然需要控制每一步实际进入模型的信息,并保证关键规则在压缩或重置后能够继续生效。

持久化状态决定任务中断后如何继续

只存在于对话中的信息,会随着上下文重置、进程退出或会话结束而消失。长程 Agent 因此需要一套独立于当前对话的持久状态。

一种成本很低的状态持久化方式,是直接在代码仓库中维护四个文件。

SPEC.md 定义最终要做什么,由人维护,Agent 不修改,用来避免长任务中的目标漂移;PLAN.md 记录执行步骤,每一步都带有明确的验收条件。相比"改进错误处理",更好的写法是明确某个请求应该返回什么状态码,以及对应测试必须通过。

PROGRESS.md 记录已经完成什么、下一步是什么,以及哪些办法已经尝试但失败,新的 Agent 可以首先从这里恢复任务进度;DECISIONS.md 则采用只追加方式,记录已经做出的关键选择及原因,避免后续会话重新讨论已经解决的问题。

在此基础上,每一个可以正常工作的修改都做一次小粒度 Git 提交 。这样可以直接通过 git revert 回滚,通过代码差异进行审查,Git 历史本身也能承担一部分任务执行记录。

如果项目包含大量相对独立的功能,还可以增加一个简单的 JSON 状态表,记录每个功能当前是通过还是失败。

「Agent Harness 设计」中将这一套状态设计概括为:If it isn****'t in a file, it doesn't exist.

DeepSeek Harness 将同一类问题进一步系统化到会话层一个会话的核心是一条只追加的 SessionEvent 事件日志。用户消息、Agent 回复、工具调用、工具结果、轮次、步骤,以及 Goal、授权确认、上下文压缩等状态都会作为事件持续追加。模型使用的消息历史同样从这条事件日志中派生。

官方架构将这一约束表述为:**Model-visible means logged。**也就是:凡是真正进入模型请求、对模型可见的信息,都必须能够从日志中重建。

统一的事件日志进一步成为恢复、分叉、重放和持久化等能力的基础。DeepSeek 当前为会话持久化提供 JSONL 和 SQLite 两种后端

崩溃恢复同样建立在这套机制上。对于从持久化存储冷恢复的会话,如果发现某个轮次在崩溃前已经写入 turn/start,但没有正常写入 turn/end,系统不会删除已经持久化的中间事件,而是补记一个 interruptedturn/end,为这次异常中断补上明确边界。

会话查询可以在这套逻辑会话数据上进行会话和事件查询,并提供可选的全文检索能力。不过这些能力并不会默认全部暴露给模型:当前内置 Agent 预设不挂载面向模型的会话搜索工具,SQLite 全文索引默认也处于关闭状态。

对于长程 Agent,"记忆"至少包含两个层面:当前模型使用的上下文,以及能够跨上下文重置和进程重启恢复的持久状态。

权限边界决定 Agent 可以触碰什么

当 Agent 拥有执行 Shell、修改代码库、调用已经登录的 CLI 乃至读取本地凭证的能力时,自然语言提示词很难单独构成可靠的安全边界。提示词中的行为约束与运行时的实际执行权限,需要分开处理。

权限边界至少需要覆盖四个方面:文件系统与网络访问、授权确认、共享系统入口,以及凭证。

首先,文件系统和网络边界尽量放在操作系统或执行环境层:限制 Agent 可以写入哪些目录,并通过代理和允许列表控制网络访问。这样 Agent 启动的子进程仍然处于同一套边界中。

其次,授权确认不适合作为主要安全边界。真正需要人工判断的高风险操作可以要求确认,大量默认通过的确认只会持续阻塞无人值守执行。

多人使用 Agent 访问共享系统时,可以在共享系统前增加网关,只向当前任务暴露声明需要的能力,同时记录每一次调用。凭证则尽量采用短生命周期、按任务限定作用域的 Token,减少长期凭证进入 Agent 执行环境。

DeepSeek Harness 的实现进一步区分了提示词指导与实际权限

Plan Mode 提供软性指导,用于调整 Agent 当前收到的提示信息;沙箱和授权确认则独立承担执行层限制。

提示词中写"不要修改这个目录"属于模型行为约束;执行环境实际拒绝对应写操作,才构成真实的权限边界。

DeepSeek 当前的 SandboxMode 包含 read-onlyworkspace-writedanger-full-access。本地沙箱后端根据平台使用 Linux bwrap / Landlock、macOS Seatbelt,以及 Windows ACL、受限令牌等机制。

这套策略主要面向需要受限进程执行的能力,并非所有工具都统一经过同一个沙箱。

沙箱还会区分 fullpartial 两种执行完整度。当策略要求受限执行,而当前环境无法提供对应沙箱时,系统采用失败即关闭,不会静默退化成不受限执行;如果调用方要求完整保证,也不能把 partial 当成 full

授权确认负责判断某个具体操作是否允许继续。当前策略包括 asknever,没有可用的授权处理器时不会自动放行。

SandboxMode 当前约束的是文件系统影响,网络访问和进程可见性不属于这一抽象本身的保证范围。

所以,沙箱只是权限体系的一部分。网络允许列表、凭证、网关、授权确认和审计分别处理不同类型的执行风险。

Verified 决定任务何时完成

Loop 停止后,系统仍需判断执行结果是否满足验收条件。

为了区分"停止执行"和"通过验收",本文把一次任务的结束进一步拆成三个层次:

Stop(停止) ≠ Done(自报完成) ≠ Verified(已验证)

Stop 表示当前 Loop 已经停止;Done 表示执行 Agent 判断目标已经完成;Verified 则要求系统根据验收条件和可检查证据确认结果成立。

任务验收可以从五个方面减少执行 Agent 自我判断带来的偏差。

首先是在新会话中执行审查。审查者不携带实现阶段的对话上下文,可以减少生成阶段的错误假设继续影响验收。

其次要依赖真实运行,而不是只看代码差异。Web 应用应该实际通过浏览器打开和操作,CLI 应真正执行命令。只让模型再读一遍代码差异,本质上仍然缺少真实运行证据。

历史失败还可以沉淀成评测集。这里建议先从 20~50 个 Agent 曾经做错的真实任务开始,这个数量属于「Agent Harness 设计」经验之谈,不是统一标准。

同一个任务还应该执行多次,并关注表现最差的一次。建议每个任务运行 3 次。若单次成功率为 75%,连续 3 次全部通过的概率约为 42%,因此一次成功运行很难证明 Harness 已经稳定。

还要警惕自信但错误的回答:Agent 的失败不一定表现为直接崩溃,也可能是在已经出现错误后,生成一段流畅解释,判断这个错误不影响结果。验证机制因此需要同时检查错误附近的模型输出和最终运行状态。

目前重试策略仍没有统一、充分验证的方案。失败后重试多少次、采用怎样的退避策略、继续当前会话还是重新启动干净会话,都需要结合具体任务和失败类型设计。「Agent Harness 设计」也明确把这一部分视为尚未形成可靠经验数据的区域。

DeepSeek Harness 当前没有把执行者上报的 complete 视为独立的完成认证。同会话目标与 Ralph 的 complete / blocked 仍属于模型或执行者声明;独立评估器、完成凭证、确定性检查器、对抗式验证器,以及相关的验收条件、执行器与隔离契约,目前仍属于延后工作。

DeepSeek 也没有直接引入 Claude Code 式评估器。其设计说明认为,只读取对话记录的模型评估器可以作为一种验证策略,但不足以直接形成通用可信的完成凭证。

Claude Code /goal 采用了另一种完成验收机制:用户先定义完成条件,每个轮次结束后,系统额外调用一个小型快速模型作为评估器,默认使用 Haiku,根据完成条件和当前对话判断目标是否满足。这个评估器本身不调用工具,因此它能验证到什么程度,取决于执行 Agent 是否已经把测试结果等关键证据带入对话记录。

Claude Code Hooks 提供了另一层验证机制。确定性条件可以通过 Command Hook 运行测试、Lint 或检查文件状态;需要语义判断时可以使用 Prompt Hook;需要读取文件、搜索代码或执行命令的复杂验证,可以使用 Agent Hook。Anthropic 当前仍将 Agent Hook 标记为实验性能力,并建议生产工作流优先使用确定性的 Command Hook。

OpenAI 的 Harness Engineering 实践则强调提高环境的 Agent 可读性:让 Agent 能够访问应用 UI、DOM 快照、截图、日志、指标和 Traces,并直接启动和操作应用,从真实运行状态中获得验证证据。Codex 还会审查自己的修改,并请求额外的 Agent 审查,根据人类或其他 Agent 的反馈继续迭代;人类仍负责优先级、验收条件和最终结果验收。

OpenAI 同时强调,这种高度自治依赖具体代码仓库的结构和工具体系,不能直接假设同样的效果可以迁移到其他工程环境。

为了区分单次任务的完成验收与 Harness 本身的长期可靠性,本文把验证进一步分成两个层面。

运行时验收发生在任务执行过程中:根据预先定义的验收条件和可检查证据判断当前任务是否可以结束。测试、构建、静态分析和运行状态等都可以提供证据,最终判断可以由确定性检查器、评估器或独立审查 Agent 完成。

系统级评测则面向 Harness 本身的长期表现:把真实失败案例持续加入回归评测集,通过一批任务和多次运行观察 Harness 的能力、稳定性和回归情况。

Anthropic 的 Agent Eval 实践把评分器分成代码评分、模型评分和人工评分 三类,同时区分能力评测和回归评测。对于 Coding Agent,单元测试、静态分析和结果验证等确定性方法可以直接参与结果检查;开放程度更高的任务,再根据需要加入模型评分或人工评分。

验证的核心不是再堆一个"裁判模型",而是先让执行结果产生可检查的证据,再交由程序、独立评估器、审查 Agent 或人完成最终判断。

Harness 的工程价值在于可控执行

Harness 往往并不是从零开始设计出来的。只要系统里已经存在反复使用的指令****、自动化测试、权限规则和完成条件,Harness 实际上就已经存在;区别在于这些机制是被有意识地设计,还是由各种临时补丁长期累积出来。

DeepSeek Harness 的 Everything is a Plugin 展示了一种模块化的组织方式:Agent Loop、工具注册表、会话日志和 Model Adapter 等组件都可以通过插件组合和替换;Agent 预设控制一个会话实际获得的工具、提示词和其他能力;事件日志保存持久状态;上下文压缩管理模型当前看到的信息;沙箱和授权确认负责部分执行边界。

独立评估目前仍属于 DeepSeek Harness 的延后工作。能够让 Agent 持续运行,并不自动意味着系统已经解决了任务完成状态的验证。

Harness 本身也会增加工程和运行成本,因此并非所有任务都需要把这六层机制做满。对于需要长时间无人值守、跨会话恢复、严格权限控制和独立验收的任务,这些额外机制更有价值;对于很短、很容易人工确认的一次性任务,简单 Harness 往往已经足够。

如果从一个最小版本开始,这里有一套轻量级实践:指令****文件保持简短,把它作为正式文档的索引;同一类问题反复出现后,将文字提醒升级为 Linter 或构建规则;再配合四个持久文件、不能被上下文压缩丢失的固定规则,以及一组小型评测集。

核心思路是逐步把原本依赖人反复提醒和记忆的约束,固化为 Harness 中可执行、可恢复、可验证的机制。

最后,建议优先从停止规则外部持久状态开始。这两项实现成本相对较低,而且对具体模型版本的依赖较小。

设计 Agent Harness,最终需要回答六个问题:任务如何持续运行、Agent 能看到哪些工具、当前上下文保留什么、长期状态如何恢复、执行权限如何限制,以及什么证据足以确认任务完成。

这些机制共同决定 Agent 能否在长程任务中持续执行、在中断后恢复、在明确边界内操作,并通过可检查的证据完成任务验收。