它到底是什么:谁拿着计划

subagent、skill、agent team 和工作流都能跑多步任务,官方给的分界线只有一条——谁决定下一步。 前三者由 Claude 逐轮判断派谁、做什么,每个结果都回到某个上下文窗口;工作流把这套判断写成脚本,运行时执行。

SubagentsSkillsAgent teamsWorkflows
是什么Claude 派出的工人Claude 遵循的指令一个 lead 监督多个对等会话运行时执行的脚本
谁决定下一步Claude,逐轮Claude,按提示lead agent,逐轮脚本
中间结果在哪Claude 的上下文Claude 的上下文共享任务列表脚本变量
可复用的是工人定义指令团队定义编排本身
规模每轮几个同 subagent一小撮长跑同伴每次几十到上百个
被打断重来这一轮重来这一轮同伴继续跑同一会话内可续跑

把计划搬进代码还带来一个质量上的好处:脚本可以固化可重复的质量模式——让独立智能体互相对抗式复核发现, 或者从几个角度各起一版方案再互相权衡,比单遍跑出来的结论可信。内置的 /deep-research 就是这样: 多角度搜索、抓取并交叉核对来源、对每条结论投票,没通过交叉验证的结论直接过滤掉;验证者遇到限流或 API 错误无法核对时, 报告会把那条标为「未验证」而不是当成被推翻。

三种触发方式

1. 在提示里要一个

提示里包含关键词 ultracode,或者用自己的话说「use a workflow」「用工作流跑」,Claude 就为这个任务写一段脚本而不是逐轮做。 v2.1.160 之前的字面关键词是 workflow,自然语言在新旧版本都有效。关键词只决定 Claude 怎么组织工作: 智能体的每一次工具调用仍然走会话原有的权限检查和沙箱。

ultracode: audit every API endpoint under src/routes/ for missing auth checks

误触了想取消:macOS 按 Option+W、Windows / Linux 按 Alt+W 去掉本条提示的高亮,或者把光标放在关键词后面退格。 彻底不想让它触发,在 /config 里关掉 Ultracode keyword trigger。

关键词只认你亲手输入的提示:交互式命令行、IDE 扩展面板、Remote Control 客户端,或 Agent SDK 里把 origin 标成 human 的输入。 通过 -p 传入、SDK 未标记为人类输入、定时任务提示、webhook 或 PR 评论转发进来的文本都不会启动工作流——v2.1.210 之前这些路径也会触发, 这是一个安全收紧。

2. /effort ultracode:让 Claude 自己决定

ultracode 是 Claude Code 的一个设置,把 xhigh 推理强度和自动工作流编排绑在一起。开着它,Claude 会为会话里每个有分量的任务自行规划工作流, 一个请求可能连着跑三个:一个理解代码、一个改、一个验证。/effort ultracode 只管当前会话,claude --effort ultracode 启动即开,ultracode 设置项让每个会话默认开;回到日常小活记得 /effort high 降回来。 只有支持 xhigh 的模型才提供这个档,需要 v2.1.203+。

3. 跑现成的命令

内置的 /deep-research(需要 WebSearch 工具可用)、你自己保存过的工作流、插件里分发的工作流,都作为斜杠命令出现在自动补全里。 它们只在你调用时才运行。

放行规则:不同权限模式下什么时候问你

命令行里每次运行前会展示计划的阶段,选项是「Yes, run it」「Yes, and don't ask again for 这个工作流 in 这个项目」「View raw script」「No」;Ctrl+G 用编辑器打开脚本,Tab 可以在运行前改提示。「不再询问」只对按名字运行的内置、已保存或插件工作流提供,对 Claude 临时为当前任务写的脚本不提供。

权限模式何时询问
Auto只在首次启动时问一次,任何 Yes 都记进用户设置;ultracode 开着时完全跳过
Manual / accept edits每次运行都问,除非对该工作流在该项目选过「不再询问」
Bypass permissions不问,直接开跑
claude -p / Agent SDK不问;Workflow 工具调用走会话正常的权限评估

