Skip to content

4.3 Agent Preset 与作用域组合

本章概览:如何让"不同会话拥有不同能力集合"——agent preset 的组合机制、dsh-scope 的作用域分层(agent → preset → global),以及子代理如何继承父组合。

preset 是什么

一个 preset 是存放一份 agent.cordis.yml 的目录。roster(ctx.agentPresets)在进程内以 standing scope 挂载一次;每个选择该 preset 的会话,其 agent 作用域 key 通过 dsh-scope 的父链父级化到该挂载上。

要点(详见 1.3 配置树):

  • 发现即读盘list() / resolve() 每次重读根目录;
  • 健康检查:组合缺失/不可加载的目录以 broken 原因列出;
  • 默认 idctx.agentPresets.defaultId,未命名时挂载的 preset。

出处:packages/preset/agent-presets/README.mddeepseek-harness-src/packages/preset/agent-presets/README.md

dsh-scope:作用域分层

dsh-scopecore/scope)是按 agent 划分作用域的注册原语。注册落进"调用上下文作用域所在的层":

  • 宿主/仓库插件行 → global 层
  • preset standing 组合挂载的插件 → preset 层
  • 通过 agent.ctx 的注册 → agent 层

读取合并"global 层 + 查看者作用域的链",解析顺序 agent → preset → global(最近者遮蔽最远者,同层重名才按 rank 决定)。ctx.toolsctx.systemPromptctx.skills 等都按此形状分层。

出处:packages/core/scope/README.mdpackages/core/tools/README.md

mount 与 recompose

  • ctx.agentPresets.mount(agentCtx, id?):组合一个 agent——确保 standing 挂载(single-flight),并把 agent 的作用域 key 父级化到它,返回 preset 供调用方记录。唯一支持的调用点是 agent 工厂的 setup(agentCtx) 钩子:只有在那里,agent 尚未发布,被拒绝的组合会把整个创建回滚,而不是留下半组合的会话;
  • ctx.agentPresets.recompose(agentCtx, id):把 agent 重链到另一个 preset 的 standing 组合。仅在 agent 未产生任何内容时有效(调用方负责检查);新挂载先确保成功再移链,失败保持原状。因为两个组合会向同一层注册同名工具,不能共存——recompose 先卸载旧子树再挂载新子树;
  • 组合代次:每个代次记录组合文件的 stamp(mtime + size);文件变更使下一会话起新代次,已加入的会话继续用自己运行的那代——运行中会话的组合在其文件变化/消失后仍然存活。

子代理继承:composeFrom 而非 mount

子代理通过 ctx.agentPresets.composeFrom(agentCtx, parentCtx) 绑定父代理的 standing 组合,绝不重新 mount:

  • 所有模型可见行都在 agent 平面上——工具注册表的 global 层是空的,子代理若不绑定,将带着空工具注册表(且没有父代理的任何提示片段)到达模型
  • 重挂载父 preset 会产生两个问题:文件编辑后会给孩子不同代次;preset 被删除后孩子直接失败。绑定是同步的,这是进程内 subagent 驱动能在同步创建窗口内组合孩子的原因;
  • 孩子把加入的 preset id 记录在自己的持久 header 上——冷读孩子历史时重建它实际运行过的组合,而非部署默认。

出处:packages/preset/agent-presets/README.mddeepseek-harness-src/packages/preset/agent-presets/README.md

会话运行哪个 preset

  • 创建 header 记录会话开始时的 preset;resolveSessionPreset(session) 得出它运行的 preset——两者在空白会话切换后不同,所以恢复、fork、picker 摘要都走解析而非读 header;
  • 切换是会话事件agent-preset/selected 在交换提交后追加——preset 决定模型看到的工具 schema 与提示片段,必须可从日志重建(模型可见 ⟺ 已记录);
  • 该提交事实还会以非作用域的 cordis 事件 agent-preset/selected(sessionId, agentPreset)(client-safe ./types 导出)重发,允许远程消费方使会话派生状态失效。

关键设计决策

决策理由
standing mount 一次、多会话共享工具的挂载与提示片段只存在一份,会话以 Session/Agent 为 key 保持隔离
子代理绑定(composeFrom)而非挂载同步、无组合失败模式、孩子与父运行同一代次
文件 stamp 决定代次文件是唯一组合编辑器;stamp 把编辑带到后续会话
切换仅限空白会话已有内容的会话重组合会重放历史到新工具集无法行动的局面

小结

preset + scope 分层让"能力集合"成为会话级变量:进程级组合包定产品形态,preset 定会话能力,agent.ctx 定个体差异,子代理继承父组合。这是 DSH 实现"子代理能力与父一致"的关键机制。

参考资料

本文档为学习用途的原创讲解,基于 MIT 许可的开源项目 deepseek-ai/deepseek-harness 编写;所有引用均注明出处。