Whale 动态工作流:终端内的多 Agent 编排
用 JavaScript 脚本编排多个 AI Agent——扇出研究、多角度审查、流水线处理、对抗验证。 兼容 Claude Code,无需修改即可运行。
Whale 团队
Engineering
Whale 的 动态工作流 让你超越单轮 Agent 对话的限制。
不再由模型决定下一步做什么——你编写一个 JavaScript 脚本来控制流程:
循环、扇出、屏障、流水线,而每个 agent() 调用负责实际的 LLM 工作。
结果是确定性的、可重复的、可扩展的多 Agent 编排,一切都在你的终端中完成。
什么是动态工作流?
动态工作流是一个 JavaScript 文件,使用 Whale 的运行时全局变量——agent()、
parallel()、pipeline()、phase()、log() 和
budget——来协调多个 AI Agent。脚本在隔离的 QuickJS 沙箱中运行,
与你的对话上下文分离,仅通过 agent() 叶子节点与外界通信。
.whale/workflows/ 使用,无需修改。
Chat vs Workflow:何时使用?
| 维度 | Chat | Workflow |
|---|---|---|
| 谁决定下一步 | 模型逐轮决定 | 脚本控制 |
| 中间结果存放 | 对话上下文 | 脚本变量 |
| 可重复性 | 每次临时处理 | 编排被代码化 |
| 规模 | 每轮几次调用 | 每次数十到数百个 Agent |
| 中断恢复 | 丢失上下文,重新开始 | 同一会话内可恢复 |
工作流的典型应用场景:
- 扇出研究 — 并行搜索多个角度,交叉验证发现
- 多角度审查 — 从多个视角审查代码或设计,然后综合
- 流水线处理 — 分阶段处理(提取 → 转换 → 加载)
- 对抗验证 — 生成独立的反方 Agent 来反驳每个发现
- 循环直到干净 — 持续查找,直到连续多轮无新发现
工作流的运行机制
- 隔离执行 — 脚本在 QuickJS 沙箱中运行,与对话上下文隔离
- 可恢复 — 同一会话内,已完成的
agent()调用返回缓存结果;仅变更或新增的调用重新执行 - 无主机 API — 脚本不能直接访问文件系统、网络或
require();所有 I/O 通过agent()叶子节点进行 - 并发 — 默认最多 3 个并发 Agent,可配置上限
- Token 预算 — 可选的总 completion token 上限
编写你的第一个自定义工作流
每个工作流脚本都以 meta 导出开始,定义其标识和阶段,
然后是包含编排逻辑的默认导出。
基本结构
export const meta = {
name: "my-workflow",
description: "这个工作流的简短描述",
phases: [
{ title: "收集", detail: "收集信息" },
{ title: "分析", detail: "分析结果并生成报告" },
],
};
export default async function main(args) {
const input = args || "默认输入";
phase("收集");
const data = await agent(`收集关于 ${input} 的信息`, {
label: "collector",
schema: {
type: "object",
required: ["findings"],
properties: {
findings: { type: "array", items: { type: "string" } },
},
},
});
phase("分析");
const report = await agent(
`基于以下发现生成报告:${data.findings.join("、")}`,
{ label: "analyst" },
);
return report;
} 保存工作流的位置
| 位置 | 范围 | 共享方式 |
|---|---|---|
| .whale/workflows/<名称>.js | 项目级 | 版本控制,团队共享 |
| ~/.whale/workflows/<名称>.js | 用户全局 | 跨项目可用 |
.claude/workflows/<名称>.js
复制到 .whale/workflows/<名称>.js 即可。所有 API 完全匹配。
实战示例:扇出研究
// .whale/workflows/research.js
export const meta = {
name: "research",
description: "多角度扇出搜索,然后综合",
phases: [
{ title: "搜索", detail: "多角度并行搜索" },
{ title: "综合", detail: "合并发现为一份报告" },
],
};
export default async function main(args) {
const topic = args || "默认主题";
phase("搜索");
const results = await parallel([
() => agent(`搜索 ${topic} 的最佳实践`),
() => agent(`找出 ${topic} 的常见错误`),
() => agent(`查找 ${topic} 的工具和框架`),
]);
phase("综合");
return await agent(
`将以下发现综合成一份简洁指南:\n\n${results.join("\n\n")}`,
{ label: "synthesizer" },
);
} 实战示例:循环直到干净的死代码扫描
const DRY_STREAK = 2
const MAX_ROUNDS = 5
const found = []
let emptyRounds = 0
let round = 0
while (emptyRounds < DRY_STREAK && round < MAX_ROUNDS) {
round++
phase("查找")
const { items } = await agent(
`第 ${round} 轮。扫描未引用符号。忽略已发现的:` +
`${found.map(r => r.symbol).join("、") || "暂无"}.`,
{ label: `find:round-${round}`, phase: "查找", schema: DEAD },
)
if (items.length === 0) {
emptyRounds++
continue
}
emptyRounds = 0
found.push(...items)
}
return { rounds: round, candidates: found } 实战示例:带屏障的并行摘要
phase("加载")
const { items } = await agent("读取反馈 CSV", { schema: ITEMS })
// 屏障:需要所有摘要才能聚类
const summaries = await parallel(items.map(it => () =>
agent(`摘要:${it.text}`, { label: `summarize:${it.id}` }),
))
phase("聚类")
const { themes } = await agent(
`将 ${summaries.length} 个项目聚类为排名主题:\n\n` +
summaries.map(s => `- ${s}`).join("\n"),
{ label: "cluster", schema: THEMES },
)
return { themes } 内置工作流:deep-research
Whale 内置了 deep-research 工作流,执行多阶段深度研究:
界定问题范围、多角度搜索、获取来源、对抗验证、综合引用报告。
阶段:范围界定 → 搜索 → 获取 → 验证 → 综合 管理工作流运行
在 TUI 中使用 /workflows 打开工作流面板:
- ↑ / ↓ — 选择阶段或 Agent
- Enter / → — 深入查看提示、工具调用和结果
- Esc — 返回上一级
- j / k — 在 Agent 详情中滚动
- p — 暂停/恢复
- x — 停止运行中的 Agent 或整个工作流
API 参考
| API | 用途 |
|---|---|
| agent(prompt, opts?) | 运行子 Agent,返回完整响应文本 |
| parallel(thunks) | 并发运行多个 agent thunk,返回结果数组 |
| pipeline(stages) | 按顺序运行阶段,每个接收前一个输出 |
| phase(name, detail?) | 声明命名阶段,用于进度追踪 |
| log(...args) | 记录工作流输出,在面板中可见 |
| budget | 只读,剩余 token 预算 |
| args | 只读,传递给工作流的参数 |
故障排除
| 问题 | 原因 | 修复 |
|---|---|---|
| "script must begin with export const meta" | 脚本头部错误 | 第一个非注释行必须是 export const meta = { ... } |
| "invalid workflow filename" | 不是 kebab-case | 使用 my-workflow.js |
| "filename must match meta.name" | 文件名不匹配 | my-workflow.js ⇔ name: "my-workflow" |
| "agent call limit exceeded" | 超出 Agent 调用限制 | 增加预算或减少 Agent |
| "workflow() cannot be called from within" | 嵌套工作流 | 仅主工作流可调子工作流 |
开始构建
动态工作流是 Whale 最强大的功能之一。无论你是构建研究流水线、 代码审查框架还是对抗验证器,JavaScript API 都为你提供了对多 Agent 编排的完全控制—— 一切都在你的终端中完成。
要开始使用,在你的项目中创建 .whale/workflows/ 目录,
编写你的第一个工作流脚本,然后向 Whale 描述它。
工作流面板(/workflows)让你实时查看每个阶段和 Agent 调用。