DeepSeek Harness(dsh)最值得研究的,不是它又接入了多少模型、工具或界面,而是它改变了 Harness 的架构主语。

传统工作流把任务图放在中心:节点做什么,边通向哪里,失败后重试还是补偿。许多 Coding Harness 也有插件、Hook、MCP 和扩展包,但 Agent Loop、会话状态与工具分发通常仍由一个固定运行时掌握。

DeepSeek Harness 选择了另一条路。模型适配器、工具注册表、Session Log、Agent Loop、Workflow Engine、沙箱、存储和 UI 都进入同一套插件装配与生命周期机制。Workflow 没有消失,它只是从架构中心降为一项可选能力。

这形成了一个很实用的判断:

流程图回答“下一步执行什么”,插件树回答“运行时由什么组成”。

两张图可以叠在一起,却不能互相替代。

本文以 2026-08-21 的官方源码快照 b150a55 为基线。项目在 2026-08-24 仍标注为 developer preview,公开 API 和插件边界可能继续发生破坏性变化。

先把两张图分开

“插件”和“流程”都在谈组合,很容易被混为一谈。最简单的区分方法,是看图里的边表示什么。

在工作流图中,边表示控制转移或数据依赖:A 跑完以后执行 B,条件 C 成立时转到 D。LangGraph 的 state、node、edge,Google ADK 的 Sequential、Parallel、Loop Agent,以及 Airflow 的 DAG,都属于这一类。

在插件树中,边表示装配与能力依赖:谁提供 ctx.llm,谁消费 ctx.tools,插件卸载时哪些监听器、注册项和下游能力随之失效。它描述的是运行时拓扑,而不是某个任务的时间顺序。

问题 插件树 工作流图
基本单位 能力、服务、插件实例 步骤、节点、状态
边的含义 提供、依赖、作用域、装卸 先后、分支、并行、重试
主要状态 插件是否激活,服务是否可用 任务运行到哪里,状态如何转移
失败处理 卸载、依赖失效、清理 effect 节点重试、回滚、补偿、恢复
典型变化 替换模型、存储、Loop 或 UI 增加节点、修改边、调整条件
核心问题 系统拥有哪些能力 任务下一步做什么

这一区分也解释了 DeepSeek Harness 为什么仍然带有 Workflow,却不能被概括成 Workflow Engine。它在插件树里安装了一个 Workflow Engine,正如安装一个 Shell、文件系统或 Subagent Provider。

flowchart LR
    subgraph PT[插件树:运行时组成]
        LLM[LLM Service]
        LOG[Session Log]
        TOOLS[Tool Registry]
        LOOP[Agent Loop]
        WF[Workflow Engine]
        UI[UI]
        LLM --> LOOP
        LOG --> LOOP
        TOOLS --> LOOP
        WF --> TOOLS
        LOG --> UI
    end

    subgraph WG[工作流图:任务执行]
        A[分析任务] --> B{需要并行?}
        B -->|是| C[启动多个 Agent]
        B -->|否| D[直接执行]
        C --> E[汇总结果]
        D --> E
    end

    WF -. 承载一次运行 .-> WG

图中虚线是关键:工作流运行在插件提供的能力之上,工作流本身并不定义整个 Harness 由哪些部件构成。

DeepSeek Harness 到底插件化了什么

官方首页把模型、工具、Skills、Sessions、Sandboxes、Storage、Loops、Scheduling 和 UI 都列为插件。源码里的范围更具体。

生成的 Capability Seams 目录 给能力标注了三种角色:coreseambundle。例如:

  • ctx.llm 是 seam,由具体模型适配器提供。
  • Session 与 Tool Registry 属于 core 能力。
  • ctx.skillsctx.sandboxctx.fsctx.subagentsctx.workflowEngine 是 seam。
  • ctx.agentLoop 被标为 bundle,当前目录还说明它是唯一的具体 Loop 插件。

