跳到主要内容

DeepSeek Harness

· 阅读需 11 分钟
otqsoft
Front And Rear End Engineers @ gitee

DeepSeek Harness(dsh)是由 DeepSeek AI 开发的开源 agent harness(智能体框架)。

DeepSeek Harness 的核心公式只有一行:

Model + Harness = Agent
  • Model(模型)负责思考:推理、决策、规划;
  • Harness(挽具/机架)负责执行:读文件、跑命令、调工具、管理会话、持久化、与 UI 通信……连续工作数小时不中断。

在这个公式里,模型只是"大脑",而 Harness 是整套"身体"。大脑可以随时更换(DeepSeek、通义、任何 OpenAI 兼容端点、甚至本地模型),身体则可以像乐高一样自由拼装。而"身体"的拼装方式。

环境要求

项目要求
Node.js22 或更新(官方按现行 Node 版本测试;Windows 上建议用最新的 LTS),版本使用22.17.0
包管理器pnpm 必须可用dsh plugin 命令会把参数直接转发给 pnpm 来管理插件;没有 pnpm 会报 pnpm not found on PATH
操作系统Windows / macOS / Linux 均可;shell 按平台自动选择:Windows 用 PowerShell(pwsh),macOS/Linux 用 bash,无需手动配置
网络首次启动需要访问 DeepSeek API(api.deepseek.com 及 OpenAI 兼容端点),后续会话也依赖网络

提示:项目是 ESM-first。Windows 用户请确保 PowerShell 7+(pwsh)可用,DSH 在 win32 上默认挂载 pwsh-sandbox 作为执行沙箱。

安装

全局安装 CLI

dsh 是一个 npm CLI 包(@deepseek-ai/dsh,bin 名为 dsh):

# 安装稳定版(如果 latest tag 已发布)
npm install -g @deepseek-ai/dsh

# 当前为 0.1.0-rc.6 候选版,可显式指定版本
npm install -g @deepseek-ai/dsh@0.1.0-rc.6

验证安装:

dsh --help
dsh --version

dsh --help 打印的是启动器(launcher)自身的帮助(--profile--patch--dump-config 等);而 dsh web --help 打印的是 Web 应用自己的帮助——这两者是不同的,后面会详细说。

不需要 git clone 仓库。发布包已包含全部运行时与前端产物;仓库源码仅供开发(pnpm run build 后再跑 TypeScript 入口)。

dsh 装好后自带完整的插件栈(@deepseek-ai/dsh-base 基础层、dsh-web-app / dsh-headless 模式层,以及 186 个 dsh-* 插件包)。首次使用 webheadless profile 时,会自动从随附模板初始化,无需手动建目录。

配置 API Key

DSH 把"密钥"和"配置"彻底分开:配置里只写引用名(如 DEEPSEEK_API_KEY),值放在凭证存储里。凭证解析优先级(高 → 低):

