万物皆插件:DeepSeek Harness 的核心架构、Cordis 内核与 Agent 可组合性
DeepSeek Harness 不是又一个“把大模型接上几个工具”的 Agent Demo。它更激进的设计是:模型、工具、技能、会话、沙箱、文件系统、Agent Loop、编排甚至 UI,都可以被实现为插件,并在运行时组合、替换和扩展。
一、先纠正一个容易混淆的概念
DeepSeek Harness 最核心的产品设计:
Everything is a Plugin:万物皆插件。
DeepSeek 官方仓库将 DeepSeek Harness,也就是 dsh,定义为由 DeepSeek AI 开发的开源 Agent Harness,并明确说明它采用“所有东西都是插件”的架构,同时建立在 Cordis 之上。DeepSeek Harness 官方 GitHub 仓库
官方仓库还标注了几个重要事实:
当前属于 Developer Preview;
仍在快速迭代;
可能存在兼容性破坏性变化;
可以通过 npm 方式启动 Web UI;
支持从源码构建;
插件可以通过 dsh-plugin 主题被发现;
项目采用 MIT License。
所以,本文不再把它写成一个抽象的“DeepSeek API 包装器”,而是从官方仓库和 Cordis 设计出发,重点分析:
插件化内核;
运行时上下文;
服务与事件;
空间和时间上的可组合性;
能力插件;
Agent Loop 插件;
Runtime Mode;
插件装配和替换;
会话轨迹与可恢复执行。
二、DeepSeek Harness 想解决什么问题
传统 Agent 框架通常有一套固定骨架:
一个 Agent 类 一个固定的模型调用循环 一组工具 一个会话对象 一个固定 UI 一套固定状态管理当你要替换某一部分时,往往需要:
修改核心代码;
继承内部类;
覆盖生命周期方法;
绕过框架默认行为;
重新打包整个应用。
这会导致框架越来越像一个“大单体”。
DeepSeek Harness 的设计目标,是把 Agent 的每个能力拆成可以动态装配的插件:
模型是插件 工具是插件 Skill 是插件 Session 是插件 Sandbox 是插件 Filesystem 是插件 Agent Loop 是插件 Scheduler 是插件 Orchestrator 是插件 UI 是插件 Storage 是插件 Telemetry 是插件这样,使用者可以在不修改核心内核的情况下:
替换模型;
替换本地 Shell;
把本地文件系统换成远程容器;
把默认 Agent Loop 换成 Benchmark Loop;
加载不同的 Skill 集合;
用最小运行时进行评测;
自定义 Web UI;
添加新的子 Agent 调度器。
三、官方定位与资料边界
DeepSeek Harness 的官方仓库目前是最重要的一手资料。仓库 README 明确写出:
DeepSeek Harness: Everything is a Plugin.并将 dsh 描述为开源 Agent Harness,而不是单纯的模型 SDK。官方 README
它依赖的 Cordis 是一个“Spatiotemporal Composability”元框架,中文可以理解为“时空可组合性元框架”。Cordis 官方仓库也明确说明当前仍在活跃开发,API 尚未稳定。Cordis 官方 GitHub 仓库
本文中可以分成三类信息:
官方明确内容
DeepSeek Harness 由 DeepSeek AI 开发;
核心理念是 Everything is a Plugin;
底层使用 Cordis;
当前处于 Developer Preview;
支持 npm 启动 Web UI;
支持从 GitHub 源码构建;
MIT License。
官方仓库结构可以直接观察到的内容
官方仓库公开了 apps、packages、native、python、docs、examples 和 website 等目录,可以看出它不是一个单文件 Demo,而是一个包含运行时、应用、原生扩展和开发文档的工程。官方仓库目录
根据架构和公开材料推导的内容
具体插件接口、某些运行模式、生命周期细节、内部事件名和部分包的调用关系,需要以实际源码和版本为准。下文对于这些部分会使用“参考理解”或“架构推导”的表述,不把推测伪装成官方 API。
四、Cordis:为什么它适合做 Harness 内核
如果 Harness 的每个组件都是插件,那么核心内核不能依赖某个固定的 Agent 类。它需要一个更通用的运行时,能够:
注册插件;
管理插件依赖;
创建运行上下文;
提供服务;
发布和订阅事件;
管理生命周期;
支持插件动态组合;
让插件之间低耦合通信。
这正是 Cordis 这类元框架的作用。
可以把 Cordis Context 理解为一个运行时容器:
Context ├── Plugin Registry ├── Service Container ├── Event Bus ├── Lifecycle Manager ├── Scope Manager └── Disposable Resources插件启动后,可以向 Context 注册:
服务;
事件监听器;
工具;
配置;
数据模型;
生命周期钩子;
其他插件依赖。
五、什么叫“万物皆插件”
1. 插件不是只有 Tool
传统理解中的插件,通常只是一个外部工具,例如:
search plugin browser plugin database plugin但 DeepSeek Harness 把插件边界扩大到整个 Agent 系统。
一个插件可能提供:
一个模型适配器;
一个 Tool;
一个 Skill;
一个文件系统;
一个 Shell 执行器;
一个沙箱;
一个 Session 后端;
一个存储系统;
一个 Agent Loop;
一个 UI;
一个事件处理器;
一个 Subagent;
一个 Workflow;
一个 Scheduler。
2. 插件可以组合
例如,标准编码 Agent 可以由以下插件组合:
DeepSeek Model + Standard Agent Loop + Filesystem + Shell + Git + LSP + Skill Loader + Approval + Sandbox + Web UI最小 Benchmark Agent 可能只需要:
DeepSeek Model + Minimal Loop + Read File + Apply Patch + Test Runner两者使用同一套内核,但装配出来的是不同产品。
3. 插件可以替换
把本地 Shell 换成远程容器:
LocalShellPlugin -> RemoteContainerShellPlugin把文件系统换成内存文件系统:
WorkspaceFS -> InMemoryFS把默认 Agent Loop 换成评测 Loop:
StandardLoop -> BenchmarkLoop核心代码无需知道具体实现,只依赖插件提供的接口和服务。
六、DeepSeek Harness 的逻辑架构
flowchart TD C[Cordis Context] --> PR[Plugin Registry] C --> LC[Lifecycle Manager] C --> EB[Event Bus] C --> SC[Service Container] PR --> P1[Model Plugin] PR --> P2[Agent Loop Plugin] PR --> P3[Tool Plugin] PR --> P4[Skill Plugin] PR --> P5[Session Plugin] PR --> P6[Filesystem Plugin] PR --> P7[Sandbox Plugin] PR --> P8[UI Plugin] PR --> P9[Storage Plugin] P1 --> LLM[DeepSeek Model] P2 --> LOOP[Runtime Loop] P3 --> TOOL[Tool Registry] P4 --> SKILL[Skill Registry] P5 --> SESSION[Session and Trajectory] P6 --> FS[Workspace FS] P7 --> SB[Sandbox] P8 --> UI[Web UI or CLI] P9 --> DB[Persistent Storage] LOOP --> TOOL LOOP --> SKILL LOOP --> SESSION LOOP --> SB LOOP --> LLM LOOP --> EB EB --> TRACE[Trace and Replay] EB --> OBS[Observability]核心关系不是:
Harness -> Agent -> Tools而是:
Context -> 装配 Plugins -> 插件注册 Services -> Agent Loop 通过 Services 工作 -> Event Bus 连接运行过程 -> Session 保存轨迹和状态七、插件的三层结构
一个比较清晰的插件设计,可以分为三层。
1. Contract:能力契约
定义插件提供什么能力:
interface FileSystem { read(path): Promise<string> write(path, content): Promise<void> list(path): Promise<Entry[]> }2. Runtime:运行时实现
定义能力怎样执行:
LocalFileSystem RemoteFileSystem InMemoryFileSystem SandboxedFileSystem3. Model-facing Tool:暴露给模型的工具
定义模型如何调用:
read_file write_file list_directory这样可以把“模型看到的工具”和“底层真实实现”解耦。
例如模型都调用 read_file,但底层可以是:
本地磁盘 远程容器 Git worktree 内存快照 远程开发环境这也是插件化真正有价值的地方:替换实现,不改变上层语义。
八、Agent Loop 也可以是插件
这是“万物皆插件”最重要的部分之一。
传统框架中,Agent Loop 往往写死在 Runner 里:
请求模型 -> 检查工具调用 -> 执行工具 -> 拼接消息 -> 再次请求模型DeepSeek Harness 可以把这一套循环本身作为一个插件。
Standard Loop
适合完整编码任务:
读取项目 -> 规划 -> 修改文件 -> 执行测试 -> 根据错误继续修复 -> 输出总结Minimal Loop
适合基准测试或能力验证:
读取文件 -> 修改文件 -> 运行有限测试Code Loop
一种参考思路是让模型把多步操作编译成可执行代码,再由运行时执行。这种方式可以减少每一步都重新请求模型的开销,但需要更严格的权限和失败控制。
Creator Loop
适合插件开发者查看当前上下文、动态装配能力和调试插件。
需要说明:具体 Runtime Mode 的名称、行为和配置方式应以当前官方版本文档为准。网络资料中出现的 Standard、Code、Minimal、Creator 等称呼,有些来自社区讨论或二手材料,不能在未核对源码时直接视为稳定官方 API。
九、插件生命周期
一个插件通常有以下生命周期:
Declared -> Resolved -> Created -> Started -> Active -> Stopped -> Disposed参考接口:
interface Plugin { name(): string dependencies(): string[] apply(ctx: Context): void start?(): Promise<void> stop?(): Promise<void> }插件启动时可能:
注册服务;
注册工具;
监听事件;
加载配置;
创建文件句柄;
启动子进程;
连接 MCP;
注册 UI 页面。
插件停止时需要释放:
进程;
网络连接;
文件句柄;
定时器;
事件监听;
临时目录;
子 Agent。
如果插件没有正确释放资源,长时间运行的 Agent 会出现内存泄漏、重复监听和僵尸进程。
十、服务、事件和插件之间如何通信
插件之间不应该大量直接互相调用内部对象,而应该通过 Context 暴露的服务和事件通信。
服务调用
filesystem.read(path) session.append(event) approval.request(action) telemetry.record(span)事件通信
ModelRequestStarted ToolCallRequested ToolExecutionFinished FileChanged UserApprovalRequired SessionPaused SessionResumed RunCompleted例如,Shell 插件只负责执行命令并发布 ToolExecutionFinished;Telemetry 插件监听事件并记录耗时;UI 插件监听同一事件并更新界面。
这样 Shell 插件不需要依赖 UI,也不需要知道 Telemetry 的实现。
十一、插件装配过程
Harness 启动时可以经历:
读取配置 -> 创建 Cordis Context -> 加载核心插件 -> 解析插件依赖 -> 注册服务 -> 初始化模型插件 -> 初始化工具和 Skill -> 初始化 Session -> 初始化 UI -> 启动 Agent Loop -> 等待用户任务配置可以表达一组能力:
model = deepseek loop = standard filesystem = workspace shell = sandboxed ui = web storage = sqlite skills = [git, testing, refactor]理想情况下,切换实现只改配置,不改核心代码。
十二、插件如何影响模型上下文
插件并不是加载后就自动等于模型能力。一个插件至少要决定三件事:
1. 是否注册服务
例如注册 filesystem 服务。
2. 是否暴露工具
例如暴露 read_file、write_file、list_directory。
3. 是否注入上下文
例如 Skill 插件可以注入:
使用规则;
工作流程;
文件格式;
示例;
约束;
验证方法。
因此插件通常包含:
Runtime Service Model-facing Tools Context Contribution Event Handlers Configuration Permissions插件可以只提供内部服务,也可以为模型提供可见工具,还可以二者同时提供。
十三、Skill、Tool、Workflow 和 Subagent 的区别
Tool
一个原子动作:
read_file write_file run_command search_codeSkill
一组领域能力和使用规则:
Git 操作 Skill Java 重构 Skill 数据库迁移 Skill 测试编写 SkillSkill 往往同时包含说明文档、工具组合和验证方式。
Workflow
一组有固定顺序和分支的步骤:
分析需求 -> 生成计划 -> 修改代码 -> 运行测试 -> 代码审查Subagent
拥有独立上下文和角色的子 Agent:
主 Agent -> 调度代码分析子 Agent -> 调度测试子 Agent -> 调度安全审查子 Agent在“万物皆插件”模式下,这些能力都可以通过插件注册到同一个 Context 中。
十四、Session 与 Trajectory
Harness 的 Session 不应只是一个 messages 数组。
更合理的 Session 包含:
session_id workspace active_plugins runtime_mode messages tool_calls observations approvals checkpoints events artifacts parent_session fork_source statusTrajectory 可以理解为一次 Agent 执行轨迹,记录:
用户输入 -> 模型响应 -> 工具调用 -> 工具结果 -> 文件变化 -> 测试结果 -> 下一轮模型决策如果每个事件都被追加保存,系统就可以支持:
查看轨迹;
搜索历史;
从某个节点恢复;
Fork 出新的会话;
重放某次执行;
对比不同插件组合的结果;
复现工具错误。
十五、Checkpoint、Resume 和 Fork
Checkpoint
保存某个时间点的运行状态:
active_plugins context messages files_snapshot pending_tools permissions loop_stateResume
从 Checkpoint 继续运行。恢复前需要检查:
插件版本是否变化;
工作区是否被外部修改;
未完成工具是否有副作用;
远程任务是否可能已执行;
权限是否仍然有效。
Fork
从旧轨迹创建新的分支会话:
Session A | +--> Session B:尝试方案一 | +--> Session C:尝试方案二Fork 对调试 Prompt、比较模型、验证插件组合非常有价值。
十六、为什么“插件化权限”比 Prompt 限制更可靠
如果系统只在 Prompt 中告诉模型:
不要访问项目目录之外的文件 不要执行危险命令 不要修改生产数据这只是软约束。
插件化设计可以把权限落实到能力装配层:
没有 write_file 插件,就没有写文件能力;
没有网络插件,就没有网络访问能力;
只注册只读数据库插件,就不能执行写 SQL;
把 Shell 插件连接到沙箱,就不能访问宿主机;
不挂载某个目录,模型就无法读取该目录。
这相当于把安全策略从“告诉模型不要做什么”变成“运行时根本不提供某种能力”。
十七、插件与 MCP 的关系
MCP 是外部工具接入协议,插件是 Harness 内部的能力装配机制。
两者可以这样理解:
MCP Server -> 提供外部工具和资源 MCP Plugin -> 负责连接 MCP Server -> 将 MCP 工具注册到 Context -> 处理权限和生命周期 -> 将结果转换成 Harness Observation所以 MCP 可以作为一个插件的实现来源,但插件不等于 MCP。
本地文件系统、Agent Loop、Session、UI 和 Scheduler 通常不需要通过 MCP 实现,它们可以直接是原生插件。
十八、一次完整运行过程
用户输入:
帮我修复这个项目的登录问题并运行测试。1. 创建 Context
Harness 创建 Cordis Context,并装配:
DeepSeek Model Standard Agent Loop Workspace Filesystem Sandboxed Shell Git Tool Testing Skill Session Storage Web UI2. 加载插件
各插件注册自己的服务、工具、事件和上下文贡献。
3. 创建 Session
Session 记录工作目录、启用插件、用户任务和运行模式。
4. Agent Loop 调用模型
模型看到:
系统规则;
项目上下文;
当前任务;
可用工具;
Skill 说明;
权限边界。
5. 模型选择工具
模型请求:
list_files search_code read_fileTool 插件执行并返回 Observation。
6. 修改能力触发策略
模型请求 write_file。Policy 插件判断该操作是否需要审批。
7. 执行修改并保存事件
Filesystem 插件写入文件,Event Bus 发布 FileChanged,Session 保存轨迹。
8. 执行测试
Shell 插件在 Sandbox 中执行测试,并把退出码、输出和耗时作为 Observation。
9. 继续循环
如果测试失败,Agent Loop 将失败日志重新交给模型;如果通过,则进入完成阶段。
10. 输出结果
UI 插件展示:
修改文件;
测试结果;
工具调用轨迹;
消耗统计;
最终总结。
十九、插件化带来的优点
1. 可替换
模型、工具、文件系统、Loop 和 UI 都可以替换。
2. 可组合
通过不同配置组合出编码 Agent、评测 Agent、数据处理 Agent 和科研 Agent。
3. 可隔离
插件边界可以承载权限、资源和生命周期隔离。
4. 可测试
可以用 Fake Model、InMemoryFS 和 Mock Tool 组成测试运行时。
5. 可观测
事件流天然适合轨迹记录、回放和指标统计。
6. 可演化
新增能力通过插件加入,不必持续修改核心内核。
二十、插件化带来的代价
1. 依赖关系复杂
插件之间可能形成隐式依赖,启动顺序和版本兼容需要管理。
2. 调试链路变长
一次工具调用可能经过:
UI -> Agent Loop -> Tool Registry -> Policy -> Plugin Service -> Sandbox -> External Process3. 类型和契约要求更高
插件之间必须有稳定接口,否则替换实现很容易造成运行时错误。
4. 组合空间爆炸
插件越多,可能的运行时组合越多,测试矩阵也会增长。
5. API 稳定性风险
官方仓库目前处于 Developer Preview,README 明确提醒可能存在兼容性破坏性变化。官方 Developer Preview 说明
二十一、DeepSeek Harness 与传统 Agent 框架的区别
| 维度 | 传统 Agent 框架 | DeepSeek Harness 的插件化思路 |
|—|—|—|
| 核心单元 | Agent、Tool、Workflow | Plugin、Context、Service、Event |
| Agent Loop | 通常固定或继承扩展 | Loop 本身也可替换 |
| 模型 | 通常是配置项 | 模型适配器是插件 |
| 文件系统 | 常常内置 | 文件系统是可替换插件 |
| Sandbox | 外部能力或固定实现 | 沙箱可以作为插件 |
| Session | 通常是框架对象 | Session 能力可被替换 |
| UI | 框架绑定或单独实现 | UI 也可以是插件 |
| 通信 | 直接调用较多 | 服务和事件解耦 |
| 扩展方式 | 继承、Hook、注册 Tool | 插件装配、替换和组合 |
| 目标 | 快速构建 Agent | 构建可组合的 Agent 操作系统 |
二十二、参考插件接口
下面是帮助理解的伪代码,不代表官方稳定 API:
interface Plugin { name(): string dependencies(): string[] apply(ctx: Context): void start?(): Promise<void> stop?(): Promise<void> } interface Context { provide<T>(key: string, service: T): void get<T>(key: string): T on(event: string, handler: Function): void emit(event: string, payload: unknown): void } interface AgentLoopPlugin { run(input: AgentInput): AsyncIterable<AgentEvent> } interface ToolPlugin { definition(): ToolDefinition execute(input: unknown): Promise<ToolResult> } interface FilesystemPlugin { read(path: string): Promise<string> write(path: string, content: string): Promise<void> list(path: string): Promise<Entry[]> }二十三、如何开发一个插件
一个插件开发流程可以是:
1. 明确插件提供的能力 2. 定义接口和服务契约 3. 定义模型可见工具 4. 定义配置项 5. 定义权限级别 6. 定义生命周期 7. 定义事件 8. 编写单元测试 9. 使用最小 Context 验证 10. 在完整 Runtime 中测试例如一个 Git 插件应该至少考虑:
git_status;
git_diff;
git_log;
git_branch;
git_commit;
是否允许 push;
是否需要审批;
是否在当前 workspace;
命令输出是否截断;
并发执行是否安全。
二十四、适合哪些场景
编码 Agent
组合文件系统、Shell、Git、LSP、测试和代码审查插件。
Benchmark
使用 Minimal Loop、内存文件系统和受限工具,确保评测可重复。
企业内部 Agent
组合权限、审计、MCP、审批、知识库和内部 API 插件。
数据处理 Agent
组合文件、表格、Python 沙箱、任务队列和结果导出插件。
多 Agent 协作
组合 Subagent、Workflow、Scheduler 和共享 Session 插件。
二十五、当前使用时需要注意什么
1. Developer Preview
不要把当前 API 当成长期稳定接口。升级前应锁定版本并阅读变更记录。
2. 插件版本兼容
插件不仅依赖模型,还依赖:
Harness Core;
Cordis;
Node.js;
UI 协议;
Tool Schema;
Session 数据结构。
3. 权限默认最小化
不要因为插件方便,就默认挂载宿主机文件系统和无限制 Shell。
4. 运行轨迹需要脱敏
Trajectory 可能包含:
系统提示词;
私有代码;
API Token;
文件内容;
数据库查询;
用户隐私。
保存和导出前需要脱敏。
5. 插件不是越多越好
插件过多会导致:
模型工具选择困难;
上下文膨胀;
权限面增大;
启动时间变长;
运行组合难以测试。
二十六、总结
DeepSeek Harness 真正有意思的地方,不是它又增加了多少工具,而是它重新定义了 Agent 的扩展单位。
过去我们会说:
给 Agent 加 Tool 给 Agent 加 Memory 给 Agent 加 MCP 给 Agent 加 Workflow而“万物皆插件”的思路是:
Tool 是插件 Memory 是插件 MCP 是插件 Workflow 是插件 Agent Loop 是插件 Session 是插件 Sandbox 是插件 Filesystem 是插件 UI 是插件 Orchestrator 也是插件核心内核只负责:
管理 Context 装配 Plugin 提供 Service 分发 Event 管理 Lifecycle这让 Agent 从一个固定类,变成了一个可以被重新组合的运行时系统。
最终可以用一句话概括:
DeepSeek Harness 的重点不是“给 DeepSeek 加工具”,而是把整个 Agent 运行环境拆成插件,让模型、能力、执行循环和交互界面都可以被替换和重组。
参考资料
DeepSeek Harness 官方 GitHub 仓库
DeepSeek Harness 中文 README
Cordis 官方 GitHub 仓库
Cordis Primer 文档
DeepSeek Harness 官方页面
DeepSeek Tool Calls 官方文档