这组标注纠正了一个容易过度解读的口号。“Everything is a Plugin”不等于“系统没有内核”。Cordis 的 Context、Loader、Fiber、Effect 协议,以及若干服务定义,仍是固定底座。官方所说的“没有 privileged core”,更准确的理解是:扩展 Harness 能力时,不必持续修改一个包办模型、工具、会话和控制流的特权 Agent 核心。

插件覆盖的是 Harness 本体,而不只是核心旁边的装饰性钩子。

Profile、Bundle 与 Patch 先组装运行时

DeepSeek Harness 的配置不是任务 DAG。它先选择 Profile,再叠加 Bundle,最后应用 Patch 层,得到一棵 Plugin Tree。

flowchart TB
    P[Profile]
    B1[Base Bundle]
    B2[Code / Standard / Minimal Bundle]
    X1[平台 Patch]
    X2[用户 Patch]
    T[最终 Plugin Tree]
    C[Cordis Context]

    P --> B1
    P --> B2
    B1 --> T
    B2 --> T
    X1 --> T
    X2 --> T
    T --> C

    C --> S1[LLM / Session / Tools]
    C --> S2[Agent Loop / Workflow]
    C --> S3[Sandbox / FS / UI]

官方基础 Bundle 的 cordis.patch.yml 特别注明:行顺序没有加载语义,最后写入的 Patch 决定配置,服务是否可用才决定插件何时激活。

这和 YAML 形式的工作流有本质差别。工作流文件的行或边通常在表达执行拓扑;这里的配置在表达运行时装配,加载次序由依赖满足关系导出。

Service 与 Inject 描述空间组合性

Cordis 把插件贡献的能力暴露为 Service。消费者用 inject 声明所需服务,不靠隐含的全局单例或人工安排加载顺序。

一个插件只有在依赖满足后才会进入 ACTIVE。提供方消失时,依赖它的插件会被 Dispose;提供方恢复后,消费者可以重新加载。这就是 Cordis 论文所谓的 spatial composability:组件关系随着运行时拓扑变化而重新解析。

它带来的不只是依赖注入。普通依赖注入容器常在进程启动时完成一次装配;Cordis 把依赖满足和插件生命周期绑定起来,因此更接近反应式能力拓扑。

代价同样明显。缺失依赖会让 Fiber 合法地停在 PENDING,如果只盯着业务日志,很容易误以为插件根本没有执行。循环依赖则会让相关组件长期无法激活。Cordis 文档因此要求从 Fiber 状态和依赖图诊断,而不是继续调整配置顺序。

Effect 描述时间组合性

插件注册工具、监听事件、启动定时器或暴露服务时,会产生副作用。Cordis 用 Effect 把“做了什么”和“如何清理”绑定到同一个插件生命周期。

插件卸载时,Cordis 递归释放它的 Fiber,并撤销已登记的 Effect。事件监听器、服务注册和子插件不会变成长期泄漏的幽灵状态。这就是 temporal composability。

它和工作流里的“补偿节点”不是同一个东西:

  • Effect 清理针对运行时装配,例如移除监听器、注销工具、关闭插件持有的资源。
  • 补偿节点针对业务执行结果,例如退款、撤销订单或恢复数据库记录。

Cordis 论文专门划出了系统边界。只有运行时能够独占修改并恢复的状态,才可能被完整追踪。网络消息、外部数据库写入、支付等已经越过边界的 emission,仍需要延迟提交或业务补偿。把 ctx.effect() 理解成跨系统事务,会得出危险的架构结论。

Event 不只是回调列表

Cordis 提供多种事件分发语义:普通广播、串行处理,以及 Waterfall Middleware。Waterfall 允许插件包装下游处理、拦截请求或增加策略,因此很适合日志、权限、Prompt 变换、工具门禁等横切能力。

事件监听也是 Effect,插件卸载时会随之移除。横切策略不必散落进每一条工作流的每一个节点。

