DeepSeek Harness 深度评测 · Ep5DEEP DIVE

Ep 5 DeepSeek Harness 深度评测 连载中

领域 Agent 与框架

同一个星期,两家都交了 harness 的定制权——写一个插件装进 DeepSeek Harness,再看 Claude Code 的 mods

2026-09-23 阅读约 22 分钟 正文约 8640 字

视频版:B站 公开投稿中无对应视频(已核对全部 16 个投稿) 视频总览 →

本期要点POINTS

本期要点

本期未收录要点:抽取阶段判定该篇正文没有可提炼的线索性结论(不造数、不空着)。

关键实测数据DATA

关键实测数据

8 条
本期自测读数
2026-09-21 — 2026-09-21 · 自有数据
8 条
云(云 GPU / 云 API)
不与他环境混评
8 / 8
原始记录可直达
公开仓固定链接(带 commit SHA)
云(云 GPU / 云 API) · 8 条
被测项 指标 值 实测日期 原始记录
MCP Registry 快照 抓取页数 1106 页 2026-09-21 原始记录 ↗
MCP Registry 快照 版本行(同一服务端多版本各占一行) 110574 行 2026-09-21 原始记录 ↗
MCP Registry 快照 唯一服务端 33903 个 2026-09-21 原始记录 ↗
MCP Registry 快照 唯一发布者 19979 个 2026-09-21 原始记录 ↗
MCP Registry 快照 版本数中位数 1 个 2026-09-21 原始记录 ↗
MCP Registry 快照 只发过一个版本的服务端占比 62.83 % 2026-09-21 原始记录 ↗
MCP Registry 快照 远程服务端未声明认证头占比 80.2 % 2026-09-21 原始记录 ↗
MCP Registry 快照 前 10 发布者占比 13.35 % 2026-09-21 原始记录 ↗

口径:本地与云不混评(每条读数标了运行环境,两边数字不放在一起比); 一行 = 一条可核读数;论文与第三方数字不进本表(见上方来源表)。 「原始记录」指向公开仓 cnopens/ruiowl-evidence 的固定链接(带 commit SHA,防漂移);标「未收录」者为本地从未留存原始数据文件,不补造。

锐Owl · DSH 系列 Ep5(全局期号 ep16)· 配套视频《同一个星期,两家都交了 harness 的定制权》(6:29.5) 一手材料:本机真机演示 5 段(M4 · dsh 0.1.0-rc.6 · node v24.15.0 · DSH 源码 @47f9438)+ 官方 MCP registry 全量抓取(1,106 页,快照 2026-09-21T13:11:38Z)+ 两家官方源码与文档 立场:不评谁抄谁,只比机制。结论落在两句话上——「定制权可以交出去,兜底权不行」、「规模不解决治理,只会放大它」


开篇:为什么写这篇

2026-09-18,Claude Code 从 2.1.277 起支持 AGENTS.md:项目里没有 CLAUDE.md,就去读 AGENTS.md。这条 CHANGELOG 读起来像一次迟到一年的兼容性修复。

真正值得记的是工程师在帖子里的那句话:这个功能是用 Claude Code 的 mods 做的,mods 是他们接下来要推的定制方式,用来定制 Claude Code 的 harness——harness 就是模型外面那一层,负责组装上下文、调工具、渲染会话的软件层。

一个月前开源的那套 DeepSeek Harness,旗号喊的是 「Everything is a plugin」:模型、工具、技能、会话、沙箱,全部拆成可插拔组件。中文报道在 9-20 自己就把两家放在了一起说。

视频里我用六分半把这套对照讲完了。这篇长文补视频装不下的那一半:把两个框架的插件机制拆到可对照的粒度、把我真机上跑出来的原始输出逐条留档、把生态的账用一次全量抓取算清楚,以及一条在动手之前你不会意识到的东西——插件系统教你的第一课,不是它能做什么,而是它失败的时候什么样。

一句话分工:视频讲结论,长文交证据。


一、两家说的「插件」,都不是普通扩展

先把「插件」这个词对齐。两家给出的定义,几乎是同一句话。

维度 DeepSeek Harness(Cordis) Claude Code(Plugins / Mods)
插件形态 导出 apply(ctx) 的函数(也可以是对象,或 extends Service 的类) 行为写在 hooks module 里的插件:一个 register(on, options) 入口
描述与装配 插件不自带启动代码;cordis.yml 是一份配置项列表;profile 侧是补丁层表(insert 逐行 id / name / config,整行替换 config) marketplace.json(目录)+ .claude-plugin/plugin.json(清单);安装时拷贝到缓存(除非用 link 或相对路径)
官方的定位 「一切皆插件」:连会话、沙箱都是可替换组件 mods/README.md 首段原文:A mod is a Claude Code plugin whose behaviour lives in a hooks module —— 一个 mod,就是一个改引擎行为的插件

