ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

DeepSeek Harness 从零运行与 Agent Preset 对照实验:一份带源码和实测数据的完整报告

DeepSeek Harness 从零运行与 Agent Preset 对照实验:一份带源码和实测数据的完整报告

本文是一份 DeepSeek Harness 的实战记录:把 DSH 从零跑起来,再用两份对照实验把它拆开看。
与常见"安装教程"不同,本文包含三样东西:两套可复现的对照实验方法、官方源码(v0.2.0-rc.2)的逐文件解剖、以及在同一台机器上真实跑出来的 8 次运行数据(4 个会话 × 两份对照实验)。
全文命令与数据均可复现,实测环境:Windows + Node 24 + dsh 0.2.0-rc.2。


一、先搞清楚要干什么

本文的目标不是"装完能用"就结束,而是建立一个可观察的 DSH 环境,然后用对照实验把它的运行机制拆开看。

正确的打开方式是三段:

  1. 跑起来:装环境、启动 Web UI、接一个模型、选工作区;
  2. 做两个对照实验:
    • 实验 1:创建 4 个会话,分别用 4 套 Preset,问同一个问题——“你当前可以使用哪些能力?不要执行任何操作,只按类别说明。”(关键:用 UI/Trace 取证,不能拿模型自述当证据)
    • 实验 2:4 套 Preset 跑同一个任务——“读取当前目录,创建 3 个文本文件,统计总行数,然后给出摘要。除完成任务外,不做额外修改。”——比较执行轨迹;
  3. 想一个更大的问题:官方 Benchmark 为什么选 Minimal?(结论后面第八章展开)

三个环节环环相扣,下面逐个给结果。

二、环境准备与安装(含国内网络三大坑)

要求就一条:Node.js^22.19.0或>=24.0.0,装 Node 24 准没错。

node-v# v24.12.0 ✅

三种安装方式,按需选择:

# 方式一:免安装直接跑(官方推荐)npx @deepseek-ai/dsh web# 方式二:全局安装(长期使用)npminstall-g@deepseek-ai/dsh dsh--version# 0.2.0-rc.2# 方式三:从源码(改代码/写插件才需要)gitclone https://github.com/deepseek-ai/deepseek-harness.gitcddeepseek-harness&&corepackenable&&pnpminstall&&pnpmrun build&&pnpmdsh web

⚠️国内网络三大坑(全部实测踩过):

坑现象解决
GitHub 直连clone 超时地址前加镜像:https://ghproxy.net/https://github.com/...
npm 官方源慢npx 卡在依赖解析前加npm_config_registry=https://registry.npmmirror.com(实测 538 个依赖包从"卡几分钟"到39 秒)
Windows corepackcorepack enable报 EPERM要写 Node 安装目录,需管理员终端;不走源码路线可跳过

三、启动与第一次配置

dsh web# 终端输出:dsh web: http://127.0.0.1:3080/?token=一串字符

必须带?token=访问——那是本次启动的临时钥匙,浏览器用它换取签名的会话 cookie。直接开127.0.0.1:3080会返回 401,这不是故障,是设计。

接下来三步:

  1. 配置模型:设置 → 模型 → DeepSeek (deepseek-official),填入 platform.deepseek.com 申请的 API 密钥。默认模型DeepSeek-V4.1-Flash(推理等级 High),上下文窗口 100 万 token,支持图片。
  2. 选择工作区。
  3. 选模式(Preset):输入框上方有"标准模式"按钮,点开就是 4 套模式。

⚠️ 关于工作区,一个真实踩坑记录

很多教程(包括我)会以为"从哪个目录启动,默认工作区就是哪"。实测发现不是:DSH Web 界面里的"默认工作区"是它自动注册的C:\Users\<你>\Documents\deepseek-harness\default-workspace,跟启动目录无关。

而"添加工作区"按钮会触发服务端弹 Windows 原生文件夹对话框——如果你的 dsh 是在后台/非交互终端里启动的,这个对话框弹不出来(报win32 folder dialog worker exited before reporting a result),前端表现为"无法打开文件夹 / directoryPicker failed"。

结论:做实验直接用默认工作区即可(它天然是个空目录,正适合);要加自定义目录,请在普通终端启动 dsh 后手动选择。

四、认识 4 套 Agent Preset(界面 + 源码逐文件解剖)

界面上有四种模式(点输入框上方的模式按钮可见):

