写 dynamic workflow
一个 dynamic workflow 把「下一步跑什么」的决策从 LLM 手里收走,交给一段 确定性的 JavaScript 脚本,由 runtime 在后台执行。要写这样的脚本,就用本 skill。这里 要守的纪律很少,就三条:先问清自己到底需不需要 workflow、按 work 的形状选范式、照 runtime 自己的 validation 契约来写——权威的闸是 harness,别去重新实现它。
1. 先问清自己——你究竟需不需要 workflow?
workflow 是有开销的,只值得任务要协调几十到几百个 agent、且必须把中间结果挡在 context
之外时用。若你还没在派发决策关确认过这一步,先回 master-orchestrator-guide 的
dispatch.md(选择标准一节)过一遍——「该选 workflow 还是 subagent」是那里的判断标准单一
持有,本节不复述。确认要上 workflow 之后,才往下走范式决策树。
2. 范式决策树
照 work 的形状选,不是凭口味。(完整语义见 references/mechanism.md;完整 pattern
目录见 references/patterns.md。)
- 任务互相独立,且你要把全部结果一起收齐 → fan-out
(
parallel(),一道 barrier)。模板:assets/templates/fan-out.js。 - 多阶段、阶段之间无须同步 → pipeline
(
pipeline(),流式——默认就用它;item A 可以走到 stage 2,而 item B 还在 stage 1)。 模板:assets/templates/pipeline.js。 - 数量未知 → loop:
- 深度要随一个
'+Nk'budget 伸缩 → loop-until-budget (assets/templates/loop-until-budget.js)。 - 规模未知的发现(找出所有某类东西)→ loop-until-dry
(
assets/templates/loop-until-dry.js)。
- 深度要随一个
- 连 work-list 都还不知道 → scout-then-fanout:先派一个 scout agent 把这份 list
枚举出来,再对它 pipeline / parallel。这是现实里最常见的入口形状。
模板:
assets/templates/scout-then-fanout.js。
默认用
pipeline()。 只有当下游某个 stage 真的要拿整批前一阶段的集合时(dedup / merge、按 count 提前退出、「跟其余全部比一遍」),才换成 barrier(parallel())。「代码更 整齐」不是理由——barrier 的 latency 是实打实的。见references/mechanism.md§3 的 smell-test。
真实的 workflow 会把这几种形状叠在一起。 fan-out 里套一个 loop、scout 之后接一个 verify stage、pipeline 当中夹一道 self-repair gate——这些组合形态(bug-hunt-loop、 pr-issue-triage、dep-upgrade-sweep 等)住在
references/patterns.md,并整套 ship 在assets/examples/里。当你的 work 套不进任何一个裸形状时,从最接近的那个组合 example 起手。
3. 写作流程——照 harness 契约起草,再 launch
起草:从
assets/templates/里的某个骨架(或assets/examples/里某个完整组合) 起手,填进真实的 prompt、schema、work-list。meta必须是第一条语句、且是一个纯字面量 (name+description)。照 harness 的 validation 契约写。 runtime 才是权威的 checker——没有一个独立的 linter 要你跑,你也不该自己造一个。契约如下:
meta是第一条语句、是纯字面量(name+description必填)——harness 在 launch 时校验。- 不出现
Date.now()/Math.random()/ 无参new Date()——它们会破坏 resume,harness 在 runtime 抛错。 - 不出现
require/ node-builtin import /process.*——sandbox 一律拒收。 parallel()收 thunk(() => ...),不收裸 promise(裸 promise 会立刻 eager 执行、 barrier 也就丢了)。- 守住 caps(16 并发 / 1,000 总量 / 单次调用 4,096 / 512 KB)。
每条约束的含义和缘由见
references/mechanism.md。Launch。 harness 拒收脚本或抛错时,它的报错就是权威——读它,照
references/mechanism.md修好,再 relaunch。
为什么不配 linter?
meta(launch 时)和 determinism / caps / escape(runtime 时) harness 都已经权威地校验过了。再造一个独立的 static linter,无非是把 harness 自己的检查 用启发式重写一遍——会漂、还比真货差。所以本 skill 只教你契约,不 ship 第二个 validator。 (编排原则「信确定性 endpoint、不信 prose 自检」在这里由 harness 兑现——它就是那个 endpoint。)
4. Reference 索引——动手猜之前先读
references/mechanism.md——对引擎下任何判断之前先读它。已确认的契约 vs 内部 未知;7 个 primitive 的真实语义;parallel(barrier)vspipeline(streaming)+ smell-test;Date.now()为什么会破坏 resume;resume =「最长未变前缀」;硬 caps (16 并发 / 1,000 总量 / 单次调用 4,096 / 512 KB)。references/patterns.md——挑形状:控制流 primitive(fan-out+synthesize、 pipeline-by-default、loop-until-{count,budget,dry}、scout-then-fanout)、质量 pattern (adversarial-verify、perspective-diverse-verify、judge-panel、multi-modal-sweep、 completeness-critic、migrate→transform→verify)、组合形态(bug-hunt-loop、 pr-issue-triage、dep-upgrade-sweep、test-generation-and-repair、tournament-bracket、 self-repair-loop、staged-escalation)。顶部有一份 section TOC;每节都讲清何时用 + 骨架 + 由哪个 bundled 资产演示。每个形状都有一个 bundled 文件演示——没有只剩 prose 的空壳形状。references/api-reference.md——primitive 签名、agent()的每个选项 (label/phase/schema/model/isolation/agentType)、cache-key 四要素、failure 语义。没有任何编造的选项。assets/templates/——5 个控制流骨架(copy → fill)。
assets/examples/——12 个完整、真实-prompt 的 workflow(分别何时读)
| Example | 何时读 |
|---|---|
review-adversarial-verify.js |
跨多个维度 review 改动的代码,再在出报告前逐条 refute 每个 finding(adversarial-verify 的典范组合)。 |
design-judge-panel.js |
生成 N 个独立设计方案、用一个 judge panel 打分、从胜者综合。 |
research-multimodal-sweep.js |
从多个搜索角度研究一个问题 → dedup → deep-read → completeness critic。 |
migrate-discover-transform-verify.js |
一场迁移:先发现 site,在隔离 worktree 里逐个 transform,再 gate-verify(唯一用 isolation:'worktree' 的资产)。 |
bug-hunt-loop.js |
全仓搜 bug 直到连续 K 个 dry round,再对每个幸存者 adversarially verify(loop-until-dry + adversarial-verify)。 |
pr-issue-triage.js |
scout 打开的 PR/issue、fan out 一个分类器、用 judge 把这批排成优先级队列(scout-then-fanout + judge-panel)。 |
dep-upgrade-sweep.js |
发现过时的 dep,在隔离 worktree 里逐个 upgrade、gate,只保留转绿的 bump。 |
test-generation-and-repair.js |
给每个 module 生成 test,再在 attempt cap 之内把每个失败的 suite self-repair 到绿。 |
tournament-bracket.js |
靠两两淘汰从众多候选里选出一个胜者(相对比较,不是绝对打分)。 |
self-repair-loop.js |
把一个 artifact 驱动到通过某个 gate,把失败诊断喂回有界的重试。 |
staged-escalation.js |
先用便宜的 pass 试每一项;只在信心低的地方升级到强模型。 |
nested-workflow-composition.js |
用 workflow() 把一个 saved/file workflow 当子步骤组合进来(共享 budget/caps、一层嵌套、逐项 catch-and-degrade,唯一用 workflow() 的资产)。 |
每个 bundled template 和 example 都是照 harness 契约写的,随便挑一个都是 known-good 的 起点。