← 表格可左右滑动查看

差异在装配方式,共同点在它们动的东西:不是给应用加功能,而是注册进框架自己的运行机制。也就是说,插件是框架的定制权。

那么问题立刻变成一句话:定制权交出去之后,谁负责这些东西?


二、先把它装上:三行代码 + 一行配置

文档说得再漂亮都不算数,我自己写一个。插件本体就三行(hello.ts):

export const name = 'hello'

export function apply(ctx: Context) {
  console.log('hello from my first plugin')
}

配置文件一行(cordis.yml):

- name: './hello.ts'

跑起来(演示①):

hello from my first plugin

打印完那句 hello,进程自己退出。装上了,没有注册表、没有清单、没有构建步骤。

2.1 两类失败:它敢不敢在你犯错的时候吵起来

这才是本节的重点。 我在插件系统里踩过的坑告诉我:判断一个插件系统成不成熟,看它失败时的样子,比看它成功时的功能准得多。

第一类失败:插件自己抛异常。 我在 apply 里直接 throw new Error('apply exploded'),再跑一次(演示②a):

Error: failed to apply loader entry (./hello-throw.ts): apply exploded
→ 进程终止

报错写得清清楚楚:哪个插件、哪一步、为什么。加载失败就是失败,它不会假装跳过——这是失败关闭(fail-closed)的默认值,也是 DeepSeek Harness 在权限侧一贯的口径(权限默认值 + 失败关闭)。

第二类失败:模块名拼错一个字母。 这次报错换了一层(演示②b):

Error: failed to import loader entry (./hello-typo.ts): Cannot find module ...
[cause]: Error [ERR_MODULE_NOT_FOUND]
→ 进程终止

区别不在「是否终止」(两段实测都终止),在报错的层级:它只说「找不到这个模块」,不会正面告诉你「这个插件没生效」。官方把这条写进了文档,提示很直白:新加的配置项好像没生效?先检查拼写。

口径说明:官方文档另有一句提醒——启动阶段这类报告可能丢失。我没有在完整 harness 启动流程下复现这一点,所以不把它当作演示结论。

一行配置的错误,代价是「静默无效」。这是所有插件系统的通病,也是为什么「装上了」这句话在工程上永远需要证据。


三、插件什么时候活,不由写配置的人决定

插件装上了,就一定会跑吗?不一定。这一节是我这次实测里最想让你看的一幕。

我准备两个插件:greeter.ts 提供能力(自己注册一个 greeter 服务),consumer.ts 使用能力——它的写法只有一句关键声明:

export const inject = ['greeter']

三种状态,跑三遍(演示③):

状态 配置顺序 实际输出
① 提供方在前 Hello, world!
② 两行对调(使用方在前) Hello, world!(一模一样)
③ 删掉提供方,只留使用方 什么都没有,也不报错,退出码 0

← 表格可左右滑动查看

第二列值得停一下:顺序不重要。你把使用方写在提供方前面,照样跑。第三列更值得停:它没死,它在等——等那个能力出现,它才会活过来。

这是插件系统的第二课:一个插件什么时候活,不由写配置的人决定,由依赖决定。 Cordis 里激活顺序由 inject 声明推导(各项并发启动),配置文件里那几行的先后只是个书写顺序。

对做框架的人来说,这条意味着:配置文件的语义是「声明我有什么、我需要什么」,不是「按这个顺序执行」。对用框架的人来说,它解释了一种最难查的故障——什么都没发生。没有报错、没有日志、退出码 0,因为在你眼里它「没生效」,在框架眼里它「条件没满足」。


四、能干净地拿掉,才算装上

插件能跑不算本事,能干净地拿掉才算。这一节是本期最硬的证据。

我写了一个 lifecycle.ts:一个插件每 200 毫秒打印一次 tick(心跳),而在注册它的同一处,把「怎么撤销」也一起写了进去(Cordis 的 ctx.plugin() 返回 fiber,fiber.dispose() 就是它的撤销)。然后主动卸载它(演示④):

heartbeat plugin loading
tick
tick
tick
heartbeat cleaned up
disposed

注意看 tick 那三下:卸载那一刻心跳停住了,紧接着打出 heartbeat cleaned up,最后 disposed。我一行额外的清理代码都没写。

