WORKFLOW_SCRIPTS — 确定性多 agent 工作流编排
Feature Flag:FEATURE_WORKFLOW_SCRIPTS=1引擎包:@claude-code-best/workflow-engine(确定性 JS 脚本编排,零核心层运行时依赖) 集成层:src/workflow/
一、功能概述
WORKFLOW_SCRIPTS 让 Claude Code 用确定性 JavaScript 脚本编排多个子 agent:可分解/并行、多视角置信、规模超单上下文、可 resume/可审计。- 编排原语:
agent/parallel/pipeline/phase/log/workflow(见引擎包)。 - 确定性:脚本在受限沙箱内执行,禁用
Date.now()/Math.random()/ 无参new Date(),保证 journal 可重放。 - 深度后端:单一
claude-codeAgentAdapter 接入当前会话体系(provider / model / agentType / 工具),workflow 内的agent()调用真实子 agent。 - 监控面板:
/workflows双栏实时面板(见 §六)。 - 编排手册:
/ultracode注入编排工作法(见 §七)。
历史说明:早期版本为 YAML/JSON DSL + 全 Stub 实现(WorkflowDetailDialog 等),已全量重写为引擎驱动的 JS 方案。
二、实现架构
2.1 模块清单
| 层 | 文件 | 职责 |
|---|---|---|
| 引擎 | packages/workflow-engine/src/ | 确定性脚本沙箱 + hooks + journal + budget + 信号量;导出 createWorkflowTool |
| 工具装配 | src/workflow/wiring.ts | createWorkflowToolCore() —— 用 WorkflowService.ports 组装 Workflow 工具 |
| 服务门面 | src/workflow/service.ts | WorkflowService 单例:launch / kill / subscribe / listRuns / listNamed / getWorkflowService() |
| 端口 | src/workflow/ports.ts | createWorkflowPorts() 聚合所有端口(agentRunner/registry/progress/task/journal/permission/logger/hostFactory) |
| 后端注册 | src/workflow/registry.ts | buildRegistry() 注册 claude-code 后端并设为默认 |
| 深度后端 | src/workflow/backends/claudeCodeBackend.ts | AgentAdapter:按 agentType/model 解析会话体系,跑真实子 agent,结构化输出 |
| Host 句柄 | src/workflow/hostHandle.ts | buildHostBundle() 不透明包装 toolUseContext/canUseTool/parentMessage |
| 进度总线 | src/workflow/progress/bus.ts | 基于 Set 的进度事件发射 |
| 进度状态 | src/workflow/progress/store.ts | reducer:按 agentId 精确关联 agent_done(修并发竞态) |
| 监控面板 | src/workflow/panel/*.tsx | /workflows 双栏 UI(见 §六) |
| 命名命令 | src/workflow/namedWorkflowCommands.ts | 扫描 .claude/workflows/ 生成 /<name> 命令 |
| 权限请求 | src/workflow/WorkflowPermissionRequest.tsx | workflow 启动权限 UI |
2.2 注册点
| 位置 | 内容 |
|---|---|
src/tools.ts:152-153,254 | createWorkflowToolCore() 动态加载并注册 Workflow 工具(feature-gated) |
src/commands.ts:95-97,392 | /workflows 命令(local-jsx,加载 panelCall.js) |
src/skills/bundled/ultracode.ts + index.ts | /ultracode 知识 skill(registerBundledSkill) |
三、编排原语
workflow 脚本内可用的钩子(语义详见引擎包engine/hooks.ts):
| 原语 | 语义 |
|---|---|
agent(prompt, opts?) | 派发一个子 agent;返回最终文本,或(带 opts.schema)结构化对象。opts:model / agentType / label / phase / schema |
parallel([() => …]) | 并发跑 thunk 数组,barrier(等全部完成);单项抛错 → 该项 null,其余保留 |
pipeline(items, s1, s2, …) | 每个 item 链式过各 stage;item 间无 barrier,stage 内顺序;单 item 某 stage 抛错 → 该 item null |
phase(title) | 标记阶段(面板按此分组展示) |
log(msg) | 进度日志(面板展示,无状态变更) |
workflow(name | { scriptPath }, args?) | 嵌套一层子 workflow(仅允许一层) |
parallel/pipeline ≤ MAX_ITEMS_PER_CALL(4096);单 workflow 总 agent ≤ MAX_TOTAL_AGENTS(1000);并发 cap 默认 = DEFAULT_MAX_CONCURRENCY(3),可经 Workflow 工具的 maxConcurrency 入参覆盖,绝对上限 MAX_CONCURRENCY_CAP(16)。
四、编写 workflow
脚本置于.claude/workflows/<name>.js|.mjs(也接受 .ts,但引擎不转译 TS,含类型注解会报语法错——推荐 .js/.mjs),自动成为 /<name> 命令。
new AsyncFunction 的函数体,不是 ESM 模块:
- 禁
import:agent/parallel/pipeline/phase/log/workflow与args/budget是注入的形参,直接用。 - 禁 TS 语法:不要类型注解(
x: number)、interface、enum、as、泛型。引擎不转译,即便文件是.ts也会原样报语法错。 - 只允许一处
export const meta = {...}(引擎正则提取剥离);不要export其他、不要export default。 - 顶层
return返回结果。
- 禁
Date.now()/Math.random()/ 无参new Date()(沙箱强制抛错)。需时间戳/随机种子经args传入。 export const meta = { ... }必须是纯字面量(无变量、函数调用、模板插值)——加载期求值,否则抛ScriptError。
五、Workflow 工具
模型通过Workflow 工具启动 workflow(input schema 见引擎包 tool/schema.ts):
| 字段 | 说明 |
|---|---|
script | 内联脚本字符串 |
name | 命名 workflow 名(对应 .claude/workflows/<name>) |
scriptPath | 脚本文件路径 |
args | 透传给脚本的 args(任意 JSON 值) |
resumeFromRunId | 从既有 runId 重放(已完成 agent() 秒回,发散点后现场重跑) |
六、监控面板:/workflows
/workflows 打开三区焦点面板(local-jsx,全屏):
- 顶部 tabs:每个 run 一个 tab(状态圆点 + workflow 名 +
#runId短码);同名脚本多次跑会多个 tab。 - 左 phase 侧栏:
All+ 合并 meta 声明的 phase(未启动○pending 灰)与实际 phase(●running /✓done);选中即决定右栏筛选。 - 右 agent 列表:按选中 phase 过滤;状态色 + 行尾文字(
running/object/text/dead)。
Tab/Shift+Tab 切 run · ←/→ 切左右焦点列(phases ↔ agents)· ↑/↓ 列内移动 · r resume · x kill · n 新建提示 · q/Esc 退出。
视觉:无内框,左右一条竖线分隔;聚焦列标题橙粗;选中/光标行铺橙底(backgroundColor),文字色不变。
进度按引擎 agentId 精确关联 agent_done(解决并发 LIFO 竞态)。pending phase 来自 run_started 事件携带的 meta.phases,store 落地 declaredPhases,面板 mergePhases 合并。useSyncExternalStore 订阅 WorkflowService,稳定快照,无变更不重渲染。
七、/ultracode skill
/ultracode(src/skills/bundled/ultracode.ts)注入多 agent workflow 编排工作法:何时用 / 何时不用、编排原语速查、质量模式库(adversarial-verify / judge-panel / loop-until-dry / multi-modal-sweep / completeness-critic)、确定性约束、后端路由、resume/budget、文件与命令。
纯知识 prompt skill:零运行时副作用,不改主循环、不切换行为开关。调用即把手册注入上下文。
八、resume / journal / budget
- journal:每次 run 记录到
.claude/workflow-runs/<runId>/journal.jsonl。resumeFromRunId重放 journal,已完成agent()秒回缓存结果。 - budget:
budget.total为 token 硬顶(默认null= 无限);budget.spent()/budget.remaining()读实时消耗;耗尽后再发agent()抛错。 - 并发:引擎
Semaphore默认许可 3(DEFAULT_MAX_CONCURRENCY),可经 Workflow 工具的maxConcurrency入参 per-run 覆盖(钳到[1, MAX_CONCURRENCY_CAP=16])。 - 错误:脚本语法/meta 错 →
parseScript即时返错(不进后台);agent 抛错 →kind:'dead'→null,workflow 继续(parallel/pipeline容错);WorkflowAbortedError→killed。
九、文件索引
| 文件 | 职责 |
|---|---|
src/workflow/wiring.ts | Workflow 工具装配(createWorkflowToolCore) |
src/workflow/service.ts | WorkflowService 门面 |
src/workflow/ports.ts | 端口聚合(createWorkflowPorts) |
src/workflow/registry.ts | AgentAdapterRegistry + 默认后端 |
src/workflow/backends/claudeCodeBackend.ts | 深度后端 AgentAdapter |
src/workflow/hostHandle.ts | 不透明 host 句柄(buildHostBundle) |
src/workflow/progress/bus.ts | 进度事件总线 |
src/workflow/progress/store.ts | 进度 reducer(agentId 关联) |
src/workflow/panel/*.tsx | /workflows 双栏面板 |
src/workflow/namedWorkflowCommands.ts | /<name> 命令发现 |
src/workflow/WorkflowPermissionRequest.tsx | 启动权限 UI |
src/skills/bundled/ultracode.ts | /ultracode 知识 skill |
src/tools.ts:152-153,254 | 工具注册 |
src/commands.ts:95-97,392 | /workflows 命令注册 |
packages/workflow-engine/ | 引擎包(hooks / journal / budget / 并发) |