本文面向第一次接触 DeepSeek Harness 的开发者,按“先建立整体模型,再进入实现细节”的顺序说明它的定位、架构、运行方式、适用场景与可能的发展方向。

内容以仓库当前公开实现为依据,版本背景为 0.1.2-alpha 系列开发预览版(核对时仓库 package.json 为 0.1.2-alpha.2,版本以仓库为准)。文中“当前实现”与“发展判断”会明确区分;社区讨论中的想法不等同于官方路线图。

目录

  1. 术语速查
  2. 它是什么
  3. 先建立一个整体模型
  4. 为什么说 Everything is a Plugin
  5. 启动、Profile 与 Bundle
  6. Agent Loop:模型如何完成一个任务
  7. Session Event Log:为什么它不是普通聊天记录
  8. 工具系统与安全控制
  9. Subagent、Workflow 与 Agent Teams
  10. 更多能力家族速览
  11. Web、SDK 与 API
  12. 它适合解决什么问题
  13. 它的优势与代价
  14. 发展方向:事实与判断
  15. 推荐阅读路径
  16. 快速上手与构建环境
  17. 常见误解

术语速查

第一次阅读时把它当作词典:遇到不认识的词回来查;每个词在正文中都有更完整的解释。

术语一句话定义
Harness围绕大模型构建可运行 Agent 的基础运行时,负责模型调用、上下文、工具、会话、权限与扩展的组合
Plugin(插件)注册服务、监听事件、声明依赖的 Cordis 单元;Agent 的能力由一组插件共同组成
Seam(能力缝)一个可替换能力的三段式结构:Service Definition(定义)+ Provider(实现)+ Consumer(接入 Agent)
Scope(作用域)注册的可见范围:贡献要么全局可见,要么只属于某个 Agent;子代理不继承父代理的作用域
Profile一套命名的运行时组成,例如 web、headless、sdk、acp
Bundle一组可安装的 Cordis 配置行与代码,可作为基础包或 patch 层叠加到 Profile
Turn / Step / Roundstep = 一次模型请求及其引发的工具执行;turn = 零个或多个 step;round = 外层策略的一次迭代(如目标轮)
Session Event Log会话的追加式事件日志,是运行时事实来源;模型上下文、UI、恢复、分叉、遥测都从它派生
Projection(投影)从事件流派生的只读视图,例如模型消息历史、Web Transcript、持久化状态
Compaction接近上下文上限时对旧历史做摘要压缩,并裁剪过大的工具输出
Goal(目标)附着在会话上的持久化完成目标,带阶段与轮次上限,可驱动自动续跑
Human Command/ 开头的命令(如 /plan、/compact、/goal),由人触发、不经模型回合直接执行

1. 它是什么

DeepSeek Harness 是 DeepSeek AI 开源的通用 Agent Harness。这里的 Harness 可以理解为“围绕大模型构建可运行 Agent 的基础运行时”,它负责把模型调用、上下文、工具、会话、权限、子代理、工作流、Web UI 和 SDK 组合成一个可扩展系统。

它不是一个只提供聊天窗口的应用,也不是一个只封装 HTTP 请求的模型 SDK。它更接近一个“可配置的 Agent 操作系统”:模型是决策者,Harness 负责提供能力、保存状态、执行动作、承接扩展,并把运行过程投影到用户界面或外部协议。

项目的核心定位可以概括为三点:

  • 以 Cordis 插件系统为运行时基础,所有主要能力都可以被装配、替换或裁剪。
  • 以事件日志作为会话事实来源,使模型上下文、UI、恢复、分叉和遥测可以从同一条记录派生。
  • 以工具和能力扩展为中心,把一个简单 Agent 逐步组合成多代理、工作流和可动态扩展的运行环境。

官方仓库仍将项目标注为开发预览版,接口和存储格式可能发生不兼容变化。项目的整体说明见 官方 README

2. 先建立一个整体模型

从外部看,用户提交一个任务,模型思考并调用工具,最后返回结果。从内部看,DeepSeek Harness 会把这个过程拆成多个相互协作的层:

用户 / Web UI / TypeScript SDK / Python SDK / ACP
                         |
                  API 与连接层
                         |
           Profile + Bundle + Cordis Context
                         |
     Session | Agent Loop | System Prompt | Tool Runtime
                         |
  LLM Provider | Shell | FS | Web | LSP | Sandbox | Subagent
                         |
             JSONL / SQLite / 文件系统 / 外部进程

