<!-- title: 动态工作流：Claude自写千Agent编排脚本 -->

## 概述

本教程聚焦 Claude Code 于 2026 年 5 月正式落地的**动态工作流（Dynamic Workflows）**——一项让 Claude 自己编写 JavaScript 编排脚本、把成百上千个子代理（subagent）调度成一整条流水线的自动化能力。你将学到：动态工作流与子代理、Skill、Agent Teams 的本质区别；如何用 `ultracode` 关键词触发编排；如何读懂、保存、参数化、续跑 Claude 写出的脚本；以及成本、权限与无人值守（`claude -p`）下的实战控制。适合已经熟悉 `-p` 模式与基础子代理、希望把"人盯单次对话"升级为"代码化可复跑大规模编排"的中高级用户。

## 前置条件

- Claude Code **v2.1.154 及以上**（动态工作流的最低版本；保存到就近 `.claude/workflows/` 的行为需 v2.1.178+）。
- 一个付费订阅（Pro/Max/Team/Enterprise），或通过 Anthropic API、Amazon Bedrock、Google Vertex AI、Microsoft Foundry 接入。Pro 用户需在 `/config` 的 **Dynamic workflows** 行手动开启。
- 终端里能正常跑 `claude`；若要在脚本里复跑，建议同时具备 `git` 与一个待处理的真实代码仓库。
- 对"子代理 = Claude 在对话中临时派生的工作者"这一概念有基本认知。

## 一、动态工作流到底是什么

子代理（Subagents）、Skill、Agent Teams、Workflows 都能完成多步骤任务，区别在于**"谁掌握计划"**。

在子代理、Skill、Agent Teams 模式下，Claude 自己当指挥：它逐轮决定下一步派谁、分什么活，而每一步的中间结果都回到 **Claude 的上下文窗口**里。规模一大，上下文就会被日志挤爆，编排也变得不可复现。

动态工作流把**计划搬进代码**。Claude 针对你描述的任务，写出一个 JavaScript 编排脚本；一个独立运行时在后台执行它，会话保持响应。循环、分支、中间结果都存在**脚本变量**里，Claude 的上下文只保留最终答案。脚本可读、可改、可重新运行——这就是"脚本取代上下文窗口"的核心思想。

| 维度 | 子代理 Subagents | Skill | Agent Teams | 动态工作流 Workflows |
|---|---|---|---|---|
| 本质 | Claude 派生的工作者 | Claude 遵循的指令 | 主代理监督若干同伴会话 | 运行时执行的脚本 |
| 谁决定下一步 | Claude，逐轮 | Claude，按提示 | 主代理，逐轮 | **脚本** |
| 中间结果在哪 | Claude 上下文 | Claude 上下文 | 共享任务列表 | **脚本变量** |
| 可复用的是什么 | 工作者定义 | 指令本身 | 团队定义 | **整套编排** |
| 规模 | 单轮几次委派 | 同子代理 | 少量长跑同伴 | **数十到数百个代理** |
| 中断后 | 重启该轮 | 重启该轮 | 同伴继续跑 | **同会话内可续跑** |

另一层价值在于**可复用的质量模式**：脚本可以让多个独立代理互相"对抗式审查（adversarial review）"彼此的发现，或从多个独立角度起草方案再权衡，从而得到比单趟遍历更可信的结果——这不仅是"跑更多代理"，而是"跑得更稳"。

## 二、运行时提供的脚本原语

Claude 写出的脚本并非任意 JS，而是运行在受控沙箱里、只能调用一组固定原语的程序。掌握这组原语，你就能读懂并微调 Claude 的产出：

- `agent(prompt, {label, phase, schema, model, isolation, agentType})`：派生一个子代理，返回它的最终文本；带 `schema` 时返回结构化对象（强制走结构化输出工具，免解析）。
- `parallel(thunks)`：**屏障式**并发，等所有任务返回；某任务抛错会落成 `null`，不会拖垮整批。
- `pipeline(items, stage1, stage2, ...)`：**流水线**，每个 item 独立穿过所有阶段，阶段间无屏障，墙钟等于最慢的单条链路——这是大规模编排的默认骨架。
- `phase(title)`：声明一个进度阶段，配合 `/workflows` 视图分组展示。
- `log(message)`：向用户输出一行进度旁白。
- `args`：保存的工作流可接收的结构化入参全局变量。
- `budget`：当前轮次的 token 目标，用于按预算动态扩缩 finder 数量。

