之前:守着终端吃灰,一跑就是两小时
我们团队接了一个活:把一套用 Django 2.2 写的后台管理系统,升级到 Django 4.2,顺便换掉一个过时的第三方支付库。代码大概 8 万行,涉及十几个 app,还有 2000 多个单元测试。
用老方法写 Claude Code 任务:拆成十个子步骤,逐一粘贴、确认、等待。每次升级一个 app 后,跑测试、修失败、再跑、修——经常卡在某个 pyproject.toml 依赖冲突上,Claude 自动退出,得我手动改完再切回终端重新跑。最烦的是周末加班,盯着它跑测试,想走开吃个饭都不敢。
有一次,升级 accounts 模块,单元测试执行到 893/2147 时,中间一个 flaky 测试(用了 mock.patch 没清理干净)死循环,Claude 一直在重试那个 case,我手动按 Ctrl+C 都没反应,最后是远程 SSH 踢掉进程才停。那天晚上回去我就想:能不能有个模式,让它自己决定怎么分拆、怎么重试,失败了就换个路子再来?我待旁边反正也帮不上忙。
现在:一个 /goal 扔进去,然后去健身
动态工作流是 Claude Code 新加的。核心就一句话:你不需要手写 step-by-step 了,给一个目标,它自己会拆成多个并行子 agent,每个子 agent 拿一个子目标,独立拉代码、写测试、调用工具、检查结果,最后主 agent 汇总。而且子 agent 可以失败多次,主 agent 会重新分配。
我们现在的流程:
- 进到项目根目录,跑
claude。 - 先打
/effort选ultracode——这个模式会开更大的 token 预算,让 Claude 能跑更长的规划链。 - 然后直接打
/goal,后面写上目标:/goal 将项目从 Django 2.2 升级到 4.2,替换 payment 库为 stripe 的 python SDK, 确保所有单元测试通过,覆盖率不低于 80%,并且生成一份迁移报告。 注意:payment 库的 migration 脚本需要手动激活环境变量 STRIPE_SECRET。 - 然后按回车,站起来,锁屏。
第一次跑的时候我还是心虚的,开着手机 SSH 看日志。结果是:它花了 38 秒做规划,日志里显示生成了 47 个子 agent:
[Planner] Decomposing goal into 47 sub-agents:
- agent-001: update requirements/dependencies
- agent-002: run `django-upgrade` on accounts app
- agent-003: run `django-upgrade` on orders app
...
- agent-012: fix deprecated `url()` -> `path()` in urls.py
- agent-013: replace `paypal_rest_sdk` calls in payment module
...
- agent-045: run full test suite, collect failures
- agent-046: for each failure, trigger sub-agent to fix
- agent-047: generate migration report
这 47 个 agent 分 5 波并行执行,每波 8-12 个。如果某个子 agent 失败(比如因为依赖缓存没更新),主 agent 会把它标记为 FAILED_WITH_CAUSE,然后生成一个新的 agent 重做,最多 3 次。整个过程大概跑了 52 分钟。我在健身房划了半小时椭圆机,回来看了一眼:测试全绿,一份 30 页的迁移报告已经在 docs 目录下。
数字化结果——不一定漂亮,但管用
具体数据:
-
全量升级时间:从原来人工值守约 3.5 小时(包括手动修复依赖重新跑测试),降到单次 52 分钟。之后跑一次回归测试(只跑原有案例),从 1 小时降到 23 分钟——因为它跑的时候会并行构建依赖缓存。
-
一次通过率:第一次跑就通过的次数 / 总任务数。我们统计了 7 次不同的重构/升级任务,一次通过率从手动模式的 40% 升到 78%。(这里一次通过指:全部测试通过且没有遗留异常,不需要我手动修改代码再重跑。)原因很简单:手动模式下,我可能会漏掉一个不兼容的模板标签,但 Claude 的 agent 会按 app 扫描所有文件,几乎不漏。
-
子 agent 失败分布:47 个 agent 里,初始轮有 9 个失败。其中 3 个是因为
pip install超时(环境问题),2 个是因为旧代码里用了django.utils.six(已经移除了,agent 发现 import 异常后自动回退),4 个是因为 payment 库替换过程中,有旧函数签名在 view 里被硬编码。主 agent 针对这 9 个失败生成重试 agent,最终 7 个成功,剩下 2 个需要我确认 stripe 的 API key 是否该放在环境变量还是 settings 里(非代码问题)。我觉得这个还挺合理的。 -
token 消耗:ultracode 模式大概吃掉 70 万个输入 token(因为要加载整个项目代码用于规划),输出 token 约 12 万。一次跑下来大概 $4-6 美金的 API 成本。相比我们人工花的时间,这点钱太小了。
哪些场景能用,哪些不行
适用:
- 大规模重构/升级,依赖关系复杂,需要一个 agent 决定先改哪个模块、后改哪个。
- 需要回归测试且测试时长较长,可以并行跑子 agent 加速。
- 有明确的 pass/fail 标准(比如测试全绿、覆盖率达标),Claude 自己判断成功与否。
- 你能接受“可能不完全完美”:它生成的迁移报告我最后审了一轮,有一条废弃的
django-filter的用法没 catch 到,但测试覆盖到了,不碍事。
不适用:
- 需要实时交互的创意任务(比如写一首诗,然后要不断调风格)——子 agent 调度会破坏上下文。
- 项目依赖外部服务或网络,超时容易被误判为“子 agent 失败”。我们在一台网络不稳定的机器上跑过一次,12 个 agent 里有 5 个因为
pip install超时失败,重试 3 次后依然失败,最后主 agent 停在那里要我手动解决网络。建议跑之前先确保网络稳定。 - 需要手动执行 GUI 操作的任务(比如点击浏览器元素)——目前只能调用 shell 和文件系统。
- 对 token 成本敏感的预算环境。一次全量跑 $5-8 美金,如果每天跑几十次就贵了。
踩的几个坑(翻车细节)
坑 1:子 agent 相互踩文件
第一次跑大型任务(5 万行代码),有多个子 agent 同时编辑同一个文件(比如 urls.py),结果出现双写冲突,一个 agent 在文件头添加了 # deprecated 注释,另一个在后面加了 import。最终结果是文件里 import 语句顺序乱了,但代码还能跑——万一将来有严格 lint 规则,可能会炸。解决方案:在 /goal 末尾加上“确保子 agent 编辑的文件不冲突,如果冲突则排队”。现在它会在规划阶段分析文件依赖,给冲突写加锁(其实是代理写到一个临时文件再合并),没有再出过问题。
坑 2:/goal 目标太模糊
第一次我写“重构 payment 模块”,结果它花了 15 分钟规划出 80 个 agent,包含了安装 docker、配置 stripe webhook 等不是必要的事。第一次失败是因为我没给 stripe secret,它到处找配置找不到,还生成了一个 agent 去查 1Password 集成(它当然没有权限)。后来我发现目标写具体点,特别是“排除什么”写清楚。比如:“升级 Django 版本到 4.2,只修改代码,不修改基础设施配置,假设 stripe secret 已在环境变量中。”
坑 3:ultracode 模式下的幻觉
有一次它规划出一个 agent 叫“删除所有 comment 字段”,我看日志立刻 Ctrl+C。因为我们的项目根本没有 comment 字段,它大概是看到了 Comment 模型产生的幻觉。后来我添加了一个步骤要求:任何删除/重大变更前,必须输出 diff 让用户确认。现在加上 /goal 后面补一句“对每个删除操作,先打印 diff 并暂停等待确认”,但这样就牺牲了“无人值守”的好处。我们目前妥协方案:只对生产分支做无人值守跑,对 feature 分支做严格确认。说实话,这个取舍还没找到完美解。
坑 4:/effort ultracode 不是银弹
如果项目代码过于巨大(比如 30 万行),输入 token 可能接近模型上限。我们遇到一个场景:规划阶段就把上下文塞满了,子 agent 启动后没有足够的剩余 token 去理解代码细节,导致频繁修改错误。后来发现 Claude Code 其实有限制:动态工作流默认以主 agent 的上下文为准,没法独立分配 token 给子 agent(存疑,我还没完全验证)。我们当前的处理:先对代码做一次依赖分析,把不需要的测试数据文件排除(用 .claudeignore),把输入 token 从 900k 降到 500k 左右,效果好了很多。
最后一点感觉
动态工作流 + /goal 确实算一个里程碑——之前所有 agent 框架(LangGraph、CrewAI、Swarm)都要求你至少写一个 DAG 或 YAML 配置,而 Claude Code 把它变成了一个自然语言命令加一个回车。虽然还有很多 edge case,但已经让我敢在跑大型任务时离开电脑了。不过我还是建议第一次用的人,在它跑的时候开着 SSH/Terminal 手机 app 看着——万一炸了,能手动关掉,别让 bill 跑到上百美元。等跑了三五次熟悉了,再去健身房。
我觉得 6 个月后这个功能会更成熟,如果 Anthropic 能把并发限制和 token 分配做得更透明,它会抢掉很多手动 CI 脚本的饭碗。至少我的组已经开始往里面塞更多的自动化测试任务了。下周我打算试一下让它在部署前自动跑压测并输出性能对比——如果真能跑通,那就真的可以下班后去跑个 5 公里了。