可以把它理解成四个方向的组合:

  1. 向上是交互入口:Web 页面、命令行、SDK 和自动化协议。
  2. 中间是 Agent 主干:会话、提示词、工具运行时和 Agent Loop。
  3. 向下是能力提供者:模型、文件系统、Shell、网页、LSP、沙箱和子代理。
  4. 横向是插件与事件:它们把能力注册到共享的 Cordis Context,并用事件连接运行时各部分。

仓库的架构总览、包分组、启动规则和 Agent Loop 语义集中写在 docs/architecture.md。如果只读一份源码文档,优先读它。

2.1 一次真实任务的时间线

用一个具体任务把上面的分层串起来。假设用户通过 Web UI 提交“帮我看看项目里哪个测试失败了”:

  1. dsh web 启动后,Web Profile 组合出包含 Agent Loop、工具、Session 持久化的运行时。
  2. 用户输入进入会话 inbox,turn/start 打开一个 turn。
  3. Agent Loop 从 Session 事件派生模型历史,加上 System Prompt 与可见工具 Schema,向 LLM 发出请求。
  4. 模型返回流式文本(assistant/chunkassistant/message),UI 实时显示。
  5. 模型调用 bash 工具运行测试:tools/pre-execute 先做权限与审批检查,tools/execute 执行,tool/result 把输出写回事件流。
  6. 工具结果成为下一步请求的一部分,模型据此定位失败原因并给出结论;直到没有更多工具调用,turn/end 关闭。
  7. 每一条事实都以事件追加进 Session 日志;即使进程重启,也能从日志恢复并继续。
  8. 如果上下文接近上限,Compaction 会压缩早期历史;如果设置了目标,Goal 系统会在 turn 结束后继续推进自动工作(分别见 6.4 与 5.5)。

3. 为什么说 Everything is a Plugin

3.1 Cordis 提供什么

DeepSeek Harness 使用 Cordis 作为插件框架。一个 Cordis 插件可以注册服务、监听事件、声明依赖,并通过可撤销的 effect 管理生命周期。

这意味着 Agent 不是把所有逻辑硬编码在一个巨大的主类中,而是由一组插件共同组成。例如:

  • LLM 插件提供模型调用能力。
  • Session 插件提供会话和事件记录。
  • System Prompt 插件负责拼装系统提示词。
  • Tools 插件管理工具注册、参数校验、执行管线和结果。
  • Agent Loop 插件驱动每一轮模型请求与工具调用。
  • Shell、FS、Web、LSP 和 Sandbox 插件提供外部世界的操作能力。
  • Subagent 和 Workflow 插件提供多代理协作与程序化编排。

插件之间不是通过大量全局变量互相引用,而是通过 Context 中的服务和事件通信。Cordis 的服务、依赖注入、事件模式和生命周期语义见 Cordis Primer

3.2 Capability Seam:能力的三段式结构

一个完整能力通常由三类角色构成:

角色责任
Service Definition声明稳定的类型、方法和事件
Service Provider提供具体实现,例如本地进程、远程服务或持久化后端
Consumer把能力接入 Agent,例如注册模型、暴露工具或驱动 UI

例如,Shell 能力可以拥有统一的 Service Definition,然后分别接入本地 Shell、PowerShell 或受控执行环境。Agent 只依赖能力定义,不需要把每一种底层实现写死在循环里。

3.3 这种设计解决了什么

它主要解决的是“同一个 Agent 主干,如何在不同环境中拥有不同能力”:

  • Web Profile 可以挂载浏览器 UI 和远程连接。
  • Headless Profile 可以只保留命令行任务所需能力。
  • SDK Profile 可以把 Agent 暴露为 JSON-RPC 服务。
  • 测试环境可以替换模型、存储和工具实现。
  • 用户可以通过配置文件选择插件和覆盖配置,而不用修改 Agent Loop。

代价是理解成本更高。阅读一个功能时,通常要同时寻找定义、实现、消费者、配置行和事件,而不是只打开一个文件。

3.4 作用域(Scope):能力如何对每个 Agent 定制

插件组合解决“系统由哪些能力构成”,作用域解决“同一个能力对不同 Agent 呈现什么”。注册到共享 Context 的贡献——工具、提示词片段、变量、监听器——要么是全局的,要么属于某个 Agent 的作用域;约定是“一个存活中的 Agent 就是它自己作用域的 key”。