这套机制并非没有陷阱。Waterfall 处理器忘记调用 next() 会静默吞掉后续链路;多个异步 Disposer 虽按逆序开始,却可能并发完成。存在严格清理顺序时,官方建议把步骤放进同一个 Disposer。插件架构把扩展点统一了,也把调试重心从“哪条边没走”转向“哪个服务、Fiber 或 Middleware 改变了运行时”。

一次 Agent Turn 仍然有清晰控制流

插件化不等于没有控制流。DeepSeek Harness 的 Agent Turn 仍会经过输入记录、上下文派生、模型调用、工具调用、结果回写和后续迭代。

区别在于,这些阶段依赖的能力从 Context 取得,阶段之间还暴露 typed events。模型适配器、系统 Prompt、工具注册、Loop 策略和会话投影可以分别替换,而不必把全部变化塞进一段中央循环。

sequenceDiagram
    participant Entry as Entry Plugin
    participant Log as Session Log
    participant Loop as Agent Loop Plugin
    participant LLM as ctx.llm Provider
    participant Tools as Tool Registry

    Entry->>Log: append user input
    Entry->>Loop: start turn
    Loop->>Log: derive model-visible messages
    Loop->>LLM: request completion
    LLM-->>Loop: text / tool calls
    Loop->>Log: append assistant output
    Loop->>Tools: execute selected tools
    Tools-->>Loop: tool results
    Loop->>Log: append tool results
    Loop->>LLM: continue if needed

其中 Session Log 是可见历史的真相源。官方架构用一句严格约束概括它:模型可见的内容必须被记录。deriveMessages() 从追加式日志投影出模型消息,UI、Fork、Replay 和恢复逻辑也可以基于同一记录工作。

这里还要避免另一个混淆:追加式 Session Log 不自动等于 Durable Workflow Checkpoint。它能证明会话发生过什么,却不必然保存任意任务图的节点状态、重试游标和恢复语义。

Workflow 在 DSH 里为什么只是 Seam

DeepSeek Harness 确实提供动态 Workflow。模型可以编写编排脚本,调用 agent()parallel()pipeline()phase(),由 Worker Thread Engine 执行。

但官方 Workflow 子系统文档 明确把它定义为 optional capability,不属于 Agent Loop:

  1. dsh-workflow 定义 ctx.workflowEngine 契约。
  2. dsh-workflow-worker-thread 提供一个 Worker Thread 实现。
  3. dsh-tool-workflow 把能力暴露给模型。

定义、实现和消费方分开,意味着可以替换引擎而不修改模型工具。Workflow 事件只暴露观察快照,不把带有 cancel()dispose() 的活跃句柄交给订阅者。phase() 也只是进度分组标签,不暗示控制结构。

这正是插件机制与流程编排关系的源码级证据:DSH 能运行工作流,但 Workflow Engine 仍服从 Service、Provider、Consumer 和生命周期契约。

当前实现的边界也说明它尚不是一个 Durable Workflow 平台。官方 README 列出的限制包括:只支持前台运行;没有 Journaling 与 Resume;不能保存或嵌套 Workflow;没有内建 Token Budget 词汇;运行句柄由持有者负责清理。Worker Thread 用来防止同步死循环阻塞 Harness,并提供强制终止手段,node:vm 不是安全边界。

因此,DSH 的 Workflow 与 LangGraph、Airflow 不宜只按功能多少排高下。前者首先是插件化 Harness 中的一项模型能力;后两者把持久任务图或 DAG 调度放在产品中心。

和传统流程编排的真正分工

传统 Workflow Orchestrator 的强项,是把业务过程做成显式、可追踪的执行图。

以 LangGraph 为例,StateGraph 围绕 State、Node、Edge 组织。Checkpointer 在每个 Super-step 保存状态,使中断、回放、Human-in-the-loop 和故障恢复成为图运行时的一部分。Airflow 更偏批处理与调度,Scheduler 监控 DAG 和 Task Instance,再把可执行任务交给 Executor。