注意几条硬约束（脚本里无法使用）：`Date.now()`、`Math.random()`、无参 `new Date()` 都会抛错——它们会破坏"可续跑"的确定性。时间戳需通过 `args` 传入，随机性靠"按 index 变化 prompt"来实现。

## 三、第一步：跑通内置 `/deep-research`

最快体验动态工作流的方式是跑内置命令 `/deep-research`，它针对一个问题在多个角度扇出网络检索、抓取并交叉校验来源、对每条论断投票，最后产出带引用的报告。

```
/deep-research Node.js v20 到 v22 的权限模型发生了哪些变化？
```

预期行为：

1. Claude Code 弹出**是否允许该工作流**的确认（取决于权限模式）。
2. 选 `Yes` 后，运行在后台启动，你的会话保持响应。
3. 输入框下方任务面板出现一行进度摘要；按 `↓` 聚焦、`Enter` 展开，或运行 `/workflows` 用方向键选中该运行、`Enter` 进入进度视图。

进入 `/workflows` 后，视图列出每个阶段的代理数、token 总量、耗时。底部按键说明：

| 按键 | 动作 |
|---|---|
| `↑` / `↓` | 选择阶段或代理 |
| `Enter` / `→` | 钻入阶段，再钻入单个代理查看其 prompt、最近工具调用与结果 |
| `Esc` | 返回上一层 |
| `j` / `k` | 代理详情溢出时滚动 |
| `p` | 暂停 / 恢复运行 |
| `x` | 停止选中代理，或（焦点在整条运行时）停止整条工作流 |
| `r` | 重启某个运行中的代理 |
| `s` | **把本次运行的脚本保存为命令** |

**常见问题**：报告迟迟不出——多半是某个阶段的代理在等不在白名单里的工具确认。解决：开跑前把代理需要的命令加进工具白名单（见第六节）。

## 四、第二步：让 Claude 为你的任务写工作流

两种触发方式：

**方式 A：单次任务里带 `ultracode` 关键词**（或自然语言"用工作流来做"/"run a workflow"）。关键词会被高亮，Claude 据此为该任务写脚本而非逐轮推进：

```
ultracode: 审计 src/routes/ 下每个 API 端点是否缺少鉴权检查
```

若误触，macOS 按 `Option+W`、Windows/Linux 按 `Alt+W` 取消本次高亮；要彻底关闭关键词触发，在 `/config` 关掉 **Ultracode keyword trigger**。

**方式 B：整会话开启 `/effort ultracode`**——它把 `xhigh` 推理强度与自动工作流编排合二为一。开启后 Claude 对每个实质性任务都会规划工作流；单个请求甚至可能变成"理解代码 → 实施改动 → 验证"一连串多条工作流。注意：ultracode 仅当前会话有效，重开会话即重置，且回到常规工作要 `/effort high` 降档。

**批准计划**：CLI 会在运行前展示规划的阶段，给出选项：

- `Yes, run it`：开始运行；
- `Yes, and don't ask again for <name> in <path>`：开始，且本项目该工作流今后不再询问；
- `View raw script`：先读脚本；
- `No`：取消；
- `Ctrl+G` 在编辑器打开脚本；`Tab` 在运行前调整 prompt。

是否看到此提示取决于权限模式（见下表）。值得强调：**无论你会话处于什么模式，工作流派生的子代理始终以 `acceptEdits` 模式运行并继承你的工具白名单**，文件编辑自动放行；但不在白名单里的 shell、网络抓取、MCP 工具仍可能在运行中弹确认——长跑前先把它们加进白名单。

