编程 DeepSeek 开源 Agent 框架 dsh:一切皆插件,一条 npx 起 Web UI

2026-10-02 20:01:02

DeepSeek 开源 Agent 框架 dsh:一切皆插件,一条 npx 起 Web UI

DeepSeek Harness(dsh)是 DeepSeek AI 以 MIT 协议开源的 agent harness,目前处于开发者预览阶段,会快速迭代并出现破坏兼容性的变更。它构建在「一切皆插件」架构之上,由 Cordis 插件系统驱动,设计参考论文 A Programming Paradigm for Spatiotemporal Composability。

项目地址:

  • GitHub:https://github.com/deepseek-ai/deepseek-harness
  • 中文 README:https://github.com/deepseek-ai/deepseek-harness/blob/master/README.zh.md
  • 文档:https://deepseek-harness.github.io/deepseek-harness/
  • 官网:https://deepseek.com/harness/
  • Cordis:https://github.com/cordiverse/cordis

运行

装好 Node.js 后直接:

npx @deepseek-ai/dsh web

默认在 http://127.0.0.1:3080 启动 Web UI。本机启动会用默认浏览器打开页面;SSH 启动只打印宿主机 URL,本地转发地址由 SSH 客户端或编辑器一侧持有。加 --no-open 只运行服务器,不打开浏览器。

从源码运行:

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web

pnpm run build 准备仓库产物,pnpm dsh web 直接使用已构建产物,不重新构建。

架构

Cordis 是底层插件框架,也是一个小型运行时。每项能力——工具、LLM 适配器、文件访问,乃至 agent loop 智能体循环本身——都是挂载到共享上下文中的插件。模型、工具、技能、会话、沙箱、存储、循环、调度、UI 等所有 Agent 能力都由插件提供,并通过 Cordis 服务与事件彼此协作。开发者无需改动源码,即可在配置层选择、替换或扩展任一能力。运行中的 dsh 是一棵插件树,由启动时按序叠加的各层组合而成。

profile 就是这些层:

  • dsh-base:web、headless、sdk、acp 共享的第一层,包含模型适配器、工具、持久化、沙箱与审批策略、设置、凭据、遥测。
  • dsh-web-app:增加浏览器应用。
  • dsh-headless:增加不带服务器的一次性运行器。
  • dsh-sdk-app:增加 SDK JSON-RPC 服务器。
  • dsh-acp-app:增加仅用于自动化的 ACP 服务器。
  • dsh-sdk-minimal:刻意保留的例外,一个组合包拥有完整的显式 SDK 配置树,不应用 dsh-base。

随附 profile 为 web、headless、sdk、sdk-minimal 和 acp,可用 dsh --profile 或 dsh 选择。plugin 表示管理命令,同名 profile 必须用 --profile plugin 选择。自定义插件组合由 profile 与有序 patch 文件表达。

运行模式

  • 标准模式:提供完整的工具组合。
  • PTC 模式:通过模型生成的一段代码(Code Mode SDK,一个 TypeScript 程序)组合多轮工具调用,具备标准模式全部能力。
  • 极简模式:仅保留一个 shell 工具与一个文件编辑工具,用于最小化环境下的模型基准测试。
  • 创造模式:可以检查当前运行时、在内存中试验 Cordis 插件,并据此组合和创作新的模式,通过 @deepseek-ai/dsh-tool-cordis 工具提供。

会话日志

模型看到的一切都会写入仅追加(append-only)设计的会话日志:系统提示词、思维链、工具调用与结果、子 Agent 调度,以及每一次上下文注入。在 Trajectory 视图中可按来源查看。恢复、分叉、检索与回放共享同一份事件流。JSONL v0 使用 session.jsonl[.zstd],v1 及后续版本使用 session.vN[...];已提交 generation 路径绝不重命名、替换或删除。模型可见即已记录:运行时不变量会检查模型请求是否可从日志重建。

写一个插件

DSH 插件本质是 Cordis 插件——一个导出 name 和 apply(ctx, config) 的模块(或继承 Service 的 class),另加 package.json 里的 dsh 清单字段告诉 loader 怎么挂载、依赖什么。

import type { Context } from '@deepseek-ai/cordis'

export const name = 'hello-dsh'

export function apply(ctx: Context) {
ctx.on('session/created', () => {
console.log('[hello-dsh] 新会话!')
})
}
  • name 是插件在组合里的唯一 id,也用于 patch 定位。
  • apply(ctx, config) 是入口;注册的监听器 / 工具随调用 fiber 卸载自动清理。
  • 通过 ctx 注册的东西(事件监听、工具、定时器)在插件卸载时自动清理,不需要手动 removeListener / clearInterval。需要手动释放的资源(网络连接、文件句柄)用 ctx.effect() 交清理函数。

注册一个可被模型调用的工具,用 defineTool:

import { defineTool } from '@deepseek-ai/dsh-tools'

export const name = 'greet-tool'
export const inject = ['tools']

export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'greet',
description: 'Greet the named person.',
parameters: { name: { type: 'string', required: true, description: 'Who to greet' } },
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
async execute(args) {
return `Hello, ${args.name}!`
},
}))
}

inject: ['tools'] 让插件等待工具注册表就绪;defineTool 把 parameters 规约转换为向模型展示的 JSON Schema,推导 args 类型,并在 execute 前校验模型提供的参数。

安装插件与热更新

  • bundle 型:dsh plugin --profile web add "github:dsh-external/my-plugin#main"
  • 本地目录开发:dsh plugin --profile web add link:/path/to/my-plugin
  • patch 层手动挂载:编辑 cordis.patch.yml 的 insert 段。

启动维护 $DSH_HOME/profiles/node_modules 扁平闭包 fallback,让 out-of-tree 插件解析到同一个 cordis 实例。验证组合里能看到插件:

dsh web --dump-config | grep hello-dsh

热更新边界:每次启动由 watchUserPatches 热应用的只有 profile 自身的 cordis.patch.yml——编辑它,框架会卸载旧插件实例、按新配置加载;读或解析失败则保留上一个好树,并广播 hmr/config-update-failed。--patch 覆盖层与 bundle 的 patch 文件改动需要重启生效。

临时开发不需要打包,用 --patch 覆盖层:

pnpm dsh web --patch ./scratch-plugin/cordis.yml

打开 http://127.0.0.1:3080,终端出现 [hello-plugin] plugin loaded!。插件路径必须是绝对路径;patch 文件只贡献配置,不会改变 loader 解析模块路径所用的 profile 目录。

常见坑

现象处理方式
裸名 cordis / schemastery 解析失败用 @deepseek-ai/cordis;必要时把裸名装进插件自身 node_modules
未声明 inject 就访问服务Proxy 拒绝;先 inject: ['tools'] 再 ctx.tools
patch 层 name 不符静默跳过,条不生效;检查 id/name 是否与目标行一致
以为 config 会深合并config 是整行替换,patch 没给全的字段走 schema 默认
--patch 写相对路径官方要求绝对路径,用 pwd 的结果拼
只导 Config interface 不导同名 schema无校验无默认值

安全与许可

运行前请阅读 SAFETY.md。开发者预览版后续会有破坏性更新。为插件仓库添加 dsh-plugin 话题便于被发现,反馈走 GitHub Discussions。

复制全文 生成海报 DeepSeek Agent框架 Cordis Node.js 插件架构

推荐文章

程序员茄子在线接单