我们已经习惯向大模型提问:解释一段代码、生成一个函数、分析一次报错。模型往往能给出像样的答案。
但把问题换成“请把这个项目里的问题修好,并验证结果”,难度就变了。
它需要读取目录、理解约束、定位原因、修改文件、运行测试;测试失败后还要继续排查。任务中途,用户可能改变要求,工具可能超时,上下文可能接近上限,进程也可能退出。
从回答问题到完成任务,中间隔着一整套运行系统。
DeepSeek Harness,简称 DSH,关注的正是这套系统:如何把模型、工具、上下文、任务状态和执行策略组织起来,让 Agent 能够持续推进工作,也能够在必要的时候停下来。
它最有辨识度的设计是 Everything is a Plugin——一切皆插件。模型适配器、工具注册表、会话日志,甚至 Agent 的执行循环本身,都通过插件装配。
本文沿着“一个任务如何被持续执行”这条主线,拆解 DSH 的核心架构,并讨论它的工程价值与现实边界。
阅读范围:本文主要依据本地 DeepSeek Harness 源码、架构文档及配套插件示例撰写。源码快照为
99f6f02,提交日期为 2026 年 8 月 17 日。2026 年 9 月 15 日查阅的官方仓库仍将项目标注为开发者预览版;后续版本的命令、接口和行为可能变化。本文讨论架构与实现,不作性能排名。
一、Harness 到底是什么?
Harness 在 Agent 语境中,可以理解为让模型在真实环境里工作的运行支撑系统。
模型负责理解输入、生成内容、提出工具调用。Harness 负责接住这些输出,并把它们转化为受管理的执行过程。
例如,模型提出“运行测试”,后面至少还有这些问题:
运行哪个工具,参数是否有效? 在哪个目录、哪个执行环境中运行? 当前权限是否允许,是否需要用户批准? 超时、失败或取消之后怎么处理? 工具结果怎样进入下一次模型请求? 执行记录保存在哪里,之后如何恢复和检查?
为了帮助理解,可以写出一个概念性的关系:
Agent 系统 = 模型能力 + 工具能力 + 状态管理 + 执行与控制机制。
这不是严格的数学公式,但指出了一个事实:模型能力只是任务执行的一部分。
同一个模型,置于不同 Harness 中,可能表现出很不一样的做事方式。差别往往来自它能接触什么工具、得到什么反馈、保留哪些历史,以及系统如何决定下一步。
DSH 的定位,就是提供一个可组合、可扩展的 Agent 运行时。官方仓库将其描述为由 DeepSeek AI 开发、基于 Cordis 的开源 Agent Harness,并采用 MIT 许可证。官方仓库
二、先看全貌:一个运行中的 DSH 是怎样拼起来的?
理解 DSH,可以先把它看成五组相互配合的组件:
这是便于阅读的概念分组。实际运行结构是一棵由配置装配出来的插件树。
图 1|DSH 架构总览。配置装配运行时插件树,Cordis 管理依赖、事件与生命周期;图中按职责分组。
其中有三个容易混淆的概念。
Profile:一次部署的组合方案
Profile 决定启动哪些 Bundle、安装哪些外部插件,以及采用哪些用户配置。源码提供了 web、headless 等模板。
web 面向浏览器交互;headless 可以执行一次任务而不启动 Web 服务。
Bundle:一组可分发的插件配置与代码
Bundle 把相关配置行和插件代码组织成可安装的单元。
例如,基础 Bundle 提供模型适配、工具、持久化、权限等能力,Web Bundle 再叠加浏览器应用。
Agent Preset:单个会话的能力组合
Profile 面向运行实例,Agent Preset 则进一步决定某个会话中的 Agent 使用怎样的能力集合。
这使同一套运行时可以承载不同用途的 Agent,而不必把差异都塞进系统提示词。
配置还可以分层覆盖。源码中的装配顺序包括 Bundle、Profile 补丁、全局补丁和命令行补丁。需要注意,补丁对目标配置行的 config 采用整体替换,不能想当然地当成逐字段深度合并。
DSH 的产品形态,由一组明确的组件及其配置共同决定。 这也是后续讨论“一切皆插件”的起点。架构文档(本文源码版本)
三、Cordis:让“一切皆插件”成为可管理的运行结构
插件机制并不罕见。DSH 的特点在于:插件化深入到了 Agent 运行时内部。
工具可以是插件,模型适配器可以是插件,负责执行循环的组件同样可以替换。这种结构要求底层框架处理好三个问题:依赖、通信和生命周期。
1. 用服务依赖表达装配关系
Cordis 通过 Context 提供共享服务。例如:
ctx.llm:模型调用能力;ctx.tools:工具注册与执行;ctx.sessions:会话与事件日志;ctx.agents:运行中的 Agent。
插件通过 inject 声明所需服务。依赖尚未就绪时,框架会等待相应条件,而不是要求开发者手动猜测启动顺序。
这样,依赖关系就进入了可检查的运行结构。
2. 用事件提供扩展点
DSH 在模型请求、工具执行、回合结束等位置暴露事件。插件可以观察过程,也可以在约定的位置实施策略。
例如:
agent/pre-step:决定哪些输入进入下一步;llm/stream:参与模型请求与流式输出链路;tools/pre-execute:执行前检查;agent/turn-stopping:在回合关闭前参与继续执行的决策。
不同事件有不同的分发语义。其中 waterfall 类似中间件链:监听器调用 next() 才会把控制权交给下游。忘记调用,可能会提前截断整条链路。
这说明插件扩展虽然灵活,仍然依赖清晰的契约。
3. 用可回收的注册管理生命周期
工具定义、事件监听器和其他运行时贡献,应通过 ctx.effect()、ctx.on() 等机制登记。插件卸载时,框架据此回收对应资源。
这对动态加载尤其重要:插件撤下之后,不能还残留一份工具定义,或留着一个继续触发的监听器。
这里的“可逆”,有明确范围。
框架能够撤销受管理的注册与资源,已经发生的业务操作则需要另行处理。 插件写过的文件、提交过的数据、发起过的外部请求,不会随着卸载自动还原。
因此,Cordis 提供的是运行结构的生命周期管理;业务回滚仍需要备份、事务或补偿机制。Cordis 入门文档
四、Agent Loop:模型如何从一步走到下一步?
理解持续执行,首先要区分 Step 和 Turn。
一个 Step,是一次模型请求,加上这次请求触发的工具执行。
一个 Turn,是零个或多个 Step 组成的一轮工作。如果输入在进入模型之前被拒绝,这一轮也可能没有任何 Step。
用修复测试失败的任务举例:
用户提出任务,运行时接收输入。 模型请求读取相关文件。 文件工具执行,结果写入会话。 模型根据结果提出修改。 修改工具执行,模型继续请求运行测试。 测试失败信息进入下一次请求。 模型继续修复,直到给出结果或遇到停止条件。
其中,每次“请求模型,再处理工具调用”构成一个 Step,多次 Step 可以属于同一个 Turn。
图 2|Agent 执行闭环。工具调用按需发生,结果写入会话并成为后续请求的依据;是否继续由下一步工作决定。
工具输出如何成为下一步的依据?
DSH 不只调用工具,还把调用和结果记录为会话事件,再从会话中派生后续模型请求的历史。
于是,“运行测试失败”成为模型能继续利用的上下文。模型才有机会依据实际报错调整行动。
工具调度也不意味着全部串行。源码区分可并发调用与需要独占执行的调用:适合并行的工作进入有界并发池,需要独占的调用形成执行屏障。
即便部分执行过程重叠,结果仍按模型原始调用顺序提交,避免仅因完成时间不同而打乱上下文。
为什么它不会天然永远执行?
Agent Loop 有明确的停止边界。当工具不再要求后续请求、也没有待处理的下一步输入时,一轮工作可以结束。
回合关闭前,扩展点还允许插件通过新的输入推动下一步。但“不断调用模型”本身不能证明任务在取得进展。
循环负责推进执行;目标管理和验收机制负责回答,还要不要继续、做到什么程度才算完成。
五、持续做事的关键:Goal、子 Agent 与 Workflow
DSH 提供了几种不同层次的持续执行机制。理解它们的分工,比笼统地说“支持长任务”更有价值。
图 3|四种长任务组织方式。同会话接力、子任务委派、程序化编排与全新执行者接力,分别应对不同任务结构。
1. Goal:在同一个会话中继续推进目标
Goal 服务保存一个当前目标,包括目标状态、版本和已启动的目标轮数。状态变更通过 goal/change 事件写入会话。
单独的 goal-round-driver 插件负责推进:当 Agent 空闲、目标仍处于激活且允许继续的状态、轮数还有余量时,它安排下一轮目标输入。
这意味着,任务不必依赖用户一次次手动输入“继续”。
目标状态与继续执行的权限被分开处理:
目标状态持久保存,恢复后仍能知道此前要做什么; 自动继续的授权只存在于当前进程生命周期中,不会直接随日志恢复。
因此,会话恢复或分叉可以保留目标,却不会仅因旧日志中的目标仍为 active 就自动开始工作;需要显式恢复操作重新激活继续执行。
此外,用户输入会影响自动轮次安排,取消、暂停、阻塞和完成状态也会抑制后续推进。
这是长任务系统中很有价值的一种区分:记得任务,与获准继续执行任务,是两件分别管理的事。
Goal 也有现实限制。该版本主要限制轮数,不能据此推导出固定 Token、费用或时间上限;完成状态由调用方记录,还没有独立验收器替它证明目标已经实现。Goal 服务
2. 子 Agent:把边界清楚的工作委派出去
子 Agent 适合承担能够独立描述和验收的任务,例如检查一组接口、分析某个模块,或审阅一个限定范围的改动。
DSH 为子 Agent 定义统一接口,再提供不同实现:创建全新子 Agent、继承父会话已完成历史的分叉,以及通过 SDK、ACP 或特定外部产品适配器进行委派。
源码中能看到面向 Codex、Claude Code 等执行后端的适配器。实际使用还取决于相应依赖、凭据与运行环境是否就绪。
统一接口的意义是让上层编排减少对具体执行后端的耦合。它不会消除多 Agent 的协调成本:任务拆分、上下文交接、共享文件冲突,以及结果复核,仍需要设计。
3. Workflow:把协作顺序表达成程序
当任务需要“并行分析,再汇总”“逐项处理,再进入下一阶段”时,Workflow 提供程序化编排能力。
本地实现暴露了 agent()、parallel()、pipeline() 等接口,并对并发数、总子 Agent 数和取消流程进行管理。
工作流脚本运行在 Worker Thread 中。这能避免脚本中的同步忙循环阻塞宿主事件循环,也提供强制终止工作线程的手段。
不过,Worker Thread 和 node:vm 在这里不构成安全沙箱;源码文档对此有明确说明。Workflow 实现
4. Ralph:每轮换一个新的执行者
源码还实现了固定策略的 Ralph 工作流:每一轮启动一个不继承父对话的新子 Agent,交给它同一个目标、当前轮次和上一轮的结构化交接报告。
连续性主要依靠共享工作区和交接信息维持。
它与同会话 Goal 的取舍不同:Goal 延续已有上下文;Ralph 让新的执行者重新观察工作成果,同时付出上下文重建的成本。源码要求仅在人类明确请求这种执行方式时使用。
Ralph 返回的完成或阻塞状态,同样属于工作 Agent 的报告,不能当成独立验证结论。
六、会话日志:持续执行背后的事实底座
在长任务中,一个经常被低估的问题是:系统究竟相信哪份记录?
如果模型上下文、UI 展示和磁盘历史分别维护,很容易出现不一致:界面显示工具成功了,模型却没收到结果;恢复之后,某个关键约束又丢失了。
DSH 把只追加的 Session Event 日志放在核心位置。用户输入、模型输出、工具调用与结果,以及目标等状态变化,都可以进入这条事实流。
模型请求历史通过 deriveMessages() 等投影机制从日志中生成。UI、恢复、分叉和持久化也以事件流为基础。
项目强调的约束是:进入模型请求的内容,应能够从日志中重建。
这让排查问题有了具体依据:
它当时读到了什么输入? 发起了什么工具调用? 工具实际返回了什么? 在哪一步选择了继续、结束或报错?
不过,“可重建记录”不等于“重新运行一定得到同样结果”。模型生成可能变化,外部文件、网络服务和运行环境也可能变化。
日志帮助复盘和恢复;外部操作是否成功,仍应以对应系统的状态和验证证据为准。
七、上下文压缩:让任务继续,也要承认信息损失
任务越长,工具输出和历史消息越多。模型上下文窗口有限,运行时必须决定哪些信息继续原样保留,哪些信息需要浓缩。
DSH 的基本压缩实现大致包含三个环节:
根据当前请求构成和模型容量评估上下文压力。 在配置了对应裁剪服务时,先缩减过大的工具结果,必要时再对旧历史生成摘要。 保留近期的完整片段,用摘要替代模型请求视图中的较早区间。
这里有一个重要设计:压缩修改模型看到的历史视图,原始事件记录仍保留在日志中。
“完整保留执行历史”和“每次给模型发送全部历史”因此可以分别处理。
图 4|会话日志与上下文压缩。原始事件保留在日志中,压缩后的请求视图由摘要和近期片段构成。
压缩还要照顾工具调用与结果的配对,避免留下孤立的调用或结果,让后续模型请求失去结构上的完整性。
DSH 也关注缓存。很多包的文档会专门解释对 Token 和 KV Cache 的影响。复用稳定前缀有助于缓存命中,但压缩替换了部分历史,会改变相应位置之后的复用边界;摘要调用本身也会产生额外消耗。
上下文管理是一项在信息保留、请求成本和执行连续性之间做取舍的工程工作。 摘要仍可能遗漏约束,因此重要结论、验收命令和交接信息,也适合保存在可重新读取的项目文件中。
持久日志同样不应直接等同于完善的长期记忆系统。跨会话检索、知识更新和冲突处理,还需要额外的组织方式与组件。上下文压缩实现说明
八、能力接缝:为什么它能够替换执行后端?
DSH 用 Capability Seam 描述可替换的能力边界,可以理解为“预留了标准接口的连接处”。
一个完整接缝有三个角色:
以文件访问为例,上层消费者依赖文件系统接口,下层 Provider 决定实际访问本地环境还是某种远端环境。
模型适配、Shell、子 Agent、上下文压缩等能力也采用类似思路。
这种结构带来的收益,是把经常变化的实现放在可替换的边界后面,让调用方尽量保持稳定。
但替换 Provider 需要满足整组契约。特别是文件系统和子进程等能力,需要指向一致的执行世界:读取的是远端文件,执行命令却落在本地,就无法形成可靠闭环。
架构中存在远端适配空间,也不代表某个具体后端已经达到生产成熟度。例如,本地仓库将 E2B 相关部分标注为 POC,应按概念验证实现理解。
九、扩展怎么落地?看一个“用量与余额”插件
当前资料目录中有一个具体示例:为 DSH 增加 Token 用量概览和 DeepSeek 账户余额面板。
这个例子说明,插件机制如何把已有服务连接成用户看得见的功能。
Host 端:读取与组织数据
宿主侧代码读取会话查询、实时投影或持久化投影缓存,聚合模型 Provider 上报的 Token 用量,再通过 RPC 暴露给前端。
账户余额查询则经凭据服务获取密钥,通过 Shell 调用接口,最后返回适合展示的数据。
Client 端:接入已有界面
浏览器侧通过 host.call() 获取数据,将界面注册到侧栏入口、浮层和设置页等插槽中。
这让数据能力和展示位置能够分别扩展。对于这样的功能,开发者无需修改 Agent Loop。
不过,并非每个 DSH 插件都必须包含 Host 和 Client 两部分。纯工具、策略或服务插件可以只提供它需要的那一侧。
图 5|“用量与余额”插件数据流。Host 侧读取和组织数据,Client 侧通过 RPC 获取结果,再注册到已有界面插槽。
一个细节,体现插件开发的责任边界
示例把密钥通过环境变量传给 Shell,避免在代码中硬编码密钥。但 Shell 展开请求头之后,密钥仍可能短暂进入 curl 的进程参数。
示例 README 已记录这一限制,并提出通过标准输入传递请求头配置的改进方向。
因此,不能把“通过凭据服务读取”直接写成“密钥绝不会暴露”。服务接口提供了集中管理入口,调用方式仍需要开发者审查。
同样,会话用量统计来自本地记录,不应据此声称它覆盖了整个供应商账户的全部消费。
动态插件:把想法变成运行时实验
DSH 提供 cordis_inspect、cordis_define、cordis_run、cordis_stop 等工具,让 Agent 查询可用接口,定义并运行临时插件。
这是一项很有探索价值的能力:Agent 可以在已有服务和扩展点上,临时补充工具、提示词贡献或界面功能。
但该版本的动态定义仅存在于进程内存中,重启后消失,也不会自动变成持久安装的插件。长期保留与分发,仍要走正常的插件开发、测试和安装流程。
将它理解为可交互的运行时扩展实验,比直接宣称“Agent 已经实现自主进化”更符合源码展示的能力范围。动态插件工具说明
十、Plugin、Skill、MCP:分别在扩展什么?
围绕 Agent 的几个常见概念,可以按职责区分:
三者可以配合使用。例如,Plugin 提供 MCP 客户端能力,MCP 连接外部系统,Skill 指导 Agent 如何利用这些工具完成业务流程。
选择扩展方式时,可以先问三个问题:
我需要改变运行时行为吗? 我主要是在固化做事方法吗? 我是在连接一个外部系统吗?
明确问题,往往比先寻找插件更有帮助。
十一、控制能力越重要,边界就越要讲清楚
持续执行的 Agent 可以读写文件、运行命令和调用外部服务。它需要把“模型提出操作”和“系统允许操作”分开处理。
DSH 的工具管线包含执行前策略、审批、只能进一步限制调用的 Guard、执行包装、结果处理和日志记录等环节。
按照本地管线文档,当策略要求询问用户时,审批发生在 Guard 检查之前;审批服务缺失或无法给出有效响应时,该请求被拒绝。工具执行还可以受底层文件系统策略和进程沙箱实现约束。
这些机制分别承担不同责任:
策略与审批决定是否允许这次调用; Guard 保留必须执行的限制; 沙箱约束受其覆盖的执行环境; 日志记录模型可见的调用与最终结果。
需要同时记住:同进程插件本身属于运行时信任边界的一部分。 插件框架的可装卸能力,并不自动把不可信插件变成安全代码;动态插件与 Workflow 文档也都明确说明,相关 VM 机制不提供强安全隔离。
“插件卸载”“会话恢复”“沙箱执行”各有作用范围,不能互相替代。工具执行管线
十二、如何评价 DSH 的价值与代价?
从本地实现看,DSH 的价值可以归纳为三个方面。
第一,Agent 的关键组成变得可以分别研究和替换。
开发者可以沿着公开的接口与事件,研究模型调用、工具执行、压缩策略和继续执行机制,减少为了一个功能直接修改主循环的需要。
第二,长任务的状态与控制问题被认真建模。
会话日志、目标版本、执行授权、取消、插件卸载和子任务清理,都有明确的位置。这些机制未必直接提升模型推理能力,却决定了运行系统是否容易理解、恢复和维护。
第三,扩展覆盖了从执行能力到交互界面的多个层面。
同一套插件思路,可以用于增加一个工具、替换一个 Provider,也可以用于增加一块设置界面,为搭建不同形态的 Agent 产品提供基础。
代价同样存在。
抽象会增加学习与排障成本
开发者需要理解服务、作用域、事件、配置层和生命周期。一次“工具没有出现”,可能来自未满足的依赖,也可能来自注册范围或配置覆盖。
这种复杂度是否值得,需要结合产品的变化频率与扩展需求判断。
持续运行会放大验收与预算的重要性
增加轮数并不保证成功。模型可能围绕错误假设反复尝试,多 Agent 也会增加重复阅读与结果整合的成本。
真正有用的验收标准应尽量落到可观察结果上,例如测试是否通过、文件是否生成、接口响应是否符合约定。
在当前实现中,Goal 或 Ralph 记录的“完成”仍不能替代独立验证。
架构潜力需要实际任务验证
本文进行了源码与文档阅读,没有开展任务成功率、Token 消耗或延迟基准测试,因此不据此宣称 DSH 比其他产品更快、更便宜或更可靠。
截至本文核对时间,官方仍提示开发者预览阶段会有破坏兼容性的变更。对于团队应用,兼容性、插件质量、执行隔离和可复现部署,需要一起评估。官方项目状态
十三、从哪里开始理解和实践?
官方 README 给出的 Web 入口是:
npx @deepseek-ai/dsh web
默认 Web 地址为 http://127.0.0.1:3080。需要安装 Node.js,并按所用版本的设置流程配置模型服务与凭据。官方运行说明
第一次实践,可以选择一个边界清楚、可验证的小任务:为一个函数补齐指定边界条件,并运行对应测试。
观察四件事就足够有收获:
模型如何决定读取哪些文件。 工具调用与结果如何呈现在会话中。 测试失败后,Agent 如何继续调整。 最终结论是否有实际执行证据支持。
如果要阅读源码,可以依次看:
docs/architecture.md:建立整体地图;docs/cordis-primer.md:理解插件、服务与生命周期;packages/core/agent-loop:理解 Step、Turn 与工具调度;packages/core/session:理解事件记录与模型历史;packages/goal:理解同会话目标如何继续推进;packages/compaction:理解有限上下文如何承载长任务;packages/subagent与packages/workflow:理解委派与编排。
再结合“用量与余额”这样的小插件阅读服务调用和界面插槽,会比一开始遍历所有包更容易建立具体认识。
结语:让模型能力进入一个可持续运行的系统
DeepSeek Harness 把 Agent 的执行过程拆成了一组可以组合、观察和替换的组件。
沿着一个任务向下看:模型负责提出下一步,工具把行动落到环境中,日志保存事实,上下文管理维持工作连续性,Goal 和 Workflow 组织更长的执行过程,权限与生命周期机制约束它们何时运行、何时停止。
这些部分共同决定,Agent 能否把一次有用的回答,延伸成一段有依据的工作过程。
“能持续做事”的衡量标准,是持续取得可验证的进展,并在完成、受阻或失去授权时正确停下。
这正是理解 DeepSeek Harness 最值得抓住的主线,也是构建可靠 Agent 系统时绕不开的工程问题。
CadenzaOS:https://github.com/SuperTapir/CadenzaOS
PCB Atelier:https://github.com/SuperTapir/pcb-atelier
tapir-skills:https://github.com/SuperTapir/tapir-skills
PCB_lightgraph:https://github.com/tomatorigid/PCB_lightgraph
我用AI编程复刻了老罗的TNT,还顺手做了个万能遥控器……:https://www.bilibili.com/video/BV1qMKg6uEJr
送朋友一张PCB做的贺卡!:https://www.bilibili.com/video/BV11MjE6qEXb
🎉🕯🎂🕯🎉(我的第一块 PCB Art 作品图案取自这位老师的视频):https://www.bilibili.com/video/BV1ihNx61Ewq
从零开始的二次元电路板艺术画设计教程:https://www.bilibili.com/video/BV1CQjz6ZELZ
-END -
如果您关注前端+AI 相关领域可以扫码进群交流
添加小编微信进群😊
关于奇舞团
奇舞团是 360 集团最大的大前端团队,非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。