DeepSeek Harness (DSH) 插件机制解析:一切皆插件的 Agent 运行时

DeepSeek Harness (DSH) 插件机制解析:一切皆插件的 Agent 运行时

基于 deepseek-ai/deepseek-harness 仓库源码分析


一句话结论

dsh(DeepSeek Harness)是一个 Agent harness,核心设计是**「一切皆插件」**------它没有把功能写死在框架里,而是构建在基于 source-vendored 的 Cordis 4.0(vendor/cordis/,重命名 @deepseek-ai/cordis)之上,所有能力都以插件形式挂载。理解 dsh 的插件机制,就理解了整个 harness 的运行逻辑。


一、总体架构

六层结构:界面层(web/cli)→ 启动层(app-boot)→ 组合层(bundle patch)→ 核心层(约 50 个功能包)→ 能力层(工具、记忆、会话等)→ 框架层(vendor 的 Cordis/loader/include)。


二、插件机制的 4 个核心概念

1. Context 是 Proxy,不是普通对象

vendor/cordis/src/reflect.tsget 陷阱 :读 ctx.xxx 时沿 fiber 链向上查找,找不到就报 cannot get property "X" without inject

含义:插件不能随便读全局状态------每个属性都必须能追溯到注入来源。这保证了依赖关系的显式化。

2. Fiber 生命周期状态机

graph LR P[PENDING] --> L[LOADING] --> A[ACTIVE] L --> F[FAILED] A --> U[UNLOADING] --> D[DISPOSED] A --> F

PENDING → LOADING → ACTIVE / FAILED → UNLOADING → DISPOSED。epoch 依赖串fiber.ts _refresh())驱动自动 reload/unload------依赖版本变化时,相关 fiber 自动刷新。

3. ctx.effect() 是唯一注册原语

  • 所有副作用(监听事件、注册工具、创建资源)都必须通过 ctx.effect() 注册
  • disposers 逆序执行:卸载 = 精确回滚
  • 好处:无论插件以什么顺序加载/卸载,清理都不会泄漏

4. 事件 5 种分发方式

方式 语义 典型场景
emit 广播,不等待 通知类事件
parallel 并行执行 无依赖的监听者
serial 串行执行 有顺序要求的监听者
bail 短路返回 审批/校验,可拒绝
waterfall 逐个传递返回值 策略注入点

waterfall 是插件机制的关键:返回值可以修改后传给下一个监听者。dsh 的策略注入点全部用 waterfall:

  • tools/pre-execute(工具执行前拦截)
  • agent/request(组装请求前修改)
  • llm/stream(流式输出逐段加工)
  • internal/config(配置合并)

三、Profile 与 bundle 贴纸叠层

Profile = $DSH_HOME/profiles/<name>/,内容是一份 bundle 有序列表 + cordis.patch.yml

bundle 补丁顺序(后贴赢)

  1. bundles(按配置顺序)
  2. profile patch
  3. home patch
  4. --patch overlays(命令行)

就像贴纸叠层:后贴的覆盖先贴的。调试命令:dsh --profile web --dump-config 可离线打印最终插件树。


四、Loader 与 Include:插件的加载与配置

