乐于分享
好东西不私藏

DeepSeek Harness插件初识之开发你的第一个插件

DeepSeek Harness插件初识之开发你的第一个插件

用了世界上最轻最轻的声音,轻轻唤你的名字每夜每夜。


本文让我们一起通过编写一个简单的示例插件,从而快速的认识和学习deepseek-harness插件开发的过程。首先你依旧需要按照deepseek-harness,这非常的简单,你只需要有一个良好的网络,安装好合适的node版本即可快速的安装。deepseek-harness地址如下[https://github.com/deepseek-ai/deepseek-harness],参考官方readme即可快速安装:

git clone https://github.com/deepseek-ai/deepseek-harness.gitcd deepseek-harnesspnpm installpnpm run buildpnpm dsh web

当然如果需要安装到全局请使用:

npm install -g @deepseek-ai/dsh dsh --version

官方文档向你展示了什么是插件,插件具备哪些必要的属性,这里我们直接在一个具体的例子上学习。让我们来开发一个mini-soul插件,该插件很简单,为你的agent设置一个身份。一个积极乐观的人生导师,还是一个嘴贱腹黑的个性助手,完全取决你的设计。开发一个插件很简单,首先让我们创建一个mini-soul工程目录,然后需要为其添加如下的项目格式:

PS D:\AI\mini-soul> ls    目录: D:\AI\mini-soulMode                 LastWriteTime         Length Name                                                                                               ---d-----        2026-08-18     20:30                lib                                                                                                d-----        2026-08-20      0:15                souls                                                                                                                                                                                            -a----        2026-08-18     19:28             55 cordis.patch.yml                                                                                   -a----        2026-08-18     19:27            795 package.json                                                                                       PS D:\AI\mini-soul> 

lib目录存储你开发的核心的js代码,souls目录这里存在我们的身份模板作为我们代码处理的材料。package.json是一个项目配置声明文件,它不仅记录当前项目的名称、版本、入口文件和分发清单等标准npm元信息,还通过dsh.bundle字段显式注册并指向同目录下的cordis.patch.yml,将其作为当前组合包贡献给Harness的配置层(Patch Layer)。而cordis.patch.yml则是承载具体插件实例化参数和挂载id的纯配置数据文件。反正我们就知道一个简单的插件项目下面应该包含这几个东西。让我们具体看看几个文件中应该填写什么内容。

package.json文件

该文件描述项目的基本信息信息,并且通过dsh.bundle执行当前目录下的cordis.patch.yml文件。package.json文件应该包含项目的名称、版本、方便人类快速了解插件项目的说明、项目是否使用ESM语法,外部引用的入口声明,以及通过dsh.bundle指出当前包是一个组合包和将cordis.patch.yml作为当前包提供给系统的配置文件。那么一个示例性的写法如下:

{    "name": "mini-soul",    "version": "0.1.0",    "description": "Simplified persona plugin for DeepSeek Harness (learning project)",    "type": "module",    "main": "./lib/index.js",    "exports":{        ".":"./lib/index.js"    },    "files": [        "lib",        "souls",        "cordis.patch.yml"    ],    "dsh":{        "bundle":{            "patch":"./cordis.patch.yml"        }    },    "peerDependencies": {        "@deepseek-ai/cordis": "4.0.1",        "@deepseek-ai/dsh-host-webserver": "0.0.1-rc.1",        "@deepseek-ai/dsh-system-prompt": "0.0.1-rc.1"    },    "scripts": {        "test": "node --test ./test/*.test.js",        "check": "node --check ./lib/index.js"    },    "engines": {        "node": ">=22"    }}

cordis.patch.yml文件

该文件用户插件的显式声明配置。例如通过如下的配置你可以向当前的系统新插入一个你的插件:

- insert:    - id: mini-soul           # 唯一标识符      name: 'mini-soul'       # 指向 npm 包名      config:                 # 可选,传给插件的参数        persona: '助手'

通过如下的配置可以覆盖当前已有的插件:

- id: mini-soul  name: 'mini-soul'  config:    persona: '冷酷的哲学家'   # 这会完全覆盖之前 insert 时的 config

通过如下的配置将删除该插件,后续无法覆盖该插件除非重新插入:

- id: some-default-plugin  $remove: true

config字段可选,将作为一个参数传递入口来引用上下文的服务或者命令行参数。那么我们的人物画像例子如下:

- insert:    - id: mini-soul      name: 'mini-soul'

这是一个极简的例子,这将将我们的人物画像插件mini-soul插入到当前的系统之中。

index.js核心逻辑文件

在该文件中我们需要声明导出的插件名称以及对应的函数处理逻辑,以便于系统能够调用我们开发的插件,例如:

export const name = "mini-soul";export async function apply(ctx) {}

由于我们开发的是人物画像插件,因此需要将提示词注入系统,因此需要访问deepseek-harness的系统提示词服务,通过Cordis依赖注入systemPrompt服务,这样在我们的插件加载之前deepseek-harness就会提前将对于的服务注入,避免我们的插件在运行时因缺少依赖而崩溃。代码示例如下:

export const name = "mini-soul";export const inject = ["systemPrompt"];export async function apply(ctx) {}

接下来让我们完善这个逻辑,就是读取souls文件夹下的default.md人物画像文件,并注入系统提示词即可。

import { readFile } from "node:fs/promises";import { homedir } from "node:os";import { join } from "node:path";export const name = "mini-soul";export const inject = ["systemPrompt"];export async function apply(ctx) {  console.log("[mini-solu] plugin loaded!!!");  const soulsDir = join(homedir(),".dsh");  const personaFile = join(soulsDir,"profiles/web/node_modules/mini-soul/souls","default.md");  let personaText = "";  try {    personaText = await readFile(personaFile,'utf-8');    console.log('[mini-soul] 已读取人格文件:' + personaFile);  } catch (error) {    console.log('[mini-soul] 读取文件失败,错误为:' + error);    console.log('[mini-soul] 请先创建 personaFile 文件!!!');  }  const disposeSection = ctx.systemPrompt.section({    name: "mini-soul:persona",    order: 0,    text: personaText  });  console.log('[mini-soul] 人格已被注入系统提示词!!!');  return function cleanup(){    disposeSection();    console.log('[mini-soul] plugin unloaded!!!');  };}

ctx.systemPrompt.section({ ... })向系统提示词追加一段文本,mini-soul:persona默认的人物画像,我们通过指定该名字即可覆盖原始的人物画像,order指定为第一顺位。disposeSection作为一个局部清理函数,用于在插件卸载时合理的卸载插件相关的资源。

添加插件到deepseek-harness

通过如下的命令可将我们的示例插件添加到dsh中,原始的dsh自我介绍如下:

使用如下命令集成我们的插件:

D:\AI\mini-soul>dsh plugin --profile web add D:\AI\mini-soul -- -wAlready up to datedependencies:+ mini-soul 0.1.0 <- D:\AI\mini-soulDone in 384msD:\AI\mini-soul>dsh web[mini-solu] plugin loaded!!![mini-soul] 已读取人格文件:C:\Users\xxxxx\.dsh\profiles\web\node_modules\mini-soul\souls\default.md[mini-soul] 人格已被注入系统提示词!!!dsh web: http://127.0.0.1:3080[mini-soul] plugin unloaded!!!D:\AI\mini-soul>dsh web[mini-solu] plugin loaded!!![mini-soul] 已读取人格文件:C:\Users\xxxxx\.dsh\profiles\web\node_modules\mini-soul\souls\default.md[mini-soul] 人格已被注入系统提示词!!!dsh web: http://127.0.0.1:3080

使用插件后的效果。

插件列表显示我们的插件。

关于更多的细节,请参考deepseek-harness插件开发文档[https://deepseek-harness.github.io/deepseek-harness/develop/basic/]。