犀牛鸟 2026 研究笔记 estelledc.github.io

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.tssrc/Task.tssrc/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)

局限性


下一步