上线一周狂揽 17 万 Star,DeepSeek Harness「万物皆插件」架构硬核拆解

上线一周狂揽 17 万 Star,DeepSeek Harness「万物皆插件」架构硬核拆解

Ren Echo Lv4

2026 年 8 月,AI Agent 框架赛道的「王炸」来了:DeepSeek 官方开源的 DeepSeek Harness(命令名 dsh)上线仅一周就冲上 17.5 万 Star,直接登顶 GitHub 趋势榜首。它的口号只有一句——「Everything is a Plugin(万物皆插件)」:模型适配器、工具注册表、会话日志、甚至 Agent 循环本身,全部是插件,全部可以从配置里替换。这跟我们熟悉的「核心循环焊死、外围靠 hook 打补丁」的框架思路完全不同。今天我就把它拆开,看看到底硬核在哪,以及你能不能马上用起来。

一、核心痛点:Agent 框架为什么「焊死」了

先说清楚它要解决什么问题。过去两年,市面上的 Agent 框架大致分两类:

  • 一类是闭源 CLI(比如各家 Coding Agent):Agent 循环(loop)是特权代码,你只能通过有限的 hook、权限规则、MCP 服务器去「旁路」影响它。想换掉它的模型路由、想改它的工具执行策略、想给它加一种全新的持久化后端,基本不可能——除非官方给你留了接口。
  • 另一类是「胶水型」开源框架:把 LLM 调用、工具调用、记忆、规划揉进一个大而全的类里,扩展靠继承 + 覆盖方法。随着功能膨胀,那个「核心类」会越来越像一坨谁也动不了的巨石。

DeepSeek Harness 换了一条路:它没有特权核心。官方架构文档的原话是「There is no privileged core to patch」——你想扩展它,只需要「挂载一个插件到别的插件旁边」,而不是去改一个神圣不可侵犯的循环。注册到 Context 上的东西是「可逆副作用」,插件卸载时自动回卷(unwind)。

DeepSeek AI 官方 Logo

这个设计不是凭空来的。它底层驱动着一个名为 Cordis 的插件框架,Cordis 的设计出自论文《_A Programming Paradigm for Spatiotemporal Composability_》——直译过来是「一种面向时空可组合性的编程范式」。名字很唬人,拆开看其实非常扎实。

二、底层硬核拆解:Cordis 的五个核心概念

Cordis 被 vendored(直接源码内嵌)进 DeepSeek Harness 仓库里。要理解「万物皆插件」,先吃透它的五个概念:

1. 插件(Plugin)是一个实现了 Service 的对象。
它可以是一个带 injectapply(ctx) 字段的函数,也可以是一个 Service 子类,其生命周期由 Cordis 挂载进当前 Context。

2. Context 是一个「服务仓库」。
每个服务在 Context 上认领一个稳定的 key,比如 ctx.toolsctx.llmctx.sessions。其他插件通过 key 来查找服务,而不是 import 一个具体实现。这一条是「可替换」的根基——你换掉 ctx.llm 背后的实现,所有依赖它的插件无感知。

3. 用 inject 声明依赖。
一个插件在 inject 里声明它需要的服务,Cordis 会等这些服务就位后再激活它。加载顺序由「服务依赖」表达,而不是手工写启动序列。

4. 类型化事件(Typed Events)做通信。
服务通过 TypeScript 的声明合并(declaration merging)声明事件名,然后以四种方式之一派发:

分发模式 是否 await 分发顺序 是否有返回值
emit 按注册顺序观察
waterfall 按注册顺序观察
parallel 并行观察
serial 按注册顺序观察

其中 waterfall 是「环绕式中间件」:监听器收到 (...args, next),调用 next() 就把控制权交给下一个监听器,直接 return 则短路。策略类监听器(比如审批策略)可以「不调用 next()」来一锤定音,只做标注的监听器则必须 next()

5. 注册是可逆副作用(Reversible Effects)。
提示段落、工具 schema、适配器、Provider、监听器,全部通过 ctx.effect()ctx.on() 安装,所以 reload 和 teardown 时能可预测地回卷。

这五条合起来,就是「时空可组合」:空间上,任何能力都是 Context 上一个可定位、可替换的服务;时间上,任何注册都有明确的挂载与卸载边界,可以按需热插拔。

DeepSeek Harness 插件树:没有特权核心,一切皆插件

三、架构全景:Profile、Bundle 与「插件树」