原理一句话:在这个框架里,「注册」这个动作本身就带着「怎么撤销」——注册即副作用(effect),disposer 附着在插件上,插件被卸载时,它加过的东西自己收回。框架之外申请的资源(定时器、连接、文件句柄)必须用 ctx.effect() 包一层,才能进入同一套回收。

Claude Code 这边是一套不同的答案:

  • /reload-plugins —— 插件改动不用重启就生效(--force 可强制);
  • enabledPlugins / /plugin disable —— 装了哪些插件写在设置里,可以逐个关掉;
  • 安装时把插件目录拷贝到缓存 —— 好处是版本固定、多来源互不干扰;代价是插件引用不了目录外的文件,官方只能建议你用软链接绕过。

两种做法的背后是同一件事:系统必须随时知道「哪些东西是谁加进来的」,否则卸不干净。这不是洁癖——上下文、工具、权限、后台任务都是插件加进来的,收不回去就是长期泄漏。

顺带一句:这期的立意在上一期(ep15《Agent 动手之后,谁来拦》)就有了前身——那期拆的是权限的闸门,这期拆的是装配的闸门,同一个问题的两面。


五、真正的分叉:谁的策略在最外层

到这里,两家还挺像:都定义插件、都用配置装配、都要能卸载。真正的分叉在最后一层——谁的策略在最外层。

先看 DeepSeek Harness 的装配方式:它是一层一层叠起来的。用 --dump-config 把装配结果打出来(演示⑤),每一行插件后面都标着它来自哪一层、被哪一层改过:

# == @deepseek-ai/dsh-base
- id: timer
# == @deepseek-ai/dsh-base, patched by @deepseek-ai/dsh-web-app
- id: hmr

这就是「层栈 + 行级覆盖」的真身:你的配置加在上面,框架与组织策略在下面兜着,而且覆盖关系是可读的、可审计的。再往下一层是沙箱三档与审批的两道闸门(ask / 确定性拒绝,ep15 已拆)。

Claude Code 源码里有一个内置 mod 叫 sec-default,位置在最外层(内置 tier,官方测试用 claude plugin test mods/diff 可验证)。它做的事一句话能说完:把组织的托管设置、工具策略、项目指令,放在用户自己装的插件够不着的地方——而它自己不新增任何策略。

翻译成人话:你可以随便装插件,但你装的东西碰不到企业定下的规矩。 另一个内置 mod telemetry 更直接:拒收已安装的第三方插件接入它的遥测通道。企业侧还留了 strictKnownMarketplaces,限定只能从白名单市场装。

两家的答案其实一致:定制权可以交出去,兜底权不行。

这也是我们做选型建议时的第一条判据:不要问「它能不能装插件」,问「最外层是谁、这一层能不能被插件改」。


六、生态的账:三万个服务端,中位一版

兜底这件事,规模越大越要命。所以最后一步,我去把生态的账算清楚——不用三方统计,直接抓官方 MCP registry 全量(mcp_registry_census.py,1,106 页,快照 2026-09-21T13:11:38Z):

指标 本机全量结果
唯一服务端 33,903
版本行(同一服务端多版本各占一行) 110,574
唯一发布者 19,979
版本数中位数 1
只发过一个版本的服务端 62.83%(21,301 个)
远程服务端未声明认证头 80.2%(36,509 / 45,520)
前 10 发布者占比 13.35%(最大单一发布者 2,341 个)

← 表格可左右滑动查看

⚠️ 口径必须写清楚:这里的数字是本机对官方 registry API 的全量抓取,与三方统计(例如常被引用的「30,375 个 server」)属于不同筛选与时点,两者不可混比。本文与视频一律用本机口径,并标注快照时刻。

再叠加一份已被会议录用的论文(arXiv 2609.17274《After the Party: Growth, Governance, and Security Scanning in the OpenClaw Agent Skill Ecosystem》,APSEC 2026):61,990 条技能里,三个安全扫描器对 23,702 条判断不一致;77.86% 零 star 零评论;85.06% 可读技能带特权证据;前 10% 吃掉 46.93% 的下载。

两套独立数据指向同一个结论:生态爆炸 ≠ 生态健康。注意力极度集中在头部,大多数条目无人维护,安全信号本身不可靠(连扫描器都吵)。

这就是为什么「最外层」必须存在,而且不能指望生态自己长出来:规模从不解决治理,它只会把治理问题放大。


七、结论与可复用判据

7.1 三条判据(下次选型直接用)

  1. 看失败:插件写错的时候,它明确报错还是静默跳过?敢吵的系统比聪明的系统更值得信。
  2. 看回收:注册这个动作,带不带撤销?要手工写清理代码的系统,一定会有漏的。
  3. 看最外层:策略能不能被用户装的插件改到?定制权可以交,兜底权不能交。

