news 2026/9/18 22:57:24

DeepSeek Harness 计划模式(Plan Mode)完全指南:per-agent 协作状态、配置与受审退出机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DeepSeek Harness 计划模式(Plan Mode)完全指南:per-agent 协作状态、配置与受审退出机制

DeepSeek Harness 计划模式(Plan Mode)完全指南:per-agent 协作状态、配置与受审退出机制

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

导读:Plan Mode 是 DeepSeek Harness 提供的一种按 Agent(per-agent)持久化的协作状态——开启后,Agent 在"先探索与设计、后执行"的引导下工作,并把完整方案通过exit_plan_mode工具提交给人类审批。本文以.agents/notes/archived/feature/2026-07-07-plan-mode.md这份设计文档为骨架,结合当前仓库中落地实现的@deepseek-ai/dsh-plan-mode包(位于 packages/plan/plan-mode)、docs/subsystems/plan.md 子系统参考、工具目录与配置目录,完整讲解其设计动机、当前简化后的契约、配置方式、命令行用法、底层事件折叠原理,以及它与沙箱、审批等强制轴的边界。

Plan Mode 的核心思想可以用一句话概括:模式是"软"的——它只通过提示词引导模型,从不自行执行任何限制;真正的强制力来自独立的沙箱模式与审批策略两个轴。理解这条"软引导 + 独立强制"的边界,是正确使用和部署 Plan Mode 的前提。

1. 背景与设计动机:为什么需要一种"具名的会话模式"

在设计 Plan Mode 之前,DeepSeek Harness 缺少一种持久化手段,让某个 Agent 进入一种可区分的"工作姿态"(working stance)。设计文档(2026-07-07-plan-mode.md)明确指出,Plan Mode 需要同时满足四个要求:

  1. 在规划引导下探索与设计:模型在执行前先产出可评审的产物(plan artifact);
  2. 跨越明确的审批边界:方案必须经过人类显式同意才能进入执行;
  3. 可复现(reconstructable):会话恢复(resume)或派生(fork)时,模式状态必须无额外机制地还原,且不能让模型可见的请求与会话日志发生偏离;
  4. 与既有扩展接缝协作system-prompt/assemble负责按步装配引导;ctx.userInteraction承载审批提问与纠错反馈;SessionEventMap承载持久的 per-agent 事实。

围绕这些接缝,原设计提出了一套泛化命名模式注册表(generic named-mode registry)mode/set事件、ctx.modes服务、ModeConfig.modes定义映射、dsh-mode包。但后续的简化决策(2026-07-22-plan-specific-collaboration-state.md)发现:产品只发货了plan这一个模式,泛化 API 的所有"未来可能"支持(模式名校验正则、保留名规则、ctx.modes.list()、已退休定义回退)都是无人消费的维护负担,而且 "mode" 一词横跨了多个不相关领域——沙箱模式是ctx.sandboxPolicy拥有的强制执行策略,plan 模式是贡献引导与受审退出的协作姿态,二者不应被塞进同一个命名模式抽象。

因此,当前仓库中的落地形态是plan 专属的产品包

  • 包名:@deepseek-ai/dsh-plan-mode,位于 packages/plan/plan-mode;
  • 持久事实:plan/mode: { active: boolean }(替代原设计的mode/set: { mode: string });
  • 折叠函数:foldPlanMode(events),空日志默认值为false
  • 服务:ctx.planMode.get(agent)返回{ active, pending? }set(agent, active)记录边界应用的选择;
  • 提示词区块:固定的plan:policy(替代mode:policy);
  • 命令与工具:/plan [message]/plan offexit_plan_mode

设计历史说明:原文档中描述的泛化mode/setctx.modesModeConfig.modes定义映射等 API 属于已被简化决策取代的历史设计,当前仓库不再提供;exit_plan_modeplan/mode才是现行契约。阅读本指南时请以"当前实现"一节为准。

2. 当前实现:Plan Mode 的设计契约

