专题篇章 · 拆开 DeepSeek Harness

Skill、Preset 与自我修改

cordis_define 让 Agent 在运行时改写自己的运行时

本页解决的问题

先给结论

「Skill、Preset 与自我修改」要解决的关键问题是什么?

cordis_define 让 Agent 在运行时改写自己的运行时

判断标准

让这个结论先证明自己值得留下。 把这一页当成决策工具,而不是需要背下来的定义。把概念连到一个真实任务、一个可观察结果,以及一个能改变你判断的失败上。

下一步

写下一个问题:试完这个方法后,你能用什么证据回答它?

常见误区

结论听起来很完整,却没有检查最关键的假设。

课程目标读完你能说清三件事:发布文里的「标准 / 代码 / 极简 / 创造」四种模式为什么只是四份 YAML;创造模式里 Agent 怎么用 cordis_definecordis_run 在运行时给自己长出新工具,以及这套自我修改的信任边界画在哪;skill 分层注册表里 preset 层怎么遮蔽全局层。
交互演示 · 一次自我修改的全程

场景:创造模式(cordis preset)的会话里,用户说「给我做一个统计代码行数的工具」。左边是运行时的实时状态,右边是 Agent 的动作,跟着字幕走一遍。

0 / 8

插件登记簿(Plugin / Package)

loc · Package v1未定义
loc · Package v2未定义

工具目录

bashstr_replacesubagentcordis_inspect_querycordis_definecordis_runloc_count

Agent 的动作

cordis_inspect_query → 读 Service 与 Builtin 的精确签名
cordis_define kind:"new" → 返回 pluginId=loc / packageId=v1
cordis_run mode:"run" → v1 激活,loc_count 进目录
工具集变了 → 日志记录变更后的完整请求头
loc_count → 结果把空行也算进去了,要改
cordis_define kind:"existing" → 追加 v2,v1 原样保留
cordis_run mode:"update" → 切到 v2,失败可回滚 v1
把插件行写进 ~/.dsh/.agent-presets/my-mode/ → 第五种模式
点「播放」,看 Agent 怎么在运行时给自己长出一个新工具。
演示为教学化模拟,流程依据 packages/extensions/tool-cordis/src/index.ts 中 cordis_define 与 cordis_run 的工具描述原文(第 148 至 259 行)整理,核对日期 2026-08-13。
逻辑拆解 · 模式只是一份 YAML

先解发布文那个悬念:标准、代码、极简、创造四种模式,在源码里找不到一行模式分支。apps/cli/config/agent-presets/ 下就是四个目录,每个目录一份 agent.cordis.yml,一份文件描述一种插件组合,给一个会话挂载。极简模式全文 62 行:persona 一句「You are a helpful software engineer assistant.」加 complete: true(拒绝任何后续拼装往提示词里加料),工具只有持久 bash 和编辑器,连压缩都没有,这是拿来跑基准测试的配置。创造模式则是标准模式原封不动,多挂三样:自指工具集 tool-cordis、一个教写组合的 skill、一段教模型分清两个平面的 persona。

两个平面是这套体系的坐标系。HOST 组合放跨会话共享的东西:持久化、沙箱与审批、模型路由、subagent 注册表。AGENT PRESET 放一个会话贡献给这些注册表的东西:它的工具、persona、提示词段落。有个细节能看出边界画得多细:preset 里发布服务的行,要么归 host,要么包进 isolate realm。极简模式想用不带沙箱的本地文件系统,就把 fs-local 包在自己的 realm 里,只遮蔽自己这个会话的 fs,别的会话照旧走沙箱(minimal/agent.cordis.yml 第 46 至 57 行)。

skill 也是分层的。全局层放部署级注册的(仓库插件),preset 层放随 preset 走的,读取时近层同名直接赢,排序权重只在同一层内起作用。创造模式那个 editing-cordis-compositions skill 就住在 preset 目录里,跟着 preset 被复制和编辑,理由写在 yml 注释里:它描述的是这个部署的两个平面,preset 才是被复制的单位(cordis/agent.cordis.yml 第 248 至 254 行)。设计记录里还专门否决过跨层合并排序的方案,遮蔽必须干脆,不然模型看到两个同名 skill 会无所适从(.agents/notes/implemented/architecture/2026-08-09-layered-skill-registry.zh.md)。

HOST 组合 · 跨会话共享 持久化 · 沙箱与审批 · 模型路由 · subagent 注册表 skill 注册表 · 全局层 部署级 skill,被近层同名条目遮蔽 四份 preset YAML standard · code · minimal · cordis 每份 = 一个会话的插件组合,含自己的 skill 层与 isolate realm 创造模式的自我修改闭环 cordis_inspect_query 读运行时 cordis_define 只记录源码,不执行 cordis_run 激活不可变 Package 失败:currentPackageId 不动,可回滚 满意:落盘成新 preset 目录 发行版 preset 目录一个字不许改 模式没有专门代码,模式 = 插件组合;自我修改改的也是同一种东西:往组合里加行、减行
教学化结构图:节点与连线用于解释源码关系,内容经过课程化整理。
define 不执行