| 权限模式 | 何时弹出批准 |
|---|---|
| Default / accept edits | 每次运行（除非已选"本项目不再询问"） |
| Auto | 仅首次启动；任一 `Yes` 会记入用户设置，后续自动启动；ultracode 下直接跳过 |
| Bypass permissions / `claude -p` / Agent SDK | **从不**，立即启动 |

## 五、第三步：读懂 Claude 写出的脚本

每次运行都会把脚本写到会话目录下的 `~/.claude/projects/<session>/` 里。Claude 启动时会拿到该路径——你可以直接要求它"把刚才写的脚本路径给我"，然后打开阅读、与上次运行的脚本 diff、甚至编辑后让 Claude 用修改版重跑。

下面是一段典型编排脚本的结构（以"路由鉴权审计"为例，省略 schema 细节）。它体现官方推荐的**默认流水线 + 对抗式校验**模式：先按维度找问题，每个发现立即独立校验，校验通过的才进入综合。

```javascript
export const meta = {
  name: 'auth-audit',
  description: '审计 src/routes 下缺失鉴权的端点',
  phases: [{ title: '扫描' }, { title: '校验' }],
};

const ROUTES = [
  'src/routes/users.ts',
  'src/routes/orders.ts',
  'src/routes/admin.ts',
  // ...args 传入或 glob 得到的全部路由文件
];

phase('扫描');

// 流水线：每个文件独立穿过"扫描 → 校验"，阶段间无屏障
const results = await pipeline(
  ROUTES,
  (file) => agent(
    `读取 ${file}，列出所有未做鉴权检查的端点及缺失的中间件`,
    { label: `scan:${file}`, phase: '扫描', schema: FINDINGS_SCHEMA }
  ),
  (scan, file) => parallel((scan?.findings || []).map((f) => () =>
    agent(
      `对抗式核验：${f.title} 真的缺鉴权吗？默认怀疑，给出依据`,
      { label: `verify:${file}`, phase: '校验', schema: VERDICT_SCHEMA }
    ).then((v) => ({ ...f, file, verdict: v }))
  ))
);

// 只保留校验通过的真实问题
const confirmed = results
  .flat().filter(Boolean)
  .filter((f) => f.verdict?.isReal);

log(`确认 ${confirmed.length} 处鉴权缺失`);
return { confirmed };
```

关键读法：

- `meta` 必须是纯字面量，`phases` 的标题与 `phase()` 调用一一对应，否则进度视图对不上。
- 默认用 `pipeline` 而非"先 `parallel` 全扫、再 `parallel` 全校验"——后者会引入屏障，快文件被慢文件拖着白白等待。
- `schema` 把非结构化文本变成可校验对象，下游 `.filter()` 直接可用，免去正则解析。
- `budget` 可用于按 token 预算扩缩 finder：`while (budget.total && budget.remaining() > 50_000) { ... }`，没设目标时 `remaining()` 为 `Infinity`，所以务必先判 `budget.total`。

## 六、第四步：保存为可复用命令并参数化

一条工作流跑出满意结果后，按 `s` 保存。保存对话框里 `Tab` 在两个位置间切换：

- **`.claude/workflows/`（项目级）**：随仓库克隆共享给团队；
- **`~/.claude/workflows/`（用户级）**：所有项目可用，仅你可见。

保存后它就成了 `/<name>` 命令，出现在 `/` 自动补全里，与内置的 `/deep-research` 并列。v2.1.178 起，保存到项目位置会写入从当前工作目录到仓库根之间**已存在的最近一个** `.claude/workflows/`（适合 monorepo 按包归位）；同名时项目级优先于用户级。

**参数化**靠 `args` 全局变量。保存的工作流在运行时可接收结构化入参：

```
> 用 /triage-issues 处理 issue 1024、1025、1030
```

Claude 把列表作为结构化数据传给脚本，`args` 在脚本内是数组，可直接 `args.map(...)`，不必先解析字符串。省略 `args` 时它为 `undefined`。

> 注意：`args` 必须是真 JSON 值而非字符串化的 JSON，否则 `args.filter`/`args.map` 会抛错。

