博客

DeepSeek Harness:可热插拔的循环,不是可上生产的工作流

2026年8月19日

English

DeepSeek 在 8 月中旬同时推了 V4-Pro 和 DeepSeek Harnessdsh)。仓库几天过十万星,叙事很快变成「开源 Claude Code」。口号也好记:Agent = 模型 + Harness,以及 一切皆插件——模型、工具、会话、沙箱,连 agent loop 本身 都是 Cordis 插件,配置里就能换。

deepseek-ai/deepseek-harness

MIT 许可的开发预览:一切皆插件,包括模型适配器、工具注册表、session log,以及 agent loop。

View on GitHub

星数证明一件事:大家确实饥渴一份能拆开看的开源 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、好了。

轨迹要记的是 每一次真正发给模型的那一包

  1. 当时拼出来的系统提示(挂了哪些插件)
  2. 当时的工具 schema
  3. 用户没写、但被注入的东西:AGENTS.md、skill、文件变更通知
  4. 模型吐出的原始 tool 参数(不替它改写)
  5. 回灌给模型的那一截测试失败原文(不是磁盘上的完整 log)
  6. 若做过压缩:哪些旧消息被摘要换掉了

同一句「修测试」,拿掉 web search、挂上一个 skill、或换了 loop,聊天看起来一样,认知轨迹完全不同。后训练如果要学「看见这些 → 决定调那个工具」,学的是这包东西,不是用户那一句话。

DeepSeek 作为训练实验室,把轨迹做成可平移的样本,动机说得通。官方文本写的是可追溯、可回放、可 fork。我没有他们内部管线的证据,不必把「这就是 RL 数据工厂」说成已验证事实。能确定的是:这份 log 同时服务评测、调试和——如果他们要的话——后训练。

热插拔:下一轮看见的世界换了

热插拔落到模型眼里,经常被简化成「每轮工具不同」。大致对,但换的不只是工具。

还是那句「修测试」。第 1 步挂着 Standard 循环 + bash + 编辑器 + web search。跑完 npm test 之后,你(或 Agent 自己)卸掉 search、挂上内部 jira 插件,进程不用重启。Cordis 要把 search 注册过的 schema、prompt 段落、监听器撤干净,再挂上 jira。第 2 次模型调用看见的工具面已经变了。

第 1 轮工具面第 2 轮工具面bash编辑器web searchbash编辑器jira卸载 search挂上 jira同一个进程,不重启——模型只看得见右边这份

再极端:把 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 是第三种:给实验室用的本机内核。

Kocoro-lab/Kocoro

Go 编写的单 Agent 运行时:MCP 兼容、loop 冻结、为长任务做 checkpoint。

View on GitHub
DSH session logKocoro sessionShannon 的 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 checkpointKocoro 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
云端工具换 adapterGateway / integration
人格与裁剪preset / bundleNamed agent
执行档换 loop 或 profileExecution 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 和桌面上过夜的工作流,循环得先钉死。