犀牛鸟 2026 · 开源研究笔记

Claude Code Dynamic Workflow + Ultracode:编排外置与确定性调度

一句话定位:Dynamic Workflow 是 Claude Code 的”编排外置”层——把原本消耗 token 的调度逻辑移到确定性 JavaScript 脚本中,让模型只负责执行具体任务,实现 1000 个子 agent 的并行编排。

调研时间:2026-06-22
依据版本:泄露源码包(2026-03-31 stub)+ 官方文档(v2.1.154+)+ 社区实战
核心文件:src/tasks.ts、src/Task.ts、src/tasks/LocalWorkflowTask.js(DCE 剔除)


证据等级汇总

结论 来源
TaskType 含 local_workflow(ID 前缀 w/) [源码] Task.ts
WORKFLOW_SCRIPTS flag 守护 LocalWorkflowTask 加载 [源码] tasks.ts
实现文件被 DCE 剔除,泄露包中仅有 stub [源码] tasks.ts
5 个原语 API(agent/parallel/pipeline/phase/log) [官方] code.claude.com/docs/en/workflows
受限 JS 沙箱(无 fs/net/child_process) [官方] 文档 + [社区] 实战验证
并发上限 16 / 总 agent 上限 1000 [官方] 文档
Ultracode = effort xhigh + 自动 workflow 决策 [社区] 多源交叉验证
Resume 机制(确定性重放) [官方] 文档
v2.1.154(2026-05-28)正式发布 [官方] 博客
Bun Zig→Rust 移植案例(75 万行,11 天) [社区] 知乎

日常类比

传统模式像一个人独自装修房子——自己量尺寸、买材料、刷墙、装灯,每件事串行做,而且每做一步都要在脑子里记住”接下来该干什么”(消耗 context)。

Dynamic Workflow 像请了一个工头——工头手里有一张施工计划表(JS 脚本),按计划派电工、水管工、油漆工同时开工。工头自己不搬砖(不消耗 model token),只负责看计划表决定”谁先谁后、谁能并行”。工人(子 agent)各自独立干活,完成后向工头汇报。

类比边界:真实系统中”施工计划表”是 Claude 自己写的(或用户预定义的),而且工头可以根据中间结果动态调整后续步骤——这比纸质计划表灵活得多。


架构全景

