(三)88K Stars的Agent框架长什么样?DeepSeek Harness架构全解析
(三)88K Stars的Agent框架长什么样?DeepSeek Harness架构全解析
项目地址:https://github.com/deepseek-ai/deepseek-harness
⭐ 88,000+ Stars | MIT License | 语言:TypeScript
开篇:一个"没有核心"的Agent框架
当大多数AI框架还在争论"该用LangChain还是LlamaIndex"时,DeepSeek扔出了一个重磅炸弹——Harness。
这个斩获88K Stars的开源项目,用一句"Everything is a Plugin"彻底颠覆了传统Agent框架的设计哲学。没有特权核心、没有硬编码逻辑,甚至连模型适配器、工具注册表、会话管理这些"基础设施",统统都是可插拔的插件。
今天,我们就来拆解这个"叛逆"框架的完整架构。
一、整体架构:三层金字塔
Harness的架构可以用一个三层金字塔来概括:
┌─────────────────┐
│ Application │ ← 你的Agent应用
│ (Web/CLI/API) │
└────────┬────────┘
│
┌────────▼────────┐
│ Cordis │ ← 可逆编程运行时
│ (插件系统) │
└────────┬────────┘
│
┌────────▼────────┐
│ Capability │ ← 能力边界层
│ Seams │
└─────────────────┘
1.1 最底层:Capability Seams(能力边界)
这是Harness最精妙的设计。Seam原意是"接缝",在Harness中代表着能力的边界和交换点。
传统框架中,如果你想把"本地执行Bash"换成"云端E2B沙箱执行",可能需要改几十处代码。但在Harness中,只需要换一个FS Provider——因为文件系统、Shell执行、工具调用这些能力,都被抽象成了Seam。
Seam的三角色模型:
- Service Definition:能力接口定义(如
interface IFileSystem) - Provider:能力实现者(如
LocalFSProvider、E2BProvider) - Consumer:能力使用者(如
BashTool、FileEditor)
// 换个Provider,整个Agent的"工作环境"就变了
ctx.provide('fs', new E2BFileSystem()) // 云端执行
ctx.provide('fs', new LocalFileSystem()) // 本地执行
1.2 中间层:Cordis运行时
Cordis是Harness的心脏,一个专为可逆编程设计的运行时。
什么是可逆编程?想象一下:
- 传统插件系统:加载容易,卸载难(内存泄漏、状态污染)
- Cordis插件:加载和卸载完全对称,就像搭积木一样,想拆就拆
Cordis的核心是EffectScope——每个插件都在自己的作用域内运行,作用域可以:
- fork:创建子作用域
- ensure:确保资源存在
- reset:重置状态
- dispose:完全清理
// 插件的生命周期完全可控
const scope = ctx.scope.fork()
await scope.plugin(MyPlugin)
await scope.reset() // 干净重置
await scope.dispose() // 彻底销毁
1.3 最上层:Application
Harness提供三种开箱即用的应用形态:
| 形态 | 命令 | 适用场景 |
|---|---|---|
| Web UI | npx @deepseek-ai/dsh web |
可视化交互、演示 |
| Headless | npx @deepseek-ai/dsh headless |
服务器部署、API服务 |
| CLI | npx @deepseek-ai/dsh |
命令行操作、脚本化 |
二、一切皆插件:没有特权核心
Harness最 radical 的设计是:框架本身没有特权核心。
让我们看看传统Agent框架 vs Harness的区别:
| 组件 | 传统框架 | Harness |
|---|---|---|
| 模型适配器 | 硬编码在核心 | llm 插件 |
| 工具注册表 | 全局单例 | tools 插件 |
| 会话管理 | 核心服务 | sessions 插件 |
| Agent Loop | 内置主循环 | agent-loop 插件 |
| 系统提示词 | 写死在代码 | system-prompt 插件 |
这意味着什么?你可以完全替换框架的任何部分,而不会破坏其他功能。
2.1 插件的Ctx键
Harness使用**上下文(Context)**作为插件间通信的唯一方式:
// 核心插件提供的ctx键
ctx.sessions // 会话管理(core/session)
ctx.systemPrompt // 系统提示词(core/system-prompt)
ctx.tools // 工具注册表(core/tools)
ctx.agents // Agent实例管理(core/agent)
ctx.agentLoop // Agent主循环(core/agent-loop)
ctx.llm // 模型适配层(llm/llm)
每个插件通过provide注册自己的服务,通过inject消费其他服务。
三、事件驱动:Agent Loop的瀑布流
Harness的Agent不是"轮询-响应"模式,而是纯事件驱动。
一个完整的对话周期(Turn)会产生这样的事件流:
turn/start
↓
agent/pre-step ← waterfall(需调用next())
↓
step/start
↓
agent/request ← waterfall
↓
llm/stream ← waterfall
↓
assistant/chunk ← 流式输出片段
↓
assistant/message ← 完整消息
↓
tool/call ← 工具调用(可能有多个)
↓
tools/pre-execute ← waterfall
↓
tools/execute
↓
tools/post-execute
↓
step/end
↓
turn/end
3.1 四种事件分发模式
Cordis支持四种事件分发方式:
| 模式 | 特点 | 适用场景 |
|---|---|---|
| emit | 广播,不关心返回值 | 日志、通知 |
| parallel | 并行执行所有监听者 | 独立副作用 |
| serial | 串行执行 | 有序处理 |
| bail | 返回第一个非空值 | 策略选择 |
| waterfall | 可拦截、可修改 | 中间件、预处理 |
waterfall事件是Harness的精髓——它允许插件在事件传播过程中"插手",比如:
- 在
agent/pre-step中修改输入 - 在
llm/stream中拦截并修改模型输出 - 在
tools/pre-execute中添加权限检查
四、配置系统:Profile + Bundle + Patch
Harness的配置系统同样体现了"分层叠加"的思想:
4.1 三层配置模型
Base Bundle (dsh-base)
↓
Profile Config (cordis.patch.yml)
↓
Home Config (~/.config/dsh/)
↓
CLI Patch (--patch)
- Bundle:代码分发单元,包含一组插件和默认配置
- Profile:预定义的配置组合(如
dsh-web-app、dsh-headless) - Patch:无侵入式的配置覆盖
4.2 常用Profile
| Profile | 用途 | 包含的核心包 |
|---|---|---|
dsh-base |
基础功能 | core/, llm/, tools/* |
dsh-web-app |
Web界面 | + web-ui, react组件 |
dsh-headless |
无头服务 | + api-server |
4.3 调试配置
# 查看实际生效的完整配置
npx @deepseek-ai/dsh web --dump-config
这个命令会输出所有合并后的配置,是排查问题的利器。
五、60+包的组织结构
Harness的代码库采用monorepo管理,packages目录下包含60多个包:
packages/
├── core/ # 核心插件
│ ├── agent/ # Agent实例管理
│ ├── agent-loop/ # Agent主循环
│ ├── session/ # 会话管理
│ ├── system-prompt/ # 系统提示词
│ └── tools/ # 工具注册表
├── llm/ # 模型适配层
│ ├── llm/ # 抽象接口
│ ├── anthropic/ # Claude适配器
│ ├── openai/ # GPT适配器
│ ├── deepseek/ # DeepSeek适配器
│ └── ...
├── tools/ # 内置工具
│ ├── bash/ # Bash执行
│ ├── file/ # 文件编辑
│ ├── git/ # Git操作
│ └── ...
├── capabilities/ # 能力边界实现
│ ├── fs/ # 文件系统
│ ├── shell/ # Shell执行
│ └── telemetry/ # 遥测
└── apps/ # 应用层
├── web-ui/ # Web界面
├── cli/ # 命令行
└── api-server/ # API服务
六、为什么Harness值得关注?
6.1 对比传统框架
| 特性 | LangChain | AutoGPT | Harness |
|---|---|---|---|
| 架构 | 链式调用 | 自主循环 | 插件化+事件驱动 |
| 可扩展性 | 中等 | 低 | 极高 |
| 可逆性 | 无 | 无 | 原生支持 |
| 能力边界 | 硬编码 | 硬编码 | Seam抽象 |
| 部署形态 | 库 | 应用 | Web/Headless/CLI |
6.2 适用场景
- 快速原型:用Web UI验证Agent想法
- 生产部署:Headless模式提供API服务
- 深度定制:替换任意组件,打造专属Agent
- 研究实验:利用可逆性测试不同策略
七、快速上手
# 1. 安装
npm install -g @deepseek-ai/dsh
# 2. 启动Web界面
npx @deepseek-ai/dsh web
# 访问 http://127.0.0.1:3080
# 3. 配置模型(config.toml)
[llm]
provider = "deepseek"
api_key = "your-api-key"
# 4. 开始对话
结语:插件化是Agent框架的终极形态吗?
Harness用88K Stars证明了一件事:当一切皆插件,创新就没有边界。
传统框架的"核心团队决定一切"模式,在Harness中变成了"社区共同定义框架"。每个人都可以:
- 写一个新插件,扩展Harness的能力
- 替换现有插件,实现自己的逻辑
- 组合不同插件,创造全新的Agent形态
这不是一个框架,而是一个Agent操作系统。
下一篇预告:
(四)比LangChain更优雅?DeepSeek Harness的插件化Agent设计
我们将深入对比Harness与LangChain的架构差异,看看"无核心"设计到底强在哪里。
本文是「DeepSeek Harness源码分析」系列第3篇,系列共100篇,涵盖架构、源码、实战全流程。
更多推荐


所有评论(0)