一个 DeepSeek Harness 预设就是一个目录加两个小 YAML 文件。本篇从零造一个只读代码审查员——shell 硬禁用、审查员人设到位——文中每个片段都逐行对照过官方内置预设的真实格式,不是凭记忆转述。
<你的预设id>/
├── agent.cordis.yml # 组合本体——必需,这个文件就是预设
└── preset.yml # 选择器展示元数据(name/description/order)
设计笔记把两件事变成了官方规则:
[a-z0-9][a-z0-9-]*——小写、连字符、无空格。校验发生在目录名被使用之前。铁律现在是官方规则。 内置预设拒绝写入和删除——部署自带的副本就是坏掉的本地预设的对照参考。官方支持的创作路径,笔记原话:“duplicate, then edit”(复制,然后改)。
npx @deepseek-ai/dsh web # UI 在 http://127.0.0.1:3080
不确定你的构建实际启动了哪些插件行?这条命令打印完整组合树,而且它打印出的任何一行都可以被你自己的 patch 替换:
dsh --profile web --dump-config
把 standard(或想要最小基线就复制 minimal)复制到 dsh home 下的预设根目录——社区文档记载为 $DSH_HOME/.agent-presets/——命名为新 id:my-reviewer。roster 通过文件系统扫描发现用户自建预设。
preset.yml 决定选择器里显示什么。内置预设自己就是这么用的(对,官方显示名就是中文):
name: My Read-Only Reviewer
description: Reads everything, executes nothing. Findings sorted by severity.
order: 10
order 决定选择器排序——内置四套占了 1–4,你的从 10 开始。
agent.cordis.yml 是一列行(row)。每行有本地 id、指向真实包名的 name、可选的 config。三种形态覆盖几乎所有场景:
persona 行——身份是一个可组合的包,不是一段提示词字符串:
- id: persona
name: '@deepseek-ai/dsh-persona'
config:
text: |-
You are a staff-level code reviewer. You never run or modify code.
Report findings as BLOCKER / MAJOR / MINOR / NIT, each with file:line
and a concrete suggested fix.
工具行——只挂 agent 应该看到的:
- id: tool-fs
name: '@deepseek-ai/dsh-tool-fs'
- id: tool-fs-search
name: '@deepseek-ai/dsh-tool-fs-search'
禁用是结构性的。 disabled: true 让这一行在本预设中不挂载——不是劝模型别用,是根本不在。一个绝不能执行任何东西的审查员:
- id: tool-bash
name: '@deepseek-ai/dsh-tool-bash'
disabled: true
你最常用到的真实包名词汇表:dsh-tool-fs、dsh-tool-fs-search、dsh-tool-str-replace-editor、dsh-tool-bash、dsh-tool-web(config 含 fetch 和 searchTimeoutMs)、dsh-tool-skill、dsh-tool-goal、dsh-tool-todo、dsh-tool-ask-user、dsh-tool-jobs、dsh-persona、dsh-agent-instructions。内置的 standard/agent.cordis.yml 是权威目录——先读它,再发明 id。
顺带一提:四套内置预设的官方中文名是 标准模式(order 1)、PTC 模式(order 2,即英文说的 Code mode)、极简模式(order 3)、创造模式(order 4)——中文语境里大家说的 “PTC” 是官方命名,不是社区绰号。
有些能力以组的形式出现:一个带 isolate realm 的 cordis:group 行加子行。计划模式和委派都会遇到:
- id: planning
name: cordis:group
group: true
isolate:
planMode: true
config:
- id: plan-mode
name: '@deepseek-ai/dsh-plan-mode'
realm 规则是强制的、不是建议:组外的服务行会发布进进程全局的 root realm,挂载时会直接拒绝,而不是放任两个会话相撞。复制内置预设时,保持它的组结构不动。
新开一个会话并选择你的预设。然后测边界,别只测 happy path:
preset.yml 里的名字。设计笔记给出的两条切换规则:只能在会话还是空白时选预设(一旦跑过一轮,历史是在那套工具下产生的,host 会拒绝换装);恢复会话时重建的是它创建时的组合——preset id 随会话头持久化。你改文件只影响下一个会话,绝不动正在运行的。
如果包名不被识别,多半是拼写错误或包被改名——--dump-config 列出你的构建里真正能解析的东西。
权威范例就是官方的 standard/agent.cordis.yml——复制它、保持组结构不动、逐行裁剪,直到工具集恰好是你想要的 agent 形态。(本站也在筹备一个精选社区目录,等每个预设都在真实安装上验证过后就会上线。)