界面名称官方描述(实测截图原文)
标准模式处理代码、文件和资料,适合大多数任务。Agent 会按需使用检索、编辑和终端等工具。
PTC 模式包含标准模式的所有能力,更适合批量调用工具、并对结果进行筛选、整理、去重、统计或汇总的任务。
极简模式Agent 仅使用终端工具完成任务,适合测试和对比其基础表现。
创造模式用对话定制 DSH:让 Agent 编写插件,添加新功能或界面;也能组合工具和提示词,创建自己的模式。

光看描述不够,直接看源码。4 套 Preset 在官方仓库里的位置是:

packages/bundle/web-app/presets/ ├── standard.patch.yml # 标准 ├── ptc.patch.yml # PTC ├── minimal.patch.yml # 极简 └── cordis.patch.yml # 创造(目录名 cordis,界面叫"创造模式")

⚠️ 版本说明:早期资料里第四套常被称作Creative(目录cordis/)、PTC 的呈现模式写作mode: code;当前 0.2.0-rc.2 代码里呈现模式已是mode: ptc,界面名是"创造模式"。版本敏感内容以你安装的版本为准。

(至于"默认进哪个模式"——由packages/bundle/web-app/cordis.patch.yml第 574 行的agent-preset-registry决定:default: standard。)

4.1 Standard:能力基线

standard.patch.yml 就是一份"插件清单",全文约 137 行,挂载的东西包括:

  • 身份:persona(“You are a coding agent powered by the {{model}} model.”)、agent-instructions、time-context
  • 执行:tool-bash(Win 禁用)/ tool-pwsh(非 Win 禁用)、tool-fs、tool-fs-search
  • 任务:tool-jobs、tool-schedule、command-goal、tool-goal
  • 规划:plan-mode(isolate: planMode)
  • 上下文:compaction(压缩)+ tool-result-pruner(阈值 8192 字符,头 4096/尾 1024)
  • 委派:tool-subagent(spawn)、tool-subagent-fork(fork)、workflow-ptc、tool-workflow
  • 交互:tool-ask-user、tool-todo、tool-web、present

4.2 PTC:和 Standard 只差三行

把两个文件 diff 一下(这是全文最震撼的一个事实):

# 差异一、二:关掉 workflow 相关工具 - id: workflow-ptc disabled: true - id: tool-workflow disabled: true # 差异三:新增"工具呈现"插件 + - id: tool-presentation + name: '@deepseek-ai/dsh-agent-tool-presentation' + config: + mode: ptc

三行。没有第二套工具实现、没有第二套循环——PTC 改变的只是工具呈现给模型的方式(从"逐个原生调用"变成"模型写一段 TypeScript 程序批量调用")。这就是Capability ≠ Presentation(能力 ≠ 呈现)的直观含义。这个结论一会儿会被实验直接验证。

4.3 Minimal:61 行的"极限瘦身"

minimal.patch.yml 全文只有 61 行,整个 Preset 只有两项:

-id:personaname:'@deepseek-ai/dsh-persona'config:prefix:You are a helpful software engineer assistant.complete:trueincludeRuntimeContext:false# ← 关键:不注入运行时上下文-id:persistent-shell# 组:pty + 持久 bash/pwsh

翻译成人话:一个人设 + 一个持久终端。没有文件工具、没有技能、没有子代理、没有压缩,而且连运行时上下文都不注入——这条includeRuntimeContext: false就是"极简"最狠的一刀,实验中它会带来断崖式差异。

4.4 cordis(创造模式):把 Runtime 变成"可操作对象"

相对 Standard 的差异集中在技能组:

-id:tool-cordisname:'@deepseek-ai/dsh-tool-cordis'# 只读运行时 API 查询-id:skill-filesystemconfig:customSkillDirs:[.../dsh-agent-preset/skills]# 4 个专属技能-id:tool-skill

专属技能目录里是 4 个包:agent-experience、cordis-composition-reference、cordis-plugin-development、editing-cordis-compositions——从名字就能看出主题:读 Cordis 组合、写 Cordis 插件、编辑组合。再叠加 Host 侧的插件管理器,Agent 就能在授权范围内观察甚至修改承载自己的运行时组合(cordis_mount的典型流程:检查运行时 → 生成临时插件 → 挂载 → 会话获得新能力 → 验证 → 卸载)。同理,这也是信任边界而非沙箱——能力越强,越需要外层的权限、审查与恢复机制。

五、实验 1:4 个会话问同一句话

方法要点

问完之后,模型的自述不能当证据——它可能遗漏工具、把能力合并成模糊概念、甚至说错。正确做法是打开会话的"轨迹"面板,看运行时实际注入的上下文和工具调用。

