DeepSeek 在 8 月中旬同时推了 V4-Pro 和 DeepSeek Harness(dsh)。仓库几天过十万星,叙事很快变成「开源 Claude Code」。口号也好记:Agent = 模型 + Harness,以及 一切皆插件——模型、工具、会话、沙箱,连 agent loop 本身 都是 Cordis 插件,配置里就能换。
MIT 许可的开发预览:一切皆插件,包括模型适配器、工具注册表、session log,以及 agent loop。
星数证明一件事:大家确实饥渴一份能拆开看的开源 harness。它不证明这份预览能替你跑稳定任务。README 自己用大写写了:THERE WILL BE COMPATIBILITY-BREAKING CHANGES。核心仓库暂时不收外部 PR。我读的是官方架构文档和 Cordis 论文,不是一次 bake-off。下面按这个范围说话。
论文在说插件,不是更聪明的 Agent
底层论文是北大 + DeepSeek 的 A Programming Paradigm for Spatiotemporal Composability(2026-08-13 预印本)。它不声称提高 SWE-bench。它形式化两件事:
- 时间可组合:插件卸掉后,副作用能完整回滚。
- 空间可组合:插件声明依赖,内核接线、再接线。
HN 上有人把它收成「带析构传播的 DI 容器」。这个收法粗鲁,但方向对。Cordis 解决的是 进程内如何挂上、卸掉、不留幽灵注册。这和「Agent 更可靠」不是同一类问题。
把 loop 做成插件,是因为他们把 harness 本身当成实验变量:换循环、换工具面、甚至让 Agent 热挂自己的插件。论文里「自进化 harness」是用例,不是附赠彩蛋。实验室需要这个自由度。生产编排通常需要相反的东西:把循环冻住,把不变量写死。
「认知轨迹」不是聊天记录
DSH 第二条设计原则更值得认真看:every run is traceable。规则写得很硬——模型可见 ⟺ 必须落盘。LLM 消息历史是从 append-only 的 session log 派生 的,不是单独存一份聊天。
这和「用户说了什么、助手回了什么」不是一层。假设用户只说:「把失败的测试修了。」
聊天记录大概是:跑测试、改 foo.ts、好了。
轨迹要记的是 每一次真正发给模型的那一包:
- 当时拼出来的系统提示(挂了哪些插件)
- 当时的工具 schema
- 用户没写、但被注入的东西:
AGENTS.md、skill、文件变更通知 - 模型吐出的原始 tool 参数(不替它改写)
- 回灌给模型的那一截测试失败原文(不是磁盘上的完整 log)
- 若做过压缩:哪些旧消息被摘要换掉了
同一句「修测试」,拿掉 web search、挂上一个 skill、或换了 loop,聊天看起来一样,认知轨迹完全不同。后训练如果要学「看见这些 → 决定调那个工具」,学的是这包东西,不是用户那一句话。
DeepSeek 作为训练实验室,把轨迹做成可平移的样本,动机说得通。官方文本写的是可追溯、可回放、可 fork。我没有他们内部管线的证据,不必把「这就是 RL 数据工厂」说成已验证事实。能确定的是:这份 log 同时服务评测、调试和——如果他们要的话——后训练。
热插拔:下一轮看见的世界换了
热插拔落到模型眼里,经常被简化成「每轮工具不同」。大致对,但换的不只是工具。
还是那句「修测试」。第 1 步挂着 Standard 循环 + bash + 编辑器 + web search。跑完 npm test 之后,你(或 Agent 自己)卸掉 search、挂上内部 jira 插件,进程不用重启。Cordis 要把 search 注册过的 schema、prompt 段落、监听器撤干净,再挂上 jira。第 2 次模型调用看见的工具面已经变了。
再极端:把 agent-loop 换成 Code mode。后面不再一轮一轮 tool_call,改成模型写一段 TypeScript,在隔离 worker 里连打已有工具。还是没重启。
这不是「装个 MCP,开一条新聊天」。这是运行中改 下一包模型输入。卸载必须回滚干净,否则上一轮的幽灵 schema 会污染下一轮——轨迹一旦脏了,后训练和评测一起脏。
代价也很直白:同一任务,中途拔过插件,结果很难复现,除非把当时的插件树一起钉死。开发预览还声明会破坏兼容。这不是疏忽,是把 harness 当实验台之后的必然产物。
「写代码变成工具」其实是两件事
宣传里常把 Code mode 说成模型自己造工具。拆开看:
Code mode 不注册新工具。现有工具被编成一份 TypeScript SDK。模型写的是这次任务的编排程序:
const fail = await tools.bash("npm test")
const files = await tools.grep("expected", "src/")
await tools.edit("src/foo.ts", old, neu)
五次模型往返,收成一次调用。程序用完就没了。
自挂插件 才是「写成工具」:写一个 Cordis 插件,热挂上去,下一轮 schema 里真的多一项。这是热插拔,不是 Code mode。
前者省 round-trip,值得当可选能力来评估。后者改能力边界,也是任务不稳的来源。两者都不是 Temporal 意义上的工作流。
三种日志,不要焊成第四种
我这边同时维护两套和 harness 有关的东西。Kocoro 是本机 / IM / Desktop 上的单 Agent 运行时,loop 在 internal/agent 里,故意冻住。Shannon 是服务端多 Agent 编排,Go Orchestrator 跑在 Temporal 上。DSH 是第三种:给实验室用的本机内核。
Go 编写的单 Agent 运行时:MCP 兼容、loop 冻结、为长任务做 checkpoint。
| DSH session log | Kocoro session | Shannon 的 Temporal history | |
|---|---|---|---|
| 记什么 | 模型看见的每一步 | 用户对话 + 压缩检查点 | 编排控制流:Activity、子 Workflow、定时器、Signal |
| 能回答 | 当时喂给模型的是哪一包 | 聊过什么、这一 turn 能否接着跑 | 任务卡在哪、谁批准了、为何重试 |
| 崩溃后 | 应用自己恢复会话 | 应用自己恢复 turn | 基础设施重放历史,接着跑 |
| 适合 | 评测、回放、改 harness | 连续产品会话 | 长任务、人在环、多 Agent |
DSH 的「模型可见必须落盘」和 Temporal 的「执行必须可重放」精神相近,作用域不同。前者保 prompt。后者保编排。Cordis 管进程内挂卸。Temporal 管跨进程活下去。一个 DI 内核替不了一个耐用工作流机。
Shannon 用 Workflow 换策略(DAG / ReAct / Swarm),并且用 GetVersion() 管代码演进。这已经是「可换循环」的生产版:可重放、可版本,不是热挂。Kocoro 把 cache、压缩、审批、权限写进 loop,正是因为这些不变量一松就漂——我在 mid-turn checkpoint 和 Kocoro harness 里写过这类纪律。把 loop 插件化,等于邀请这些纪律在配置层漂移。
同一类扩展,两份合同
DSH 把一切做成插件,是因为它要当 框架。同一套 Cordis 内核,换 profile / bundle,就能变成 Standard、极简或 Creator,甚至把 Claude Code 当子 agent 嵌进去。用户是「重组 agent 的开发者」。
Kocoro 的用户是另一回事:一个人的 Mac,同时接着多路 IM、本地文件和 GUI。扩展面其实已经分层,只是不叫 plugin。工具注册是 local 优先,然后 MCP,然后 gateway;每次 run 克隆一份运行时配置,并发 session 才不会串状态。和 dsh 插件对上的,是这些层,不是那个可卸的 loop:
| 换的是什么 | 在 DSH | 在 Kocoro |
|---|---|---|
| 知识 / 流程 | skill 插件 | Skill(marketplace + ClawHub) |
| 外接工具进程 | tool / MCP 插件 | MCP |
| 云端工具 | 换 adapter | Gateway / integration |
| 人格与裁剪 | preset / bundle | Named agent |
| 执行档 | 换 loop 或 profile | Execution profile |
| Agent 循环 | 也是插件,可热卸 | 冻在 loop.go |
对框架来说,循环可卸是功能。对这份本机合同来说,循环就是合同本身:轮次上限、中途 drain、日期翻转、旧截图过滤、cache_break。权限、审批、记忆、channel binding 同样 fail-closed——不是口味配置。工具 schema 还要稳定排序,才能保住 prompt cache;热插拔一旦打乱顺序,hit rate 跟着掉。
所以看起来「dsh 什么都能换、Kocoro 好像更少插件」,差的不是开放程度。差的是谁被允许重组。IM 频道怎么接入、模型适配器怎么收口、按场景换一套工具包,这些仍然可以是明确的安装面。它们不需要把 loop、权限和 cache 放进同一套可逆 effect 里。Cordis 那套时空可组合是 TypeScript 内核;Go daemon 对上它,不是演进,是换一个产品。
星数测的是饥渴,不是就绪
DSH 有四个模式:Standard、Code、Minimal、Creator。Minimal(bash + 编辑器)用来公平评模型,这是好事。Creator 用来拼 preset,也合理。缺的是:仓库文档里我没读到一份官方的、钉死组合之后对 Claude Code / Codex 的任务对照。没有这份对照,就不该把星数读成「已经更好用」。
沙箱文档也写得很清楚:文件系统分档(只读 / workspace-write / 全开)是一回事,网络和进程可见性不在这套词汇里。当编程助手、在可丢的目录里玩,足够。当稳定工作流——要过崩溃、人审、预算、审计——不够。后者是 Shannon 为什么把编排放进 Temporal,而不是放进插件树。
DSH 真正好看的地方,仍是那条硬 log,以及 Minimal / Code 这种按任务收窄工具面的方式。它不证明 loop 也该可卸,更不证明 Cordis 和 Temporal 是同一层东西。
一句话:框架赢在组合自由度,本机 agent 赢在合同。实验室可以热拔插。要在 IM 和桌面上过夜的工作流,循环得先钉死。