【学习笔记】Claude Code 动态工作流(Dynamic Workflows)详解,并与 /goal 命令对比

23 min

本篇记录 Claude Code 的动态工作流(Dynamic Workflows),并把它与 /goal 命令放在一起对比。

两者都解决”让 Claude 持续干活、减少人盯着”这件事,但思路截然不同:动态工作流把编排逻辑写进一段可复用、可重跑的脚本,由 runtime 调度数十到上百个 subagent 并行执行;/goal 则是在当前会话里设置一个完成条件,让 Claude 一轮一轮地逼近目标,直到一个小模型判定条件满足。理解它们的分工,才能在合适的场景用合适的工具。


1. 一句话区分两者

先用最直观的方式建立一个心智模型:

动态工作流/goal
本质Claude 写的一段编排脚本,由 runtime 执行当前会话里的一个”完成条件”
谁决定下一步做什么脚本(循环、分支都在代码里)Claude 自己(每轮临场决定)
并发规模一次运行数十到上百个 subagent单 agent,一轮一轮串行推进
中间结果放哪脚本变量里(不进主上下文)Claude 的上下文窗口里
什么时候停脚本执行完毕一个独立的小模型判定条件已满足
可复用性编排本身可保存为命令、可重跑会话级,条件满足即清除
核心价值把”计划”固化成代码,可并行 + 可对抗式自检把”什么时候算做完”外包给一个廉价快速的评判模型

一句话总结:动态工作流把”怎么做”固化成脚本并并行放大,/goal 把”做没做完”交给一个独立评判者。 它们并不冲突,甚至可以组合使用。


2. 动态工作流是什么

2.1 核心定义

动态工作流(Dynamic Workflow)是一段编排 subagent 的 JavaScript 脚本。Claude 针对你描述的任务自己写出这段脚本,然后由一个 runtime 在后台执行,你的会话保持响应。

关键点拆解:

  • Claude 写脚本,不是你写:你只需要描述任务,Claude 把循环、分支、并行 fan-out 都翻译成代码。
  • 后台执行:脚本在独立于对话的环境里运行,中间结果留在脚本变量里,不占用 Claude 的上下文窗口——最终只有合并后的答案回到会话。
  • 可重跑、可复用:每次运行都会把脚本写到会话目录下的文件里,你可以读取、diff、编辑后重新启动;满意了还能保存成自己的命令。

为什么这很重要?因为在大规模任务里,Claude 的上下文窗口是瓶颈。传统方式下无论是 subagent、skill 还是 agent team,编排者都是 Claude 本人——它逐轮决定下一步 spawn 什么、每个结果都落进上下文。一旦任务大起来,上下文先撑爆。动态工作流把”计划”从 Claude 脑子里搬进代码,Claude 的上下文只承载最终结论。

2.2 与 subagent / skill / agent team 的区别

官方给了一张很清晰的对比表,核心是”谁持有计划(who holds the plan)“:

SubagentsSkillsAgent teamsWorkflows
是什么Claude 派生出的 workerClaude 遵循的指令一个 lead agent 监督若干 peer 会话runtime 执行的脚本
谁决定下一步Claude,逐轮Claude,遵循 promptlead agent,逐轮脚本
中间结果在哪Claude 上下文Claude 上下文共享任务列表脚本变量
可复用的是worker 定义指令team 定义编排本身
规模每轮几个委派任务同 subagent少量长期 peer数十到上百个 agent
中断后重启该轮重启该轮teammate 继续跑同会话内可恢复

可以看到,前三种方案的共同点是”Claude 是编排者”,结果都在上下文里;动态工作流是唯一一个把编排搬进代码、能横向扩展到上百 agent 的方案。

2.3 不只是”跑更多 agent”,还能做质量模式

把计划搬进代码还有一个被低估的好处:可以套用可复用的质量模式,而不只是无脑堆 agent 数量。典型的几种:

  • 对抗式自检(adversarial verify):让独立 agent 互相挑刺、投票,多数通过才采纳,过滤掉”看着合理但其实错”的发现。
  • 多角度起草 + 评审(judge panel):从几个独立角度各起草一版方案,平行打分,取最优并嫁接其他版本的亮点。
  • 多模态扫荡(multi-modal sweep):多个 agent 各用一种检索角度(按容器 / 按内容 / 按实体 / 按时间),互不可见,覆盖单角度搜不全的长尾。
  • 直到搜干为止(loop-until-dry):持续派 finder,直到连续若干轮没有新发现。