补一条给写插件的人:别假设你的插件一定会被激活。依赖没满足时它安静地不活,这在设计上是对的——你的插件应该能在「没被启动」的情况下也不出问题。

7.2 局限(写清楚比藏着好)

  • 演示是本地单机、最小复现:一个插件、一个服务依赖,覆盖的是激活与回收机制,不覆盖多插件冲突、热更新、生产规模下的内存与启动耗时。
  • DSH 侧源码版本为 @47f9438(本地仓);上游有更新,机制结论以该 commit 为准,版本差异不做推断。
  • Claude Code 的 mods 官方标注 early access、API 可能随版本变动(2.1.269+ 起才有 function hooks)——本文对其机制的描述是就 2026-09-21 时点而言。
  • 生态数据是同一天的一次快照,不作为趋势判断;两套数据(registry / 论文)口径与对象不同,只作方向性互证。
  • 视频最终采用全卡片版(演示录屏为可选增强);文内所有命令输出均为 M4 真机实跑原样照录,脚本 m4_dsh_plugin_demo.sh 可复现。

复现

# 前置:dsh 0.1.0-rc.6 / node v24.15.0 / DSH 仓 @47f9438(含 vendor/cordis)
cd ~/workspace/ruiowl-content/ep16-dsh-ep5-plugin
bash m4_dsh_plugin_demo.sh prepare   # 生成演示文件
bash m4_dsh_plugin_demo.sh 1         # ① 装上:hello from my first plugin
bash m4_dsh_plugin_demo.sh 2         # ② 两类失败(a 抛异常 / b 模块名拼错)
bash m4_dsh_plugin_demo.sh 3         # ③ 依赖驱动激活(顺序无关 / 缺依赖静默)
bash m4_dsh_plugin_demo.sh 4         # ④ 卸载即回收(tick ×3 → cleaned up → disposed)
bash m4_dsh_plugin_demo.sh 5         # ⑤ 层栈装配(--dump-config)

生态普查(只读官方接口,约 1,106 页):

python3 mcp_registry_census.py      # 产出 ep16-mcp-census.json(含快照时刻)

来源

# 来源 用途
1 本次真机演示(M4 · dsh 0.1.0-rc.6 · node v24.15.0 · DSH 源码 @47f9438;脚本 m4_dsh_plugin_demo.sh,原始输出见 ep16-script.md、录制手册 ep16-demo-recording.md) 第二~四章全部实测输出(自有数据)
2 anthropics/claude-code → mods/README.md、mods/{sec-default,diff,telemetry,agents-md}/、CHANGELOG ## 2.1.277(api.github.com 直读,2026-09-21 核) 第一章、第五章机制证据(mods 定义、sec-default 位置与职责、AGENTS.md 支持版本与日期)
3 Thariq(@trq212)2026-09-18 X 帖(多源逐字引用一致) 「mods = 定制 harness 的方式」口径与第一个内置 mod
4 Claude Code 官方文档(plugins / plugin-marketplaces / discover-plugins) /reload-plugins、enabledPlugins、安装拷贝到缓存、企业市场限制
5 官方 MCP registry API 本机全量抓取(mcp_registry_census.py,1,106 页;快照 2026-09-21T13:11:38Z) 第六章全部数字(自有数据,口径与时点已标注)
6 arXiv 2609.17274《After the Party: Growth, Governance, and Security Scanning in the OpenClaw Agent Skill Ecosystem》(APSEC 2026) 第六章论文侧数据(摘要逐句核对)
7 DeepSeek Harness 源码 @47f9438 + 官方 docs/cordis-tutorial/* 第一~五章机制(apply/inject/effect-disposer/层栈 patch)

← 表格可左右滑动查看


附:一句话口径(供简介 / 三件套复用)

同一个星期,两家都把 harness 的定制权交了出去:一边把 mods 定义为「定制 harness 的方式」,一边开源时喊「一切皆插件」。我亲手写了插件装进 DeepSeek Harness——三行代码装上,卸载时心跳自己停住;再去看 Claude Code 的 sec-default,企业策略放在用户装的插件够不着的地方。定制权可以交给所有人,兜底权只能留给自己。

信号来源SIGNALS

信号来源

这一期从哪条雷达长出来(雷达 → 产出的双向可追溯):

node_links/radar_items.intent 的 feeds 指向关系当前为 0(M2 首轮回填统一先落 standalone,待人工指认)——回填后此处显示「雷达 YYYY-Www 条目 ③ → 已成为本期」。

来源表SOURCES

来源表

该篇正文里没有可解析的「来源」小节(早期篇目未写文末来源表)——不补造。