先学会读"轨迹"面板

第一次打开轨迹可能有点懵,它其实长这样(以本机实测的布局为准):

  • 顶部列:时长 / 轮次 / 调用——一眼看出这轮跑了几步、调了几个工具、快不快;
  • 消息条目(按时间顺序):
    • 用户:你发的那句话;
    • 上下文:运行时实际注入的东西——第一条是 runtime context(文件策略、审批策略、工作区路径),第二条常是 skills 清单(<available_skills>...的 system-reminder);
    • 助手:模型的思考和输出;
    • 工具:工具的调用参数(JSON)与返回值;PTC 模式下会显示为工具 run_code+嵌套的"子工具"(pwsh、write 等),非常直观地展示"程序化调用";
  • 底部:用量栏(轮/步、tok/s、缓存命中、上下文占比)。

一句话:轨迹面板 = "模型这轮到底看到了什么、做了什么"的全记录。实验 1 的结论全部从这里取证,而不是从模型的回答里取证。

实测数据(同一模型 DeepSeek-V4.1-Flash,仅 Preset 不同)

观测项标准模式PTC 模式极简模式创造模式
首轮用量8.5K tok9.4K tok1.8K tok10.2K tok
轮 / 步1 / 11 / 11 / 11 / 1
缓存命中10%0%0%17%
轨迹里的"上下文"段✅ 有✅ 有❌整段消失✅ 有
模型自述的关键句列出 8 类具体工具“run_code 是唯一可直接调用的工具”泛泛而谈、无具体工具名,还误判"没有互联网访问"标准能力 +运行时检查(Inspect Provider) +插件/bundle 管理

三条硬结论(都由 Trace 佐证)

  1. 极简模式的"薄"是断崖式的:用量 1.8K vs 8.5~10.2K,差 5~6 倍;轨迹里连"上下文"段都没有——因为includeRuntimeContext: false。模型连自己有哪些工具都"说不上来"。
  2. PTC 把"呈现方式"的变化做到了极致:模型自述"run_code 是唯一可直接调用的工具"。底层工具一个没少(diff 只有三行),但模型的视角里只有一个入口。能力存在 ≠ 能力以什么形式被看到。
  3. 创造模式真实暴露了运行时工具:模型说自己能查询 Inspect Provider(服务方法、事件、配置 Schema、工具 Schema)、能管理 profile 的插件与 bundle——这不是"提示词里写的话术",而是 trace 里可查、源码里可对的真实暴露。
  4. 技能目录也是"可组合项":标准/PTC 会话的 skills 清单来自机器上已有的通用技能;创造模式会话的清单开头换成了agent-experience、cordis-composition-reference等预设专属技能——同一套技能机制,不同 Preset 挂不同的目录。

六、实验 2:同一任务,四条轨迹

方法:控制变量 + 每跑复位

  • 同一个模型、同一个空工作区、同一句任务指令;
  • 每跑结束把工作区清空复位,保证 4 次运行的初始状态完全一致。

观测表

观测项标准模式PTC 模式极简模式创造模式
模型可见工具形态原生工具逐个调用仅 run_code(子工具经程序调用)仅持久 pwsh原生工具 + 运行时工具
Model Request 次数4 步4 步5 步6 步
工具调用/派发数5 次run_code×3(内含 7 次子工具)4 次9 次
总用量34.1K tok37.4K tok9.4K tok58.9K tok
速度222 tok/s239 tok/s206 tok/s235 tok/s
Subagent/Workflow 出现否否否否
Cordis Runtime 工具暴露否否否是(未用,但已暴露)
最终结果文件✅ 行数❌文件✅ 行数❌文件✅ 行数✅文件✅ 行数✅

四跑详情(每条结论都有三重证据:轨迹 + 用量 + 文件系统复核)

① 标准模式:列目录 → 并行写 3 个文件 → pwsh 统计 → 总结。产物note-alpha/beta/gamma.txt。它报告27 行(9+10+8)——实际 41 行(15+16+10,wc -l 复核)❌

② PTC 模式:全程只发run_code,子工具(pwsh、cmd、write)由程序内部调用。一个细节:它前两次列目录被沙箱部分拦截(轨迹原文 “File sandbox enforcement is partial on this host”),多花一步探查。产物note-1/2/3.txt。报告6 行(2+2+2)——实际 9 行(3+4+2)❌

③ 极简模式:只有一个持久 pwsh,全程用命令行完成(Set-Content -Encoding UTF8)。报告6 行——实际 6 行✅

