goal 跨重启活着,但它不调度工作
2026-08-15 · 6 分钟阅读
dsh-goal 让一个长期完成目标在多轮、会话恢复、fork 与进程重启后持续存在。用户和 agent 都可以对目标做 create、edit、pause、resume、complete、block 或 clear。
最容易被误解的一点
这个包只存储和提供 goal 状态,不启动任何工作。
模型工具、/goal 命令、续行驱动器都是消费同一份 goal 状态的独立包。所以只挂 dsh-goal 的话,目标能存下来,但不会有任何东西去推进它。
续行权限是进程本地的,不是持久状态。这一点在排查「重启后为什么没自动继续」时很关键。
每会话最多一个
服务每会话至多保留一个当前 goal。未完成的 goal 必须先 edit、pause、resume、block 或 clear,才能被另一个替代;已完成的 goal 可以直接替换。
更新走比较并交换——陈旧视图会被拒绝。所以拿到 goal 之后要连着 id 和 revision 一起用,不能只凭 id 直接写。
Round 上限约束的是什么
- name: '@deepseek-ai/dsh-goal'
config:
defaultMaxGoalRounds: 256
默认 256,约束的是自动续行的次数。指定了自身上限的 create 请求会覆盖这个默认值。它必须是个正的安全整数。
被阻塞的 goal 会保留稳定的策略代码和面向人的说明——这样上层能区分「因为策略被挡」和「因为出错被挡」。
它和会话投影的关系
GoalService 要求组合提供 ctx.sessionProjections,并在启动时注册 goal 投影单元。没有组合投影注册表的组合无法激活 ctx.goals。
该单元版本为 6,宿主状态保留最新的有效当前 goal、所有曾使用的 goal id,以及第一次严格回放失败的信息。客户端视图提供当前 goal——首次 create 之前和 clear tombstone 之后为 null。
载体通过历史尾页和 session/projection 推送帧向客户端提供值。
什么时候不该用
- 常规单轮工作 — 不该建 goal。它是为跨多轮的长期目标设计的。
- 并行目标 — 不支持。一个会话同时只有一个当前 goal。
文档里的判据是:goal 适合一个需要跨自动 Goal Round 持续的长期完成目标——比如完成一次迁移,或修复所有失败的文档门禁。
小结
把 goal 理解成「一个带 CAS 语义的持久状态槽」比理解成「任务调度器」更准确。它保证目标不丢、可校验、能跨重启,但推进目标的工作由别的包负责。