## 七、第五步：监控、暂停与续跑

工作流全程在后台，会话始终可交互。`/workflows` 随时列出运行中与已完成的运行。

**续跑是动态工作流区别于子代理的关键能力**：停掉一条运行后，已完成的代理返回**缓存结果**，剩余部分实时重跑。从 `/workflows` 选中运行按 `p` 即可，或让 Claude 用同一脚本重启。

限制：续跑**仅在同一 Claude Code 会话内有效**。退出 Claude Code 时若仍有工作流在跑，下次会话会**全新启动**该工作流——这是设计取舍，保证确定性。

## 八、第六步：成本与规模控制

一条工作流派生大量代理，单次运行的 token 消耗显著高于对话式推进，且计入套餐用量与速率限制。控制手段：

- **先小切片**：全仓库审计前先用单个目录试跑；宽问题前先用窄问题试跑。`/workflows` 实时显示每个代理的 token，随时停而不丢已完成工作。
- **硬上限兜底**：运行时强制最多 **16 个并发代理**（CPU 核少的机器更少）、**单次运行总计 1000 个代理**，防止脚本失控烧钱。
- **模型路由**：每个代理默认用会话模型，但脚本可把对模型强度要求低的阶段路由到更便宜的模型。做法：开跑前确认 `/model`；或在描述任务时直接要求"扫描阶段用更小的模型"。

## 九、第七步：权限与无人值守

动态工作流在 CLI、桌面端、IDE 扩展、**非交互的 `claude -p`** 以及 **Agent SDK** 上均可用，禁用设置在所有界面通用。

无人值守场景（CI/管道）的两条要点：

1. **`claude -p` 与 Agent SDK 没有人可被提示**，工具调用按你配置的权限规则直接执行，工作流立即启动不询问。务必在开跑前把代理需要的命令写进白名单。
2. 子代理恒以 `acceptEdits` + 继承白名单运行——这是默认安全位，意味着文件改动会自动发生，需配合白名单收敛"能跑什么命令、能访问哪些 MCP 工具"。

**关闭工作流**（任选其一，跨会话持久）：

- `/config` 里关掉 **Dynamic workflows**；
- `~/.claude/settings.json` 设 `"disableWorkflows": true`；
- 环境变量 `CLAUDE_CODE_DISABLE_WORKFLOWS=1`（启动时读取，放哪都生效）；
- 组织级在 managed settings 设 `"disableWorkflows": true`，或用 Claude Code 管理后台开关。

关闭后，内置工作流命令不可用、`ultracode` 关键词不再触发、`/effort` 菜单移除 ultracode 项。

## 十、实战案例：全仓库鉴权缺失审计工作流

目标：把"路由鉴权审计"做成团队可一键复跑、可按 issue 列表参数化的命令。

**1. 触发并迭代**。在仓库根目录：

```
ultraccode: 审计 src/routes/ 下每个端点的鉴权缺口，
对每个候选发现用独立代理对抗式核验，只保留核验通过的真实问题，
按文件聚合输出 Markdown 报告
```

**2. 审阅脚本**。批准前选 `View raw script`，确认它的扇出对象是路由文件全集、校验阶段默认怀疑（`isReal` 默认 false）、综合阶段去重。

**3. 小切片试跑**。先临时把脚本里 `ROUTES` 缩成两个文件，确认 `findings → verify → filter(isReal)` 链路闭合、token 可控，再恢复全集。

**4. 保存为命令**。运行 `/workflows`，选中运行，按 `s`，`Tab` 选 `.claude/workflows/`，命名为 `auth-audit`，回车。此后：

```
/auth-audit                          # 审计全部路由
/auth-audit routes=["src/routes/admin.ts"]   # 带结构化 args 只审指定文件
```

**5. 接入 CI（无人值守）**。在流水线脚本里：

```bash
claude -p "/auth-audit" --output-format json > audit.json
# audit.json 即脚本 return 的结构化结果，可直接被下游解析
```