这些模式靠单轮对话是拼不出来的,必须由脚本来表达循环和聚合。


3. 怎么用动态工作流

⚠️ 关键区分:默认是”一次性”的,保存后才可反复调用

这是动态工作流最容易被误解的一点。你描述任务时,Claude 是为这次任务临时写一段脚本,跑完就结束——它不会自动变成以后能反复调用的命令。下次遇到类似任务,Claude 会重新写一个新脚本。

工作流其实分两层:

  • 编排脚本:可临时现写,针对具体任务;落在本会话目录下,同会话内可重跑/恢复/编辑后重跑,但退出会话就没了。
  • 命令:只有你手动保存(在 /workflows 里按 s,见 3.4)后,脚本才升级成一个 /<名字> 命令,未来任何会话都能调用、还能传 args 参数。

一句话:未保存 = 一次性临时脚本;按 s 保存 = 创建一次、永久可调用的命令。 别指望”用一次就自动存下来”。

3.1 三种触发方式

  1. 直接跑内置工作流/deep-research 是内置示例,对一个问题多角度 fan-out 搜索、交叉核对来源、投票、产出带引用的报告。
  2. 在 prompt 里点名要一个工作流:用自己的话说”use a workflow / run a workflow”,或在 prompt 里包含关键字 ultracode,Claude 就会为该任务写一个工作流脚本而不是逐轮推进。
  3. 让 Claude 自动决定(ultracode 模式):执行 /effort ultracode,它把 xhigh 推理强度与自动工作流编排结合,此后会话里每个实质任务都可能触发工作流。
ultracode: audit every API endpoint under src/routes/ for missing auth checks

小提示:ultracode 是会话级的,新开会话会重置;回到日常活儿用 /effort high 降档。它只在支持 xhigh 的模型上出现。如果误触发了关键字,在 macOS 上按 Option+W(Windows/Linux 是 Alt+W)可以取消这次高亮;要彻底关掉关键字触发,去 /config 关掉 Ultracode keyword trigger。

3.2 内置工作流:/deep-research

最快的上手路径就是直接跑 /deep-research

/deep-research What changed in the Node.js permission model between v20 and v22?

它会在后台多阶段工作,你的会话保持空闲,最后给你一份报告而不是一轮轮的对话记录。报告里每条结论都标注来源,交叉核对没通过的声明会被过滤掉。

3.3 审批与权限

启动一个运行前,Claude Code 会让你确认计划。CLI 里会展示规划的各阶段,选项包括:直接运行、本项目内对该工作流不再询问、先看原始脚本、取消。Ctrl+G 可以在编辑器里打开脚本,Tab 可以在运行前调整 prompt。

不同权限模式下,询问的时机不同:

权限模式询问时机
Default / accept edits每次都问(除非本项目对该工作流选了”不再问”)
Auto仅首次启动;任何 Yes 会记进用户设置,之后免问;ultracode 开启时完全跳过
Bypass permissions / claude -p / Agent SDK从不询问,直接启动

需要留意:权限模式只管”启动询问”这一层。工作流产出的 subagent 始终运行在 acceptEdits 模式、继承你的工具 allowlist,文件编辑自动放行。但不在 allowlist 里的 shell 命令、web fetch、MCP 工具,仍可能在运行中弹询问。所以长任务前,最好把 agent 需要的命令提前加进 allowlist。

3.4 保存为命令并传参

跑出一个满意的工作流后,可以把它保存成命令复用:/workflows → 选中该运行 → 按 s。保存位置(Tab 切换):

  • .claude/workflows/(项目级,跟仓库共享给所有 clone 的人)
  • ~/.claude/workflows/(用户级,全项目可用,仅自己可见)

保存后会以 /<名字> 形式出现在 / 补全里。同名时项目级优先。

保存的工作流还能通过 args 参数接收输入,脚本里以全局 args 读取,可以直接当数组/对象用,无需手动解析:

> Run /triage-issues on issues 1024, 1025, and 1030

3.5 观察运行:/workflows

工作流在后台跑,会话保持响应。任何时候执行 /workflows 可以列出运行中和已完成的运行,选中后进入进度视图:

按键动作
/ 选择阶段或 agent
Enter钻进阶段、再钻进 agent 看它的 prompt、工具调用和结果
Esc退回一层
p暂停 / 恢复运行
x停掉选中的 agent,或(焦点在运行上时)停掉整个工作流
r重启选中的运行中 agent
s把该运行的脚本保存为命令