一个正在运行的 dsh,本质上是一棵在启动时按有序层级组装出来的插件树。这里有两个关键概念:

  • Profile(配置文件):存放在 Harness 主目录里的一个「命名组合」,它列出自己堆叠的 Bundle、自己安装的树外插件、以及用户自己的 cordis.patch.ymlwebheadless 就是官方随附的两个模板。
  • Bundle(分发包):Cordis 配置行 + 它们挂载代码的分发格式。每个 Bundle 在自己的 package.json 里通过 dsh 字段声明自己:dsh.profile 列出 profile 的 Bundle,dsh.bundle 指向 bundle 的 patch 文件。

层级按这个顺序作用于一个「空条目列表」:profile 里按顺序列出的每个 Bundle → profile 的 cordis.patch.yml → 主目录级 patch → 命令行 --patch 覆盖层。一个 patch 按 id 定位某一行、整体替换它的配置,或插入新行。

想看你的机器实际会启动出什么树,一条命令:

1
dsh --profile web --dump-config

打印出来的每一行,都可以用你自己的 patch 替换掉。官方仓库里,dsh-base 是每个 profile 的第一层(模型适配器、工具、持久化、沙箱与审批策略、设置、凭据、遥测),dsh-web-app 叠上浏览器应用,dsh-headless 则是一个连服务器都没有的一次性运行器。

核心包(都是插件,都往 Cordis 树上挂):