`claude -p` 下工作流立即启动、无人工确认；`--output-format json` 让脚本 `return` 的对象原样落盘，供 CI 判定"是否存在 confirmed 缺口 → 是否阻断合并"。

**6. 续跑**。若本地长跑被中断，同会话内 `/workflows` → 选中 → `p` 续跑，已完成文件走缓存；CI 里则因每次新会话只能全新重跑，故务必保证脚本幂等（校验阶段对同一发现结论一致）。

## 工作流执行生命周期

```mermaid
flowchart TD
    A[prompt 带 ultracode 关键词] --> B{权限模式判断}
    B -->|Default/acceptEdits| C[弹批准: Yes/不再问/看脚本/No]
    B -->|Auto| D[首次确认后自动启动]
    B -->|Bypass / claude -p / SDK| E[立即启动 无确认]
    C --> F[Claude 写 JS 编排脚本]
    D --> F
    E --> F
    F --> G[脚本写入 ~/.claude/projects/会话/]
    G --> H[后台运行时执行]
    H --> I[16并发/1000上限内扇出子代理]
    I --> J[中间结果存脚本变量 不进上下文]
    J --> K{暂停?}
    K -->|是| L[已完成代理缓存 剩余实时重跑]
    K -->|否| M[综合阶段: 去重/对抗校验]
    L --> M
    M --> N[最终答案返回会话]
    N --> O{满意?}
    O -->|是, 按 s| P[保存为 .claude/workflows/ 命令]
    O -->|否| Q[编辑脚本 让 Claude 用修改版重跑]
    Q --> H
```

## 训练营适用性评估

- **进阶 AI 工程训练营 / 企业级 Agent 实战营**：高度契合。把"会话级编排"升级到"代码化可复跑大规模编排"是进阶核心一跃，建议放在 `-p` 模式与子代理章节之后。
- **预计教学时长**：讲授 + 内置 `/deep-research` 动手约 **45 分钟**；自定义工作流的编写、保存、参数化与 CI 接入约 **90 分钟**；总计约 **2.5–3 课时**。
- **前置依赖**：学员需先掌握子代理概念、`/config` 与 `/model` 基本操作、`claude -p` 非交互模式。
- **学员产出物**：一条保存在 `.claude/workflows/` 下、带 `args` 参数、可被 CI 用 `--output-format json` 调用的团队级工作流命令。

## 延伸阅读

- Claude Code 官方文档《Orchestrate subagents at scale with dynamic workflows》——权威特性说明与限制。
- Claude 博客《Introducing dynamic workflows in Claude Code》——设计动机与典型场景。
- 《Claude Code Headless: The Complete Self-Hosting Guide (2026)》——`claude -p` 与 CI 接入的工程实践。
- 《Mastering Claude Code Sessions: -continue & -resume》——会话续接机制，与工作流的"同会话续跑"互补。

## 参考来源

1. [Orchestrate subagents at scale with dynamic workflows — Claude Code Docs](https://code.claude.com/docs/en/workflows) — 动态工作流官方权威文档，覆盖触发、保存、续跑、限制与权限。
2. [Run Claude Code programmatically — Claude Code Docs (Headless)](https://code.claude.com/docs/en/headless) — `claude -p` 与 Agent SDK 非交互运行机制，含 `--output-format` 与权限规则。
3. [Work with sessions — Claude Code Docs](https://code.claude.com/docs/en/agent-sdk/sessions) — `continue`/`resume`/`fork` 会话管理，解释工作流"同会话续跑"的会话边界。
4. [Introducing dynamic workflows in Claude Code — Claude Blog](https://claude.com/blog/introducing-dynamic-workflows-in-claude-code) — 官方发布公告，"脚本取代上下文窗口"的动机与场景。
5. [Claude Code Dynamic Workflows: Scripts Replace Context Windows (TechTimes, 2026)](https://www.techtimes.com/articles/317363/20260529/claude-code-dynamic-workflows-scripts-replace-context-windows-ultracode-automates-orchestration.htm) — 第三方对 2026-05-28 发布与 ultracode 自动编排的解读。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