4. 工作流如何运行

4.1 脚本即真相

每次运行都会把脚本写到 ~/.claude/projects/ 下你当前会话目录里的一个文件。Claude 启动时会拿到这个路径,所以你可以:

  • 打开它,看 Claude 写了什么编排逻辑;
  • 和上次运行的脚本 diff;
  • 编辑后让 Claude 从编辑版重新启动。

runtime 会持续追踪每个 agent 的结果,这也是”同会话内可恢复”的基础。

4.2 运行时的约束

约束原因
运行中不接受用户输入只有 agent 的权限询问能暂停运行;需要阶段间人工签字的,把每个阶段拆成独立工作流
工作流脚本本身不能直接访问文件系统或 shellagent 来读写文件、跑命令,脚本只负责协调 agent
最多 16 个并发 agent(CPU 核少的机器更少)限制本地资源占用
单次运行总计最多 1,000 个 agent防止失控循环

4.3 恢复与成本

  • 恢复:停止后可恢复——已完成的 agent 返回缓存结果,其余实跑。恢复仅限同一 Claude Code 会话;退出再开会从头来。
  • 成本:一次运行可能比在对话里逐轮做同一件事显著更费 token,因为它会 spawn 很多 agent,计入你计划的用量和速率限制。控制成本的三招:
    1. 先小切片试跑——一个目录而非整个仓库、一个窄问题而非宽问题,用 /workflows 看每个 agent 的 token 用量,随时停而不丢已完成的工作。
    2. 大跑前确认 /model——如果你平时会切小模型做日常活儿,开跑前确认模型。
    3. 让脚本给不需要最强模型的阶段路由小模型——描述任务时直接说。

4.4 关闭工作流

三档开关:/config 里 toggle “Dynamic workflows”、在 ~/.claude/settings.json"disableWorkflows": true、或设环境变量 CLAUDE_CODE_DISABLE_WORKFLOWS=1。组织级关闭则在 managed settings 里设 disableWorkflows,或用 Claude Code 管理后台的 toggle。关闭后,内置工作流命令不可用、ultracode 关键字失效、/effort 菜单移除 ultracode 选项。


5. /goal 是什么

5.1 核心机制

/goal 设置一个完成条件,Claude 在没有你逐轮提示的情况下持续工作。每轮结束后,一个小型快速模型检查条件是否成立;不成立,Claude 就开下一轮而不是交还控制权;成立,目标自动清除。

它本质上是一个会话级的、基于 prompt 的 Stop hook 封装。每轮 Claude 结束时,把条件和当前对话发给你配置的小快模型(默认 Haiku),它返回 yes/no 加一句理由:

  • no → Claude 继续干活,理由作为下一轮的指引;
  • yes → 清除目标,在 transcript 里记一条”已达成”。

要求:Claude Code v2.1.139+,且必须在已接受 trust dialog 的 workspace 里运行(因为 evaluator 属于 hooks 系统)。disableAllHooks 或 managed allowManagedHooksOnly 开启时不可用。

5.2 适合什么样的任务

/goal 适合有可验证终态的实质工作

  • 把某个模块迁移到新 API,直到所有调用点都能编译、测试通过
  • 按设计文档实现功能,直到所有验收标准成立
  • 把大文件拆成聚焦的小模块,直到每个都低于体积预算
  • 清理一个带标签的 issue backlog,直到队列空了

注意 evaluator 不独立跑命令、不读文件,它只能依据 Claude 自己在对话里呈现的内容来判断。所以条件要写成”Claude 的输出能证明的东西”。

5.3 写好一个条件

一个好条件通常包含三部分:

  1. 一个可测量的终态:测试结果、构建退出码、文件数量、空队列;
  2. 一个明确的检查方式:比如”npm test 退出码为 0”或”git status 干净”;
  3. 不能破坏的约束:比如”不修改任何其他测试文件”。

条件最多 4,000 字符。想约束运行时长,可以在条件里加一条 turn/时间子句,如 or stop after 20 turns

5.4 用法速查

/goal all tests in test/auth pass and the lint step is clean   # 设置(会立即开始一轮)
/goal                                                          # 不带参数 = 查看状态(条件、已运行时长、轮数、token、最新理由)
/goal clear                                                    # 提前清除