cordis_define 只校验参数和语法、把源码记成一个不可变 Package,不申请审批、不执行、不动 currentPackageId。要让它跑起来,得再调 cordis_run。定义与激活分开,改坏了才有得回滚。

失败不动指针

cordis_run 只在完全成功后才切 currentPackageId;启动失败时旧 current 原地不动。改版本用 kind:"existing" 追加新 Package,旧版本永远保留,回滚就是 run 一个旧 ID。

边界是信任

创造模式文件头原话:「Treat a session on this preset as shell access」。模型写的 JS 贴着活运行时跑,没有沙箱兜底,防线画在谁能用这个 preset 上,代码本身不设围栏。

关键证据 · 文件头的警告与近层遮蔽

第一段证据是创造模式 YAML 的文件头。前八行讲它是什么:标准模式加自指工具集。后四行是信任声明,把「当 shell 权限对待」写进了配置文件的注释里:

apps/cli/config/agent-presets/cordis/agent.cordis.yml第 1 至 12 行
# The `cordis` agent preset: the standard coding agent, plus the ability to
# read and write the runtime it is running in.
#
# It exists so a person can ask an agent to author another agent. Everything in
# `standard` is here unchanged; what is added is the self-referential Cordis
# toolset, a skill that teaches composition authoring, and a persona that says
# which of the two planes an edit belongs to.
#
# TRUST: `cordis_mount` evaluates model-written JavaScript against the live
# runtime, and a composition this agent writes becomes a preset other sessions
# mount. Treat a session on this preset as shell access — the toolset's own
# documentation makes the same statement.
源码快照说明:依据本地仓库 deepseek-harness-master,核对文件 apps/cli/config/agent-presets/cordis/agent.cordis.yml,核对日期 2026-08-13。代码块保留源码原文。

第二条证据是 skill 注册表的合并读取,逻辑不贴代码也说得清。collectFresh 把所有层排成一列:全局层排最前,preset 作用域链按远祖先在前、本层最后依次跟上。然后按顺序把每一层的条目灌进同一个 Map,键是 skill 名字。Map 的天性就是后写的覆盖先写的,所以近层同名条目自动替换远层,遮蔽就是一次 Map.set,没有任何跨层的权重比较。函数头上的注释把这条规则和工具注册表的遮蔽规则对齐了,还补了一句:排序权重只在同一层内对重名起作用。

出处:packages/skill/skill/src/index.ts 第 552 至 566 行的 collectFresh,核对日期 2026-08-13。

还有两条机制值得记住,出处写在这里。其一,动态插件让工具集中途变了形状时,会话日志会记录变更后的完整请求头,维持「模型看到的 ⟺ 日志里的」不变量(.agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.zh.md)。其二,persona 明令 Agent 绝不许编辑发行版 preset 目录:升级会整个覆盖它,而且改坏 cordis preset 等于亲手关掉自己所在的模式,要改就复制出去改副本(cordis/agent.cordis.yml 第 27 行)。

横向对比 · 一份配置描述角色 vs 一整包插件组合角色

Claude Code 定义一个角色,用的是一个带 frontmatter 的 markdown 文件:写清 description、可用工具、model,AgentTool 的调用参数还能临时覆盖 frontmatter 里的 model 字段(书稿 study/chapters/05-multi-agent.md 第 32 至 38 行引 AgentTool.tsx 的 inputSchema)。Skills 同理,一个目录一份 SKILL.md。这条路线是「配置描述一个角色」:角色能差异化的维度,取决于框架在 frontmatter 里开放了哪些字段。

DSH 的 preset 是「整包插件组合一个角色」:persona 只是组合里普通的一行插件,和工具、压缩策略、subagent 后端平起平坐。极简模式甚至能换掉整个文件系统实现、关掉压缩,这种深度的差异化在 frontmatter 字段里表达不出来。代价也直白:写一份 preset 要懂两个平面和 isolate realm,门槛比写一份 markdown 高得多,所以创造模式才要随身带一个教学 skill,再配一个能读运行时的 cordis_inspect_query。一边是低门槛的角色卡,一边是全功率的组合语言,两家对写角色的人是谁,想得很不一样。

课堂练习
01

推演两个边界场景

其一:创造模式的 Agent 一时糊涂,直接编辑了发行版的 cordis/agent.cordis.yml 并且改坏了,下一个想用创造模式的会话会发生什么?persona 第 27 行为什么把复制出去改副本写成铁律?其二:你自己组装第五种模式时,把两份 preset 都想发布的同名服务行都留在了各自文件里且都没包 isolate realm,两个会话同时挂载会怎样?提示:回看极简模式是怎么用 realm 遮蔽 fs 的。