④ 创造模式:列目录 → 写 3 个文件 → pwsh 统计 →read 三个文件交叉验证→ 发现计数不对(轨迹原文:“它报每文件 2 行,而 read 显示为 3/5/2 行”)→换[System.IO.File]::ReadAllText+ 正则重算→ 报告10 行——实际 10 行✅

七、那个"行数不对"是 bug 吗?——一个真实的编码陷阱

标准/PTC 数错行,我一开始以为是 Harness 的问题,于是做了复现:在同一个文件上,Get-Content(默认)数出 9 行,Get-Content -Encoding UTF8数出 15 行,wc -l数出 15 行。

原因:本机没有 PowerShell 7,DSH 的 pwsh 工具实际执行的是Windows PowerShell 5.1。它读取UTF-8(无 BOM)中文文件时默认按 ANSI(GBK)解码,会把一部分字节两两配对成双字节字符,顺带吞掉夹在中间的换行符——中文行越多,少算越多。

所以这不是 DSH 的 bug,是一个经典的 Windows 编码坑。而这段插曲反而贡献了实验里最有趣的一组对照:

  • 标准/PTC 都直接采信了错误计数;
  • 极简模式因为内容用 ASCII + 显式-Encoding UTF8,恰好绕开了(它自己都没意识到);
  • 创造模式主动交叉验证发现了不一致并修正——多花了 2 步和约 2 万 token,把数数对了。

同一个模型、同一个任务,仅仅换一套 Harness 组合,"数得对不对"都变了。这是"Agent = Model × Harness 共同作用"最生动的一手证据。

八、为什么官方 Benchmark 选 Minimal?

实验做完之后,再来看官方 Benchmark 的设计,会特别有感。

官方BENCHMARK.md用的是 Python SDK 里jsonrpc-agent 的 Minimal variant,并且为不同任务使用独立的 Workspace 和 Session ID。目的只有一个:尽量减少额外 Harness 能力对实验的影响,让测量更接近"模型的基础任务能力"。

原因就是我们实验 2 里眼睁睁看到的:Runtime 里的能力越多,变量越复杂——Skills、Planner、Workflow、Subagent、动态 Context 都可能改变模型的执行路径(我们的四条轨迹就是活例子:步数 4/4/5/6、工具调用 5/7/4/9)。变量不固定,结果就无法只归因于模型本身。

但有一个重要提醒:Minimal 下测到的不是"纯模型能力"。只要模型跑在 Agent Runtime 里,结果永远是 Model 与 Harness 共同作用的——同一模型在 Standard 下表现更好,提升可能来自更丰富的工具与上下文;反过来,复杂 Harness 引入多余的工具调用、过量的上下文、更长的执行链,性能下降也不能只怪模型。

所以评价要分两类:

类型关注点
Model Benchmark模型本身的能力
Agent Benchmark模型接入具体 Harness 之后,Agent 系统的整体表现

“一个模型在纯模型 Benchmark 上很强"并不意味着放进任何 Agent Runtime 都同样强。研究 Agent 时,除了问"用了什么模型”,还要继续问:“这个模型运行在什么样的 Harness 中?它获得了哪些工具、上下文和执行策略?”

DSH 把 4 套 Preset 预置在脸上,恰恰就是把这些原本容易被忽略的 Harness 变量显式暴露出来——这也是我们做这两个实验的全部意义。

九、回到源码:这 4 套模式是怎么"装"进会话的?

实验现象背后的机制,源码里写得清清楚楚。打开packages/bundle/web-app/cordis.patch.yml,能看到一段注释:

# ── the agent plane moves behind agent presets ──# Web surface disables them here and lets each session mount a preset instead.# (agent 平面搬到 agent preset 之后:Web 表层在这里禁用它们,# 改为让每个会话自行挂载一个 preset。)

三个层次的机关:

  1. Host Plane(宿主层):整进程一份的共享基础设施(Tool Registry、Model Route、持久化、沙箱/审批、子 Agent 注册)——在 web patch 里挂载;
  2. Agent Plane(会话层):每个会话按所选 Preset 挂载一份"子插件树"——即上面 4 个 patch 文件的内容;
  3. 组合的叠加:Profile(web)→ Bundle(dsh-base、dsh-web-app)→ Home patch →--patch覆盖层,逐层 patch 成最终插件树。

不信可以打印整棵树:

dsh--profileweb --dump-config