补充:

  • stop / off / reset / none / cancel 都是 clear 的别名;/clear 新开会话也会清掉。
  • 会话结束时仍 active 的目标,用 --resume / --continue 恢复会话时会带回来(但轮数、计时、token 基线重置);已达成或已清除的不会恢复。
  • 非交互模式可用:claude -p "/goal CHANGELOG.md has an entry for every PR merged this week" 会一次跑到完成,Ctrl+C 中断。
  • 与 auto mode 互补:auto mode 在单轮内自动批准工具调用、Claude 自行判断做完与否;/goal 加的是一个独立的评判者,在每轮之后检查你的条件。auto 去 per-tool 的询问,/goal 去 per-turn 的询问。

6. 全面对比

把两者放在一起,从七个维度对照:

6.1 解决的问题

  • 动态工作流:解决”任务太大、单会话编排不过来 / 上下文装不下”——把编排固化成脚本,横向并行放大。
  • /goal:解决”任务有明确终点,但我不想逐轮催 Claude”——把”做没做完”外包给独立评判模型。

6.2 并行 vs 串行

  • 动态工作流:并行,一次运行可调度数十到上百个 subagent(受 16 并发上限节流)。
  • /goal串行,单 agent 一轮一轮推进。

6.3 上下文消耗

  • 动态工作流:中间结果留脚本变量,只把最终答案回主上下文,省主上下文。
  • /goal:每轮结果都在主上下文里累积,长任务下上下文压力大。

6.4 可复用 / 可重跑

  • 动态工作流:编排可保存为命令、可 diff、可编辑、可重跑、可恢复(同会话)。
  • /goal:会话级条件,满足即清除,不可跨会话复用(恢复也只带回 active 条件,统计重置)。

6.5 质量保障方式

  • 动态工作流:脚本可表达对抗式自检、judge panel、loop-until-dry 等可复用质量模式——结构性更强。
  • /goal:靠 evaluator 判条件成立与否,是终态门禁,不做过程性交叉验证。

6.6 成本结构

  • 动态工作流:——很多 agent,token 消耗可能显著高于对话推进;但每个阶段可路由小模型控本。
  • /goal:相对克制——主轮按需走,evaluator 跑小快模型、开销通常可忽略。

6.7 典型场景

场景推荐
全仓库 bug 扫荡 / 安全审计动态工作流(多角度并行 + 对抗式自检)
500 文件 API 迁移动态工作流(pipeline 逐文件迁移 + 验证)
多来源交叉核对的研究报告动态工作流(/deep-research
把一个模块迁到新 API 直到测试全绿/goal
按设计文档实现直到验收标准成立/goal
清空一个 issue backlog/goal
一个复杂决策,想从多角度起草再择优动态工作流(judge panel)

7. 它们可以组合吗

可以,而且组合起来很有用。一个典型模式是:/goal 持续推进,让其中的某些阶段由工作流完成。

比如”直到整个仓库的所有 API 端点都通过 auth 审计并修复”这种大目标:

  • 工作流负责单次扫描/修复这种适合并行的活儿;
  • /goal 负责整体终态门禁——每轮(可能含一次工作流运行)结束后,由独立 evaluator 判定”是否所有端点都已审计且无缺失”。

要注意两者的运行模型不同:工作流是”跑完脚本即止”,/goal 是”条件满足即止”。组合时,工作流作为推进手段,/goal 作为终止判据,分工清晰。


8. 选型决策清单

当你下次面对一个”想让 Claude 多干一会儿”的任务,按这几个问题快速分流:

  1. 任务能否拆成大量互相独立的子任务? 能 → 动态工作流的并行 fan-out 最划算。
  2. 子任务的结果需要互相交叉验证才可信吗? 需要 → 动态工作流(对抗式自检/judge panel)。
  3. 任务规模大到单会话上下文装不下中间过程吗? 是 → 动态工作流(中间结果不进主上下文)。
  4. 任务的终点是一个可由对话输出证明的客观条件吗?(测试通过、构建退出码、队列空)是 → /goal
  5. 你只是不想逐轮催,但任务本身是串行的? 是 → /goal
  6. 你希望这套流程以后能反复重跑、可版本化? 是 → 动态工作流(保存为命令)。

一句话收尾:要”并行放大 + 固化流程 + 交叉自检”,用动态工作流;要”持续推进 + 客观终态门禁”,用 `/goal”;两者还能组合。


参考来源