Files
research-blog/content/posts/deepseek-harness-architecture-evaluation.md
T
2026-08-14 11:42:57 +08:00

283 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
{
"title": "DeepSeek Harness 通过插件组装 Agent 运行时",
"summary": "从一个 greet 工具的完整生命周期出发,分开解释启动装配、请求调用、事件记录和协议边界,再核对 DeepSeek Harness 的架构取舍与公开评测证据。",
"date": "2026-08-14",
"updated": "2026-08-14",
"topic": "agent-systems",
"tags": ["deepseek", "agent-harness", "architecture", "evaluation", "cordis"],
"kind": "article",
"status": "published",
"visibility": "public",
"canonicalUrl": "https://blog.k1412.top/articles/deepseek-harness-architecture-evaluation/",
"sourceRepo": "https://git.k1412.top/wuyang/research-blog"
}
---
> DeepSeek Harness 目前适合进入持续观察和隔离试点。在兼容性、发布稳定性和 Agent 任务评测补齐前,它不适合作为组织级默认 Harness。
## 本文解释 DeepSeek Harness 的运行机制和采用边界
本文面向理解大模型、API 和基本工具调用,但尚不了解 Cordis 或 Agent Runtime 内部结构的读者。它回答三个问题:DeepSeek Harness 实际如何组装和运行 Agent;它与常见 coding agent 系统的关键差异是什么;当前公开证据是否足以支持观察、试点或正式采用。
调研冻结在 2026 年 8 月 14 日,目标代码固定为提交 [`47f943859bef60e4160492346772ded9b24f765a`](https://github.com/deepseek-ai/deepseek-harness/tree/47f943859bef60e4160492346772ded9b24f765a)。横向对照也固定到同日抓取的 Codex、Gemini CLI 与 OpenHands 提交。本文不评价 DeepSeek 模型能力,不使用 GitHub star 数作为成熟度证据,也不把不同项目、不同模型、不同任务下的数字拼成排行榜。
## DeepSeek Harness 是一套 Agent 运行外壳
DeepSeek Harness(命令名 `dsh`)不是一个模型,也不是某个单独工具的封装。它是一个 **Agent Harness**:负责把模型、工具、会话状态、执行循环、权限策略和用户入口组装成一个可以持续运行的 Agent 应用。
先建立四个最小概念:
| 名称 | 简要定义 | 在 dsh 中负责什么 |
|---|---|---|
| Agent | 能接收目标、调用模型和工具、保留状态并继续工作的程序 | 一个 Agent 由模型、工具、会话和执行循环共同组成 |
| Agent Harness | 承载 Agent 的运行外壳 | 启动组件、接收请求、管理状态、执行工具并暴露 Web/协议入口 |
| Cordis | dsh 进程内部的插件装配器和生命周期管理器 | 决定有哪些插件、依赖是否满足,以及变化时如何卸载和重建 |
| Agent loop | 一次任务中的“模型—工具—模型”循环 | 组装上下文,调用模型,执行工具,再把结果交回模型直到结束 |
dsh 主体是 TypeScript monorepo,运行在 Node.js ESM 环境;冻结提交的根配置要求 Node.js 22.19 以上或 24 以上。Cordis 插件在运行时是由 Node 加载的 JavaScript/TypeScript 模块,通常导出 `apply(ctx, config)`。[根 package.json](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/package.json) [第一个 Cordis 插件](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-tutorial/01-first-plugin.zh.md)
理解这套架构最重要的前提是把两个问题分开:**启动装配**回答“哪些组件存在、谁依赖谁、谁随谁卸载”;**请求执行**回答“用户的一条消息在已经启动的组件之间怎样移动”。Cordis 插件树主要回答前一个问题,不是用户请求的调用顺序。
## `greet` 工具展示了完整的插件生命周期
假设现有 Profile 已经包含 LLM、工具注册表、会话、Agent loop 和 Web/ACP/SDK 入口。我们只增加一个虚构示例包 `@acme/dsh-greet-tool`,让模型能够调用 `greet`。下面代码根据官方教程的工具插件写法精简;它只演示插件机制,不是仓库已经发布的包。
```ts
import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const inject = ['tools']
export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'greet',
description: 'Greet the named person.',
parameters: {
name: { type: 'string', required: true },
},
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
execute: async ({ name }) => `Hello, ${name}!`,
}))
}
```
把它加入 Profile 的 `cordis.patch.yml`:
```yaml
- insert:
- id: greet-tool
name: '@acme/dsh-greet-tool'
```
这个工具从配置到卸载会经历六个连续阶段。
### 配置先决定要挂载的插件
dsh 不会直接把某一个 YAML 文件原样交给 Cordis。它先读取 Profile 指定的有序 Bundle,依次应用各 Bundle 的 patch,再叠加 Profile 自身 patch、Harness home patch 和本次命令行 `--patch`,最终得到一组有效配置行。`greet-tool` 是其中一行;它的 `id` 是稳定身份,`name` 指向要加载的模块。[CLI 组合参考](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/apps/cli/reference/README.md)
如果后层 patch 命中同一个 `id`,该行的 `config` 会整体替换,不是字段级深合并。这里的配置合成只回答“本次启动要挂载什么”,尚未执行任何用户请求。
### Loader 创建 Fiber,`inject` 决定插件何时启动
启动器创建根 `Context` 并挂载 Loader。Loader 解析 `@acme/dsh-greet-tool`,为这次插件挂载创建一个 Fiber。Fiber 不是线程或操作系统进程,而是 **一个插件实例的运行时句柄**:它记录父上下文、配置、依赖、状态、注册的 effect 和清理过程。
插件导出了 `inject = ['tools']`,所以 Cordis 会检查名为 `tools` 的 Service 是否已经存在。若不存在,Fiber 保持 `PENDING`,不会调用 `apply`;当 `ctx.tools` 出现后,Fiber 进入 `LOADING`,执行 `apply(ctx)`,完成后进入 `ACTIVE`。因此 YAML 中哪一行写在前面并不决定启动顺序,服务依赖才决定。[Cordis 服务教程](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-tutorial/03-services.zh.md)
`apply` 中的 `ctx.tools.register(...)` 把 `greet` 的名称、参数 schema、返回值渲染和执行函数注册到工具运行时。该注册本身属于一个 effect;Cordis 会记住对应的 disposer,以便插件卸载时自动注销工具。[进入 Harness 教程](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-tutorial/07-into-the-harness.zh.md)
### 用户请求进入已经启动的 Agent
用户通过 Web、ACP 或 SDK 输入“向 Ada 问好”。入口适配器把消息交给对应 Agent 的 inbox。Agent loop 取得待处理输入,从会话日志派生历史,加入系统提示和当前可用工具 schema,然后进入一个 model step。此时 `greet` 已经是工具列表中的一项;Cordis 不再决定模型是否调用它,Cordis 只保证工具已经正确注册。
模型可以直接回答,也可以产生工具调用。这个例子中,模型返回 `greet({"name":"Ada"})`,于是 Agent loop 把调用交给统一 Tools Runtime。
### 工具调用经过统一执行管线
工具调用不会从模型直接跳进示例函数。标准路径依次经过 `tools/pre-execute`、审批、guard、`tools/execute`、工具本体、`tools/post-execute` 和结果固化。若某项策略返回 `ask`,但当前入口没有可用审批 answerer,系统会拒绝而不是静默放行。[Tools README](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/core/tools/README.md)
`greet` 执行后返回 `Hello, Ada!`。Tools Runtime 将结果交回 Agent loop,Agent loop 再把它放入下一次模型请求。模型据此生成最终回答,例如“已向 Ada 问好”。这就是 Agent loop 所负责的“模型 → 工具 → 模型”循环。
### SessionEvent 在旁路记录执行事实
用户消息、step 开始、模型消息、工具调用、工具结果和最终回答会分别追加为 `SessionEvent`。它不是调用链中的“下一台服务器”,也不负责把工具结果转发给模型;它是执行过程中形成的 durable fact。模型历史、resume、fork、轨迹视图、持久化和 UI 投影都从同一事实源派生。[持久化说明](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/session/session-persistence/README.md)
如果进程在工具调用期间中断,恢复逻辑会检查日志:工具尚未真正开始,可以安全标记失败;工具可能已经产生副作用但没有留下结果,则标记“结果未知”,提示模型先验证外部状态,避免盲目重试。这解释了事件日志为什么与执行链同样重要,但二者仍是不同关系。
### 配置或依赖变化会触发自动撤销
Fiber 的主要状态为 `PENDING → LOADING → ACTIVE → UNLOADING`,加载失败时进入 `FAILED`。如果 `tools` Service 暂时消失,已经激活的 `greet-tool` 会卸载自己的 effect,回到等待依赖的状态;服务恢复后重新加载。如果配置行被删除,旧 Fiber 完成清理后进入 `DISPOSED`,不能再次启动。HMR 则卸载旧实例,再根据新模块挂载替代实例。[Cordis 生命周期教程](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-tutorial/02-lifecycle-and-effects.zh.md) [组合与 HMR](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-tutorial/06-composition-and-hmr.zh.md)
卸载时,`greet` 的工具注册、事件监听、子插件和通过 `ctx.effect()` 管理的定时器或连接都会执行 disposer。插件不需要在每个退出分支手工寻找自己曾经注册的对象。这个“注册与撤销属于同一生命周期”是 Cordis 最核心的工程价值。
完整过程可以概括为:**配置决定挂载 `greet-tool`;`inject` 让它等待 `tools`;Fiber 激活后注册工具;Agent loop 在一次请求中让模型调用它;SessionEvent 记录事实;依赖或配置变化时 effect 自动撤销。**
## Profile 会被逐层合成为运行中的插件
![启动装配会创建 Fiber 并等待服务依赖;这不是请求调用顺序](/articles/deepseek-harness-architecture-evaluation/dsh-startup-assembly.svg)
这张图只回答启动问题。可以把它拆成配置层和运行时层。
### Bundle、Profile 和 patch 共同产生有效配置
- **Bundle** 是可复用的默认插件组合,例如一组基础服务和工具。它贡献配置行或 patch,但运行时不会把整个 Bundle 当成不可拆的黑盒。
- **Profile** 是一种产品或运行形态的入口。它选择有序 Bundle,并附加自己的 patch,例如组合 Web 或 headless 版本。
- **Harness home patch** 是用户或部署环境的持久覆盖。
- **CLI `--patch`** 是本次启动最后应用的临时覆盖。
合成结果是一组带 `id` 的配置行。每行通常包含 `name`、`config`、`inject` 和 `disabled` 等字段。稳定 `id` 让 Loader 判断一项变化是在更新已有节点,还是删除旧节点后增加新节点。
### Context、Loader 和 Fiber 管理运行实例
根 `Context` 是进程内能力和事件的访问入口;Loader 根据有效配置加载模块,并把每次挂载变成 Fiber。官方教程支持函数、带 `apply` 的对象和 `Service` 子类三种插件形态。`apply(ctx, config)` 只描述插件向当前上下文贡献什么,启动器和 Loader 负责实际挂载。[第一个 Cordis 插件](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-tutorial/01-first-plugin.zh.md)
Fiber 负责把一次插件应用变成可观察、可等待、可失败、可卸载的运行实例。它记录所需 Service 的具体实现;提供方变化时,Cordis 可以比较依赖并只重载受影响的插件,而不是重启整个进程。
### Service 和 `inject` 管理服务依赖
Service 是插件提供给其他插件的具名能力,例如 `ctx.llm`、`ctx.tools` 和 `ctx.sessions`。消费者声明 `inject: ['tools']`,只表示“我需要工具服务”,不绑定某一个具体提供包。部署可以替换 provider,而消费插件代码无需改变。
`inject` 是硬依赖:缺失时 Fiber 保持 `PENDING`。可选能力则不应写入 `inject`,而是在使用处通过 `ctx.get(...)` 探测。服务名称共享一个命名空间,这也意味着大型部署必须治理名称、提供方和配置来源。
## 一条消息会在已经启动的组件之间流转
![一次 greet 请求会在已经启动的组件之间流转,SessionEvent 位于记录旁路](/articles/deepseek-harness-architecture-evaluation/dsh-greet-request.svg)
这张图只回答运行问题。系统已经完成装配,因此请求链中不再出现 Profile、Bundle 和 Loader:
1. Web、ACP 或 SDK 入口把用户输入交给 Agent inbox。
2. Agent loop 取得输入,组装系统提示、历史和工具 schema。
3. Agent loop 调用 LLM;模型可以直接回答或请求工具。
4. 工具调用进入统一 Tools Runtime,经过策略、审批、guard 和执行阶段。
5. 工具结果回到 Agent loop,再进入下一次模型 step。
6. 模型生成最终消息,Agent loop 提交结果并在没有待处理工作时回到 idle。
dsh 同时存在两类容易混淆的“事件”。`SessionEvent` 是写入会话日志的 durable fact,承担重建、恢复和投影;`agent/pre-step`、`agent/request`、`tools/pre-execute` 等 live event 或 waterfall 是运行时扩展点,插件可以监听、修改、放行或短路当前过程。前者回答“发生过什么”,后者参与“现在怎样继续执行”。
## 插件树、依赖图和调用链表示三种不同关系
| 关系 | 它回答的问题 | `greet` 例子 |
|---|---|---|
| 插件父子与生命周期 | 谁由谁挂载,父节点卸载时谁一起清理 | Loader 挂载 `greet-tool` Fiber;删除配置时旧实例被清理 |
| Service 依赖 | 谁必须等待谁,提供方变化时谁需要重载 | `greet-tool` 通过 `inject` 等待 `tools` |
| 请求调用 | 一条消息在运行时经过哪些已经激活的组件 | Agent loop → LLM → Tools → `greet` → LLM |
所谓“Cordis 插件树”首先是一套运行实例的所有权结构;再叠加 `inject` 后,形成服务依赖图。一次请求的调用链则发生在这些实例都准备好之后。三者可能涉及相同插件,但箭头含义不同,不能用一棵树同时表示。
## Web、ACP、SDK、MCP 和 Cordis 连接不同边界
![Web、ACP、SDK、MCP 和 Cordis 连接不同边界](/articles/deepseek-harness-architecture-evaluation/dsh-protocol-boundaries.svg)
先看进程边界,再看协议名称:Web、ACP 和 SDK 把请求从外部送入 Agent;MCP 把外部工具送入 Tools;Cordis 位于 dsh 的 Node.js 进程内部,负责组件装配,不是远程协议。
| 接入面 | 连接方向与载体 | 解决的问题 |
|---|---|---|
| Cordis 插件 | dsh 进程内的 ESM 模块:`apply`、Service、Event、effect | 增加或替换模型、工具、会话、策略、loop 和 UI 组件 |
| Web | 浏览器 → dsh 为 HTTP POST;dsh → 浏览器为 WebSocket 事件 | 产品 UI、会话展示和交互操作 |
| ACP | 外部 Agent Client ↔ dsh,newline-delimited JSON-RPC over stdio | 创建会话、发送 prompt、取消和一次性权限回答的基线自动化 |
| Python / TypeScript SDK | 评测器或程序 ↔ dsh,项目自有 line JSON-RPC 2.0 over stdio | 批量任务、自动化和 benchmark runner |
| MCP client | dsh ↔ 外部 MCP Server,stdio 或 Streamable HTTP | 发现外部工具并注册为 `mcp__<server>__<tool>`;当前只桥接 Tools |
Profile、Bundle 和 patch 不在表中,因为它们是部署配置方式,不是通信协议。ACP 也不等于完整 Web 产品面:它只暴露自动化基线;SDK 线协议当前没有版本协商和单 prompt 取消;MCP 当前不桥接 Resources 和 Prompts。[ACP 协议契约](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/acp/acp/README.md) [SDK 线协议](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/sdk/protocol/README.md) [Web Connection](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/client/connection/README.md) [MCP client](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/mcp/mcp-client/README.md)
## DeepSeek Harness 的主要价值来自扩展边界和生命周期管理
1. **最值得关注的是扩展边界。** dsh 允许替换的不只包括工具和模型适配器,还包括会话、Agent loop、工具注册表、策略、持久化和 UI。Profile、Bundle 与 patch 可以逐层改写配置,比“在固定 Agent 核心外围加插件”更激进。
2. **Cordis 解决的是组合变化。** Fiber、Service、`inject` 和 effect 让插件能随配置与依赖变化安全地加载、等待、卸载和重建;它并不替代 Agent loop。
3. **Agent loop、工具管线和事件日志形成执行主链。** loop 决定下一步,Tools 执行动作,SessionEvent 保留可恢复事实;三者职责分开。
4. **工程质量证据多于效果证据。** 仓库有高覆盖率单元测试、keyless snapshot、真实 API e2e 入口、Web 性能/压力 runner 和 CI runner benchmark;但在冻结范围内没有发现公开的 Agent 任务成功率成绩。
5. **现在的合理动作是观察或隔离试点。** Developer Preview、兼容性主动破坏、会话格式 v0、无正式 GitHub Release,以及缺少可复现的目标任务评测,都会阻断生产级采用。
## 这种设计同时带来可替换性、可恢复性和安全边界
### Profile 和插件可以替换运行时结构
许多 Agent 产品把模型、会话和 loop 固定在核心,只开放工具、MCP、Skill 或 Hook。dsh 把替换面进一步下沉:可以用不同 Profile 组成 Web 或 headless 产品,也可以替换会话后端、工具策略、模型适配器乃至 Agent loop。对于需要研究不同上下文策略、执行器、持久化或交互面的团队,这能减少 fork 主干的压力。
代价是配置态数量迅速增加。某个行为可能来自 Bundle 默认值、Profile patch、home patch、命令行 overlay 或运行时插件;“一切可替换”会把复杂度从代码分支转移到组合、来源追踪和兼容性验证。官方 plugin inventory 甚至明确说明它不记录条目由哪个 Bundle、Profile 或 override 引入,也不能直接修改插件,这意味着生产排障仍需要更强的配置溯源工具。[Plugin inventory](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/host/plugin-inventory/README.md)
### 事件日志让执行、恢复和观察共享事实
事件溯源避免了“模型看到的历史、UI 显示的历史、持久化记录”长期漂移。工具调用、结果、权限变化和 turn 边界都可以成为 durable fact;模型上下文只从带 surface 语义的事件派生。这个约束对恢复尤其重要,因为系统可以识别未闭合的调用并合成明确错误状态。
但事件溯源不能自动解决格式演进。当前 `SESSION_FORMAT_VERSION = 0`,持久化协调器会拒绝无法升级的旧格式或更新格式;在 Developer Preview 阶段,这意味着长生命周期会话不应被当作稳定资产。试点需要固定提交,并接受迁移、导出或放弃历史的可能性。
### 安全策略可以组合,但不会自动覆盖所有工具
默认权限预设把 `workspace-write + ask` 与 `danger-full-access + never` 组合成两个选择,审批缺失时 fail-closed;这比把“是否询问”散落在每个工具内更清晰。[Permission presets](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/subsystems/permission-presets.md)
需要注意的是,策略 seam 只有在工具主动接入或部署增加 `tools/pre-execute` 策略时才生效。官方 Web 工具说明明确指出,它的两个工具本身不会请求 `ctx.approval`,也没有持久 URL 或域名授权;需要确认的部署必须另外挂载策略。[Web tool](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/web/tool-web/README.md) 因此,不能仅凭“系统有 approval 与 sandbox 包”推断所有能力都受到同等保护。
## 使用和扩展 DeepSeek Harness 仍有明显门槛
体验入口很短:官方给出的 Web 启动方式是 `npx @deepseek-ai/dsh web`,默认监听 `127.0.0.1:3080`。如果从源码开发,则需要 Node.js `^22.19.0` 或 `>=24.0.0`、仓库锁定的 pnpm 11.7,完成依赖安装和构建后再通过 `pnpm dsh web` 启动。[README](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/README.md) [开发指南](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/development.md)
扩展有两条路径。已有能力的轻量改造,可以先用 `dsh --profile web --dump-config` 查看最终配置,再按配置行 ID 用 patch 整体替换;新增模型、工具、策略、会话后端或 loop,则需要实现 Cordis 插件,把它加入 Bundle/Profile,并同时处理服务依赖、事件或 waterfall、effect 清理和测试。后者不是“放入一个脚本即可”的低成本插件:当前项目仍处于 Developer Preview,配置 inventory 又不能完整回答某一行由哪层引入,因此试点需要固定提交、锁定插件版本,并为每个自定义插件建立组合测试和升级回滚检查。
## DeepSeek Harness 暴露了更多运行时替换点
下表比较的是同一生命周期上的架构边界,不是产品效果排名。冻结版本分别为 [Codex `053dda6`](https://github.com/openai/codex/tree/053dda6b897887c0bbd8efa5d4952a4380dbb5e4)、[Gemini CLI `1ac3377`](https://github.com/google-gemini/gemini-cli/tree/1ac3377395868295e128b96726d605a900b5946b) 与 [OpenHands `4f465f3`](https://github.com/All-Hands-AI/OpenHands/tree/4f465f3ccada5271a3bbe4a0148941b0c40d243b)。
| 维度 | DeepSeek Harness | Codex | Gemini CLI | OpenHands |
|---|---|---|---|---|
| 首要形态 | Web、headless、SDK/ACP 由 Profile 组合 | 本地 coding agent,CLI/IDE/App 共用核心与 app-server | terminal-first CLI,CLI 与 core 分包 | Agent Server/Runtime 加 Web/Canvas 与云服务 |
| 扩展边界 | 模型、会话、loop、工具、策略、UI 都可配置替换 | Skills、MCP、Hooks、工具和客户端协议扩展,核心 loop 更集中 | Extensions、MCP、Hooks、Policy Engine、工具注册 | Skills/MCP/工具集、Agent SDK、Runtime/Cloud 服务 |
| 会话语义 | append-only SessionEvent,history 派生,支持 resume/fork/repair | thread/turn/item 持久化,支持 resume/fork/interrupt | CLI/core 管理会话历史与 checkpoint/resume | Conversation/Event 由 Agent Server 管理,Runtime 承担执行状态 |
| 工具安全 | guarded pipeline;ask 缺通道 fail-closed;沙箱与审批可组合 | OS sandbox、approval policy 与权限 profile 是产品核心能力 | sandbox、policy engine 与交互批准围绕 terminal tool | 以隔离 Runtime/sandbox 与服务端执行边界为主 |
| 主要取舍 | 最大可替换性,同时承担配置态和插件兼容复杂度 | 集成一致性与产品化成熟度 | 终端体验、Gemini 集成与扩展生态 | 隔离运行环境、长任务与服务化编排 |
dsh 试图把 Harness 自身变成可动态组合的研究与产品平台。如果团队只需要一个成熟 coding agent,深度可替换性未必能抵消兼容与运维成本;如果团队正在建设多种执行器、策略、持久化或交互形态,它提供了值得借鉴的边界设计。
## 公开证据尚不能证明 Agent 任务效果
### 冻结范围内没有公开的 Agent 任务成绩
本文把“公开 Agent 能力评测结果”限定为同时具有明确任务或数据集、指标与分母、已测量结果。按此口径,在冻结提交的 README、`BENCHMARK.md`、文档、工作流和相关文件中,没有发现 SWE-bench、Terminal-Bench、AgentBench 或 GAIA 等任务的公开成绩。
[`BENCHMARK.md`](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/BENCHMARK.md) 只有一条运行说明:通过 Python SDK 启动 `jsonrpc-agent` minimal variant,并为独立任务使用不同 workspace 与 session ID。它是 benchmark 接入口,不是评测方案或成绩。这个结论严格限于 2026 年 8 月 14 日的冻结仓库与官方公开页面;准确表述是“在该范围内未发现”,不是“项目从未评测”。
### 仓库包含三类工程评测资产
| 类型 | 任务与指标 | 是否有仓库内正式成绩 | 能说明什么 |
|---|---|---|---|
| Web 长历史性能 | 1,000 个侧边栏会话、500-turn 历史、2,100 行轨迹、100-turn soak;记录 wall/task/script/style、首 chunk、p95 等 | 未发现提交的正式运行结果 | Web UI 在高基数历史下的性能分析能力 |
| reasoning chunk 压力 | 100,000 个 chunk;最大主线程延迟与计划交互延迟门槛均为 250 ms | runner 有断言,未发现官方发布结果 | 流式 reasoning 渲染的响应性 |
| CI runner benchmark | 不同 Linux/Windows core 数下的 typecheck、文档构建和聚合 gate | 未发现结果汇总 | CI 容量与拓扑选择,不是 Agent 能力 |
仓库还包含单元测试、keyless snapshot、Web Chromium snapshot、真实组合测试与可选真实 API e2e。开发文档强调 CI 对 package source 执行逐文件 100% coverage,但也明确指出 coverage 只是必要条件,不能单独证明行为质量。[开发指南](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/development.md)
### 本地验证只能说明工程链路可以运行
冻结提交曾在 macOS arm64 上完成 typecheck;针对 Agent loop、工具管线、会话持久化和用户审批的 35 个测试文件、890 个用例通过;10 万 chunk 压力用例在补齐 Playwright Chromium 后通过,一次观测到的最大主线程延迟约 40.4 ms、计划交互延迟约 1.4 ms,低于仓库 250 ms 门槛。
这些结果只证明该提交在单台机器上的构建合约、定向组件测试与一次前端压力复现。没有运行真实模型任务、全量测试、Docker、跨平台矩阵或同任务对照;长历史性能脚本没有完成。因此它们不能填补 Agent 任务效果证据的缺口,也不应升级为官方成绩。
## 当前证据只支持观察和隔离试点
| 门槛 | 当前状态 | 证据 | 判断 |
|---|---|---|---|
| 观察 | 文档、源码和入口足以形成机制判断 | 架构文档、源码、冻结提交 | **通过** |
| 隔离试点 | 需要固定版本、一次性 workspace、低风险任务、明确权限与恢复方案 | 构建/定向测试通过;权限与恢复机制可审计 | **有条件通过** |
| 组织级采用 | 需要兼容/迁移承诺、目标任务复现评测、安全审查、升级回滚和责任人 | Developer Preview、格式 v0、无正式 Release、未发现公开 Agent 任务成绩 | **不通过** |
截至调研日,官方 README 明确标注 Developer Preview 并预告兼容性破坏;[GitHub Releases](https://github.com/deepseek-ai/deepseek-harness/releases) 页面没有正式 Release。版本与发布状态本身不否定技术价值,但会显著增加升级、会话迁移和插件兼容成本。
如果进入隔离试点,建议固定 `47f9438` 或新选定提交,使用可丢弃 workspace,保留默认 `workspace-write + ask`,逐项确认 Web、文件、shell 与外部服务能力是否真正接入审批策略,并把会话导出与版本切换当作可失败项。试点只能回答“它是否适合我们的具体任务和运维方式”,不能用一次成功演示替代采用评审。
## 团队现在适合进行受限试点
现在可以把 dsh 纳入架构观察清单,并安排一个受限试点;不应直接替换现有生产 Harness。观察重点应放在三处:插件树对多产品形态的复用是否真的降低 fork 成本;事件日志能否让恢复、审计和 UI 投影保持一致;工具策略在自定义插件和 Web 能力接入后是否仍然 fail-closed。
从“试点”升级到“采用评估”至少要看到三项变化:项目给出更稳定的发布与迁移政策;在固定模型、工具、预算和任务集下产生可复现的目标任务结果;团队完成插件供应链、权限、数据与回滚审查。任一项缺失,都应继续停留在观察或隔离环境。
## 本文结论来自冻结源码和公开资料
- 目标仓库:[deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness)
- 冻结提交:[`47f943859bef60e4160492346772ded9b24f765a`](https://github.com/deepseek-ai/deepseek-harness/tree/47f943859bef60e4160492346772ded9b24f765a)
- 主要官方文档:[README](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/README.md)、[Architecture](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/architecture.md)、[Persistence](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/session/session-persistence/README.md)、[Tools](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/core/tools/README.md)、[Benchmark entry](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/BENCHMARK.md)
- 证据等级:官方声明与源码文档、冻结源码、仓库测试/CI、边界执行结果、明确标注的推断;不同等级不互相替代。
- 未核验:真实模型端到端效果、生产负载、跨版本迁移、第三方插件生态质量、组织级安全与运维成本。