2.1 状态是日志的纯函数,而非实时镜像

Plan Mode 的持久状态是一个 log-only、whole-value-replace(整值替换)的会话事件

plan/mode: { active: boolean } // SessionEventMap 成员:仅写日志、非表面(non-surface)、 // 整值替换——日志中最后一个值即当前状态 DEFAULT = false // 空日志(无 plan/mode 事件)的折叠结果

foldPlanMode(events, end?)返回前缀中最后记录的值,不存在时返回false。因为会话日志即事实通道,所以:

  • 恢复(resume)与派生(fork):子代理的 fork 继承父代理日志中的plan/mode,无额外机制;新 spawn 的代理从非活动状态开始(无创建期 mode 选项,见下文限制);
  • 压缩(compaction)plan/mode不是表面节点,压缩无法遮蔽它;
  • UI 观察:通过session/event读取提交的模式翻转,没有agent/*实时镜像可订阅。

这个设计正是从"命名模式注册表"简化后保留不动的部分——原文档强调"折叠状态是 per-agent 的、日志独有且非表面、压缩无法遮蔽",简化后由plan/modefoldPlanMode继续承担。

2.2 待定选择与步边界(pre-step)追加

由于每个会话事件都被回合(turn)包围,一个用户选择不能立刻写入日志,而是保持pending状态,直到下一个被接受的 in-turnagent/pre-step在请求装配前追加它。具体行为(见 docs/subsystems/plan.md 与 src/index.ts):

  • set(agent, active)记录待定选择;若目标与"已记录或已待定"状态相同则为 no-op;
  • get(agent)返回{ active: boolean; pending?: boolean }——当前步装配所用的记录状态 + 等待追加的选择状态;
  • 运行中 Agent 唯一的追加点是前置的agent/pre-step监听器:它观察每一个提议的请求步(包括第 1 回合第 1 步与请求恢复重试),先调用下游监听器,只有步被接受后才追加plan/mode
  • 追加失败不能阻塞回合,选择保持 pending 等待后续被接受的 in-turn pre-step;
  • 用户选择追加时,仅当最后记录的request/header描述了相反状态,才追加一条插件来源的user/message通知("用户将此会话切换到了 plan 模式")——净零翻转(plan 后又切回)不产生任何通知,首个请求前设置的模式不通知(区块本身就是状态陈述),工具驱动的退出通过其自身的工具结果叙述。

set的返回语义(来自 docs/subsystems/plan.md 的 Cordis API 目录)为:'committed'(已立即记录)、'queued'(等待下一个被接受的 in-turn pre-step)、'cancelled'(清除了相反的待定选择,记录状态已匹配)、'noop'(已在目标状态)。

2.3 软层:计算区块 + 稳定退出工具

Plan Mode 的整个"表面"都是软的:

  • 提示词区块:注册{ name: 'plan:policy', order: 500, text: context => … },从AssembleContext.agent读取调用代理的模式,解析为配置引导文本或空串。active 时精确渲染部署配置的section文本(first-party order 500),inactive 时贡献空文本;
  • 稳定工具目录exit_plan_mode通过ctx.tools注册一次,在 plan 模式 inactive 时也保持注册,因此进入/退出 plan 模式只改变request/header中的提示词部分,原生工具 schema 与 Code Mode 的 PTC SDK 保持逐字节不变(tool-catalog 目录明确记录:"exit_plan_mode stays in the model-facing schema while planning is inactive so transitions add no tool-catalog churn on top of the plan-policy change",见 docs/tool-catalog.md);
  • 不设执行门禁:没有任何tools/pre-execute监听器,模式本身不拦截任何工具调用。

2.4 受审退出:exit_plan_mode

exit_plan_mode是 Plan Mode 与人类之间的结构化过渡,其完整契约:

  1. 参数:唯一必填参数plan: string——方案以 markdown 书写且必须以#标题开头;
  2. 前置校验:无调用代理(agent-less)时拒绝执行(沿todo_write先例);折叠模式非 active 时拒绝;空方案或无标题方案在提问前拒绝;
  3. 评审:通过 user-questions 接缝发起单选评审Approve/Keep planning+ 自由文本反馈),detail携带完整方案原文;
  4. 通过条件只有恰好一个、且无自定义文本的Approve选择表示同意,其余任何形态都 fail closed——评审未提供或失败时调用同样失败,退化为人工/plan off,绝不出现未受审退出;
  5. 批准后:记录一条 silent(不叙述)的 pending 退出选择,由下一个被接受的 in-turn pre-step 追加;plan 引导在当前工具批次的剩余部分仍然有效,工具结果本身报告状态转换;
  6. 保持规划(Keep planning):返回携带用户反馈原文的 correctiveisError,模式保持在 active,模型修订后重新提交。

渲染意图上,presentCall是一个以方案首个标题为卡题、方案 markdown 为内容的 generic 卡片,随后是 generic 结果卡片。关于视觉渲染、token 与 KV Cache 影响,packages/plan/plan-mode/README.md 的 "Model Experience" 章节有逐项说明:inactive 不增加 token;进入/退出改变 first-party order 500 之后的系统提示词,因此从该点开始的缓存路径会变化,但工具目录不再抖动。

3. 部署配置:一行 YAML 开启 Plan Mode

Plan Mode 的定义是经过校验的插件 Config,遵循仓库惯例,无需改代码即可从cordis.yml变更。当前唯一必填配置是引导文本section——任何多余字段都会在加载时失败:

- name: '@deepseek-ai/dsh-plan-mode' config: section: | You are in plan mode. Explore and design before presenting the complete plan through exit_plan_mode.
字段默认值含义
section必填plan 模式激活时以plan:policy提示词区块渲染的引导文本

校验规则(docs/subsystems/plan.md 与 docs/config-catalog.md):

  • section缺失、空白或非字符串,以及任何未知键,都在插件加载时失败,而不是被静默忽略;
  • 包本身不内置任何模型指令——规划行为的全部引导都来自部署方提供的文本;
  • 当前没有泛化的模式定义映射,也不支持通过配置添加第二个模式(原设计中"additional modes use the same config map"的泛化能力已随简化决策移除;未来若出现第二个协作姿态,将是一次显式设计决策而非配置项)。
/** Deployment-owned plan guidance. */ interface PlanModeConfig { /** Guidance rendered as the `plan:policy` prompt section while plan mode is active. */ section: string }