几个必须理解的行为:

  • 子代理不继承父代理的作用域。父子关系只作为数据(lineage:父会话、委托深度)存在,不影响可见性。因此“给子代理一套不同的工具”不是继承裁剪,而是在创建时组合出来的。
  • Setup Window 是创建子 Agent 时注入其专属世界的时机:作用域与 Agent 对象已存在,但 Agent 尚未发布、第一轮提示词尚未组装。Setup 负责注册,从不驱动 Agent。
  • Shadowing(遮蔽) 是“同名覆盖”:作用域内注册的同名工具或提示词片段替换全局同名项,这正是 per-agent persona 和 per-agent 工具变体的机制。
  • Restriction(限制)tools.restrict 按交集过滤全局工具集,被过滤掉的工具对模型既不可见也拒绝执行,与“不存在的工具”没有区别。

作用域语义的官方说明见 Scope 子系统glossary

4. 启动、Profile 与 Bundle

4.1 Profile 是一套运行时组成

DeepSeek Harness 不把“启动应用”理解为直接执行某个包的 bin,而是通过 dsh 启动一个命名 Profile。仓库当前的主要 Profile 包括:

  • web:启动浏览器端 UI 和服务端连接。
  • headless:执行一次性无界面任务。
  • sdk:通过 JSON-RPC 暴露完整 SDK 运行时。
  • sdk-minimal:提供更小的 SDK 组成树。
  • acp:面向自动化的 Agent Client Protocol 服务。

这些 Profile 共享一部分基础插件,再按用途叠加不同能力。常见的公共层是 dsh-base;Web、Headless、SDK 和 ACP 在此基础上分别添加自己的入口和连接方式。

4.2 Bundle 是可分发的配置层

Bundle 是一组可安装的 Cordis 配置行和代码。它可以作为基础能力包,也可以作为 patch layer 叠加到某个 Profile 上。

配置合成大致遵循以下顺序:

Bundle 默认配置
      ↓
Profile 补丁
      ↓
用户目录补丁
      ↓
命令行 --patch
      ↓
最终 Cordis 配置

一个 patch 通常针对完整配置行,而不是隐式地修改某个深层字段。这种方式让“当前运行了哪些插件、每个插件使用什么配置”可以被检查和复现。

Profile 和启动约束的具体说明见 架构文档中的 Application Launch 与 Profiles,基础配置可以参考 dsh-base 的 Cordis patch

4.3 为什么不鼓励直接运行包入口

项目把应用启动集中到 dsh,是为了让 Profile、配置层、生命周期、构建产物和运行环境保持一致。单独执行某个包的 bin,可能绕过这些组合规则,导致“源码能启动但正式 Profile 行为不同”的问题。

因此,理解 DeepSeek Harness 时应把 dsh 看成应用启动器,把各个 npm workspace 包看成可装配的运行时部件。

5. Agent Loop:模型如何完成一个任务

5.1 一次任务不是一次请求

Agent Loop 的核心不是“调用一次模型然后输出文本”,而是反复执行“读取上下文、请求模型、执行工具、记录结果、继续请求”的循环。

典型流程如下:

turn/start
  → 获取下一条用户输入和队列消息
  → agent/pre-step
  → step/start
  → 写入 user/message
  → 从 Session 派生模型历史
  → agent/request
  → LLM 流式响应
  → assistant/chunk*
  → assistant/message
  → tool/call*
  → tools/pre-execute
  → tools/execute
  → tools/post-execute
  → tool/result*
  → step/end
  → 继续下一步,或 agent/turn-stopping
  → turn/end

星号表示可能出现多次。模型没有工具调用时,一步可能直接结束;模型产生工具调用时,工具结果会被记录,并成为下一步模型请求的一部分。

Agent Loop 的实现位于 agent-loop 的 READMEagent.ts

5.2 Agent 的状态与控制

Agent Loop 需要处理的不只是正常成功路径,还包括:

  • 用户在运行中追加消息。
  • 用户 steer 当前任务,改变后续方向。
  • 用户 follow-up,让 Agent 在当前任务结束后继续处理。
  • 取消当前运行。
  • 工具并行执行与互斥执行。
  • 模型请求失败和重试。
  • 等待 Agent 进入 idle 状态。
  • 工具结果要求继续下一步,或要求结束当前 turn。

这也是它与简单的“while 循环调用模型”之间的主要差异:循环本身是一个带生命周期、事件和可恢复状态的运行时组件。

5.3 请求如何生成

