ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

3 条命令启动 DeepSeek Harness Web UI,1 行 yml 写出你的第一个插件

3 条命令启动 DeepSeek Harness Web UI,1 行 yml 写出你的第一个插件

3 条命令启动 DeepSeek Harness Web UI,1 行 yml 写出你的第一个插件

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

DeepSeek Harness(命令名dsh)是 DeepSeek AI 开源的 agent harness,核心卖点是“万物皆插件”:工具、LLM 适配器、界面功能全部以 Cordis 插件的形式装载和组合。如果你不想 fork 别人的成品,而是想给 agent 换一套自己的行为,它就是干这个的。这篇文章只走两条线:先把 Web UI 在本机跑起来,再写一个 5 行的插件并注册进应用。

先把 Web UI 跑起来

前置只有一个:Node 22.19+ 或 24+(仓库engines声明为^22.19.0 || >=24.0.0)。

克隆并进入仓库:

git clone https://gitcode.com/gh_mirrors/de/deepseek-harness cd deepseek-harness

装依赖并构建产物:

corepack enable pnpm install pnpm run build

终端应跑完无报错。pnpm run build这一步很多人会漏——pnpm dsh web直接复用构建产物、不会替你现场编译,漏了它启动时会缺东西。

敲回车启动:

pnpm dsh web

等编译完成后,命令会默认打开浏览器,访问地址是http://127.0.0.1:3080;不想让浏览器自动弹出就加--no-open。

💡 小技巧:不打算从源码跑时,可以试试npx @deepseek-ai/dsh web,同样能在 3080 端口起一个 Web UI。

接上模型:两条路让会话真正可用

刚打开页面时,不配置模型是发不出会话的。进入设置 → 模型:

DeepSeek 官方密钥

在 DeepSeek 卡片里填入 API 密钥并保存。密钥是只写的:落盘在$DSH_HOME/.credentials.yaml,页面只拿得到脱敏描述符,永远看不到明文。模型变更在下一次请求时生效,不用重启服务器。

另别忘了:全新 Web UI 不选工作区时,会话输入框是不可用的——先点选择工作区把你启动dsh时的项目目录加进来。

第三方网关或自定义端点

要接中转站、公司网关或自建 OpenAI 兼容服务,点添加模型提供商,把卡片切到自定义模型 API:

需要填:小写的 Provider ID、基础 URL、API 协议、凭据,以及至少一个模型。注意 Provider ID 是永久标识——请求、已保存会话、凭据引用都挂在它上面,想“重命名”只能加新的、删旧的。网关是 OpenAI 兼容的话,可以直接点获取可用模型自动拉取模型列表;拉不到就手填模型 ID,效果一样。

⚠️ 注意:一个提供商只能用一种 API 协议(OpenAI Chat Completions / OpenAI Responses / Anthropic Messages 三选一)。网关同时暴露两种协议时,要建两个提供商。

细节更全的说法在 模型配置指南 里。

认识插件:一个 5 行的 TypeScript 模块

在 Harness 里,插件就是一个导出apply函数的 TypeScript 模块。框架加载时调用apply(ctx),你通过ctx注册一切能力:

import type { Context } from '@deepseek-ai/cordis' export const name = 'hello-plugin' export function apply(ctx: Context) { console.log('[hello-plugin] plugin loaded!') }

这就是一个完整插件。三个要点记住就够用:

  • 通过ctx注册的东西——事件监听、工具、定时器——在插件卸载时全部自动清理,不用手动removeListener或clearInterval;
  • 确实需要手动清理的资源(比如网络连接),用ctx.effect(() => { ...; return cleanup })包一层,返回的清理函数会在卸载时被框架调用;
  • 要用到tools、llm这类服务,在文件顶部声明export const inject = ['tools'],框架保证依赖就绪后才会加载你的插件。

三种形态,函数形态就是默认答案

对象形式(导出带apply方法的对象)和类形式(继承Service)也接受,但类形式留给“需要向其他插件暴露服务”的场景。绝大多数情况,函数形态够了。

一行 yml 完成注册,用 --patch 启动

要让 Web UI 真的加载你写的文件,在你自己的工作目录(仓库根目录外)建一个scratch-plugin/cordis.yml,用绝对路径注册插件:

- insert: - id: hello name: '<你的插件绝对路径>/scratch-plugin/src/my-plugin.ts'

⚠️ 注意:name必须是绝对路径。这份 patch 只贡献配置,不会改变 loader 解析模块时使用的 profile 目录。另外如果路径拼错了,Cordis 只走 logger 报一条错、不会让进程崩——所以“插件没反应”时,先去查拼写。

带着这个 overlay 启动:

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

浏览器打开http://127.0.0.1:3080,启动期间终端应打印[hello-plugin] plugin loaded!——对上了,插件就在应用里了。

往深处走

  • 给 agent 写一个真工具:工具开发教程
  • 理解 loader、生命周期与服务依赖机制:Cordis 框架教程
  • 让插件接受用户配置:插件配置

DeepSeek Harness 目前处于 developer preview,会有不兼容变更,升级前看一眼 升级指南。下一步建议别停在打印日志:写一个注册真实工具的插件,在会话里让 agent 把它调起来,把“写插件 → yml 注册 → 被 agent 调用”这条完整链路走一遍。

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进