4. 命令行与前端使用:/plan、/plan off 与评审

4.1 命令契约

ctx.commands被组合时,插件注册/plan [off|message](详见 packages/interaction/commands/README.md 与 src/index.ts):

输入行为
/plan选择 active(进入 plan 模式)
/plan <message>先选择 active,再把去除首尾空白后的消息通过agent.steer()提交,使其成为受影响步中的一条普通已记录用户消息(在 plan 引导之下);图片附件随 steered 消息一并携带
/plan off选择 inactive,不经过模型输入直接退出;也能取消一个尚未生效的待定进入选择;带图片的/plan off被拒绝以免图片丢失

命令名与结果不进入模型历史;只有显式的消息体作为普通用户消息被记录。命令在任何支持斜杠命令的前端可用,如 Web 客户端(/plan可携带图片)。

4.2 完整端到端流程

  1. 用户在 Web / TUI 输入/plan [message](或直接驱动ctx.planMode);
  2. 从下一步起,每个请求都携带部署配置的plan:policy引导区块;
  3. 模型在引导下探索与设计,把变更推迟进方案;
  4. 模型调用exit_plan_mode提交 markdown 方案——用户界面显示方案卡片并弹出评审;
  5. 用户选择Approve:plan 模式在下一个步边界切换为非活动,下一步的请求头移除引导区块而工具 schema 不变,此后执行跟踪交给todo_write
  6. 用户选择Keep planning(可附反馈):模型收到携带反馈的 corrective 错误,修订后重新提交。