在构造模型请求时,Agent Loop 会组合:

  • 持久化的请求头信息。
  • System Prompt 的当前内容。
  • 从 Session 事件派生的消息历史。
  • 当前 Agent 可见的工具及其 JSON Schema。
  • 当前会话标识、取消信号和运行时上下文。

模型请求不是独立的临时变量,而是 Session 记录和当前插件状态的投影。这为恢复、审计、UI 展示和 Snapshot 测试提供了共同基础。

5.4 循环层级:turn、step 与 round

官方 glossary 用三个词定义循环的层级:

  • Step:一次模型请求加上它引发的工具执行。
  • Turn:零个或多个 step,从认领第一批输入开始,到模型与工具都不再欠工作为止。
  • Round:外层策略的一次迭代,例如一个 goal round,或 Ralph 循环中的一轮新会话尝试。轮次计数属于外层策略,不等于 session 里每个 turn 都算一轮。

Ralph 循环值得单独解释:它是把同一个目标交给“全新会话的模型”反复执行的前台工作流;每轮子会话不携带父会话与上一轮会话的对话种子,跨轮状态通过共享 workspace 与一份有界的结构化交接报告传递。它不是 session 内的 goal,也不是调度器。

5.5 目标(Goal):持久化的长任务推进

“用户提交一个任务,模型做完就停”只是基础形态。Goal 机制让一个 session 拥有一个持久化的完成目标:目标带 active / paused / blocked / complete 阶段和轮次上限,模型工具可以创建和更新目标,/goal 命令让人不经过模型回合直接控制,自动续跑驱动会把 active 目标变成一轮轮自动工作。

三个容易误解的点:

  • Goal 是状态,不是调度器,也不是独立会话。目标状态就住在 Session 事件日志里,不另设存储。
  • 一次只有一个目标生效;无关的人工 turn 不消耗目标轮次上限。
  • 续跑激活(armed)是进程内的,刻意不进入持久化回放:恢复或分叉后,必须先有人类授权的 resume 动作才能继续自动工作。这与第 7 章的安全主题一致——自动续跑默认不会在无人确认时自己恢复。

官方说明见 Goal 包组Goal 子系统

6. Session Event Log:为什么它不是普通聊天记录

6.1 Session 是事件流

Session 保存的是事件序列,而不是简单的 messages 数组。事件可能包括:

  • turn 和 step 的生命周期。
  • 用户消息、助手消息和流式文本块。
  • 模型请求头与请求上下文。
  • 工具调用、工具执行阶段和工具结果。
  • 权限、计划、子代理、文件、Shell、遥测等能力事件。

事件流是运行时事实来源,其他视图都可以从它派生:

事件流
 ├─→ 模型消息历史
 ├─→ Web UI Transcript
 ├─→ 恢复与继续执行
 ├─→ 会话分叉
 ├─→ 工具审计与遥测
 └─→ 测试 Snapshot

其中,模型真正看到的内容必须能够由 Session 事件重建。这个原则可以避免 UI 显示了一些模型无法看到的隐式状态,也避免恢复时缺少影响决策的输入。

6.2 原始流式块与派生消息

流式响应通常会先产生多个 assistant/chunk 事件,随后形成完整的 assistant/message。这样做有两个目的:

  1. UI 可以实时显示模型输出。
  2. 恢复和模型调用可以使用稳定的完整消息。

因此,事件流既服务于实时体验,也服务于事后重建。它不是为某一个消费者定制的日志格式。

6.3 持久化方式

项目提供 JSONL 和 SQLite 两种持久化方向。JSONL 适合透明的追加写入和调试;SQLite 适合结构化查询、压缩流式块和更稳定的本地存储。

持久化层会处理写入延迟、崩溃恢复和逻辑事件流重建。崩溃恢复的目标不是伪造一条完整成功记录,而是明确记录中断状态,让后续恢复能够识别未完成的 turn。

会话类型、事件词汇和持久化语义见 Session 源码持久化子系统说明

6.4 上下文压缩:长会话如何不溢出

模型上下文有上限,长会话不可能永远原样增长。Compaction 能力族解决这个问题,包含三个层次:

  • 自动压缩:token 压力接近上限时,把较早的历史浓缩成摘要,随后的模型请求基于摘要继续。
  • 按需压缩:通过 /compact 命令手动触发。
  • 工具输出裁剪:过大的工具结果先被压缩或裁掉(例如只保留结论),减少需要浓缩的内容。

