DeepSeek Harness 运行形态:一套代码,三种身份
2026/9/7 22:18:41 网站建设 项目流程

DeepSeek Harness 运行形态:一套代码,三种身份

这是 DeepSeek Harness(dsh)系列的第九篇。前八篇把「是什么」「怎么开发插件」「底层怎么转」「日志怎么追溯」「安全怎么兜底」一路聊到了「子 Agent 编排」——这八篇讲的都是它内部长什么样。从这篇开始,我们换个视角,聊它对外长成什么样:一个dsh命令,怎么同时扮演「交互式 Web 应用」「一次性命令行」「JSON-RPC 服务器」三种角色。

这也是它和很多 Agent 框架不一样的地方:SDK 和 ACP 不是单独的二进制,而是 profile。你不需要「装一个 CLI 版、再装一个 SDK 版」,只有一个入口,切个参数就换身份。

一、一个 dsh,五种入口模式

官方文档说得很直白:dsh命令是唯一受支持的 Node 应用启动器。所有形态都从它进来,切换的关键就是--profile参数:

命令用途
dsh --profile <name>启动$DSH_HOME/profiles/<name>下的命名 profile
dsh --profile acp通过 ACP stdio 服务自动化客户端,直到断开
dsh --profile headless "job"跑一个一次性持久会话,打印最终答案后退出
dsh --profile sdk通过 JSON-RPC stdio 服务 SDK 客户端,直到关闭
dsh --profile sdk-minimal用独立的极简 agent 树服务 SDK 客户端
dsh web--profile web的别名
dsh plugin --profile <name> <pnpm args>把 profile 的插件管理转发给 pnpm

其中webheadlesssdksdk-minimalacp这五个 profile 会在首次使用时从内置模板自动初始化;其它自定义 profile 必须先通过dsh plugin创建。

二、三种形态各干什么

把上表收敛一下,日常打交道最多的是三种形态:

  • web:交互式 Web UI,带浏览器界面,适合「坐在机器前」的日常开发。它启动 HTTP 服务器 + WebSocket,前端和 Agent 跑在同一个进程里。
  • headless:一次性任务。dsh --profile headless "run the tests"会新建一个持久会话,把任务跑完、打印最终答案、然后退出。适合 CI、脚本化、无人值守。
  • sdk/sdk-minimal:把 Harness 当作一个 JSON-RPC 服务器,供你自己的程序调用。区别是sdk是完整树,sdk-minimal是只有极简 agent 树的独立版本(下一篇 SDK 集成会重点讲)。

一个容易被忽略的细节:启动器只解析它自己的 flag,其余参数原样转交给被启动的 profile。所以:

dsh--profileweb--port8080# --port 属于 web 应用,不是启动器的dsh--profileheadless"run the tests"dsh--profileweb--help# 这是 web 应用的 help,不是启动器的dsh--help# 这才是启动器自己的 help

第一个它不认识、且不是--profile开头的 token,之后的所有东西就都算「应用参数」了。这个设计让每个形态可以有自己的参数空间,互不打架。

三、profile 的本质:一堆 patch 层的堆叠

「profile 就是有序的插件 bundle patch 层,叠在用户自己的覆盖层之下」——这是理解整个运行形态的核心。

一个 profile 目录里就两样关键东西:

  • package.json:既装 out-of-tree 的插件依赖,又带一个dsh.profilemanifest,里面是有序的bundles列表patchReload生命周期;
  • cordis.patch.yml用户自己的 patch 层

真正跑起来时,整棵树是这样在空 root 上逐层叠出来的:

  1. dsh.profile.bundles里每个 bundle 的 patch,按声明顺序
  2. 然后是 profile 自己的cordis.patch.yml
  3. 再是 home 级的$DSH_HOME/cordis.patch.yml
  4. 最后是--patch命令行传入的覆盖层。

bundles 里名字的解析也有优先级:先从 dsh 安装目录找内置 bundle(@deepseek-ai/dsh-basedsh-web-appdsh-headlessdsh-sdk-appdsh-sdk-minimaldsh-acp-app),再落到 profile 自己的node_modules(pnpm 装进去的 out-of-tree 插件)。

四、patchReload:改完配置要不要重启

patchReload控制 patch 文件怎么生效,两个取值:

  • live:监听 profile 和 home 级的 patch 文件,改了立刻重载;
  • startup:只在启动时应用一次。

开发插件时live能省掉反复重启的功夫,改完 patch 直接看效果;生产环境用startup更稳,避免运行中途被外部改动的文件影响。

五、不启动也能看配置

想确认某个 profile 到底组装成了什么样、某一行配置被谁覆盖成了什么值,不用真的把它跑起来。两个命令能「只看不跑」:

dsh--profilesdk-minimal --dump-default-config# 看内置默认配置dsh--profilesdk-minimal --dump-config# 看叠加你所有覆盖后的最终配置

后者尤其有用:当你搞不清「我的 patch 到底覆盖成功没有」,--dump-config会直接给出最终生效的树,一目了然。

六、避坑清单

  1. 别把形态当独立软件装。SDK、ACP 都是 profile,dsh是唯一入口。再看到「装个 sdk 二进制」的说法,多半是把它和别的框架搞混了。
  2. --port这类参数放对位置。启动器只认自己的 flag,应用参数要跟在第一个非启动器 token 之后,否则会被启动器当成非法选项报错。
  3. 自定义 profile 要先创建。只有web/headless/sdk/sdk-minimal/acp会从模板自动初始化,别的名字必须先dsh plugin建,否则启动失败。
  4. 层叠顺序别记反。越靠后的层覆盖力越强:bundle → profile → home →--patch。想临时改一个值,--patch最方便;想持久改,写 home 级 patch。
  5. 生产用startup,开发用livelive会让运行中的进程响应外部文件改动,生产环境里这是个风险点。

小结

这一篇把dsh的「对外身份」讲清楚了:一个入口、五种模式、三种常见形态,背后全是同一个「profile = patch 层堆叠」的模型。你只要记住——换形态不是换软件,是换 profile,就抓住了它的运行形态。

三种形态里,最值得开发者深挖的是sdk:它把 Harness 变成一个 JSON-RPC 服务器,让你能把自己的程序变成「能调用 Agent」的应用。下一篇(第十篇)我们就专门讲这个——怎么用 Python 和 TypeScript 把 Harness 嵌进你自己的应用里


参考:deepseek-ai/deepseek-harness 官方仓库apps/cli/README.md

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询