我实测输出1263 行、183 条插件,并且能清楚看到 4 个 preset 各自作为声明行存在(preset-standard/preset-ptc/preset-minimal/preset-cordis),文件里还有分层注释标明"这一条来自哪一层、被谁改过"。

所以 4 套 Preset 不是 4 个 Agent,而是同一棵运行时树上的 4 种"挂载方案"——这在实验 1 里的直接体现就是:会话间共享同一个模型路由和存储,但每个会话的上下文段、工具清单、技能目录都不同。

十、结论与心得

  1. 预期结论在实验里全部复现:PTC 只改了呈现(模型只见 run_code);Minimal 真的"薄"(无上下文段、1.8K 用量);创造模式真的能"看运行时"。
  2. PTC 不是无条件更快:本跑 PTC 37.4K tok,比标准模式 34.1K 还多——因为沙箱探查多花了步骤。"减少 round trip"是设计目标,不是性能保证,收益取决于任务是否适合程序化编排。
  3. Minimal 便宜且在本任务里准,但有运气成分(ASCII 内容恰好躲开编码坑)——这正说明官方 Benchmark 选它做基线的意义:变量最少,最容易把"模型本身"从"Harness 加成"里分出来。
  4. 取证意识是这次实验的最大收获:模型自述 ≠ 事实;轨迹 + 用量 + 文件系统才是证据。这条方法论比任何一个具体结论都值钱。

十一、常见问题(FAQ)

Q1:打开127.0.0.1:3080提示 401?
A:少了启动时打印的?token=xxx。用终端给出的完整链接访问,"默认工作区"和会话数据都在C:\Users\<你>\.dsh\。

Q2:极简模式为什么"连上下文都没有"?
A:源码里写了includeRuntimeContext: false,且不启用压缩。它就是刻意做成"Model + 极简 Harness"的观察基线——少,就是它的设计目的,不是配置错误。

Q3:PTC 到底快不快、省不省?
A:不一定。它的设计目标是减少"模型与工具的多次往返"(round trip),但收益取决于任务是否适合程序化编排、模型生成代码的质量、工具返回的数据量。我这次实测甚至比标准模式略贵——它是"一种更适合批量的工作方式",不是性能承诺。

Q4:为什么"数行数"三种模式结果不一样?
A:见第七节——PowerShell 5.1 的 GBK 编码陷阱。中文文件 + 默认Get-Content= 少算。写脚本统计时请显式-Encoding UTF8,或改用 ASCII 内容,或用File.ReadAllText原始层计数。

Q5:点"添加工作区"报directoryPicker failed/ 无法打开文件夹?
A:服务端弹原生对话框失败,常见于后台/非交互启动的 dsh。用默认工作区做实验,或在普通终端重启 dsh 后再添加。

Q6:我复现出来数值不一样?
A:正常。模型版本、推理等级、机器速度都会影响数值。看差异的方向(比如极简模式用量断崖式下降、PTC 模型只见 run_code),而不是盯绝对数字。

十二、自己复现这两个实验(步骤清单)

  1. 装好 dsh(第二节任一方式),dsh web启动,配好模型;
  2. 在默认工作区(或任意空目录)里做实验,别拿生产目录冒险;
  3. 实验 1:新建 4 个会话 → 各选一种模式 → 问同一句话 → 打开每个会话的"轨迹",截图"上下文"段和用量;
  4. 实验 2:确认工作区为空 → 4 个会话各跑一次任务 →跑完清空工作区再跑下一个→ 记录 7 项观测(步数、工具调用、token、是否正确),并到文件系统里wc -l复核行数;
  5. 对比你的数据和本文数据(你的模型/版本不同,数值会有差异,但差异的方向应该一致)。

附:本文证据截图清单(发布/存档时可对照)

  • 实验 1 创造模式轨迹(Creative轨迹)

  • 实验 2 四跑轨迹




参考

  • DeepSeek Harness 官方仓库:github.com/deepseek-ai/deepseek-harness(源码引用基于 v0.2.0-rc.2;preset 文件在packages/bundle/web-app/presets/)
  • 官方 BENCHMARK.md 与 Python SDK 文档(Minimal variant 的设计说明)
  • 官方文档站:deepseek-harness.github.io/deepseek-harness/

本文全部数据来自作者本机 2026-10-14 的真实运行(Windows + Node 24 + dsh 0.2.0-rc.2 + DeepSeek-V4.1-Flash),实验工作区每跑后已复位。DSH 迭代很快,版本敏感内容请以你安装的版本为准。

RELATED READING

延伸阅读

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