这些系统默认把“任务执行到哪里”当作中心事实。插件机制默认把“当前有哪些能力可用”当作中心事实。

场景 更自然的主机制 原因
多步骤审批、长期等待、失败恢复 Durable Workflow / State Graph 状态转移和恢复点必须显式
定时批处理、依赖调度、任务重试 DAG Scheduler 调度与 Task Instance 是核心对象
替换模型、存储、Loop、沙箱或 UI Plugin Runtime 变化发生在运行时能力层
按租户安装不同策略与工具 Plugin Runtime 需要作用域、依赖和卸载语义
Agent 临时生成并行研究脚本 DSH Workflow Plugin Workflow 作为模型可调用能力即可
复杂 Agent 产品 两者叠加 插件树承载能力,工作流图承载任务

一个系统完全可以同时拥有两张图。插件树提供 LLM、工具、权限、会话与 Workflow Engine;某次运行再由工作流图安排步骤。问题出在用一张图冒充另一张图:

  • 只用工作流图表达横切能力,会在大量节点里复制日志、权限、Prompt 变换和资源清理。
  • 只用插件树表达长期业务过程,会缺少清晰的状态转移、重试与恢复模型。

DSH 的价值不在于宣布流程图过时,而在于把流程图放回正确的架构层。

和其他 Coding Harness 的差别

“有插件”不是 DeepSeek Harness 的独占能力。Codex、OpenCode、Pi 等工具都有扩展面。差别要看插件能触达 Harness 的哪一层。

Harness 公开扩展面 公开架构的中心 与 DSH 的主要差别
DeepSeek Harness Service、Event、Effect、Plugin、Profile、Bundle Cordis Plugin Tree Loop、Workflow、Session、UI 等参与统一装配与生命周期
Codex MCP、Skills、Apps、审批策略、App Server 协议 Thread / Turn / Item 与 Agent 运行协议 公开扩展面没有把 Agent Loop 描述为 Cordis 式可装卸插件
OpenCode 进程内 Plugin、事件、工具、Hooks、MCP Session 与核心 Agent Runtime Plugin 能深入请求与工具链,但公开文档仍以核心运行时加扩展点表述
Pi Extensions、事件处理器、自定义工具、UI、Packages 轻量 Agent Core 与 Session 扩展能力很强,公开资料仍保留中心 Loop 与资源加载器

这里的措辞需要克制。无法从“公开文档没有某个扩展点”推出“实现上绝对不能替换”。可靠的结论只有两条:

第一,其他 Coding Harness 也可以高度扩展,DSH 的差别不是插件数量。

第二,DSH 的官方架构明确要求模型、工具、会话、Loop 和 Workflow 共同服从 Cordis 的依赖与卸载语义,这种统一覆盖范围才是它的辨识度。

从架构风格看,Codex 更像协议化 Agent Core,OpenCode 更像核心运行时加进程内 Middleware,Pi 更像轻量可编程终端 Agent 平台,DSH 更接近以插件生命周期为中心的 Agent Runtime。

它付出了什么代价

插件化没有消除复杂度,只是移动了复杂度。

调试从控制流转向运行时拓扑

工作流故障常问“哪个节点没有执行”。Cordis 故障还要问:服务是否存在,Fiber 处于 PENDINGACTIVE 还是 FAILED,Waterfall 是否短路,Patch 是否覆盖了配置,Provider 卸载后哪些消费者被连带 Dispose。

这要求更好的能力目录、Fiber 检查器、事件追踪和配置差异工具。DeepSeek Harness 已生成 Capability Catalog,但第三方插件增多后,诊断体验仍会决定架构是否真正可用。

细粒度会产生组件数量