另一条缓解路径是 Spill:当单个工具结果超过字节上限时,完整文本被保存为 artifact,模型只看到有界预览加一个可后续读取或搜索的定位符。

压缩不是删除:压缩结果仍然作为事件写回日志,恢复与审计依旧可以追溯。官方说明见 Compaction 子系统Spill 子系统

7. 工具系统与安全控制

7.1 Tool Runtime 的执行管线

工具系统不仅负责“注册一个函数”。一个工具通常包含名称、描述、参数 JSON Schema、执行逻辑、结果以及可选的 UI 展示信息。

执行过程可以被多个阶段拦截:

模型产生工具调用
        ↓
tools/pre-execute   权限、审批、策略
        ↓
tools/execute       实际执行与包装器
        ↓
tools/post-execute  收尾、指标、清理
        ↓
tool/result         写入结果并反馈给模型

Tool Runtime 还负责并发上限、执行包装器、错误处理、结果归一化和工具可见范围。源码见 packages/core/tools/src/index.ts

7.2 工具可见性与渐进披露

工具不一定要在每次请求中全部暴露给模型。运行时可以限制当前 Agent 能看到的工具,或者使用 ToolSearch 一类机制,让模型先搜索工具再按需加载详细 Schema。

这能减少上下文开销,也能把大量能力以插件方式安装而不必一次性塞进每个模型请求。

7.3 安全模型的实际含义

工具可以访问文件、Shell、网络、进程和凭据,因此“能运行”不等于“安全”。官方 SAFETY.md 明确提醒:项目没有完成安全审计,不应被视为生产安全系统;模型生成的代码和命令、第三方插件以及宿主机访问都可能带来风险。

审批、沙箱和权限控制可以降低误操作概率,但不应被理解为绝对隔离。运行不受信任任务时,应使用最小权限、无敏感凭据的临时环境,并优先使用一次性虚拟机或容器。

这一点会长期影响项目发展:工具数量越多、插件越丰富、Agent 权限越高,插件供应链、能力隔离、审计、恢复和权限策略就越重要。

7.4 审批、凭据与沙箱的具体机制

仓库提供了与上一节原则对应的具体机制:

  • 审批(Approval):一次请求对应一个一次性授权,allowed-once 只放行被询问的那一个动作;缺失、拒绝、取消或应答方不可用一律 fail-closed,不会开门。UI 通道提供人工应答,ACP 自动化桥为自身 Agent 提供机器决策。见 Approval 子系统
  • 凭据(Credentials):密钥按名字存储与引用,轮换时无需修改任何配置文件;配置文件与渲染结果里只出现名字,不出现明文。需要“问人要”的凭据走 authorization flow。见 凭据包组
  • 沙箱(Sandbox):进程执行通过 ctx.sandbox 后端约束;除本地后端外还有实验性的 E2B 远程 Linux 沙箱,可以把文件、命令与终端整体搬进远端临时环境,宿主进程、模型调用与 Session 状态都不迁移。见 Sandbox 子系统E2B 包组

这些机制降低误操作概率,但正如上一节所说,它们不等于绝对隔离。

8. Subagent、Workflow 与 Agent Teams

8.1 Subagent

Subagent 允许一个 Agent 把工作交给另一个 Agent。子代理通常拥有独立的子 Session 和一次激活过程,父 Agent 通过工具或 Provider 管理子任务。

它适合以下任务:

  • 把检索、实现、审查拆给不同角色。
  • 并行处理多个互相独立的文件或问题。
  • 让子 Agent 使用与父 Agent 不同的提示词、工具过滤器或模型。
  • 把长任务拆成可继续的子会话。

重要的是,Subagent 不是简单的函数递归。它涉及子会话持久化、激活生命周期、深度限制、取消、父子关系和冷恢复。

8.2 Workflow

Workflow 更像程序化的 Agent 编排。它允许开发者用代码表达 agent、parallel、pipeline、phase 和 log 等结构,也可以实现 Ralph 风格的迭代循环(Ralph 的定义与 turn/step/round 层级见 5.4)。

可以用下面的方式区分二者:

机制决策主体更适合
Agent Loop当前模型动态决定下一步和工具
Subagent父 Agent 与子 Agent委派、分工、隔离上下文
Workflow开发者编写的流程固定阶段、并行、流水线和重复执行

Workflow 可以改善可观测性和可复现性,但它本身不是安全边界。工作流中调用的工具仍然需要独立的权限和隔离策略。

8.3 Agent Teams

