Skip to main content

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-code AgentAdapter 接入当前会话体系(provider / model / agentType / 工具),workflow 内的 agent() 调用真实子 agent。
  • 监控面板/workflows 双栏实时面板(见 §六)。
  • 编排手册/ultracode 注入编排工作法(见 §七)。
历史说明:早期版本为 YAML/JSON DSL + 全 Stub 实现(WorkflowDetailDialog 等),已全量重写为引擎驱动的 JS 方案。

二、实现架构

   .claude/workflows/<name>.ts        Workflow 工具(name/script/scriptPath/args/resumeFromRunId)
            │                                       │
            ▼                                       ▼
   namedWorkflowCommands.ts              src/workflow/wiring.ts (createWorkflowToolCore)
   (/<name> 命令发现)                              │

                                      WorkflowService(门面:launch/kill/subscribe/listRuns/listNamed)

                                  ┌────────────────┼─────────────────┐
                                  ▼                ▼                 ▼
                          ports.ts            registry.ts        progress/
                       (端口聚合)      (AgentAdapterRegistry)  bus + store
                                  │                │
                                  ▼                ▼
                      hostHandle.ts        backends/claudeCodeBackend.ts
                     (不透明 host)       (深度读会话体系,跑真实 agent)


                  @claude-code-best/workflow-engine
                  (runWorkflow / hooks / journal / budget / 并发信号量)

2.1 模块清单

文件职责
引擎packages/workflow-engine/src/确定性脚本沙箱 + hooks + journal + budget + 信号量;导出 createWorkflowTool
工具装配src/workflow/wiring.tscreateWorkflowToolCore() —— 用 WorkflowService.ports 组装 Workflow 工具
服务门面src/workflow/service.tsWorkflowService 单例:launch / kill / subscribe / listRuns / listNamed / getWorkflowService()
端口src/workflow/ports.tscreateWorkflowPorts() 聚合所有端口(agentRunner/registry/progress/task/journal/permission/logger/hostFactory)
后端注册src/workflow/registry.tsbuildRegistry() 注册 claude-code 后端并设为默认
深度后端src/workflow/backends/claudeCodeBackend.tsAgentAdapter:按 agentType/model 解析会话体系,跑真实子 agent,结构化输出
Host 句柄src/workflow/hostHandle.tsbuildHostBundle() 不透明包装 toolUseContext/canUseTool/parentMessage
进度总线src/workflow/progress/bus.ts基于 Set 的进度事件发射
进度状态src/workflow/progress/store.tsreducer:按 agentId 精确关联 agent_done(修并发竞态)
监控面板src/workflow/panel/*.tsx/workflows 双栏 UI(见 §六)
命名命令src/workflow/namedWorkflowCommands.ts扫描 .claude/workflows/ 生成 /<name> 命令
权限请求src/workflow/WorkflowPermissionRequest.tsxworkflow 启动权限 UI

2.2 注册点

位置内容
src/tools.ts:152-153,254createWorkflowToolCore() 动态加载并注册 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/pipelineMAX_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> 命令。
// .claude/workflows/review-changes.js
export const meta = {
  name: 'review-changes',
  description: '按维度审查改动并对抗式验证',
  phases: [{ title: 'Review' }, { title: 'Verify' }],
}

const DIMENSIONS = [
  { key: 'bugs', prompt: '找正确性 bug' },
  { key: 'perf', prompt: '找性能问题' },
]

const results = await pipeline(
  DIMENSIONS,
  d => agent(d.prompt, { label: `review:${d.key}`, phase: 'Review' }),
  review => parallel(
    (review.findings || []).map(f => () =>
      agent(`对抗式验证:${f.title}`, { phase: 'Verify' })
    )
  )
)
return results.flat().filter(Boolean)
脚本执行约束(引擎执行模型,违反直接报错): 脚本是 new AsyncFunction函数体,不是 ESM 模块:
  • importagent/parallel/pipeline/phase/log/workflowargs/budget 是注入的形参,直接用。
  • 禁 TS 语法:不要类型注解(x: number)、interfaceenumas、泛型。引擎不转译,即便文件是 .ts 也会原样报语法错。
  • 只允许一处 export const meta = {...}(引擎正则提取剥离);不要 export 其他、不要 export default
  • 顶层 return 返回结果
确定性约束(违反则 resume 失效):
  • 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

/ultracodesrc/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.jsonlresumeFromRunId 重放 journal,已完成 agent() 秒回缓存结果。
  • budgetbudget.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 容错);WorkflowAbortedErrorkilled

九、文件索引

文件职责
src/workflow/wiring.tsWorkflow 工具装配(createWorkflowToolCore
src/workflow/service.tsWorkflowService 门面
src/workflow/ports.ts端口聚合(createWorkflowPorts
src/workflow/registry.tsAgentAdapterRegistry + 默认后端
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 / 并发)