Cordis 论文指出,互相依赖的组件可以拆成 Core 与 Integration Components 来消除环,但最坏情况下集成组件数量可能随交互对数增长。Bundle、约定式装配和脚手架可以缓解作者负担,不能让认知成本消失。

接口漂移不会被依赖名字自动解决

当前依赖链接主要依赖 Key Identity。独立插件可能发生接口漂移或 Key Collision。Cordis 目前借助 npm Peer Dependency 约束版本,但这依赖提供方遵守语义化版本,也难以让同一应用并存多代接口。论文把 Namespacing、Peer Dependency 和 Structural Compatibility 的统一方案留作开放问题。

可卸载不等于可信

inject 可以限制经 Context Proxy 访问的能力,不能阻止恶意代码绕过语言层对象访问宿主环境。Cordis 论文明确说,不可信插件需要进程、虚拟机、WebAssembly 或容器等外部沙箱。

动态 Workflow 的 Worker Thread 同样只是隔离与终止机制。官方文档直接说明:模型生成脚本与 Bash 能力共享信任前提,node:vm 不是安全边界。

仍处在开发者预览期

官方 README 警告 API 与插件形态会发生 Breaking Changes。Cordis 论文也是 active revision 的 Draft,现有研究展示了可实现性与应用案例,尚未给出相对传统架构的量化运行开销和开发效率对照。

因此,它目前更适合作为一个值得试验的架构方向,而不是无需验证就替换生产 Harness 的稳定标准。

两条可复用的架构判断

两张图法

遇到任何 Agent 平台,先分别画两张图:

  1. 能力图:模型、工具、状态、沙箱、权限、Loop、UI 由谁提供,如何依赖和替换。
  2. 执行图:一次任务经过哪些状态,如何分支、重试、暂停和恢复。

如果产品文档只展示第二张图,它很可能是 Workflow-first。如果第一张图也有稳定的服务契约、作用域和卸载语义,它才接近 Runtime-first。

这比统计 Plugin、Hook 或 Node 数量更有效,因为名字相同的扩展点可能处在完全不同的架构层。

Effect 所有权原则

可热替换能力至少需要三个条件:

1
可热替换能力 = 显式依赖 + 可撤销注册 + 可观测生命周期

只有 register() 没有 Disposer,不是完整插件生命周期;只有依赖注入没有依赖失效处理,也不是动态组合。Cordis 的贡献,是把这三件事放进同一个 Context 模型。

什么时候该选哪一种

如果目标是固定业务流程、长时间等待、审批、定时执行和故障恢复,优先选择成熟的 State Graph 或 Durable Workflow Engine。显式状态与恢复语义比“所有东西都可插拔”更重要。

如果目标是构建多形态 Agent 产品,需要按环境替换模型、存储、工具、Loop、沙箱与 UI,DeepSeek Harness 的插件树更贴合问题。它把扩展从局部 Hook 提升成运行时装配。

如果两类问题同时存在,不必二选一。让插件树拥有 Workflow Engine,让 Workflow 调用 Context 中的能力。架构上的分工可以压缩成一句话:

Runtime 负责能力所有权,Workflow 负责任务状态转移。

快速参考

判断项 DeepSeek Harness 当前答案 需要警惕的误读
架构中心 Cordis Plugin Tree “只是插件比较多”
Workflow 地位 可选 Capability Seam “没有 Workflow”
Agent Loop 具体 Bundle 插件 “完全没有固定底座”
依赖 Service + Inject,反应式激活 “只是启动时 DI”
清理 Effect 与 Fiber 生命周期 “任何外部副作用都能回滚”
状态 Append-only Session Log “天然等于 Durable Checkpoint”
安全 Proxy 能力约束,外部沙箱另行负责 “Worker Thread 或 node:vm 就是沙箱”
成熟度 Developer Preview “接口已经稳定”

参考资料

DeepSeek Harness 与 Cordis:

流程编排与其他 Harness:

封面图:Ayush Kumar / Unsplash