仓库还包含实验性的 Agent Teams 方向。它反映出项目正在探索多个 Agent 之间的协作、消息传递和角色分工,但实验目录中的能力不应视为稳定公共 API。

9. 更多能力家族速览

除核心循环外,仓库还按能力族组织了一批可选包,dsh 基础组合默认启用其中一部分,其余按需挂载。理解它们的方式与理解工具相同:先看 Service Definition 定义了什么,再看 Provider 怎么实现、Consumer 如何接入 Agent。

能力一句话说明官方文档
Session Query对实时与持久会话做精确查询、关系 trace 与全文搜索;Web 端可通过 /export 导出会话session-query 子系统
Jobs后台任务注册为 job,归属发起它的 Agent,完成以会话内消息通知,而不是阻塞轮询jobs 子系统
Schedule会话内定时提醒:到点以普通消息回到同一会话;提醒跨重启存活,但没有邮件或推送schedule 子系统
Webhook接收经过认证的外部事件,由受信任规则创建新的根 Sessionwebhook 子系统
Terminal持久、归属 Agent 的 PTY 会话:cwd、环境变量、已激活环境跨工具调用存活(进程内,不跨重启)terminal 子系统
Code Runtime模型写一个程序调用宿主提供的函数,运行时在隔离的 worker 线程或 CPython 子进程执行,失败作为结果的一部分返回code-runtime 子系统
Skills可复用的任务指令:Provider 贡献 → 注册表合并 → 会话目录 + skill 工具按需加载完整指令skills 子系统
Guard循环卫生:检测模型重复调用同一工具并提醒改变策略;为声明了超时的工具调用设置时间上限guard 包组
Hooks桥接已有 Claude Code / Codex 的 hooks.json,让旧配置在 Agent 运行的关键时刻照常触发hooks 包组
MCP把外部 Model Context Protocol 服务器的工具作为原生工具接入;只桥接工具,不支持 resources/prompts,默认全关MCP 包组

9.1 Human Command:斜杠命令平面

/plan/compact/goal/export 这类命令构成独立的交互层:human command 由人触发,通过 ctx.commands 由 UI 适配器解释执行,不经过模型回合,也不等于 shell 命令。命令输出属于 UI 状态,除非处理器另行写入持久化领域。理解这一层,Web UI 上的许多交互才不会与“模型工具”混淆。见 commands 子系统

9.2 Plan Mode:先设计,后执行

/plan 进入计划模式:模式激活时,Agent 先探索和设计,把完整计划呈现给用户审批,批准后再执行。计划模式是引导而非限制——所有工具仍然可用,沙箱与审批等限制单独配置。见 plan 子系统

10. Web、SDK 与 API

10.1 Web Profile

Web Profile 提供浏览器 UI、会话列表、设置、实时输出和工具交互。浏览器看到的内容主要来自 Session 事件和持久化结果,而不是直接读取 Agent 内部对象。

这种设计使 Web UI 成为 Agent 运行时的一个投影,而不是 Agent Loop 的唯一使用方式。未来可以用命令行、SDK、自动化协议或其他客户端连接同一类运行时。

10.2 TypeScript 与 Python SDK

SDK 通过 JSON-RPC 和 NDJSON 通信。TypeScript Client 与 Python SDK 都可以启动对应版本的 dsh SDK Profile,然后通过标准输入输出交换请求和事件。

这种方式的优点是客户端不必复制 Agent Loop,也不必直接依赖内部 TypeScript 类。客户端只依赖协议和生成的类型投影,从而保持运行时实现与调用方解耦。

10.3 Typert 与远程连接

远程 API 使用 Typert 相关的类型图和 RPC 网关,把 TypeScript 类型、服务方法和连接层组合起来。它的目标不是单独提供一个 REST CRUD 后端,而是把插件化服务投影到远程客户端。

这也解释了项目为什么同时维护 Host 和 Client 两个编译面:Host 运行插件和 Agent,Client 负责浏览器或 SDK 侧的类型与交互。

11. 它适合解决什么问题

11.1 个人开发助手

在受控环境中,它可以执行代码、搜索文件、运行测试、调用 LSP、访问网页,并把每一步保存在可恢复的 Session 中。

11.2 Agent 产品原型

如果要快速验证一个“模型 + 工具 + 会话 + UI”的产品,插件和 Profile 机制可以减少从零搭建运行时的工作。

11.3 多代理和自动化

Subagent、Workflow 和 ACP 使它能够承载代码审查、资料整理、任务分解、定时工作和长流程自动化。