4.3 观察模式状态

接口(如 Web UI)可以显示 plan 模式是否激活、以及请求的切换是否仍在等待生效(pending)。该状态在所有标签页一致,并在重启后保持(它来自日志折叠而非进程内变量)。

5. 依赖、接缝与优雅降级

dsh-plan-mode一个产品包,而非 capability-seam 三件套(接口/实现/消费者)——模式的可变部分是配置值而非实现,拆分会制造空的实现包(这与审批接缝、todo/先例的"不预拆分"判断一致)。其依赖关系(见 docs/tool-catalog.md 与 packages/plan/plan-mode/package.json):

  • cordisdsh-sessiondsh-agentdsh-toolsdsh-system-prompt为对等依赖;
  • 注入['tools', 'systemPrompt']
  • 执行期机会性地ctx.get)读取ctx.userQuestions(类型级对等依赖边);
  • 与前端相关的只有可选的类型级对等边(dsh-commands用于注册/plan)。

包外的一切都通过监听器参与(defensive-patterns:策略插件不得阻塞提示或回合),因此移除该包即可优雅地去掉 Plan Mode,不会破坏消费者。终端前端不需要任何模式专属代码——插件自己把每个命令注册到命令注册表,退出评审复用组合后的 user-questions 提供者的提示队列(与ask_user_question同队列,无新机制)。

当部署没有组合任何 user-questions 提供者时,Plan Mode 保持安全但手动:ctx.userQuestions缺失时接缝无法解析,exit_plan_mode返回 correctiveisError,退出降级为人工/plan off永远不会出现未受审退出。引导文本会告诉模型:通过exit_plan_mode呈现方案,若失败则用散文询问用户——模型保持呈现而非卡死。

6. 边界澄清:Plan Mode 与沙箱、审批是两个独立的轴

这是整个设计中最重要的一条边界,也是原文档 FAQ 反复强调的点:

  • Plan Mode 是协作姿态plan/mode折叠),不读取也不写沙箱与审批旋钮
  • 沙箱模式是强制旋钮sandbox/mode折叠,见 docs/subsystems/sandbox.md),负责真正的内核级只读等约束;
  • 二者互不干扰,与 Codex 将 Plan/Default 协作预设与其沙箱/审批设置分开的做法一致。

因此:

想要在规划期间获得内核强制的只读下限?同时设置两个旋钮:切换 Plan Mode并且把沙箱模式选项设为只读——顺序无关,每个开关只改变自己的折叠,无干扰、无需要退出的恢复步骤。

日志把每个轴归属到自己的事件:姿态记入plan/mode,约束记入bash/sandbox-mode

同样地,不存在 per-mode 工具允许/拒绝列表:因为"哪些工具在规划模式下安全"是每个工具自身的属性(它的效果 effects),而不是模式的属性;手工维护的名字列表会在新工具(含 MCP 服务器)到来时悄然腐烂,还会造成"看起来像安全边界而实际不是"的过度承诺。直到工具定义声明其效果元数据(原文档 Deferred 中留待的readOnlyHint/destructiveHint方向)之前,Plan Mode 的约束方式就是:section引导 + 退出评审。这是被明确接受的成本,不是缺陷。

7. 已知限制与注意事项

依据 packages/plan/plan-mode/README.md 的 "Known Limitations" 与 docs/subsystems/plan.md:

  • 引导而非强制:忽略引导的模型在规划期间仍可能执行变更;真正的防护面是评审时刻、会话日志,以及独立配置的沙箱、审批、文件系统策略;
  • 待定选择是进程本地的:回合最后一次被接受的 pre-step 之后做出的选择,若进程在另一次被接受的 in-turn pre-step 前退出则丢失(UI 需重新应用);原设计预留的 idle-record 原语是逃生舱;
  • 无创建期 plan 选项:fork 子代理继承日志中的 plan 状态;新 spawn 的子代理从 inactive 开始;
  • 活的子代理无法打开评审:被另一活代理拥有的子代理调用exit_plan_mode会失败,并被要求把未决决策写进最终结果;只有plan-review这一种专属评审渲染器(Web UI),其他交互提供者通过其通用选项流呈现同一请求;
  • 缓存影响:进入/退出 Plan Mode 会从 first-party order 500 起改变系统提示词,该点之后的缓存路径变化;但工具 schema 与 Code Mode SDK 不再抖动。