graph TB
    subgraph "用户层"
        User[用户 prompt<br>"ultracode: 审计这个项目"]
        PreDef[".claude/workflows/*.js<br>预定义脚本"]
    end

    subgraph "决策层"
        PUI[processUserInput] --> Decision{适合 Workflow?}
        Decision -->|是| Gen[Claude 生成 workflow.js]
        Decision -->|否| Normal[普通 queryLoop]
        PreDef -->|"斜杠命令触发"| Exec
    end

    subgraph "编排层(确定性 JS)"
        Gen --> Exec[Workflow 沙箱执行]
        Exec --> Phase["phase('分析')"]
        Exec --> Agent1["agent('分析前端')"]
        Exec --> Agent2["agent('分析后端')"]
        Exec --> Par["parallel([...])"]
        Exec --> Pipe["pipeline(items, stages)"]
    end

    subgraph "执行层(子 agent)"
        Agent1 --> QL1[queryLoop #1<br>独立 context]
        Agent2 --> QL2[queryLoop #2<br>独立 context]
        Par --> QL3[queryLoop #3..#N]
        QL1 --> Tools1[Read/Write/Bash/...]
        QL2 --> Tools2[Read/Write/Bash/...]
    end

    subgraph "汇总层"
        QL1 -->|结果| Exec
        QL2 -->|结果| Exec
        QL3 -->|结果| Exec
        Exec -->|最终报告| User
    end

核心概念:编排外置

传统模式的瓶颈

在普通 queryLoop 中,编排逻辑(”先做 A,再做 B,C 和 D 可以并行”)存在于模型的 context window 中:

[System Prompt] + [对话历史] + [编排推理] + [执行结果]
                                    ↑
                              消耗 token,且随任务复杂度线性增长

当任务需要协调 10+ 个步骤时,编排推理本身就占据大量 context,导致三个结构性问题:

Workflow 的解法

编排逻辑 → 确定性 JS 脚本(零 token 成本)
执行逻辑 → 子 agent 的独立 queryLoop(各自有完整 context)

关键洞察:编排是确定性的(”先 A 后 B”不需要 AI 推理),执行才需要 AI。把确定性部分移出模型,让模型专注于它擅长的事。


五个原语 API

原语 签名 作用
agent agent(prompt, opts?) → string 派发一个子 agent,返回其文本输出
parallel parallel(thunks[]) → string[] 并行执行多个 thunk,等待全部完成
pipeline pipeline(items, ...stages) → string[] 数据流式经过多个 stage
phase phase(name) 声明当前阶段(UI 进度展示)
log log(message) 输出日志到用户界面

agent() 详解

const result = await agent('分析 src/auth/ 目录的安全漏洞', {
  // 可选参数
  model: 'sonnet',        // 子 agent 使用的模型(默认继承)
  permissionMode: 'acceptEdits',  // 权限模式
  maxTurns: 50,           // 最大轮次
  tools: ['Read', 'Grep', 'Glob'],  // 限制可用工具
})

底层实现:每个 agent() 调用创建一个 TaskType='local_agent' 的任务,注册到 taskStates Map 中,启动独立的 queryLoop 循环。子 agent 拥有完整的工具集(除非通过 tools 参数限制)。

parallel() 详解

const [frontend, backend, infra] = await parallel([
  () => agent('审计前端代码'),
  () => agent('审计后端代码'),
  () => agent('审计基础设施配置'),
])
// 三个子 agent 同时启动,全部完成后继续

并发控制:实际并发数 = min(16, CPU核数 - 2)。超出的任务排队等待。

pipeline() 详解

const results = await pipeline(
  ['file1.ts', 'file2.ts', 'file3.ts'],  // items
  (file) => agent(`分析 ${file} 的类型安全问题`),  // stage 1
  (analysis) => agent(`为以下问题生成修复方案: ${analysis}`),  // stage 2
  (fix) => agent(`验证修复方案的正确性: ${fix}`),  // stage 3
)

语义:每个 item 依次经过所有 stage,但不同 item 之间可以并行(流水线并行)。


Ultracode 模式

不是独立功能,而是设置组合

组件 值
effort 级别 xhigh(非 max)
自动 workflow 模型自主判断是否需要编排
触发方式 /effort ultracode 或 prompt 含 “ultracode”

与其他模式的关系

graph LR
    subgraph "执行模式谱系"
        Plan["/plan<br>只读规划"] --> Auto["/auto<br>自动执行"]
        Auto --> Ultra["Ultracode<br>多 agent 编排"]
    end

    subgraph "编排方式"
        Single["单 agent<br>queryLoop"] --> Coord["Coordinator<br>主从模式"]
        Coord --> Swarm["Swarm<br>对等协作"]
        Swarm --> Workflow["Dynamic Workflow<br>确定性编排"]
    end

    Ultra -.->|"自动选择"| Workflow
    Ultra -.->|"简单任务退化为"| Single

Ultracode 的决策流程

用户 prompt 进入
  → processUserInput 检测 "ultracode" 关键词
    → 模型评估任务复杂度
      → 复杂(多文件/多维度/大规模): 生成 workflow.js 并执行
      → 简单: 退化为普通 queryLoop(但 effort 仍为 xhigh)

受限沙箱

Workflow 脚本运行在严格受限的 JavaScript 沙箱中 [官方]:

可用

不可用

为什么禁止 Date/Random:Resume 机制依赖确定性重放。如果脚本中有随机数或时间依赖,中断后重放会走不同路径,无法正确恢复。


Resume 机制

首次执行:
  agent('A') → 结果缓存 → agent('B') → 中断!

Resume:
  agent('A') → 命中缓存,直接返回 → agent('B') → 重新执行

实现原理:

  1. 相同脚本 + 相同输入参数 = 可恢复
  2. 每个 agent() 调用的结果被持久化
  3. Resume 时重放脚本,遇到已完成的调用直接返回缓存
  4. 只对未完成的部分启动新的子 agent

确定性要求:脚本必须是纯函数——给定相同输入,执行路径完全相同。这就是为什么禁止 Date.now() 和 Math.random()。


运行限制

限制项 值 原因
最大并发 agent min(16, CPU-2) 避免 CPU 过载
单 workflow 总 agent 1000 防止失控
pipeline 单次 items 4096 内存限制
脚本最大长度 524288 字符 沙箱解析限制
无默认 token 上限 — 用户可通过 +500k 指令设置

源码中的痕迹

Task.ts 中的类型定义 [源码]

type TaskType = 
  | 'local_bash'           // ID: b/
  | 'local_agent'          // ID: a/
  | 'remote_agent'         // ID: r/
  | 'in_process_teammate'  // ID: t/
  | 'local_workflow'       // ID: w/   ← Workflow 任务
  | 'monitor_mcp'          // ID: m/
  | 'dream'                // ID: d/

tasks.ts 中的条件加载 [源码]

const LocalWorkflowTask = feature('WORKFLOW_SCRIPTS')
  ? require('./tasks/LocalWorkflowTask.js')
  : null

关键发现:泄露源码(2026-03-31)中 WORKFLOW_SCRIPTS flag 为 false,LocalWorkflowTask.js 被 DCE 完全剔除。正式发布是 2026-05-28(v2.1.154),晚于泄露时间点近两个月。

Workflow 脚本 meta 结构 [官方]

export const meta = {
  name: 'audit-security',
  description: '全项目安全审计',
  phases: [
    { title: '扫描', detail: '识别潜在漏洞' },
    { title: '分析', detail: '评估风险等级' },
    { title: '修复', detail: '生成修复方案' },
  ],
}

七个质量模式 [社区]

社区实践中总结的高效 Workflow 编写模式:

模式 核心思想 示例
Adversarial Verify 用独立 agent 验证另一个 agent 的输出 agent('验证: ' + result)
Divide & Conquer 大任务拆成独立子任务并行 parallel([...files.map(f => () => agent(f))])
Pipeline 数据流式经过多个处理阶段 pipeline(items, analyze, fix, verify)
Loop-Until-Budget 设置 token 预算,循环直到用完 while(budget > 0) { agent(...) }
Consensus 多个 agent 独立解决同一问题,取共识 parallel([solver1, solver2, solver3]) → 投票
Escalation 简单模型先做,失败时升级到强模型 agent(p, {model:'haiku'}) → 失败 → agent(p, {model:'opus'})
Checkpoint 每阶段保存中间结果,支持断点续传 配合 Resume 机制

与其他编排方式对比

维度 queryLoop 单 agent Coordinator Swarm Dynamic Workflow
编排位置 model context 内 主 agent context 对等协商 外置 JS 脚本
编排成本 消耗 token 消耗主 agent token 消耗所有 agent token 零(确定性代码)
并行能力 无 有限(主 agent 调度) 有限(协商开销) 最多 1000 agent
确定性 否(模型决策) 否 否 是(JS 脚本)
可恢复 否 否 否 是(Resume)
适用规模 小任务 中等任务 协作任务 大规模任务
用户控制 低 中 低 高(可预定义脚本)

与开源框架对比

维度 Claude Code Workflow LangGraph CrewAI
编排语言 受限 JS(5 原语) Python(完整) Python(完整)
编排生成 AI 自动生成 用户手写 用户手写
沙箱隔离 严格(无 fs/net) 无 无
确定性保证 是(禁止副作用) 否 否
Resume 支持 内置 需自行实现 checkpoint 无
并发模型 进程级隔离 线程/协程 线程
最大并发 1000 agent 无硬限制 无硬限制
学习成本 低(5 个 API) 高(状态图 DSL) 中(角色定义)

核心差异:Claude Code 的 Workflow 是AI 生成的确定性编排——模型理解任务后自动写出调度脚本,而 LangGraph/CrewAI 需要开发者手动定义编排逻辑。这是”AI 写代码调度 AI”的范式。


ScheduleWakeup 与 /loop 的关系

Dynamic Workflow 还有一个时间维度的编排——/loop 命令配合 ScheduleWakeup 工具:

/loop "监控 CI,失败时自动修复"
  → Claude 执行一轮
    → ScheduleWakeup(delaySeconds=120, prompt="<<autonomous-loop-dynamic>>")
      → 120 秒后自动唤醒
        → 检查 CI 状态
          → 失败: 启动修复 workflow
          → 成功: ScheduleWakeup(delaySeconds=1800, reason="CI 绿了,降低频率")

间隔选择与 Prompt Cache 的关系:


实战案例

Bun 的 Zig→Rust 移植 [社区]

大规模代码审计

export const meta = {
  name: 'security-audit',
  description: '全项目安全审计',
  phases: [
    { title: '扫描' },
    { title: '分析' },
    { title: '报告' },
  ],
}

phase('扫描')
const files = await agent('列出所有处理用户输入的文件路径,每行一个')
const fileList = files.trim().split('\n')

phase('分析')
const findings = await parallel(
  fileList.map(f => () => agent(`分析 ${f} 的安全漏洞,重点关注注入和越权`))
)

phase('报告')
const report = await agent(`汇总以下发现,按严重程度排序:\n${findings.join('\n---\n')}`)
log(report)

局限性


下一步