QUOTE
Linux 用「一切皆文件」赢下三十年;DSH 用「一切皆插件」押注下一个三十年。
本文看点
02
meta harness:写个插件,重放账本验证
1991 年,一个 21 岁的芬兰学生,在赫尔辛基的宿舍里发布了 Linux 内核的第一版。三十多年后的今天,从你口袋里的手机,到天上的火箭,几乎整个数字世界都跑在它上面。
但 Linux 究竟赢在哪?比易用性,它当年被 Windows 按在地上摩擦;比资历,它出生时 UNIX 已经二十多岁。答案是它押对了一个几乎没人注意的抽象——一切皆文件。
在 Linux 眼里,键盘是文件,显示器是文件,网络连接是文件,正在运行的进程也是文件。不管你操作的是硬盘还是打印机,用的都是同一套动作:打开、读、写、关闭。这个抽象压平了世界的复杂度:每样东西都遵守同一条规矩,程序员只需学会一套接口,就能操作一切。
现在把时间拨到 2026 年。DeepSeek 开源了一个 agent harness,叫 DSH(DeepSeek Harness)。它的 README 第一页就写着四个字:一切皆插件。
模型是插件,工具是插件,文件系统是插件,Shell 是插件,沙箱是插件,会话存储是插件,Subagent 是插件,UI 是插件——甚至 Agent 的主循环本身,也是一个插件。在 DSH 眼里,没有「核心功能」和「外围功能」之分,只有「插上了的零件」和「还没插上的零件」。这套架构由从 Koishi 生态移植过来的插件框架 Cordis 驱动,仓库的 vendor 目录里躺着cordis、loader、hmr、schemastery这些熟面孔——DSH 把 Koishi 沉淀多年的插件机制整套搬来,做成了 agent 的骨架。
「一切皆文件」和「一切皆插件」,一个是操作系统的抽象,一个是 agent 框架的抽象,但它们是同一种思维:找到一个足够小的统一接口,让所有东西长成同一个形状,剩下的问题就只剩组合。
有一句经常被误解的话:「Linux 不好用。」——说这话的人,十有八九说的是 Ubuntu 或 Fedora 的某个版本,而不是 Linux 内核本身。
内核不是产品。内核只干三件事:调度进程、管理内存、抽象设备。你平时碰到的「Linux 系统」,其实是内核加上桌面环境、包管理器、浏览器拼出来的一个发行版。Ubuntu 是发行版,Debian 是发行版,CentOS 是发行版;内核是它们的共同地基。
DSH 也是这个分层结构,而且分得同样清楚:
内核层
Cordis 插件框架 + 插件协议。它只负责两件事——把插件接起来,把上下文拼起来。
官方发行版
DeepSeek 官方预置的 Web 界面与 headless CLI,只是「DeepSeek 自己拼出来的一辆样车」。
未来的第三方发行版
任何人基于插件协议拼出自己的 agent 形态——TUI、桌面客户端、工作流专用 agent,都只是插件组合的问题。
这个分层解释了一个让很多人困惑的现象:为什么 DSH 的哲学这么先进,用起来却不如 Claude Code 顺手?因为你在拿「发行版的体验」衡量「内核」。官方预置确实还毛坯——这一点后文会细说——但那是「DeepSeek 这辆样车」的问题,不是「插件协议」的问题。正如你不能因为 Ubuntu 的桌面丑,就得出「Linux 内核不行」的结论。
REFERENCE
仓库 README 里有一句话值得原样引用:「DeepSeek Harness 目前处于开发者预览阶段,正在快速迭代。未来将出现破坏兼容性的变更。」
翻译成人话:地基已经打对了,但房子还在装修,装修期间请自带帐篷。
03
THREE KERNELS
掀开引擎盖:meta harness 与 DSH 的三内核
上一节说,DSH 是「内核 + 发行版」的结构。那下一个问题自然就来了:这个内核里,到底装了什么?这一节先给结论,再掀开盖子逐个看。
结论是:DSH 的逻辑内核,不是某一个大模型,也不是一条 Trajectory,而是三个东西叠在一起。
3.1 先给结论:三个内核叠成 DSH
1程序内核:Cordis 插件组合系统——决定「能力从哪来」。
2运行内核:Agent Loop 执行循环——决定「事情怎么转」。
3状态内核:Session/Event 事件账本——决定「记忆怎么存」。
把三者合成一句话:
「DSH 把一个 Agent 表示成一棵可动态重组的插件树,并在只追加的事件账本上,不断执行「组装上下文 → 模型决策 → 工具行动 → 记录结果」的循环。」
也可以写成一个公式:
DSH = 可组合能力 × 可回放状态 × 持续执行循环
所以,DSH 更像一个Agent 操作系统,而不是一个固定的 AI 助手。
别被这句话吓到,我们一步步来:先把三个内核一个个掀开看,再回答标题里那个「meta harness」到底指什么,最后把三块拼图合起来——你就明白「操作系统」三个字不是比喻。
3.2 程序内核:一棵可动态重组的插件树
程序内核决定「能力从哪来」。在 DSH 里,一切能力都以插件的形式存在:模型、工具、文件系统、沙箱、Shell、UI——甚至 Agent 主循环本身,都是一个插件。每个插件实现一个或多个「服务」(ctx.llm、ctx.tools、ctx.fs……),服务就是插座的规格:只要插头形状对,谁生产的零件都能插。
所以一个 Agent 的完整形态,就是一棵插件树:树根是 Cordis 运行时,树枝是插件,插件还可以再挂插件(每个插件有自己的作用域 scope)。这棵树不是静态的——仓库里的 loader 和 hmr 支持在运行中挂载、卸载、替换插件,改完立刻生效。换引擎不需要停车,热插拔。
用乐高来想最贴切:没有哪个零件天生特殊,连主循环都只是一根普通树枝——想换循环?拔下来,插一个别的 agent-loop 插件。第四节讲的「接缝」,就是这棵树的零件目录。
但树再漂亮,没人转方向盘,它也只是一堆零件。谁让这棵树真正动起来?——第二个内核:运行内核。
3.3 运行内核:永不停转的四步循环
运行内核决定「事情怎么转」。无论你拼出来的 agent 长什么样,DSH 里它转的都是同一个循环:
「组装上下文 → 模型决策 → 工具行动 → 记录结果 →(回到第一步)」
拆开看:组装上下文,是把插件树上所有片段拼成一次请求——每个插件都能往这张表里注册自己的片段,比如:
// 你的插件:往系统提示里插入一段「文件权限」片段
ctx.systemPrompt.section({
name: 'workspace-guard', // 唯一名字,重名注册直接报错
order: 50, // 排序号:-100 身份 / 0 人格 / 100+ 工具说明
text: () => '你只能访问 /shared/raft 目录下的文件。',
})
模型决策,是 LLM 返回一段输出,可能是文字,也可能是「我要调用工具 X」;工具行动,是真正去执行 bash、读写文件、搜索网络;记录结果,是把这一步追加进事件账本,然后回到第一步。
用生活的话说,这个循环就是 agent 的呼吸:吸气(组装上下文)→ 思考(模型决策)→ 动手(工具行动)→ 写日记(记录结果)。而「呼吸的节奏」本身也是插件(agent-loop),想改成快呼吸、慢呼吸、先想再做——都是换插件的事。
能力有了,发动机也转起来了,还差最后一样:记忆。第三个内核,管的就是这件事。
3.4 状态内核:一本只许记账、不许涂改的账本
状态内核决定「记忆怎么存」。DSH 不保存「状态」,只保存「流水账」:会话是一条只追加(append-only)的事件流(Session/Event),用户说了什么、模型做了什么、工具返回了什么——全都记在账上,永不改写。
想读当前状态?把账本从头到尾算一遍(fold)就行——这一套的细节,第五节专门讲。这里只说它为什么是「内核」:因为账本让一切可回放。崩溃了?重放账本。要审计?重放账本。甚至——改完一个插件,把旧账本重放一遍,看新行为对不对——验证一次修改的成本,从「跑一遍真实任务」降到了「重放一次账本」。这一点有多重要,马上你就知道了。
3.5 现在回答「meta harness」:论文与 DSH 的回答
三个内核都见过了,现在可以回答这一节标题里那个词了——meta harness。它不是我发明的词,它来自今年早些时候的一篇论文:Meta-Harness: End-to-End Optimization of Model Harnesses(端到端优化模型 Harness)。论文的野心很大:把 harness 本身当作被开发、被优化的对象——不只是调模型,而是把包裹模型的整个系统(提示词、工具、循环、记忆策略)都放进优化回路,让 agent 拥有「改进自己运行框架」的能力。
方向是对的,但论文的实现非常繁复:要维护一整套复杂的元机制,去感知、评估、修改 harness 自身。很长一段时间里,我都觉得这是不可行的做法。
DSH 的发布让这件事重新变得可行,原因恰恰是它把目标简化了:在 DSH 里,harness 的一切——插件、服务、事件——都是可枚举、可替换、可回放的普通数据。于是「改进 harness」退化成了两件小事:写一个插件,然后在事件账本上重放一遍验证效果——上一节那个「重放验证」,在这里派上了用场。不再需要复杂的元层,不再需要 hook——everything is a plugin。这就是 DSH 对 meta harness 的回答。
3.6 三合一:为什么 DSH 是 Agent 操作系统
最后一块拼图。把三个内核和操作系统的组件对照一下,「操作系统」三个字就落到了实处:
| | |
|---|
| | |
| | |
| | 事件账本(状态内核 · Session/Event) |
| | LLM / 工具 / fs 等插件——大模型只是众多驱动之一 |
最后一行是整篇文章最关键的一句:在 DSH 里,大模型不是主角,它只是插在ctx.llm插座上的一个驱动。换模型 = 换驱动,不换操作系统。你以前以为自己在「用某个 AI 助手」,DSH 告诉你:助手是预装的一个 App,而 DSH 是那个能长出任何 App 的系统。
「DSH 不是一台固定的 AI 助手,而是一台能长出任何助手的操作系统。」
回到开头的公式:可组合能力(插件树)× 可回放状态(事件账本)× 持续执行循环(Agent Loop)——三内核相乘,就是 meta harness 从论文走进现实的全部秘密。
上一节说,程序内核是一棵插件树。但「树」这个说法太抽象,DSH 用一张图就把它讲具体了:文档里有一张自动生成的图,叫 capability-seams(能力接缝),列出了所有「脊柱服务」和它们可替换的实现——它就像这棵树的零件目录。
举几个例子:
ctx.llm
LLM 适配器注册表。DeepSeek、Pi AI……接什么都行,甚至能接一个「重放」适配器跑测试。
ctx.sessions / ctx.sessionPersistence
内存会话存储 + 持久化接缝,官方给了 jsonl 和 sqlite 两种实现,你也可以写第三种。
ctx.settings
用户设置接缝,默认有文件实现。
文件系统
fs 接缝下有本地实现(fs-local)和沙箱实现(fs-sandbox),还有 fs 搜索、字符串替换编辑器等工具层插件。
这就是「插头标准了,零件随便换」。举个具体的场景——也是我觉得 DSH 最值得关注的应用方向:假设你带着 agent 参加一个多 agent 协作(比如 Raft 论文那种协作场景),你希望你的 agent 只能读共享目录,不能碰你电脑里的私人文件。在传统 harness 里,你要么相信系统提示词里的叮嘱,要么去改一大片文件访问逻辑。在 DSH 里,你只需要做一件事:换一个 fs 插件——写一个「只读白名单文件系统」挂上去,agent 从物理上就无法越权。这不是约束力度的差别,是约束方式的差别:前者靠劝说,后者靠结构。
DSH 甚至为「从竞品迁移」准备了零件。仓库里有个插件叫hooks-claude-code,能直接读取并运行你现有的 Claude Code hooks 配置。但更有意思的是官方自己的注释:
REFERENCE
A native cordis plugin could do everything this bridge does — more powerfully… The bridge exists only as a compatibility path
翻译:这东西只是为了兼容你已有的配置;真正想要能力,请写原生插件。你看,连「Claude Code 的 hooks」在 DSH 里都只是一个翻译插件。你不再需要 hook,everything is a plugin。
还有一个让人会心一笑的细节:DSH 在 Linux 上跑沙箱,用的就是 Linux 自己的内核特性——Landlock。它自带一个约 300 行 C11 写的启动器landlock-run:先对自己施加 Landlock 规则集,再 exec 目标命令,规则集随 execve 继承给所有子进程,而且 fail-closed——内核不支持就拒绝运行。DSH 连安全底座都是「用 Linux 拼 Linux」。这个细节几乎可以作为整篇文章的缩影:DSH 不发明轮子,它把轮子变成可替换的零件。
还记得状态内核吗?它记起账来的方式,是整套设计里最反直觉、也最优雅的部分——Linux 的真相是文件,DSH 的真相是事件日志。
在 DSH 里,一次会话不是一堆被反复修改的 JSON 状态,而是一条只追加(append-only)的事件流。用户发了消息,追加一条;模型开始新的一步,追加一条;工具返回结果,追加一条;标题生成了,追加一条。这条日志一旦写入,就永远不会被改写。
那么问题来了:状态在哪里?答案是:状态不存在,状态是算出来的。想要当前会话的标题?把日志从头到尾「折叠」一遍,取最后一条标题事件,完事。在代码里,这个动作甚至直接就叫foldSessionTitle——fold,正是 Haskell 里那个著名的折叠函数。整个会话模型就是一个大 fold:事件流是输入,当前状态是输出。
用生活里的话说:你从不清算钱包,只保留一沓收银小票。想知道自己有多少钱?拿起每一张小票,一张张叠加计算。小票不会说谎,因为小票永远不被涂改。
1崩溃恢复即重放:进程崩了?日志还在。重新 fold 一遍,状态就回来了,一分不差。
2会话即数据:日志可以导出、迁移、换持久化方式(jsonl 还是 sqlite 只是选择),甚至可以让另一个进程从同一份日志重建出完全相同的会话——subagent、审计、测试回放,全建立在同一份真相上。
[user/message] [step/start] [tool/result] [session/title] … ──fold──▶ 当前状态
(只追加,永不改写 · 重放日志 = 重建世界)
— 图:事件日志折叠——状态不是存出来的,是算出来的
所以你可以理解为什么我说 DSH 是「结构先于代码」:事件日志是结构,fold 是算法,插件只是在日志上添加新的事件类型和折叠规则。每新增一种能力,不是往核心代码里塞逻辑,而是往日志里加一种新的事件。
故事讲到这里,DSH 好像无所不能。现在,该给它泼一盆冷水了——它当前的状态,用一句话概括:这是 1993 年的 Linux,不是今天的 Linux。
1993 年的 Linux 什么样?接口天天变,驱动要靠社区手写,装个系统要折腾一整天,文档和代码一样稀薄。但它的方向已经对了——「内核 + 发行版 + 生态」这条路一旦走通,剩下只是时间问题。今天的 DSH 处在同样的位置:
版本号 0.1.0-rc.5
官方自己声明「未来将出现破坏兼容性的变更」。
插件生态刚刚起步
质量参差不齐,官方预置的体验离 Claude Code / Codex 还有距离。
「自进化」还是实验状态
agent 现场写的插件只活在内存里,重启就消失,还没有沉淀成磁盘上永久插件的机制。
还有一个 Linux 用三十年才立起来的规矩,DSH 现在还没有:向后兼容铁律。Linux 能赢,靠的是 Linus 的一条铁律——内核随便改,但系统调用永远向后兼容,因为成千上万的应用指着它。DSH 现在最需要划清的也是这条线:到底哪一层接口「永不破坏」?我的猜测是:事件日志的格式 + service 接缝的契约。这条线不划清楚,插件生态就会一直陷入「上周写的插件,这周就坏了」的循环——而生态,恰恰是 meta harness 的全部价值所在。它的价值公式很简单:插件数量 × 插件质量。
但我不觉得这是缺陷,我觉得这是代价。任何「更本质」的东西,都必然以「更晚熟」为代价。Windows 之所以能开箱即用,是因为微软把复杂度藏在了闭源里;Linux 之所以需要三十年,是因为它把复杂度摊开给了所有人。DSH 选择了后一条路:把上下文协议开源,把复杂度摊开,把上限交给生态。这条路的前半段一定难看,但后半段的上限,不是预置应用能比的。
最后回到最朴素的问题:我该拿 DSH 怎么办?
我的建议是:把 DSH 当建材市场逛,别当精装车开。想开精装车,出门左转 Claude Code——它确实打磨得更好。但如果你想拥有「换引擎、换轮胎、换挡风玻璃」的权利,甚至想造一辆不是车的东西,那么 DSH 是当前唯一让你真能动手的地方,而且改完立刻生效,不用等厂家。
「Claude Code 是 Windows/macOS,DSH 是 Linux——你想当用户,还是想当发行版作者?」
Claude Code / Codex 是 Windows/macOS:开箱即用、一体化、打磨精致,但你不能把它的任务管理器换成自己的。DSH 是 Linux:开机要折腾,但折腾完了,这台机器是你的。
你选哪个,取决于你想当用户,还是想当发行版作者。
我是Ghost,热衷于分享 AI 观察与干货。
如果你觉得今天这篇有收获,欢迎点赞、在看、转发三连,我们下篇见。