跳过主要内容
全部文章
指南

DeepSeek-Harness 架构:一切皆插件到底是什么意思

DeepSeek-Harness 如何把工具、命令、技能、MCP、hooks 和权限全部实现成同一套插件机制,以及能力接缝模式与完整的 packages 全景图。

DeepSeek-Harness 的口号是"一切皆插件",这是一个可以拿去核实的结论,而不是营销话术:工具、斜杠命令、技能、MCP 桥接、hooks、模型适配器、权限、后台任务、子代理委派——每一个产品特性都是通过一个针对 Cordis Context 注册的插件实现的,没有任何一个特性另外配了一套独立的 manifest 格式。本文按照真实的"特性→机制"映射表,以及支撑它的 packages/ 目录树,把这件事讲清楚。

一个可以核实的结论

dsh 自己的开发者 cookbook 记录了一张"特性 → 机制"表,把每个产品能力精确映射到某个插件具体是怎么实现它的:

能力实现方式
工具ctx.tools.register();schema 自动组装进模型 prompt
命令(人类命令,/xxxctx.commands 注册;永远不会变成一条模型消息
技能注册一段 prompt + 一个工具;被调用时把内容注入 context
MCP每个 MCP 服务器对应一个插件:发现其工具后调用 ctx.tools.register()(详见我们的MCP 指南
Hook监听生命周期扩展点(agent/session-startagent/pre-steptools/pre-executesession/event);详见我们的hooks 与命令指南
模型适配器(LLM)通过 ctx.llm.registerAdapter() 注册的 LlmAdapter 子类
UI / Web 客户端节点监听 session/event,或注册一个 ConversationNodeDefinition 往内置 Web UI 里加节点
权限/沙箱tools/pre-execute 返回 allow/deny/ask;由 ctx.sandbox 支撑
后台/定时任务注册在 ctx.jobs 上;定时器触发 followup(..., {source: {kind: 'cron'}})
子代理委派注册在 ctx.subagents(一个具名 provider 注册表)上(详见我们的子代理指南

这张表的意义不在于罗列细节——而在于说明:技能、命令、hook、MCP 桥接这些在别的一些 harness 里各自有独立 manifest 格式和目录约定的东西,在 dsh 里全部是同一种机制的不同用法。每种能力类型都没有独立的分类系统或注册文件 schema。

能力接缝:这张表背后的最小单元

上表的每一行都是一个能力接缝(capability seam)——dsh 术语表对"由一个 Service Definition、一个或多个 Service Provider、一个或多个 Consumer 组成的完整可替换单元"的命名。packages/shell 是标准范例:

  • Service Definitiondsh-shellShellExecutor 这个抽象定义成一个 Cordis Service
  • Service Providerdsh-bash-localdsh-bash-sandbox 是两个可互换的具体实现——一个直接跑命令,另一个在沙箱内跑。
  • Consumerdsh-tool-bash inject 这个服务,把它作为工具暴露给模型。

替换 provider(本地执行 vs 沙箱执行),所有构建在这个接缝上的 consumer 都不需要改动就能继续工作,因为它们只依赖抽象的 ShellExecutor 接口,而不是某个具体实现。这个模式——定义一个抽象服务,注册可互换的 provider,让 consumer inject 时不关心当前生效的是哪个 provider——在上表几乎每一种能力上都重复出现。想了解让这个模式在机制层面成立的 Cordis 原语(ContextServiceinject、Fiber 生命周期),参见Cordis 详解

packages 目录全景巡览

dsh 的 packages/ 目录下大约有 150 个子包。按能力域分组,主要的有:

能力域代表包覆盖内容
LLM 适配器llm-deepseekllm-pi-aillm-retryDeepSeek 官方 chat-completions 适配器,一个用于设计验证的"孪生"适配器,以及跨 provider 的重试逻辑
MCPmcp/mcp-client以 client 角色桥接外部 MCP 服务器的 Tools
Skillskillskill-filesystemskill-badge技能 provider 注册表,加上一个本地文件系统 provider 和一个内置的"badge"技能
Subagentsubagentsubagent-claude-codesubagent-codexsubagent-acpsubagent-dsh-sdksubagent-fork-in-processsubagent-spawn-in-process委派给进程内会话、通过 ACP 委派给外部代理,或官方直接委派给 Claude Code / Codex
Hooks 桥接hooks-claude-codehooks-codex复用现有的 Claude Code / Codex hooks.json shell-hook 配置
Sandboxsandbox-localsandbox-policysandbox-windows-aclLinux bwrap/Landlock、macOS Seatbelt、Windows ACL 受限令牌三种后端
Web 访问web-search-exaweb-search-perplexityweb-search-deepseekweb-fetch-http可插拔的搜索 provider,加上一个匿名公共 HTTP(S) fetch provider
ACPacp/acp面向外部 GUI/编排客户端的"仅供自动化"ACP 服务器
SDKsdk/clientsdk/serversdk/protocolTypeScript SDK,以及Python SDK同样用到的共享 stdio JSON-RPC 协议
E2B 云沙箱e2b/e2be2b/fs-e2be2b/subprocess-e2b把本地执行环境换成 E2B 的云沙箱环境
LSPlsp/lsplsp/lsp-stdiolsp/tool-lsp语言服务器能力接缝(ctx.lsp),支持 definition/references/hover
Terminalterminal/terminalterminal/tool-terminal带 owner-scoped ID 的持久化 PTY 会话接缝
Workflowworkflow/workflowworkflow/tool-ralph一个通用工作流引擎,加上 Ralph loop 工具
Goalgoal/goalgoal/command-goal挂在会话上的持久完成目标
Session 持久化session-persistence-jsonlsession-persistence-sqlite两种可选的落盘格式
遥测session-telemetrysession-telemetry-otelOTLP 导出,默认关闭

这不是一份穷举清单——而是理解"微内核"在实践中到底意味着什么最关键的那些能力域:核心启动流程很小,几乎每一个你会认为是"dsh 的一部分"的特性,都是这约 150 个包中的某一个,以插件形式加载进来,而不是硬编码在一个单体核心里。

这套架构带来了什么好处

  • 一套生命周期覆盖一切。 无论你在构建的是一个工具、一个 hook,还是一整个 UI 面板,HMR、依赖解析、卸载时的自动清理(通过 ctx.effect())都是同一套机制——学一次 Cordis,就覆盖了所有特性类别。
  • 没有 manifest 动物园。 技能、命令、hook、MCP 各自不需要学一套独立 schema——一种插件注册模式覆盖全部,一旦内化,心智模型就很精简。
  • 可替换的实现是设计使然。 能力接缝模式(服务 + 可互换的 provider + consumer)意味着沙箱后端、记忆存储、搜索 provider 这类东西都可以被替换,而不需要动 consumer 的代码。

这套架构付出的代价

  • 从外部看,一切都长得一样。 一个工具注册和一个 hook 注册,外层都以 apply(ctx) { ... } 开头——你必须实际读进去才知道一个具体插件提供的是哪种能力,因为没有目录命名或 manifest 约定能让你一眼看出来(不像别的一些 harness 里,比如一个带 SKILL.md 文件的 skills/ 目录那样一目了然)。
  • 理解任何一个单独特性都需要 Cordis 素养,不只是高级功能才需要。 因为没有可以走捷径浏览的 manifest,哪怕理解一个简单的 hook,也需要在基础层面理解 Context/inject/生命周期——原语部分见Cordis 详解
  • 从有各能力独立 manifest 的 harness 过来,一开始可能会觉得不适应。 如果你习惯了 Claude Code 那种技能/命令/hook/MCP 各自独立 manifest 的约定,dsh 这套单一机制需要一点重新学习——直接对照参见从 Claude Code 迁移

FAQ

"一切皆插件"只是营销话术吗?

不是——它可以对照上面这张"特性→机制"表逐条核实。表里列出的每一个能力,确实都是以针对 ctx 的插件注册来实现的,底下没有藏着任何独立的 manifest 格式。

dsh 架构里"一个特性"的最小单元是什么?

是能力接缝——一个 Service Definition,加上它的 Provider(们),加上它的 Consumer(们)。单个插件通常只扮演这三种角色之一,而不是独自构成整个接缝。

"一切皆插件"意味着我可以移除核心特性吗?

原则上,对任何以可替换插件形式实现的东西来说是可以的——这正是这套设计的意义所在——但基础 bundle 默认接好了大多数 profile 需要的插件,所以移除一个通常意味着换一个替代实现,而不是完全不用它运行。

dsh 一共带了多少个包?

packages/ 下大约 150 个子包,覆盖上表列出的各个领域——LLM 适配器、MCP、技能、子代理、沙箱、SDK 等等。

如果想在这套架构上做开发,应该从哪里入手?

从一个单独的工具或 hook 入手,因为两者用的都是同一套基础的 Context/apply() 模式——参见插件开发入门Cordis 详解了解底层原语。

Next steps

想了解让这套架构成立的框架原语(ContextServiceinject、Fiber 生命周期),阅读Cordis 详解。想看 MCP 和 hooks 具体是如何嵌入这同一套机制的,参见MCP 指南hooks 与命令指南。想查阅相关术语,看术语表;想了解这与 Claude Code 各能力独立 manifest 的设计相比如何,阅读DeepSeek-Harness vs Claude Code