万物皆插件:DeepSeek Harness 的核心架构、Cordis 内核与 Agent 可组合性
万物皆插件: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
SandboxedFileSystem
3. 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_code
Skill
一组领域能力和使用规则:
Git 操作 Skill
Java 重构 Skill
数据库迁移 Skill
测试编写 Skill
Skill 往往同时包含说明文档、工具组合和验证方式。
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
status
Trajectory 可以理解为一次 Agent 执行轨迹,记录:
用户输入
-> 模型响应
-> 工具调用
-> 工具结果
-> 文件变化
-> 测试结果
-> 下一轮模型决策
如果每个事件都被追加保存,系统就可以支持:
-
查看轨迹;
-
搜索历史;
-
从某个节点恢复;
-
Fork 出新的会话;
-
重放某次执行;
-
对比不同插件组合的结果;
-
复现工具错误。
十五、Checkpoint、Resume 和 Fork
Checkpoint
保存某个时间点的运行状态:
active_plugins
context
messages
files_snapshot
pending_tools
permissions
loop_state
Resume
从 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 UI
2. 加载插件
各插件注册自己的服务、工具、事件和上下文贡献。
3. 创建 Session
Session 记录工作目录、启用插件、用户任务和运行模式。
4. Agent Loop 调用模型
模型看到:
-
系统规则;
-
项目上下文;
-
当前任务;
-
可用工具;
-
Skill 说明;
-
权限边界。
5. 模型选择工具
模型请求:
list_files
search_code
read_file
Tool 插件执行并返回 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 Process
3. 类型和契约要求更高
插件之间必须有稳定接口,否则替换实现很容易造成运行时错误。
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 运行环境拆成插件,让模型、能力、执行循环和交互界面都可以被替换和重组。
参考资料
更多推荐

所有评论(0)