动态 Workflow 编排
当一次要派 20 个 agent、跑一小时、还得能断点续跑时,光靠主 loop 里发几个 Agent 调用已经不够。
什么是 Workflow
Workflow 是一段脚本化的 agent 编排代码。它介于两种熟悉的抽象之间。
比主 loop 里"临时发几个 Agent 调用"更结构化:拓扑是你写死的,不是 Claude 临场决定要不要 fan-out、fan-out 几个。
比 Skill 更细粒度:Skill 是一段引导性指令,Workflow 是一段确定性运行时,里面明确说"这一阶段并行开 5 个 worker,下一阶段汇总"。
它的核心价值是三件事:确定性拓扑(reviewer 一定跑在 finder 之后)、大规模 fan-out(一次派 20 个 agent 处理 20 个文件不吃力)、断点续跑(跑到一半崩了,从上次的位置继续,未变更的前缀直接命中缓存)。
meta 块:workflow 的身份证
每个 workflow 文件顶部有一段 meta,它是纯字面量,不允许变量插值。
export const meta = {
name: "code-review-panel",
description: "多视角并行审查一段代码变更并汇总",
phases: ["Fan-out reviewers", "Aggregate verdict"],
};phases 只用于 UI 展示当前跑到哪一阶段,不改变执行逻辑。写字面量而不是拼接的原因很朴素:它需要在不 eval 主体的情况下被读出来。
六个核心 hook
Workflow 主体里能调的核心 hook 就这六个,学会了它们,你能拼出绝大多数编排。
agent(prompt, opts) —— 派一个 subagent,等它跑完拿到结构化结果。相当于主 loop 的 Agent 调用,但在脚本里可以拿到返回值。
parallel(thunks) —— barrier 语义:等数组里所有 thunk 都完成才 resolve。适合明确的"等这批人都跑完再往下走"。
pipeline(items, ...stages) —— 每个 item 独立穿越所有 stage,item 之间没有 barrier,wall-clock 时间等于最慢那个单项链。
phase(title) —— 打一个人类可读的阶段标记,UI 上会看到。
log(msg) —— 结构化日志,写进 workflow 的运行记录。
workflow(nameOrRef, args) —— 调用另一个 workflow 作为子步骤。允许你把编排本身拆成可复用的组件。
Pipeline 和 parallel 的取舍
这两个 API 长得像,但语义完全不同,选错了会让 wall-clock 时间翻倍。
parallel 是"barrier: 等所有 thunk 完成才返回"。用它的时候你在告诉调度器:这几件事必须都做完才能进入下一步。
pipeline 是"每个 item 独立穿越 stage 链"。20 个文件、每个文件都要过 review + test + summary 三个 stage。第一个文件走到 test stage 时,第二个文件可能才刚开始 review,谁也不等谁。总时间等于最慢那一条独立链。
默认选 pipeline。 只有当你真的需要 cross-item 汇总(比如汇总所有 review 结果做投票)时才用 parallel。这个建议来自一个观察:多数 fan-out 任务其实是 item 之间独立的,用 parallel 会引入毫无必要的 barrier,让整体时间被最慢的一项拖死。
别把 pipeline 误用为顺序执行
pipeline 不是"跑完 stage 1 再跑 stage 2"。它是"每个 item 独立走完自己的 stage 链"。如果你要的是"所有人先做完 stage 1 再一起进 stage 2",那是 parallel + 顺序。
六个可以直接抄的 pattern
Adversarial verify。主 agent 写出结果,一个 fresh model 的 verifier subagent 尝试 refute 它。做事的人不该同时是打分的人,这条 Anthropic best practices 里明确讲过。
Multi-modal sweep。同一份输入用不同 lens(性能、安全、可读性)并行审查,每一路结果独立汇报,主 loop 拿到全景图。
Judge panel。给同一个方案派 3 到 5 个 judge agent 独立打分,输出多数决和分歧点,用于选型和方案对比。
Loop-until-dry。让 agent 迭代跑,每一轮拿新证据,直到 verifier 说"没新东西了"才收工。适合开放式研究和 bug 定位。
完整性 critic。一个 critic 专门检查主 agent 有没有漏做用户列出的需求。它的 prompt 里明确带着 spec 清单,只回答"漏了哪几条"。
Budget-scaling。lead agent 根据任务复杂度动态决定要不要 fan-out:简单查询 1 个 worker、对比类 2 到 4 个、复杂研究 10 个以上。Anthropic 的 Research 系统就用这条明确写在 prompt 里的规则来防止过度投入。
Resume:断点续跑的白日梦
每次跑一个 workflow 都会拿到一个 runId。用同一个 runId 再跑一次,未变更的前缀会直接命中缓存,从上次崩掉的位置往下继续。
这一点对多 agent workflow 尤其重要。想象一下你跑一个 20-worker 的 fan-out 研究,跑了 40 分钟,某个 worker 因为 API rate limit 挂掉。没有 resume 你只能整个重跑。有 resume,前 19 个 worker 的输出全部缓存命中,几秒钟内就恢复到崩掉那一步。
Anthropic 团队讲得很直接:agent 是 stateful 的,错误会 compound,重启是"expensive and frustrating for users"。所以他们内部同样做了 checkpoint 机制。
一个可以照着改的例子
下面这段展示 pipeline + 结构化输出。20 个 PR 文件,每个都要过 review 和 test,最后汇总一份 gap 清单。
import { agent, pipeline, phase, log } from "workflow";
export const meta = {
name: "pr-multi-review",
description: "对 PR 里每个文件并行做 review + test 检查",
phases: ["Per-file review", "Aggregate gaps"],
};
export default async function run({ files, planPath }) {
phase("Per-file review");
const results = await pipeline(
files,
// stage 1: fresh subagent 做 review
(file) => agent(`审查 ${file} 是否符合 ${planPath} 里的规范`, {
subagent_type: "fresh",
tools: ["Read", "Grep", "Glob"],
}),
// stage 2: 同一个 file 的 review 结果再送给测试 agent
(review, file) => agent(`基于 review 结论跑 ${file} 相关的测试并回报`, {
subagent_type: "fresh",
tools: ["Bash", "Read"],
}),
);
phase("Aggregate gaps");
log(`收到 ${results.length} 份 per-file 报告`);
return agent("综合所有 per-file 报告,输出 gap 清单和优先级", {
subagent_type: "fork",
input: { results },
});
}pipeline 里第一个 stage 是 review,第二个 stage 是 test。20 个文件同时穿越这两个 stage,谁也不等谁。最后 parallel 结束后一个 fork subagent 汇总所有报告,输出结构化的 gap 清单。
什么时候用 Workflow
Workflow 不是替代主 loop 的 Agent 调用,它俩共存。三条判断规则:
用户明确 opt-in。 主 loop 是 Claude 判断要不要派 agent,Workflow 是你写死"这里必须 fan-out 20 个 worker"。你想要确定性,就用 Workflow。
需要确定性拓扑。 比如"reviewer 一定在 finder 之后跑""所有 worker 用完才能进入 aggregation",这些结构靠主 loop 里的自然语言约束不可靠,写在 Workflow 里是硬性的。
大规模 fan-out。 主 loop 里发 5 个 Agent 调用还行,一次要 fan-out 20 个以上就该走 Workflow,顺带拿到 resume 能力。
反过来,日常的"读几个文件回答一个问题"、"派两个 agent 并行找 bug 位置"这类场景,主 loop 里的 Agent 调用已经够用,别为了用 Workflow 而用 Workflow。Anthropic 讲的原则一直是:最简单能解决问题的方案就是最好的方案。
参考来源
- https://docs.claude.com/en/docs/claude-code/subagents — Claude Code 官方 subagents 文档,涵盖 fork 机制和自定义 agent 类型
- https://docs.claude.com/en/api/agent-sdk/subagents — Agent SDK 的 subagents 定义与 dynamic workflows 章节
- https://www.anthropic.com/engineering/multi-agent-research-system — Anthropic Research 团队的多 agent 系统实战,含 checkpoint、resume、error handling 的工程经验
- https://www.anthropic.com/engineering/building-effective-agents — Anthropic 关于 workflow vs agent 的架构区分与常见 pattern
- https://www.anthropic.com/engineering/claude-code-best-practices — Claude Code 最佳实践,含 adversarial review、fan-out across files、auto mode 的推荐做法