DeepSeek Harness 深度评测 · Ep5DEEP DIVE
领域 Agent 与框架
同一个星期,两家都交了 harness 的定制权——写一个插件装进 DeepSeek Harness,再看 Claude Code 的 mods
视频版:B站 公开投稿中无对应视频(已核对全部 16 个投稿) 视频总览 →
本期要点POINTS
本期要点
关键实测数据DATA
关键实测数据
| 被测项 | 指标 | 值 | 实测日期 | 原始记录 |
|---|---|---|---|---|
| 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· nodev24.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 三条判据(下次选型直接用)
- 看失败:插件写错的时候,它明确报错还是静默跳过?敢吵的系统比聪明的系统更值得信。
- 看回收:注册这个动作,带不带撤销?要手工写清理代码的系统,一定会有漏的。
- 看最外层:策略能不能被用户装的插件改到?定制权可以交,兜底权不能交。
补一条给写插件的人:别假设你的插件一定会被激活。依赖没满足时它安静地不活,这在设计上是对的——你的插件应该能在「没被启动」的情况下也不出问题。
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