Takeaway:模式 = 一份 YAML 描述的插件组合,自我修改 = 在运行时往这个组合里加行减行。define 只记录、run 才激活、失败不动指针,三条纪律让「Agent 写 Agent」有得后悔。安全不靠沙箱靠信任边界:给谁开创造模式,等于给谁开 shell。

「交互演示 · 一次自我修改的全程」的能力藏在每次交接里

「场景:创造模式(cordis preset)的会话里,用户说「给我做一个统计代码行数的工具」。左边是运行时的实时状态,右边是 Agent 的动作,跟着字幕走一遍」说明,Agent 的表现不只由模型决定。模型、上下文、工具、状态、权限和人之间的每次交接,都会改变任务能否继续以及出了问题能否恢复。

先写清状态,再增加能力

从「先解发布文那个悬念:标准、代码、极简、创造四种模式,在源码里找不到一行模式分支。」出发,可以把流程拆成起始状态、下一步动作、工具返回、状态更新和停止条件。这样调试时找的是第一处丢失信息或权限的位置,而不是笼统地说“模型变笨了”。

成功路径不能代表系统可靠

用「其一:创造模式的 Agent 一时糊涂,直接编辑了发行版的 cordis/agent.cordis.yml 并且改坏了,下一个想用创造模式的会话会发生什么?persona 第 27 行为什么把复制出去改副本写成铁律?其二:你自己组装第五种模式时,把两份 preset 都想发布的同名服务行都留在了各自文件里且都没包 isolate realm,两个会话同时挂载…」重放一次成功和一次失败,记录每一轮真正传入的上下文、工具结果和负责人;只要第二个人能复述这条链,系统才有可维护性。

从「交互演示 · 一次自我修改的全程」走到「逻辑拆解 · 模式只是一份 YAML」

「交互演示 · 一次自我修改的全程」先把问题落在「场景:创造模式(cordis preset)的会话里,用户说「给我做一个统计代码行数的工具」。左边是运行时的实时状态,右边是 Agent 的动作,跟着字幕走一遍」上;到了「逻辑拆解 · 模式只是一份 YAML」,讨论继续推进到「先解发布文那个悬念:标准、代码、极简、创造四种模式,在源码里找不到一行模式分支。 apps/cli/config/agent-presets/ 下就是四个目录,每个目录一份 agent.cordis.yml ,一份文件描述一种插件组合,给一个会话挂载。极简模式全文 62 行:persona 一句「You are a helpful software engineer assistant.」加 complete: tr…」。两段连起来,重点就不只是记住一个结论,而是看清它成立所依赖的条件。

把这条判断带到下一个场景

分析 Agent 时,沿着状态、动作、工具结果和下一步的顺序走一遍;每次交接都要能说明信息从哪里来、由谁确认、失败时停在哪里。

  • 「交互演示 · 一次自我修改的全程」:场景:创造模式(cordis preset)的会话里,用户说「给我做一个统计代码行数的工具」。左边是运行时的实时状态,右边是 Agent 的动作,跟着字幕走一遍
  • 「逻辑拆解 · 模式只是一份 YAML」:先解发布文那个悬念:标准、代码、极简、创造四种模式,在源码里找不到一行模式分支。 apps/cli/config/agent-presets/ 下就是四个目录,每个目录一份 agent.cordis.yml ,一份文件描述一种插件组合,给一个会话挂载。极简模式全文 62 行:persona 一句「You are a helpful software engineer assistant.」加 complete: tr…
  • 「最后的要点」:创造模式文件头原话:「Treat a session on this preset as shell access」。模型写的 JS 贴着活运行时跑,没有沙箱兜底,防线画在谁能用这个 preset 上,代码本身不设围栏

最后的「最后的要点」把讨论落到「创造模式文件头原话:「Treat a session on this preset as shell access」。模型写的 JS 贴着活运行时跑,没有沙箱兜底,防线画在谁能用这个 preset 上,代码本身不设围栏」。回看这条线索时,最值得保留的是:当输入、规模或风险改变,哪些判断需要重新做一遍。

标记为已学完 阅读进度会自动记录
← 上一篇下一篇 →

继续阅读

同一条线上的下一篇。

文章讨论

读到这里,留下一个判断。

把刚想明白的地方、还没想通的问题,留给下一位一起学习的人。

正在讨论 Skill、Preset 与自我修改 拆开 DeepSeek Harness
3条讨论文章讨论 · 与共学社区同步
在共学社区查看
AM
Asha Morgan内容编辑
观点实践记录

我把这篇文章里的一个判断改写成了今天可以验证的小实验。比记住结论更有用的是,知道下一步要观察什么。

文章讨论7 有帮助
LH
Lin Harper独立开发者
观点观点

读完以后我先回头找它成立的条件,而不是直接把方法搬进项目。这个顺序让后面的取舍清楚很多。

文章讨论5 有帮助
KM
Kiki Moore产品运营
问题问题

如果把这个判断放到真实工作里,最先需要补的约束是什么?我想知道从阅读到第一次实践之间,哪一步最值得先做。

文章讨论4 有帮助