负责什么 ctx key
core/session 追加式 SessionEvent 日志 + 内存存储 ctx.sessions
core/system-prompt 提示段落与工具 schema 组装 ctx.systemPrompt
core/tools 作用域化工具注册表 + 受保护的执行流水线 ctx.tools
core/agent Agent 接口、实时注册表、agent/* 事件 ctx.agents
core/agent-loop 实现该接口的默认驱动(循环本身) ctx.agentLoop
llm/llm 消息与流式词汇 + 适配器缝 ctx.llm

这里藏着整套设计里我最欣赏的一条不变量:「模型可见 ⟺ 已记录」(Model-visible means logged)。任何到达模型请求的内容,都必须能从会话日志里重建出来,而且有一个运行时断言(runtime invariant)在盯着这件事。这也解释了为什么新增一种「模型可见的输入」必须新增一个会话事件——fork、resume、transcript、遥测、持久化,全部从这条日志流派生。

另一根支柱是能力 Seam(Capability Seam):一个可替换的能力由三个角色组成——Service Definition(声明接口)、Service Provider(实现它)、Consumer(使用它,通常是模型侧工具)。这就是为什么「换一个 Provider,整套产品就跟着切换」:文件系统和子进程 Provider 共享同一个执行世界,把它们指向一个远程沙箱,Bash、PTY、LSP 会一起搬过去,而无需为 Provider 各写一套分叉。

四、全流程跑通:从一条命令到看懂一个真实配置

最快上手,一条命令(需要 Node.js):

1
npx @deepseek-ai/dsh web

默认在 http://127.0.0.1:3080 启动 Web UI,本机启动还会用默认浏览器打开;SSH 启动时只打印宿主机 URL。加 --no-open 只跑服务器不弹浏览器。

从源码跑(需要 Node ^22.19 或 >=24,以及 pnpm):

1
2
3
4
5
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web

真实跑 Agent 需要 DEEPSEEK_API_KEY(可另设 DEEPSEEK_BASE_URL)。仓库内置了 headless-agent(一次性任务)、jsonrpc-agent(Python SDK + JSON-RPC 驱动)、acp-agent(Agent Client Protocol 自动化服务器)、web-cordis(能改自己插件树的「自指」Agent)等示例。

想真正体会「万物皆插件」,看一个真实的 cordis.yml 就够了。下面是从官方 headless-agent 示例里裁出的片段,注意:模型、凭据、bash、持久化、子 Agent、工作流……每一项都是一个可替换的插件条目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 用户设置($DSH_HOME/settings.yaml,热重载):这里的 llm-deepseek 段
# 可以在不重启的情况下覆盖下面的适配器条目
- id: settings
name: '@deepseek-ai/dsh-settings-file'

# 凭据存储:运行时环境变量优先于 $DSH_HOME/.credentials.yaml
# 适配器在每次请求时解析 DEEPSEEK_API_KEY,密钥不会被内联进本文件
- id: credentials
name: '@deepseek-ai/dsh-credentials-local'

# DeepSeek 模型适配器——想换后端,就替换掉这一行
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
config:
thinking: enabled
reasoningEffort: max
models:
- id: deepseek-v4-pro
contextWindow: 128000

# bash 执行器 + 托管的子进程组
- id: subprocess
name: '@deepseek-ai/dsh-subprocess-local'
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
timeoutMs: 60000

# 持久化:追加式会话日志落盘(zstd 压缩)
- id: persistence
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: './.sessions'

# 子 Agent:spawn(新子进程)/ fork(复制前缀)两个独立后端
- id: subagent
name: '@deepseek-ai/dsh-subagent'
- id: tool-subagent
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
toolName: subagent
backgroundMode: continuable
maxDepth: 1

你看到的每一行(连 llm-deepseekreasoningEffort: max 这种调优)都是配置化、可 patch 的。这就是「没有特权核心」的落地形态。

写自己的插件也不难:给仓库打上 dsh-plugin topic 即可被生态发现;插件本身遵循上面的五条 Cordis 约定——在 apply(ctx)ctx.provide() 服务、在 ctx.tools 上注册工具、用 ctx.effect() 挂副作用。官方还提供了从「加一个包」「加一个工具」「加一个 LLM 适配器」「加一个 Chat 节点」到「加一张设置卡片」的完整 extension cookbook。

五、一个 Turn 是如何流动的:事件驱动的主循环

把视角拉进运行时。Harness 用两个词定义工作单元:

  • step(步):一次模型请求 + 它调用的工具。
  • turn(轮):零个或多个 step;在第一个输入被认领前开启,一旦「什么都不欠了」就关闭。

整个主循环是一串可拦截的事件(下图是官方架构文档的流程,我画成了图):

DeepSeek Harness 一个 Turn 的完整生命周期

其中 turn/*step/*user/messageassistant/*tool/*持久化的会话事件,其余是跨三个域(会话、Agent、能力)的实时扩展点。agent/pre-stepagent/requestllm/stream 和三个 tools/* 事件都是 waterfall,监听器必须 next() 才能放行;agent/turn-stoppingserial 且没有 next()。输入通过一个 inbox 进入驱动,有些消息会立刻唤醒它,被注入的上下文则先在 inbox 里排队,等别的消息来「带」它进去。

这段流程揭示了一个反直觉的设计哲学:连「模型这次能看到什么」都是由插件在 agent/pre-step 里决定的——监听器可以重写认领到的消息,也可以直接 reject 掉(reject 或首次认领被重写成空,会关闭一个「没花掉任何 step」的 turn,让日志如实记录这次尝试)。也就是说,你想做「敏感信息拦截」「上下文注入」「工具调用审计」,都不需要改循环,挂个监听器就行。

六、为什么这值得你关注:生态与信号

上线一周,DeepSeek Harness 已经不只是一个框架,而是一个正在成型的生态:

  • 官方配套了 TypeScript 与 Python 双 SDKdsh 本身用 ESM + TypeScript 严格模式编写,native/ 下还带一个 landlock 相关的 Node 原生模块(进程隔离)。
  • 社区迅速长出桌面端 deepseek-harness-desktop(已 16.5k Star),把插件生态搬进现代化桌面 App。
  • 同一周榜单上,吴恩达团队的 openworkerqm 等多智能体框架也集体霸榜——「Agent 框架 + 插件生态」是 2026 下半年的绝对主线

但它现在仍处于 developer preview,官方明确警告「未来将有破坏兼容性的变更」,会话格式 SESSION_FORMAT_VERSION 还停在 0、不做任何兼容承诺。所以现在更适合研究它的架构思路、用它跑实验,而不是立刻压上生产。

我最看重它的,其实不是某个具体功能,而是它把「可组合性」当成一等公民:当模型、工具、循环、日志全部变成可替换的插件,一个 Agent 框架就从「产品」退化成「底座」——而真正的差异化,交还给了写插件的每一个开发者。

结语

「万物皆插件」不是一句营销口号,而是 Cordis 那套「服务仓库 + 类型化事件 + 可逆副作用」范式推到极致后的自然结果。DeepSeek Harness 用一周 17 万 Star 证明了一件事:开发者要的从来不是一个更会写代码的黑盒,而是一个能按自己意愿重新拼装的底座。

如果你想上手,从 npx @deepseek-ai/dsh webdsh --profile web --dump-config 开始,把打印出来的那棵插件树读一遍——你对「Agent 框架」的理解会刷新一次。


本文所有架构细节、包名、事件流程均核对自 deepseek-ai/deepseek-harness 官方仓库的 README、docs/architecture.md、docs/cordis-primer.md、AGENTS.md 与 examples/headless-agent/cordis.yml。

📺 相关视频

  • 标题: 上线一周狂揽 17 万 Star,DeepSeek Harness「万物皆插件」架构硬核拆解
  • 作者: Ren Echo
  • 创建于 : 2026-08-21 09:30:00
  • 更新于 : 2026-08-23 09:19:18
  • 链接: https://renecho-blog.pages.dev/2026/08/21/2026-08-21-deepseek-harness-plugin-architecture/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论