11.4 Harness 研究

它特别适合研究 Agent 的基础设施问题,例如:

  • 如何记录和恢复模型上下文。
  • 如何限制模型可见工具。
  • 如何让模型在运行时发现新能力。
  • 如何协调多个 Agent。
  • 如何把 Agent 投影到不同客户端。
  • 如何测试一个包含模型、工具和持久化的完整循环。

12. 它的优势与代价

优势

  • 插件化程度高,模型、工具、存储、UI 和协议可以独立组合。
  • 事件日志让实时输出、恢复、分叉、审计和测试共享同一事实来源。
  • Profile 与 Bundle 支持按场景裁剪运行时。
  • 工具管线提供审批、并发、重试、指标和结果处理等扩展点。
  • Subagent、Workflow 和 SDK 让它不仅能做聊天,也能承载复杂任务系统。
  • 直接围绕 DeepSeek 模型和工具使用场景设计,适合研究和快速迭代。

代价

  • 学习曲线明显高于单一 Agent 示例项目。
  • 一个功能可能分布在 Service Definition、Provider、Consumer、配置行、事件和测试中。
  • 插件组合越自由,配置错误和版本不匹配的可能性越高。
  • 事件持久化、恢复和多代理生命周期带来了较高实现复杂度。
  • 访问宿主机能力的工具需要真实的安全工程,不能只依赖 UI 审批。
  • 项目仍处于早期预览阶段,升级时需要接受 API、配置和存储格式变化。

一句话评价:DeepSeek Harness 的重点不是“让模型回答得更像人”,而是“把模型变成可以被配置、观察、恢复和扩展的任务执行运行时”。

13. 发展方向:事实与判断

13.1 当前实现已经显示出的方向

从当前仓库的模块组织和公开文档,可以确认以下方向已经进入实现范围:

  1. 能力插件化:模型、工具、Shell、FS、Web、LSP、Sandbox、Skills 和 Subagent 都有独立能力分组。
  2. 长生命周期任务:Session 持久化、恢复、分叉、标题、遥测和子会话已经成为核心能力。
  3. 多代理编排:Subagent、Workflow 和实验性的 Agent Teams 共同覆盖委派与协作。
  4. 多客户端投影:Web、Headless、TypeScript SDK、Python SDK 和 ACP 使用不同入口连接相同的 Agent 思路。
  5. 运行时扩展:扩展模块允许模型检查 Cordis 服务、动态定义和运行临时插件包。

运行时扩展的约束尤其值得注意:动态定义的包是进程内版本,重启后不会自动保留,也不会替模型写入仓库文件或 Cordis 配置。可参考 extensions READMEtool-cordis README

13.2 可以合理推断的后续重点

下面是基于现有实现的工程判断,不是官方承诺的路线图:

  • 稳定的插件协议:随着插件数量增加,Service Definition、配置、事件和版本兼容会比单个 Agent 功能更重要。
  • 更强的安全隔离:本地 Shell、文件、网络、凭据和第三方插件需要更清晰的权限模型、审计和沙箱边界。
  • 更成熟的长任务恢复:需要处理挂起、重试、部分完成、子代理恢复和跨进程运行。
  • 更系统的评测:Agent Loop 的质量不能只用最终答案评价,还需要评估工具选择、上下文重建、恢复结果、权限行为和成本。
  • 更好的开发者体验:插件模板、配置诊断、运行时检查、可视化事件流和稳定的文档会直接决定生态能否扩展。
  • 更强的模型无关性:虽然项目由 DeepSeek 驱动,但能力接口若保持清晰,未来可以容纳更多模型提供者和不同推理策略。

社区已经出现关于 Harness 自我学习、反思机制和可评估 Plugin Packs 的讨论,例如 Harness Intelligence 提案任务条件化 Harness 演化提案。这些内容代表社区探索,不应当当作官方路线图。

官方早期讨论也明确把项目定位为快速演进中的预览版本,可参考 v0.1 讨论CONTRIBUTING.md

14. 推荐阅读路径