-p 和 SDK 里要让工作流启动,五选一:allow 规则里写 Workflow(放行全部)或 Workflow(<name>)(只放行一个已保存的); auto 模式让分类器审;bypass 模式;返回 allow 的 PreToolUse hook;或宿主通过 --permission-prompt-tool / SDK 的 canUseTool 放行。 Desktop 应用里则是一张带 Once / Always / Deny 的审批卡,进度在 Background tasks 侧栏。

工作流派出的子智能体沿用你的 permission rules,权限模式按子智能体的规则挑选。长跑前把它们要用的工具先加进 allow, 否则跑到一半被一个弹窗卡住——这是官方唯一会暂停运行的情形。

六种典型任务,直接抄提示

任务形状提示(你不用写脚本)
逐文件审同一类问题use a workflow to audit every route handler under src/routes/ for missing authentication checks, and adversarially verify each finding before reporting it
修到检查通过为止use a workflow to run npx tsc --noEmit and keep fixing the reported errors until the type check passes or two rounds in a row make no progress
批量并行迁移use a workflow to migrate every component under src/components/ from JavaScript to TypeScript, working on each file in its own isolated copy
逐文件审查再合并成一份use a workflow to review every file changed in this PR for correctness issues, then merge the per-file findings into one ranked summary
跨多源研究use a workflow to research how our three competitors handle rate limiting: read their public docs and recent changelog entries in parallel, then compare the approaches
找到没有新发现为止use a workflow to find flaky tests in this repo: run the suite repeatedly, record which tests fail intermittently, and stop once two rounds in a row find nothing new

脚本长什么样

保存下来的文件就是一个 meta 块加一段编排子智能体的脚本体,通常不需要手改,但认得出来很重要:

export const meta = {
  name: 'audit-routes',
  description: 'Audit every route handler for missing auth checks',
}

const found = await agent('List every .ts file under src/routes/.', {
  schema: { type: 'object', required: ['files'], properties: { files: { type: 'array', items: { type: 'string' } } } },
})

const audits = await pipeline(found.files, file =>
  agent(`Audit ${file} for missing authentication checks.`, { label: file }),
)

return audits.filter(Boolean)
  • agent() 起一个子智能体,pipeline() 对列表逐项各起一个,parallel() 同时跑一组并等全部结束;还有 phase() 给后面的智能体分组标题、log() 在进度视图上方打一行字,以及全局 args
  • agent() 被你中途停掉或遇到不可恢复的 API 错误时返回 nullpipeline() 会把 null 留在结果数组里——所以例子结尾要 filter(Boolean)
  • export const meta 必须是第一条语句、必须是纯字面量对象(含变量、函数调用或展开都会让 /name 从补全里消失);meta.phases 若列出,标题要和 phase() 传的一字不差。
  • 脚本体是纯 JavaScript,支持顶层 await,但 不能 import()(运行前就失败)、不能直接碰文件系统或 shell(那是智能体的活),Date.now()Math.random()、无参 new Date() 会抛错——时间戳走 args 传进来。

要改已保存的脚本,先跑 /workflow-authoring 这个内置 skill 加载 Claude 写脚本时依据的参考(v2.1.248+),改完 /reload-skills 重新读目录再 /name

保存、分发与传参

运行满意后在 /workflows 里选中它按 sTab 切换两个位置:项目的 .claude/workflows/(随仓库共享) 或 ~/.claude/workflows/(所有项目可用、只有你看得到;设了 CLAUDE_CONFIG_DIR 就在其下)。同名时项目级优先。 monorepo 里(v2.1.178+)保存会写到工作目录到仓库根之间最近的已存在 .claude/workflows/,加载也沿这条路径全读,重名取最近的。

团队或跨仓库分发走插件:脚本放在插件根的 workflows/ 目录,命令按插件名加前缀,比如 acme-tools 里 meta.name 为 release-audit 的脚本运行时叫/acme-tools:release-audit

已保存的工作流通过 args 收参数:「Run /triage-issues on issues 1024, 1025, and 1030」,Claude 会把列表作为结构化数据传入,脚本里直接对 args 用数组方法,不用解析;不传则为 undefined

运行机制、缓存与硬限制

