DeepSeek Harness插件开发入门指南:从零到配置化工具

作者:袖梨 2026-08-20

DeepSeek Harness插件开发入门指南:从零到配置化工具的重点在于把前置条件、操作顺序和容易误判的地方分清楚。

前言

DeepSeek Harness 是一个基于 Cordis 插件框架的 Agent 运行时环境。在 Harness 中,一切皆插件——从工具注册到 UI 渲染,从 LLM 调用到会话持久化,所有能力都以插件形式存在。下文会带你从零开始,逐步掌握插件开发的核心技能:

DeepSeek Harness插件开发入门指南:从零到配置化工具

  1. 创建第一个插件
  2. 将插件升级为可调用工具
  3. 添加插件配置(Config)并实现 Schemastery 校验
  4. 解决 Windows 开发环境下的常见问题

一、创建第一个插件

目录结构

在仓库根目录下创建 scratch-plugin 目录:

scratch-plugin/├── cordis.yml└── src/    └── my-plugin.ts

插件入口文件

// src/my-plugin.tsimport type { Context } from '@deepseek-ai/cordis'export const name = 'hello-plugin'export function apply(ctx: Context) {  console.log('[hello-plugin] plugin loaded!')  ctx.effect(() => {    const timer = setInterval(() => {      console.log('[hello-plugin] heartbeat')    }, 5000)    return () => clearInterval(timer)  })}

关键点:

  1. 插件必须导出 nameapply 函数
  2. ctx.effect() 用于注册副作用,插件卸载时会自动调用返回的清理函数
  3. 所有注册的资源(事件监听、定时器等)都会在插件卸载时自动清理

注册到 cordis.yml

# scratch-plugin/cordis.yml- insert:    - id: hello      name: 'file:///d:/codes/DeepSeek-Harness/scratch-plugin/src/my-plugin.ts'

Windows 注意:ESM 模块加载要求路径使用 file:// 协议格式,不能使用 d: 这样的裸路径。

启动插件

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

打开 http://127.0.0.1:3080,终端中会打印 [hello-plugin] plugin loaded! 和每隔 5 秒的心跳日志。

二、将插件升级为工具(Tool)

仅有心跳日志的插件并不实用。要让插件在对话框中"可用",需要注册一个工具(Tool)——即 Agent 在对话过程中可以调用的能力。

工具插件代码

// src/my-plugin.tsimport type { Context } from '@deepseek-ai/cordis'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 someone by name.',    parameters: {      name: {        type: 'string',        required: true,        description: 'The name to greet',      },    },    output: {      schema: { type: 'string' },      render: (_args, value) => [{ type: 'text', text: value }],    },    async execute(args) {      return `Hello, ${args.name}!`    },  }))}

关键点:

  1. inject = ['tools'] 声明依赖,Cordis 会确保工具注册表就绪后再加载插件
  2. defineTool 根据 parameters 自动推导并校验参数类型
  3. execute 是实际执行逻辑,output.render 负责将结果转换为模型可读的内容

在对话框中使用

启动后在对话框输入:

Use the greet tool to greet Ada.

模型会自动调用 greet 工具,传入 name: "Ada",工具返回 Hello, Ada!

三、添加插件配置:让问候语可配置

硬编码的 Hello 不够灵活。Harness 的约定是:凡是不同部署可能需要采用不同值的参数,都必须定义为配置字段

定义 Config

// src/my-plugin.tsimport type { Context } from '@deepseek-ai/cordis'import Schema from '@deepseek-ai/schemastery'import { defineTool } from '@deepseek-ai/dsh-tools'export const name = 'greet-tool'export const inject = ['tools']export interface Config {  greeting: string}export const Config: Schema = Schema.object({  greeting: Schema.string().default('Hello'),})export function apply(ctx: Context, config: Config) {  ctx.tools.register(defineTool({    name: 'greet',    description: 'Greet someone by name.',    parameters: {      name: {        type: 'string',        required: true,        description: 'The name to greet',      },    },    output: {      schema: { type: 'string' },      render: (_args, value) => [{ type: 'text', text: value }],    },    async execute(args) {      return `${config.greeting}, ${args.name}!`    },  }))}

在 cordis.yml 中传入配置

# scratch-plugin/cordis.yml- insert:    - id: hello      name: 'file:///d:/codes/DeepSeek-Harness/scratch-plugin/src/my-plugin.ts'      config:        greeting: 'Hi there'

现在工具会返回 Hi there, Ada!。如果把 greeting 改成 What's up,则返回 What's up, Ada!

四、Schemastery 的严格校验机制

你可能好奇:如果我在 cordis.yml 里把 greeting 写成数字,会怎样?

答案是:插件加载会直接失败

校验流程

Cordis 在加载插件时,会读取插件导出的 Config schema,调用其 ~standard.validate() 方法进行校验(位于 vendor/cordis/src/fiber.ts):

export function resolveConfig(runtime: Plugin.Runtime, config: any) {  if (!runtime.Config) return config  const result = runtime.Config['~standard'].validate(config)  if (result.issues) {    throw new ValidationError(result.issues)  // 校验失败 → 插件加载失败  } else {    return result.value                          // 校验通过 → 返回处理后的值  }}

校验行为

输入值校验结果config.greeting
'Hi there'✅ 通过'Hi there'
不填✅ 使用默认值'Hello'
123❌ 类型不匹配插件加载失败
不填且没有 .default()❌ 缺少必填字段插件加载失败

这种配置错误要响亮的设计,确保问题在启动阶段就被暴露,而不是在运行时才发现。

五、解决 IDE 类型检查问题

由于 scratch-plugin 不在任何 TypeScript 项目中,IDE 可能报错:

找不到模块 "@deepseek-ai/cordis" 或其相应的类型声明。

解决方案

scratch-plugin 目录下创建 tsconfig.json

{  "extends": "../tsconfig.base.json",  "compilerOptions": {    "composite": false,    "incremental": false,    "paths": {      "@deepseek-ai/cordis": ["../vendor/cordis/src"],      "@deepseek-ai/schemastery": ["../vendor/schemastery/src"],      "@deepseek-ai/dsh-tools": ["../packages/core/tools/src"]    }  },  "include": ["src/**/*"]}

继承项目的 tsconfig.base.json 并补充路径映射,IDE 就能正确解析类型了。

六、完整目录结构

scratch-plugin/├── cordis.yml          # 插件注册 + 配置├── tsconfig.json       # TypeScript 配置└── src/    └── my-plugin.ts    # 插件代码

总结

步骤内容关键 API
1创建插件骨架export name, export apply(ctx)
2注册工具ctx.tools.register(defineTool(...))
3添加配置export interface Config, export const Config = Schema.object(...)
4解决类型检查tsconfig.json 继承根配置并添加 paths

相关文章

精彩推荐