层级来源可写?
1继承的进程环境变量(export DEEPSEEK_API_KEY=…否(只读,永远最高优先)
2$DSH_HOME/.credentials.yaml 托管文档是(set/unset,Web Models 页写入)
3启动目录下的 .env(项目层)
4$DSH_HOME/.env(用户层)

方式一:环境变量(最快)

# Linux / macOS
export DEEPSEEK_API_KEY=sk-xxxx
dsh web

# Windows PowerShell
$env:DEEPSEEK_API_KEY = "sk-xxxx"
dsh web

方式二:托管凭证文档(推荐)

$DSH_HOME/.credentials.yaml只存凭证的 YAML 映射,会被严格校验(非映射结构、空值、重复键都会启动时报错):

# ~/.dsh/.credentials.yaml
DEEPSEEK_API_KEY: sk-xxxx
  • 文件权限为 0600(Windows 跳过权限检查);
  • 支持热重载:外部编辑后无需重启,下一次模型请求即生效;
  • Web 的 Models 设置页写入的就是这个文件;
  • 该文档不会被注入到进程环境变量,模型进程也不会被主动告知其路径(仅靠文件权限防止其他 OS 用户读取)。

方式三:.env 文件

启动器会分层加载两个 .env:启动目录的 .env(项目层)和 $DSH_HOME/.env(用户层),已继承的环境变量不会被覆盖。

⚠️ 安全限制:引导类变量禁止写进 .env——包括 PATHHOMENODE_OPTIONSDEEPSEEK_BASE_URLDSH_*XDG_*、代理变量等(这些"决定进程如何启动/如何联网"的变量只能由启动环境导出)。写进去会在启动时报错。

快速上手

Web 模式(推荐入门)

dsh web
# 等价于 dsh --profile web

首次运行会自动初始化 web profile,然后启动本地服务。默认参数(来自 web-app 组合配置):

  • host: 127.0.0.1
  • port: 3080

启动后在浏览器打开 http://127.0.0.1:3080 即可进入 DeepSeek Harness 的 Web 界面(会话列表、聊天、工具调用轨迹、设置等)。

常用 Web 参数:

dsh web --port 8080 # 换端口;--port 0 让系统分配空闲端口
dsh web --trusted-host my-pc # 额外信任的主机(可重复,host 或 host:port)
dsh web --help # 看 Web 应用自己的全部参数

🔒 安全设计--host 0.0.0.0故意拒绝——Web 界面具备执行命令的能力,绑定所有网卡等于把远程代码执行暴露到局域网。请保持 127.0.0.1 或显式用 --trusted-host 声明可信任的来源。

headless 模式(一次性任务)

不开浏览器、不监听端口,跑完即退:

dsh --profile headless "运行仓库里的测试,并报告结果"
  • 启动全新持久化会话 → 提交任务 → 等待全部工作完成 → 把最后一条非空 assistant 回复打印到 stdout → 退出;
  • 成功(最后一个 turn/end 正常结束)退出码为 0,失败为 1(错误信息写到 stderr);
  • 适合脚本、CI、定时任务;无交互式追问。

工作区概念:在哪个目录启动,哪个目录就是工作区

DSH 把启动时的当前目录作为默认 workspace 根(沙箱的 workspaceRoot: process.cwd())。Agent 的读写、shell 执行都被限制在这个根内(见下文权限)。所以:

cd /path/to/my-project
dsh web # 这个项目的代码就是 Agent 的"工位"

目录结构

所有用户数据集中在 DSH 家目录:默认 ~/.dsh(Windows 为 %USERPROFILE%\.dsh),可用环境变量 $DSH_HOME 改到别处(优先级:显式配置 > $DSH_HOME > ~/.dsh)。

~/.dsh/
├── profiles/
│ ├── web/ # web profile(首次使用自动初始化)
│ │ ├── package.json # dsh.profile.bundles 层清单 + 树外插件依赖
│ │ ├── cordis.patch.yml # 你的补丁层(热重载)
│ │ └── pnpm-workspace.yaml
│ └── headless/ # headless profile
├── sessions/ # 持久化会话(JSONL 追加式日志,可恢复/回放)
├── storages/ # 结构化存储(todo、goal 等状态)
├── attachments/v1/objects/ # 图片等附件(sha256 寻址)
├── settings.yaml # 用户设置(模型/Provider,热重载)
├── .credentials.yaml # 凭证文档(0600)
├── .env # 用户层环境变量
└── .anonymous-user-id # 匿名身份 UUID(删掉即重置)

管理 Profile 与插件

dsh 的核心概念是 profile$DSH_HOME/profiles/<name> 下的一个目录,由"插件 bundle 层 + 你的补丁层"组合而成。

创建自己的 profile

webheadless 有随附模板;其他任何 profile 通过 dsh plugin 首次使用时自动初始化(初始只含基础层 dsh-base):

dsh plugin --profile my-agent add @deepseek-ai/dsh-web-app # 首次运行会先初始化 my-agent

件管理命令

dsh plugin 是一个薄 pnpm 转发器:在 profile 目录里执行 pnpm,装完自动把"声明了 dsh.bundle 的包"加入该 profile 的层叠清单:

dsh plugin --profile my-agent add <package> # 安装插件
dsh plugin --profile my-agent remove <package> # 移除
dsh plugin --profile my-agent update # 更新(新版本声明了 bundle 会自动激活)
dsh plugin --profile my-agent why <package> # 查询依赖关系

注意:装的包如果没有声明 dsh.bundle,会作为普通依赖安装并给出提示(它不会成为配置层)。

启动自定义 profile

dsh --profile my-agent # 启动
dsh --profile my-agent --help # 该 profile 应用自己的参数

层叠配置(补丁层)

配置树按顺序叠加(后层覆盖前层的同 id 行):

空配置根
→ profile 的 dsh.profile.bundles 各 bundle 补丁
→ profile 目录的 cordis.patch.yml
→ $DSH_HOME/cordis.patch.yml
→ 命令行 --patch 指定的覆盖层(可重复)

常用操作:

# 预览组合后的配置树(不启动)
dsh --profile web --dump-config
dsh --profile web --dump-default-config # 只看 bundle 层,不含用户层

# 叠加一个临时补丁文件
dsh --profile web --patch ./extra.yml

cordis.patch.yml 是 YAML 数组,可对指定行改配置、禁用行、插入新行(支持 !!js 表达式),例如把默认模型换掉、开启会话全文搜索等。用户补丁层支持热重载(长驻服务下修改立即生效)。

模型与设置

默认模型

基础层内置的默认路由:

# dsh-base 的 agent-default-model 行
provider: deepseek-official
model: deepseek-v4-flash

设置文档 $DSH_HOME/settings.yaml

用户设置(模型、Provider、API 端点等)存放在 settings.yaml(YAML/JSON 均可,热重载,原子写入保留注释)。Web 界面的 Models 设置页就是读写这个文件;也可以手写:

# 示例:覆盖 DeepSeek 直连适配器的配置(字段名以实际 schema 为准)
llm-deepseek:
baseURL: https://api.deepseek.com
maxTokens: 8192

架构上 dsh-llm-deepseek(DeepSeek 官方直连)与 dsh-llm-pi-ai(多 Provider 动态路由,默认休眠、配置了 llm-pi-ai: 节才激活)是双胞胎适配器——装哪些适配器是组合决定的,跑哪些 Provider 是你的设置文档决定的

换模型/Provider 会改变请求前缀,从而影响 KV 缓存复用;同一个会话内尽量保持路由不变(DSH 会冻结调用配置、记录请求头快照)。

权限与安全

DSH 默认给你一套"受控的 Agent":

环境变量取值含义
DSH_PERMISSION_MODEread-only / workspace-write(默认)/ danger-full-access文件影响边界
批准策略ask(默认)/ never越界操作是否询问(danger-full-access 下自动为 never
  • 默认 workspace-write + ask:Agent 只能在工作区内写文件;工作区外或敏感操作会弹审批(Web 界面里就是"批准/拒绝"按钮);
  • 沙箱按平台自动选择:Windows 用 dsh-sandbox-windows-acl(ACL 受限令牌),POSIX 用本地沙箱;shell 同理(pwsh-sandbox / bash-sandbox);
  • 越权尝试会被沙箱直接拒绝([sandbox: file access denied]),而不是静默放行。

常用环境变量速查

变量作用
DSH_HOME数据家目录(默认 ~/.dsh
DEEPSEEK_API_KEYDeepSeek API Key(凭证引用 DEEPSEEK_API_KEY
DSH_PERMISSION_MODE权限预设(见上)
DSH_TELEMETRY_MODE遥测:默认 DISABLEDFULL / FEEDBACK_ONLY 显式开启)
DEEPSEEK_BASE_URLAPI 端点覆盖(只能从启动环境设置,不能写 .env
DSH_TOOLS_MODE工具呈现模式 native / code / both(临时环境开关)
DSH_SNAPSHOT=replay会话回放模式(读 cordis.snapshot.yml

常见问题排查

现象原因与处理
dsh: pnpm not found on PATH未安装 pnpm。npm install -g pnpm 或启用 corepack enable 后重试
启动报 .env sets "PATH" ... only the launching environment may set把引导类变量写进了 .env;删掉该行,改为在 shell 里 export
浏览器打不开 / 端口被占换端口:dsh web --port 8080
模型请求报 MISSING_CREDENTIAL没配 API Key:按第三节任一方式配置后重启
命令执行被拒(file access denied当前为 workspace-write 沙箱,操作越界了;在 Web 界面批准,或确认工作区正确
--host 0.0.0.0 被拒绝安全设计:DSH 拒绝全网卡绑定;用 127.0.0.1 + --trusted-host
找不到会话/设置确认 $DSH_HOME:默认 ~/.dsh;不同家目录 = 不同数据
想彻底重置删除 $DSH_HOME 下对应目录(如 sessions/settings.yaml);删 .anonymous-user-id 重置匿名身份

使用

首次进入http://127.0.0.1:3080时需要选择一个工作区和设置模型

使用DeepSeek Harness写一个竹知了的网页小游戏,看下效果,项目生成时Harness会生成“轨迹”,每一步都有详细的输入和输出,还包括系统提示词。

生成的项目目录结构

zhu-zhiliao/
├── index.html # 页面骨架(菜单 / HUD / 面板 / 引导)
├── css/
│ └── style.css # 国风样式与响应式适配
├── js/
│ ├── config.js # ★ 全部可调参数 + 外观 / 成就数据定义
│ ├── storage.js # localStorage 本地存档
│ ├── audio.js # Web Audio:鸣叫合成 / 国风音乐 / 竹制音效
│ ├── background.js # 动态竹林(昼夜双主题、萤火虫、星辰、落叶)
│ ├── cicada.js # 竹知了绘制、旋转物理、拖尾模糊、外观花纹
│ ├── challenge.js # 节奏挑战(提示点、判定、连击、粒子)
│ ├── achievements.js # 成就与外观解锁联动
│ ├── ui.js # 界面层(菜单 / 面板 / 引导 / HUD / 提示)
│ └── main.js # 主控:游戏循环、输入、模式状态机
└── tools/
├── smoke.js # 无头冒烟测试(node tools/smoke.js)
└── browser-check.js # 无头 Chrome 验收 + 截图(需本机可用 Chrome)
最后更新时间: --|访问次数: 0|备案图标豫ICP备2025159864号|