建议按下面顺序阅读,避免一开始就陷入大量包源码:

  1. 先看 官方 README,了解项目启动方式和预览版定位。
  2. 再看 架构总览,建立 Profile、Bundle、核心包和事件流的地图。
  3. Cordis Primer 补齐插件、服务、事件和 effect 的概念。
  4. Scope 子系统,理解“能力如何对每个 Agent 定制”。
  5. 阅读 Agent Loop 实现,重点跟踪 turn、step、request 和工具调用。
  6. 阅读 Session 实现,理解事件如何变成模型消息和可恢复会话。
  7. 阅读 持久化说明,理解 JSONL、SQLite 和崩溃恢复。
  8. 阅读 Tool Runtime 实现,理解工具注册、Schema、执行阶段和结果。
  9. Compaction 子系统Goal 子系统,理解长会话如何不溢出、长任务如何被持久化推进。
  10. Commands 子系统,理解斜杠命令平面与模型工具的区别。
  11. 最后阅读 扩展 Cookbook,把抽象能力对应到实际扩展方式。

带着三个问题阅读源码会更有效:

  • 这个能力由哪个 Service Definition 定义?
  • 哪个 Provider 负责实现它,哪个 Consumer 把它接入 Agent?
  • 它对模型可见的状态是否通过 Session 事件记录?

15. 快速上手与构建环境

15.1 最小的源码构建路径

仓库根目录的常用命令包括:

pnpm install
pnpm run build
pnpm run test
pnpm run typecheck
pnpm run lint

从源码构建后,直接运行:

pnpm dsh web

pnpm run build 准备仓库产物,pnpm dsh web 直接使用这些产物而不重新构建。如果只想快速体验,也可以不克隆仓库:

npx @deepseek-ai/dsh web

默认在 http://127.0.0.1:3080 启动 Web UI 并打开浏览器;SSH 启动只打印宿主机 URL,因为本地端口转发由 SSH 客户端或编辑器负责。其他 Profile(headless、sdk、acp)的用法见官方 README 或 dsh --help

实际使用时,优先通过 dsh Profile 启动应用,而不是绕过 Profile 直接运行内部包。

15.2 Node 版本提醒

项目要求 Node.js 版本为 ^22.19.0 || >=24.0.0。如果当前是 Node.js 22.16.0,pnpm 会给出 Unsupported engine 警告;这不代表电脑必须安装 nvm,而是说明当前 Node 版本低于项目声明的最低 22.x 版本。

nvm 只是切换 Node 版本的一种工具,不是项目的必需依赖。可以使用 Homebrew、fnm、asdf 或其他方式安装满足要求的 Node.js;关键是让终端中的 node --version 达到 22.19.0 及以上,或使用 24.x 版本。

15.3 共享和引用说明

本文中的仓库文件引用均指向 GitHub 上的 deepseek-ai/deepseek-harness,便于在 GitHub、Markdown 阅读器或聊天工具中直接打开。由于项目仍在快速迭代,指向 master 的链接可能随仓库更新;需要固定阅读版本时,可将链接中的 master 替换为对应 tag 或 commit。

16. 常见误解

  • 插件不等于工具。插件是组成系统的运行时单元(注册服务、监听事件、声明依赖);工具只是插件暴露给模型的一种能力形态。
  • 事件日志不是聊天记录。它是追加式事实来源,聊天记录只是它的一个投影(见第 6 章)。
  • Profile 不是配置文件。它是一套命名的运行时组成,配置只是其中一部分。
  • 作用域不是继承。子代理不继承父代理的作用域,父子关系只是数据(见 3.4)。
  • Goal 不是调度器。目标是状态,自动续跑是刻意挂载的消费方,且恢复后需要人类授权(见 5.5)。
  • Compaction 不是删除。压缩结果仍作为事件写回日志,可追溯(见 6.4)。
  • Plan Mode 是引导不是限制。它不收紧工具权限,沙箱与审批单独配置(见 9.2)。
  • MCP 只桥接工具。外部服务器的 resources 与 prompts 不支持(见第 9 章)。
  • “能运行”不等于“安全”。审批、沙箱、凭据管理降低误操作概率,但不是绝对隔离(见 7.3)。

总结

DeepSeek Harness 的核心价值可以归纳为一条链:

Cordis 插件组合
  → Agent Loop 驱动
  → 工具与外部能力执行
  → Session 事件持久化
  → Web / SDK / ACP 多端投影
  → Subagent / Workflow / 动态扩展

如果把普通 LLM 应用看成“模型加几个函数”,DeepSeek Harness 则是在研究“如何把模型、函数、状态、权限、生命周期和多客户端组织成一个可长期运行的系统”。它当前更适合开发者、研究者和需要深度定制 Agent 的团队;在用于生产环境之前,应先完成版本固定、安全隔离、权限审计、故障恢复和针对真实任务的评测。