# Dynamic Workflows（动态工作流）

> Dynamic Workflows 让 CodeBuddy 写一段 JavaScript 编排脚本，由运行时在后台调度数十甚至数百个子代理协作完成任务。脚本本身可读、可改、可重跑，适合代码库审计、大型迁移、需要交叉验证的研究类任务。

<Note>
Dynamic Workflows 目前为研究预览阶段，要求 CodeBuddy Code v2.105.0 或更高版本，默认已启用。如需关闭，可在 `/config` 中关掉 "Dynamic workflows" 开关。
</Note>

Dynamic Workflow 是一段由 CodeBuddy 为你的任务现场编写的 JavaScript 脚本，运行时在后台执行它，你的会话保持响应。脚本里包含一个或多个 [`agent()`](#脚本-api) 调用，每次调用都派出一个独立的子代理工作；脚本拿到中间结果后，可以分支、可以并行、可以再投递给下一批子代理。

当一项任务大到一个会话装不下，或者你希望编排逻辑被记录成"可重跑的脚本"时，就该用 Workflow。典型场景：

- 全 monorepo 的接口契约 / 鉴权 / 埋点巡检
- 一组 issue 的批量分诊与归属定位
- 跨多个仓库 / 多源资料的交叉印证调研
- 一个值得从多个独立角度先各自起草、再相互对照择优的方案

本页介绍：

- [何时该用 Workflow](#何时该用-workflow)（与子代理 / Skills / Agent Teams 的取舍）
- [运行内置 Workflow](#运行内置-workflow)：`/deep-research`
- [让 CodeBuddy 为你的任务写一个 Workflow](#让-codebuddy-写-workflow)，并保存复用
- [Workflow 的运行机制](#workflow-的运行机制) 与 [运行管理](#运行管理)

## 何时该用 Workflow

[子代理](sub-agents.md)、[Skills](skills.md)、[Agent Teams](agent-teams.md) 与 Workflows 都能跑多步任务，差别在于"谁握着计划"：

|                       | 子代理                       | Skills                    | Agent Teams                       | Workflows                       |
| :-------------------- | :--------------------------- | :------------------------ | :-------------------------------- | :------------------------------ |
| 本质                  | CodeBuddy 派出去的工人       | CodeBuddy 遵循的指令      | 一个领导监管一组同侪会话          | 运行时执行的一段脚本            |
| 谁决定下一步做什么    | CodeBuddy，逐轮决策          | CodeBuddy，按提示执行     | 领导代理，逐轮决策                | 脚本                            |
| 中间结果存在哪        | CodeBuddy 的上下文窗口       | CodeBuddy 的上下文窗口    | 共享任务列表                      | 脚本变量                        |
| 可重复的是什么        | 工人定义                     | 指令本身                  | 团队定义                          | 编排过程本身                    |
| 规模                  | 每轮少量委派                 | 同子代理                  | 几位长任务的同侪                  | 单次运行数十到数百个代理        |
| 中断                  | 重新开一轮                   | 重新开一轮                | 队友继续跑                        | 在同一会话内可恢复              |

Workflow 把"计划"挪进了代码。子代理 / Skills / Agent Teams 的编排者都是 CodeBuddy，每一轮它都要决定下一步派谁、做什么，所有结果都落进上下文窗口；而 Workflow 把循环、分支、中间结果都交给脚本本身管理，CodeBuddy 的上下文里只剩**最终答案**。

把计划变成代码还有第二个好处：你可以让脚本应用一种**重复可执行的质量模式**，而不只是单纯多派代理。比如让若干代理对彼此的发现做对抗式互评再上报、或者从多个角度同时起草方案再相互对比择优 —— 单次结果的可信度会比"一遍过"高得多。

## 运行内置 Workflow

最快感受 Workflow 的方式是跑 `/deep-research`，这是 CodeBuddy Code 内置的"多源交叉印证研究"工作流。会话里你会看到代理在后台分阶段推进，跑完后只拿到一份合成报告，而不是一长串逐轮对话。

### 步骤

1. **发起 Workflow**

   带一个想调研的问题运行 `/deep-research`。它会从多个角度并行搜索、抓取并交叉印证来源，最终合成一份带引用的报告。

   ```text
   /deep-research 主流前端 monorepo 工具（Turborepo / Nx / Lerna）近一年在远端缓存与任务图上的演进对比
   ```

2. **批准运行**

   CodeBuddy Code 会询问是否允许此 Workflow 运行。选择 **Yes** 继续。具体提示取决于你的[权限模式](iam.md#权限系统)。详见 [运行前批准计划](#运行前批准计划)。

3. **观察进度**

   运行在后台启动。`/workflows` 打开 Workflows 视图，方向键选中本次 run，回车进入进度页：

   ```text
   /workflows
   ```

   进度页按"阶段（phase）"展示，每个阶段标注代理数量、Token 总量与已耗时。下钻进任意阶段可以看每个代理的提示与产出。完整快捷键见 [观察运行](#观察运行)。

   你也可以从输入框下方的任务面板里直接看到一行进度摘要。按方向键 ↓ 把焦点切到任务面板，回车展开。

4. **阅读报告**

   运行结束后，报告自动落回会话。每一条主张都标注了引用来源，未通过交叉印证的主张会被剔除。

要把 Workflow 应用到你自己的任务，先 [让 CodeBuddy 写一个](#让-codebuddy-写-workflow)；当某次运行结果令人满意，可以把它[保存为命令](#保存-workflow-以便复用)。

### 内置 Workflow

CodeBuddy Code 内置如下 Workflow：

| 命令                          | 作用                                                                                                                                                                                                              |
| :---------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/deep-research <问题>`       | 多角度并行搜索、抓取并交叉印证来源，对每条主张投票，剔除未通过印证的部分，输出一份带引用的报告。需要 [WebSearch 工具](tools-reference.md) 可用。                                            |

[你自己保存的 Workflow](#保存-workflow-以便复用) 会以同样方式注册成命令，在 `/` 自动补全里与内置 Workflow 一同出现。

### 观察运行

Workflow 在后台运行，会话保持响应。任何时候 `/workflows` 都能列出活跃 / 已完成的 run，选中后进入进度视图。

```text
/workflows
```

进度视图按阶段展示，每个阶段标注代理数量、Token 总量、已耗时。底部状态栏列出全部快捷键：

| 按键          | 作用                                                                                              |
| :------------ | :------------------------------------------------------------------------------------------------ |
| `↑` / `↓`     | 选中阶段或代理                                                                                    |
| `Enter` 或 `→` | 下钻到所选阶段，再下钻到代理可读其提示、最近的工具调用与最终结果                                  |
| `Esc`         | 回退一级                                                                                          |
| `j` / `k`     | 在代理详情溢出时滚动                                                                              |
| `p`           | 暂停或恢复运行                                                                                    |
| `x`           | 中止所选代理；焦点在 run 上时中止整个 Workflow                                                    |
| `r`           | 重启所选的运行中代理                                                                              |
| `s`           | 把当前 run 的脚本[保存](#保存-workflow-以便复用)为命令                                            |

## 让 CodeBuddy 写 Workflow

让 CodeBuddy 为你的任务写 Workflow，有两种方式：

- [在提示里直接要 Workflow](#在提示里要-workflow)：用自然语言或者关键词 `ultracode`，CodeBuddy 会为这个任务写一份。
- [让 CodeBuddy 自己决定（ultracode 模式）](#ultracode-模式让-codebuddy-自己决定)：`/effort ultracode` 把 effort 等级设到 ultracode，会话里的每一个有分量的任务 CodeBuddy 都会先规划成 Workflow。

也可以直接运行已有的 Workflow 命令：内置如 `/deep-research`，或你[保存](#保存-workflow-以便复用)过的。

### 在提示里要 Workflow

不想改会话整体 effort 等级，只想让某次任务走 Workflow，在提示里加上关键词 `ultracode`。用自然语言说"用一个 workflow 跑这个"或者 "use a workflow"，效果一样：CodeBuddy 把直接请求当作同等的显式 opt-in。

```text
ultracode：扫描 packages/ 下所有 domain，找出哪些 Facade / CloudRepo 方法缺单测，按风险排序
```

CodeBuddy Code 会高亮你输入里的关键词，CodeBuddy 收到这个提示后，会为该任务写一段 Workflow 脚本，而不是逐轮地展开工作。如果你不想触发 Workflow，按 macOS 的 `Option+W`、Windows / Linux 的 `Alt+W` 取消本次提示的高亮；或者光标停在关键词后面按 Backspace 删掉它即可。要彻底关闭关键词触发，到 `/config` 关掉 "Ultracode keyword trigger"。

如果运行结果满足需要，事后可以把它[保存为命令](#保存-workflow-以便复用)。

如果你已经有用其他方式搭好的编排器（一个子代理提示词文件夹、或一个分发任务的 Skill），可以让 CodeBuddy 看一下并写一段等价的 Workflow。

### Ultracode 模式：让 CodeBuddy 自己决定

Ultracode 是 CodeBuddy Code 的一个组合配置：把 [推理强度](models.md#配置字段说明) 推到 `xhigh`，并叠加自动 Workflow 编排。开启后，CodeBuddy 会主动判断哪些任务值得走 Workflow，不必你每次提醒。

```text
/effort ultracode
```

进入 ultracode 后，一个请求可能被拆成连续多个 Workflow：先一个 run 摸代码现状、再一个 run 实施改动、再一个 run 验证。会话里**每个**任务都按这个模式跑，每条请求消耗的 Token 会比低 effort 等级显著更多、耗时也更长。

ultracode 仅在当前会话生效，新开会话自动重置。回到日常工作时用 `/effort high` 回退即可。它仅在支持 `xhigh` [推理强度](models.md#配置字段说明) 的模型上可用；不支持的模型上 `/effort` 菜单不会展示该选项。

### 运行前批准计划

CLI 里，每次启动都会弹出运行前确认：

- **Yes**：开始运行
- **Yes, and don't ask again this session**：开始运行，并在当前会话内对 Workflow 工具不再询问（仅会话级，新会话会重新询问）
- **No**：取消（也可按 `Esc`）

是否会出现这个询问，取决于你的 [权限模式](permission-modes.md)：

| 权限模式                                   | 何时询问                                                                                                                          |
| :----------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- |
| Default、Accept edits、Auto                | 每次都询问；除非你在当前会话里选过 **Yes, and don't ask again this session**。ultracode 开启时整个询问被跳过                       |
| Bypass permissions、`codebuddy -p`、Agent SDK | 永不询问，运行直接开始                                                                                                            |

权限模式只影响**启动前**这个询问。Workflow 派出去的子代理始终在 `acceptEdits` 模式下跑，并继承你的[工具白名单](settings.md#权限设置)，与你会话当前模式无关。文件改动是自动批准的。

不在白名单里的 Shell 命令、Web Fetch、MCP 工具调用，仍可能在运行中弹询问。要避免长任务被打断，启动前把代理需要的命令加进白名单。

`codebuddy -p` 与 Agent SDK 没有人机交互入口，工具调用按你配置的权限规则执行，没有交互式确认。

### 保存 Workflow 以便复用

当一段 Workflow 是你会反复跑的（比如每个分支都要做一遍的 review 流程），可以把它的脚本保存为命令。

`/workflows` 选中要保留的 run，按 `s`，在保存对话里 `Tab` 切换两个保存位置：

- 项目下 `.codebuddy/workflows/`：随仓库分发，团队所有人都看得到
- 用户目录 `~/.codebuddy/workflows/`：在所有项目都可用，仅你可见

回车保存。之后在任意会话里通过 `/<name>` 调用。

如果项目级和用户级 Workflow 重名，**项目级**优先。

### 给已保存的 Workflow 传参

保存的 Workflow 通过 `args` 接收输入。脚本里它是一个名为 `args` 的全局变量。这样不必每次改脚本就能传研究问题、目标路径列表、配置对象等。

下面这段提示触发一个保存的 Workflow，并把 issue 列表作为参数传入：

```text
> 用 /review-branch 把 feat/skills-center 最近 20 条 commit 各自跑一遍架构评审
```

CodeBuddy 把列表作为结构化数据传入，脚本可以直接对 `args` 用数组 / 对象方法，无需自己解析。如果调用方没传 `args`，脚本里 `args` 是 `undefined`。

## Workflow 的运行机制

运行时在一个隔离环境里执行脚本，与你的会话完全分离。中间结果留在脚本变量里，不会落进 CodeBuddy 的上下文。

每次 run 都会把脚本写到会话目录（`~/.codebuddy/projects/<session>/`）下的一个文件里。CodeBuddy 在 run 启动时拿到该路径，所以你可以问它"脚本在哪"。打开它可以读 CodeBuddy 写的编排逻辑、和上一次 run 做 diff、或者编辑后让 CodeBuddy 用编辑后的版本重新启动。

运行时持续记录每个代理的结果，这就是同一会话内 run [可恢复](#恢复-pause-后的-run) 的基础。

### 行为与限制

运行时施加以下约束：

| 约束                                                                 | 原因                                                                                                                       |
| :------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- |
| 运行中不接受用户输入                                                 | 唯一能让 run 暂停的是代理的权限询问。若需要阶段间签字确认，把每个阶段拆成独立 Workflow                                     |
| Workflow 自身没有直接的文件系统 / Shell 访问能力                     | 文件读写、执行命令一律由代理完成；脚本只负责协调代理                                                                       |
| 同时最多 16 个并发代理（CPU 核数少的机器上更少）                     | 限制本地资源消耗                                                                                                           |
| 单次 run 最多 1000 个代理                                            | 防止脚本失控的循环                                                                                                         |

### 确定性沙箱

运行时强制确定性，避免同一脚本两次跑出不同结果（也是 [resume 缓存命中](#恢复-pause-后的-run) 的前提）。沙箱拒绝以下不确定性 / 任意代码生成 API（编译期扫描 + 运行时拦截）：

- 时间相关：`Date.now()`、`new Date()`、`performance.now()`
- 随机数：`Math.random()`
- 任意代码生成：动态字符串求值与动态 Function 构造（沙箱关闭了 `codeGeneration.strings`）
- Node 全局：沙箱里看不到 `require` / `process` / `__dirname` / `Buffer`

需要时间戳或随机数时，用 `agent()` 让子代理拉取真实信息（搜索、读文件、调 API），把不确定性"装进"代理的结果里。

### 脚本 API

脚本是一个自包含的 JavaScript 模块，可以使用以下全局函数：

| 全局                          | 作用                                                                                                                                  |
| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ |
| `agent(prompt, options?)`     | 派一个子代理执行 `prompt`；返回它的结果。`options` 可指定 `tools` / `maxTurns` / `schema`（结构化输出）/ `model` 等                   |
| `parallel(items, options?)`   | 对 `items` 并行 fan-out，等同于 `Promise.all`，但受 16 个并发上限约束                                                                 |
| `pipeline(items, options?)`   | 顺序串联，前一段的结果传给下一段；任一段失败时其余段返回 `null`                                                                        |
| `phase(name, body)`           | 把一段编排标注成一个阶段，进度视图里会按阶段聚合显示。`body` 可以是同步或异步函数                                                     |
| `log(...)`                    | 写一条带时间戳的日志，会出现在进度视图的 Run log 里                                                                                   |
| `args`                        | 调用方传入的参数（见 [给已保存的 Workflow 传参](#给已保存的-workflow-传参)）                                                           |
| `workflow(name, args?)`       | 嵌套调用一个**已保存**的 Workflow（仅父级可调用，子级不再暴露此 hook，禁止深度嵌套）                                                    |

## 运行管理

run 一旦启动，从 `/workflows` 视图管理；也可以展开输入框下方任务面板里的进度行。

### 恢复 pause 后的 run

如果你停下了一个 run，可以再恢复：已经完成的代理直接返回缓存结果，剩余部分继续跑。`/workflows` 选中已暂停的 run 按 `p` 恢复；也可以让 CodeBuddy 用同一脚本重启 run。

恢复仅限**同一 CodeBuddy Code 会话内**。如果你退出了 CodeBuddy Code 时 Workflow 还在跑，下次会话会从头开始。

### 成本

Workflow 会派出大量代理，因此一次 run 的 Token 消耗可能远高于以对话方式做同样的任务。这些消耗按你套餐的限额计入。

要在动手做大任务前估成本，先在小切片上跑一遍：一个目录而不是整个 repo，一个具体问题而不是宽泛主题。`/workflows` 视图里每个代理的 Token 用量实时可见，随时可以 `x` 中止 run 而不丢已完成的结果。运行时的 [代理上限](#行为与限制) 也限制了一次 run 能消耗的最大代价，避免脚本写错时跑飞。

每个代理默认沿用会话当前的模型；如果脚本显式给某阶段路由到了别的模型则不同。控制成本可以从几个方面入手：

- 大任务前 `/model` 检查一遍当前模型，如果你平时切到便宜模型，注意切回来或维持
- 描述任务时主动告诉 CodeBuddy："对不需要最强模型的阶段用更便宜的模型"

### 关闭 Workflow

Workflow 在 CLI、桌面端、IDE 扩展、`codebuddy -p` 非交互模式与 [Agent SDK](sdk.md) 都可用，关闭方式在所有形态下一致。

仅对自己关闭：

- `/config` 里把 "Dynamic workflows" 关掉。会持久化到设置
- `~/.codebuddy/settings.json` 设 `"disableWorkflows": true`，会持久化
- 设环境变量 `CODEBUDDY_DISABLE_WORKFLOWS=1`，启动时读取，在哪儿设就在哪儿生效

为整个组织关闭：在 [托管设置](settings.md) 里设 `"disableWorkflows": true`。

关闭后，内置 Workflow 命令不可用，关键词 `ultracode` 不再触发，`/effort` 菜单也不再展示 ultracode 选项。

## 相关资源

- [子代理](sub-agents.md)：Workflow 编排的底层"工人"原语
- [Agent Teams](agent-teams.md)：另一种多代理协作形态，由领导代理管计划
- [Skills 技能系统](skills.md)：把"指令"沉淀成可复用 Skill
- [推理强度调整（含 ultracode）](models.md#配置字段说明)
- [Hooks 钩子系统](hooks-guide.md)：在工具调用与会话事件上挂钩子