8. 测试与验证证据

当前实现由多层测试钉住(见 packages/plan/plan-mode/tests):

  • plan-mode.spec.ts:边界顺序、重试、追加失败、HMR 释放、提示词装配、原生与 PTC 模式 schema 稳定、评审结果、不变量覆盖(经由布尔服务);
  • projection.spec.tsplan会话投影单元——把已记录的/plan命令运行转为候选目标,在plan/mode上提交记录状态,并为view推导{ active, pending }
  • integration.spec.ts:完整exit_plan_mode评审弧线的包级测试;
  • invariant.spec.tsplan/mode载荷形状校验。

仓库级测试(apps/web/tests/plan-control-row.e2e.ts)覆盖 Web 前端的 plan 控制行。原设计的录制场景(input.json中的setMode步操作与elicitationAnswers队列)随交互式 ACP 场景退役;当前 keyless TUI 场景覆盖/plan <message>进入与/plan off直接退出,并验证每个已提交的plan/mode先于其改变的request/header

9. 进一步阅读

  • 设计决策原文:2026-07-07-plan-mode.md(含 Alternatives considered 与 Consequences 的完整历史);
  • 现行设计决策:2026-07-22-plan-specific-collaboration-state.md;
  • 子系统参考:docs/subsystems/plan.md(含ctx.planMode的 Cordis API 签名);
  • 包 README:packages/plan/plan-mode/README.md(Model Experience 与限制细节);
  • 工具目录条目:docs/tool-catalog.md(exit_plan_mode的精确 schema);
  • 配置目录条目:docs/config-catalog.md(每个可接受字段的 JSDoc);
  • 源码:packages/plan/plan-mode/src/index.ts、src/types.ts、src/invariant.ts。

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 22:56:57

66页PPT拆解《底层逻辑》:IT人的可落地思维建模手册

简介&#xff1a;本资源是一份面向职场人、学生及终身学习者的思维升级工具包&#xff0c;聚焦《底层逻辑》核心思想的可视化精解&#xff0c;帮助读者穿透信息迷雾、构建系统性认知框架。66页PDF完整呈现全书六大模块&#xff1a;从“我所理解的底层逻辑”到“社会协作的底层逻…

作者头像 李华
网站建设 2026/9/18 22:52:47

ESP32-S3 多 SPI 设备并行在线:4 步让两条总线不打架

ESP32-S3 多 SPI 设备并行在线&#xff1a;4 步让两条总线不打架 【免费下载链接】arduino-esp32 Arduino core for the ESP32 family of SoCs 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 屏幕刚亮起来画面就花了&#xff0c;SD 卡里的日志文件直…

作者头像 李华
网站建设 2026/9/18 22:52:03

Linux shell命令与文件权限:从chmod到权限排查

1. 开篇&#xff1a;shell 命令和文件权限为什么必须放在一起看刚接触 Linux 的人&#xff0c;几乎都会卡在同一个地方&#xff1a;命令本身背下来了&#xff0c;cd、ls、cp、rm敲得挺顺&#xff0c;可一旦遇到Permission denied、Operation not permitted、Read-only file sys…

作者头像 李华
网站建设 2026/9/18 22:49:38

Oh My Zsh kind 插件指南:Kind 集群命令补全与快捷别名实战

Oh My Zsh kind 插件指南&#xff1a;Kind 集群命令补全与快捷别名实战 【免费下载链接】ohmyzsh &#x1f643; A delightful community-driven (with 2,500 contributors) framework for managing your zsh configuration. Includes 300 optional plugins (rails, git, macOS…

作者头像 李华