脚本在与对话隔离的运行时里执行,每次运行的脚本都会写到 ~/.claude/projects/ 下当前会话的目录,Claude 拿到路径,你可以让它把路径告诉你、去 diff 上一次的脚本,或改完让它按新版本重跑。 Claude 只能从会话已被允许读取的脚本文件启动工作流;工作目录之外的脚本要先 /add-dir 或加 Read allow 规则。

fan-out 里的 prompt cache

同一次运行里模型、effort、agent 类型、工具、输出 schema、工作目录都相同的智能体共用同一段「工具 + 系统提示」前缀,后启动的直接读先启动者的缓存。 为此 Claude Code 会把同批次的其他智能体压住最多 5 秒CLAUDE_CODE_WORKFLOW_PREFIX_STAGGER_MS,默认 5000,设 0 关闭),等第一个的响应开始再一起放出去。 注意工作流智能体的请求不在主对话的 TTL 桶里,缓存默认只保 5 分钟,订阅账号也一样;要保 1 小时把 subagentPromptCacheTtl 设成 1h,1 小时缓存写入按更高费率计。

限制为什么
运行中不接受用户输入只有智能体的权限弹窗能暂停运行;阶段间要签字就拆成多个工作流
脚本本身不能碰文件系统和 shell读写和执行都是智能体做,脚本只负责协调
不能加载模块,含 import() 的脚本运行前失败脚本体是纯 JavaScript,需要库的工作放进智能体任务
最多 16 个并发智能体,CPU 少时更少限制本机资源占用
单次 parallel() / pipeline() 最多 4,096 项超出直接报错,不静默丢弃
单次运行最多 1,000 个智能体防止失控循环

暂停、续跑与离开会话

/workflows 里按 p 暂停或恢复;停掉的运行让 Claude 用同一脚本重新启动,Claude Code 按智能体启动顺序重放:已完成的返回保存结果,但提示词第一次不同的那个(你改了脚本,或前面某个智能体返回了不同内容)及其之后的全部重跑;停止时仍在跑的从头来;失败的重跑,且它之后启动的全部重跑,包括已完成的——在 /workflows 里单独按 x 停掉一个智能体也算失败。 所以 A、B、C、D 顺序启动、B 失败,重启会从缓存拿 A,重跑 B、C、D。

离开会话时:把会话转到后台,运行会在后台会话里同样重放并继续;开着 agent view 直接退出会看到「Move to background and exit」;选「Exit and stop tasks」运行随会话停止,但保存的结果留在会话目录下,claude --resume 回来让 Claude 重启工作流时可以重放,全新会话则从头开始。

成本:先看,再放大

  • 一次运行派很多智能体,token 消耗明显高于对话里做同一件事,并且计入套餐用量与速率限制。先在一个目录或一个窄问题上试,/workflows 里看每个智能体的 token,随时停止且通常不丢已完成的工作。
  • 调度超过 25 个智能体或预估 token 超过 150 万时,输入框下方的进度行亮「Large workflow」警告——只是提醒,不会暂停;开着 ultracode 不显示,因为开它就等于接受大运行。
  • Size guideline(v2.1.219+ 默认 medium)告诉 Claude 写脚本时瞄准多少智能体,是建议不是上限:unrestricted 不设、small 少于 5、medium 少于 15、large 少于 50。/config 里改,或 /config workflowSizeGuideline=small,settings 文件里的 workflowSizeGuideline 优先于 /config。
  • 每个智能体的模型按 subagent 的选模顺序决定,脚本为某阶段指定的模型算作该次调用的模型,都没指定就用会话模型。大运行前先 /model 看一眼;描述任务时可以让 Claude 给不需要强模型的阶段用小模型。组织的 availableModels 白名单挡掉脚本要的模型时会自动替换,并在进度视图里警告。

不想要它

/config 里关掉 Dynamic workflows、~/.claude/settings.json"disableWorkflows": true,或环境变量 CLAUDE_CODE_DISABLE_WORKFLOWS=1; 组织级在 managed settings 里设同一个键,或在 Claude Code 管理后台用开关。关掉后内置工作流命令和 /workflow-authoring 不可用,ultracode 关键词失效,/effort 菜单里也没有 ultracode 档。