Loader(vendor/loader/

  • 核心模型:EntryTree / Entry
  • name 动态 import 模块 → ctx.registry.plugin() 开 fiber
  • internal/plugin 监听绑定 fiber↔entry
  • 插件自我 dispose 时写回 disabled: true(下次启动不加载)

Include(vendor/include/

  • cordis.yml 是 YAML 方言,!!js 表达式延迟求值(配置值可以引用运行期对象)
  • applyEntryPatchesid 整体替换 / insert 追加,不做深合并
  • 理解:patch 是「替换或追加」,不是「递归合并」------避免歧义

五、类型声明合并机制

  • 103 个文件 declare module '@deepseek-ai/cordis' 扩充 Context/Events 接口
  • 156 个文件用 import type {} from '@deepseek-ai/dsh-xxx' 空类型导入拉声明(编译后擦除)
  • augmentation 跟着声明它的包走,不在 cordis 包里;外部插件作者必须显式拉取

引用服务 3 件事:

  1. 类型层:拉声明(import type {}
  2. 运行层:装 provider(ctx.provide
  3. 依赖层:inject

六、一次对话的回合流程

会话日志是唯一事实来源------所有事件在发生时立刻追加(不是最后统一写)。

graph TD A[turn/start] --> B[认领输入] --> C[组装提示词] --> D[agent/pre-step] D -- 被拒 --> E[回合无 step 直接结束 turn/end] D -- 通过 --> F[step/start] --> G[user/message 落盘] G --> H[从日志推导历史] --> I[agent/request] --> J[llm/stream] J --> K[assistant/chunk*] --> L[assistant/message] --> M[tool/call] M --> N[tools/pre-execute] --> O[execute] --> P[post-execute] --> Q[tool/result] Q --> R[step/end] R -- 工具要再问一次 --> F R -- 完成 --> S[turn-stopping] --> T[turn/end]

持久事件清单turn/startuser/messageassistant/chunkassistant/messagetool/calltool/resultstep/endturn/end


七、动手理解:一个最小插件长什么样

核心 API 只有三样:

js 复制代码
// 1. defineTool:声明一个工具
const tool = defineTool({
  name: 'demo-hello',
  execute: async (args) => { /* 干活 */ }
})

// 2. ctx.tools.register:挂载到 Context
ctx.tools.register(tool)

// 3. ctx.on('session/event'):订阅会话事件
ctx.on('session/event', (event) => { /* 观察 */ })

写插件 = 注册工具 + 订阅事件 + 用 effect 管理副作用。这就是「一切皆插件」的全部要义。


八、小词典(关键术语)

术语 含义
Harness Agent 的「运行容器」,管生命周期/依赖/事件
Cordis 插件化运行时框架(dsh 的 vendored 底座)
Fiber 单个插件的运行实例,有完整生命周期
Context (ctx) 插件的运行环境,Proxy 实现,属性需注入
effect 副作用注册原语,卸载时逆序回滚
epoch 依赖版本标识,变化时驱动 fiber 自动刷新
bundle 一组插件的打包单元,可被 patch
patch 对 bundle/配置的覆写(id 替换 / insert 追加)
Profile 一份运行配置:bundle 列表 + patch
waterfall 事件分发方式,返回值逐级传递(策略注入点)
Entry/EntryTree Loader 的加载单元模型
cordis.yml 配置方言,!!js 表达式延迟求值
声明合并 declare module 扩充 Cordis 接口的机制
provider 通过 ctx.provide 提供的服务实例
inject 依赖注入声明
dump-config 离线打印最终插件树的调试命令

推荐学习资源


参考

  • 仓库:deepseek-ai/deepseek-harness
  • 源码依据:vendor/cordis/src/reflect.tsvendor/cordis/src/fiber.tsvendor/loader/vendor/include/docs/architecture.md
相关推荐
糖墨夕8 小时前
理解大语言模型:Agent 的“大脑”
前端·agent
冬奇Lab8 小时前
一天一个开源项目(第209篇):holaOS - Agent 原生的本地工作台
人工智能·开源·agent
夏文强9 小时前
DeepSeek Harness 权限与审批:给 Agent 上一把 human-in-the-loop 的安全阀
人工智能·开源·大模型·agent·deepseek
loong_XL10 小时前
生产级 Agent 开发方法论:速度、质量、价格与工程化
ai·大模型·agent·loop·智能体·vibe
jimidou11 小时前
子 Agent 能并行,却不能互相说话:Claude Code 里哪些活不该委派
agent·ai编程
DeepAgent11 小时前
AI Agent 项目赏析:DeerFlow 2.0 —— 一个真正“长跑“的 SuperAgent 是怎么设计出来的?
github·agent
Haooog11 小时前
Agent 开发中的 Memory:State、短期记忆、长期记忆与 Memory Retrieval
java·agent·memory
多学一分钟12 小时前
讲清 Agent:闭环、工具调用、记忆,以及 MCP 和 A2A
agent
每天都是不一样的太阳12 小时前
别让 AI Agent 先画靶再射箭:一套「结论忠于数据」的证据链工作流
agent·工作流引擎
静开12 小时前
模型没换、提示词没动,成功率从不到 70% 干到 95% —— 改的到底是什么
agent