1. 从"写代码"到"管流程":这次改动的本质是什么
Claude Code 最近做了一件挺有意思的事——它把自己从一个"你问我答"的编码助手,改造成了一个能主动调度任务、管理子代理、协调多工作流的调度器。很多人第一反应是"哦,又加功能了",但我看完整个设计之后,真正让我觉得值得聊的不是它多了什么按钮、多了什么命令,而是它在架构层面做了一次角色转换:从"执行者"变成了"编排者"。
这个转变为什么重要?你可以这样理解:以前的 AI 编码工具,本质上是一个坐在你旁边的实习生,你说一句它做一句,做完就等你下一句。而任务调度器模式下,它更像是一个项目经理——你给它一个目标,它自己拆任务、自己分配资源、自己决定哪个先做哪个后做、哪个需要开新的工作区、哪个需要调用外部工具。这个差别不是功能层面的差别,是范式层面的差别。
关键词里提到的 Agent、Supervisor、worktree、MCP,其实正好对应了这次改造的四个支柱:Agent 是执行单元,Supervisor 是调度逻辑,worktree 是隔离手段,MCP 是能力扩展接口。这四个东西组合在一起,才让"任务调度器"这个定位站得住脚。单独看任何一个都不新鲜,但把它们编排成一个完整的调度体系,这个设计思路才是真正值得拆解的部分。
这篇文章我会从设计动机、核心机制、实操落地、踩坑经验几个角度,把这次改动讲透。不管你是刚接触 Claude Code 的新手,还是已经在用 Agent 框架做项目的老手,应该都能从中拿到一些可以直接用的东西。
2. 为什么"调度"比"功能"更难做,也更值钱
2.1 功能是加法,调度是乘法
我先说一个反直觉的观点:给一个 AI 编码工具加功能,其实是最简单的事。加一个命令、加一个快捷键、加一个面板,这些都是线性叠加,做完了就是做完了。但做调度完全不一样,调度是乘法——你要考虑任务之间的依赖关系、资源的竞争、失败的重试、上下文的传递、并发的隔离。任何一个环节没设计好,整个系统就会从"帮你干活"变成"给你添乱"。
我举个例子。假设你让 Claude Code 做三件事:重构一个模块、给这个模块补测试、更新相关文档。如果它是执行者模式,它会一件一件做,做完重构做测试,做完测试写文档。这没问题,但效率低。如果它是调度器模式,它会发现"补测试"和"更新文档"其实可以并行,因为它们依赖的都是"重构完成"这个前置条件。于是它可以开两个工作区,一个跑测试,一个写文档,同时进行。
但这里立刻就有问题了:两个工作区怎么隔离?测试跑出来的结果怎么合并回主分支?文档写的时候如果发现重构后的接口和预期不一样怎么办?这些问题在"执行者模式"下根本不存在,因为一切都是串行的。一旦你上了调度,这些就全冒出来了。所以我说调度是乘法,它把系统的复杂度直接翻了好几倍。
2.2 Supervisor 模式解决的核心痛点
关键词里的 Supervisor,其实就是调度器的核心角色。它的职责不是干活,而是决定"谁在什么时候干什么"。这个角色在传统后端系统里很常见,比如 Kubernetes 的 Controller、Airflow 的 Scheduler,但在 AI 编码工具里,这是一个相对新的尝试。
为什么需要 Supervisor?因为单个 Agent 的能力是有边界的。一个 Agent 的上下文窗口有限,注意力有限,同时处理太多事情就会顾此失彼。Supervisor 的思路是:把大任务拆成小任务,每个小任务交给一个专门的子 Agent,Supervisor 只负责协调和汇总。这样每个子 Agent 都能在自己的小上下文里专注干活,整体效率反而更高。
这个思路其实和人类团队管理是一样的。一个技术负责人不可能自己写所有代码,他要做的是拆任务、分任务、盯进度、做集成。Claude Code 这次把自己改成调度器,本质上就是让 AI 学会了"当技术负责人"这件事。
2.3 从"对话式"到"任务式"的交互转变
还有一个容易被忽略的点:交互模式的转变。以前的 AI 编码工具是对话式的,你一句我一句,上下文靠对话历史维持。但任务调度器模式下,交互变成了任务式的——你提交一个任务,它自己去跑,跑完了给你结果。这中间它可能开了好几个工作区,调了好几个工具,但你不需要关心中间过程。
这个转变对用户的心智模型影响很大。对话式模式下,你始终在"盯着"AI 干活,它每做一步你都能看到,随时可以打断和纠正。任务式模式下,你更像是"委托"了一件事,然后等结果。这两种模式各有优劣:对话式适合探索性的、需要频繁调整的工作;任务式适合目标明确的、可以批量执行的工作。
Claude Code 这次的设计,我觉得比较聪明的地方是它没有完全抛弃对话式,而是在对话式的基础上叠加了任务调度能力。你可以继续用对话的方式和它交互,但当任务复杂到一定程度时,它会自动切换到调度模式。这个过渡做得比较自然,不会让老用户觉得"怎么突然变了"。
3. worktree 隔离机制:并行任务的物理基础
3.1 为什么必须用 git worktree 而不是分支切换
说到并行任务,很多人第一反应是"开个新分支不就行了"。但实际操作过的人都知道,分支切换在并行场景下是灾难。因为分支是共享同一个工作目录的,你切到分支 A,工作目录就变成 A 的内容;你切到分支 B,工作目录又变成 B 的内容。两个任务如果同时跑,就会互相踩脚。
git worktree 解决的正是这个问题。它允许你在同一个仓库下挂载多个独立的工作目录,每个目录对应一个分支,互不干扰。Claude Code 用 worktree 来做任务隔离,逻辑上是非常正确的选择。每个子任务在自己的 worktree 里跑,改自己的文件,跑自己的测试,完全不会影响其他任务。
我实测下来的感受是,worktree 的隔离效果确实好,但它有一个前提:你的项目得是 git 管理的,而且 worktree 的创建和清理需要额外的磁盘空间和时间。对于一个大型项目,每个 worktree 可能就是几百 MB 到几个 GB,如果你同时开五六个 worktree,磁盘压力不小。
3.2 worktree 的生命周期管理
这里有一个实操中很容易踩的坑:worktree 的清理。如果你手动创建过 worktree,你就知道git worktree list会列出一堆,git worktree remove才能删掉。如果任务跑完了但 worktree 没清理,时间一长你的仓库目录下就会堆一堆临时工作区,既占空间又乱。
Claude Code 在调度模式下,理论上应该自动管理 worktree 的生命周期——任务开始时创建,任务结束时清理。但我在实际使用中发现,如果任务异常中断(比如进程被杀、网络断了),worktree 可能会残留。所以我的建议是,定期跑一下git worktree list和git worktree prune,把那些已经不存在或者已经合并的 worktree 清理掉。
# 查看当前所有 worktree git worktree list # 清理已经失效的 worktree 引用 git worktree prune # 手动删除某个 worktree git worktree remove /path/to/worktree提示:如果你的项目用了 monorepo 或者子模块,worktree 的行为会更复杂,建议先在测试仓库里跑通再上生产项目。
3.3 worktree 与任务粒度的匹配
worktree 的粒度选择也是个学问。粒度太粗,一个 worktree 里塞太多任务,隔离效果就打折扣;粒度太细,每个小任务都开一个 worktree,创建和清理的开销就上来了。我的经验是,按照"独立可交付单元"来划分 worktree 比较合适。比如"重构用户模块"是一个单元,"给用户模块补测试"是另一个单元,这两个可以各开一个 worktree。但"改一个变量名"这种就不值得单独开 worktree,直接在原工作区做就行。
Claude Code 的调度器在决定是否开新 worktree 时,应该也是基于类似的判断逻辑。它需要评估任务的独立性、影响范围、预计耗时,然后决定是并行还是串行。这个判断逻辑做得好不好,直接决定了调度器的实用性。
4. MCP 协议:调度器的"外挂能力接口"
4.1 MCP 到底解决了什么问题
MCP 这个词在关键词里出现频率很高,但很多人对它的理解还停留在"又一个协议"的层面。我用一句话概括:MCP 让 AI 能够以标准化的方式调用外部工具和数据源。没有 MCP 之前,每个工具都要单独适配,AI 要调 Playwright 得写一套,要调数据库得写一套,要调浏览器扩展又得写一套。有了 MCP,这些工具只要实现 MCP 协议,AI 就能统一调用。
对于任务调度器来说,MCP 的意义尤其大。因为调度器的核心能力是"编排",而编排的前提是"有足够多的可编排单元"。MCP 把外部工具变成了标准化的可编排单元,调度器就可以像搭积木一样,把不同的工具组合起来完成复杂任务。
比如一个典型的场景:调度器接到任务"检查网站首页的加载性能并生成报告"。它可以拆成几步:用 Playwright MCP 打开页面、用 Chrome DevTools MCP 采集性能数据、用文件系统 MCP 写报告。每一步都是一个 MCP 调用,调度器负责把它们串起来。
4.2 常见的 MCP 工具选型
从关键词里能看到不少 MCP 相关的工具,我挑几个有代表性的说一下适用场景:
| MCP 工具 | 适用场景 | 注意事项 |
|---|---|---|
| Playwright MCP | 浏览器自动化、页面交互测试 | 需要本地有浏览器环境,首次运行会下载驱动 |
| Chrome DevTools MCP | 性能分析、网络请求抓取 | 需要 Chrome 以调试模式启动 |
| Burp Suite MCP | 安全测试、请求拦截分析 | 仅用于授权测试环境 |
| Blender MCP | 3D 场景操作、模型处理 | 需要本地安装 Blender |
| Unity MCP | 游戏引擎操作、场景编辑 | 版本兼容性需要确认 |
选型的时候我的建议是:先明确你的任务需要什么能力,再去找对应的 MCP。不要为了用 MCP 而用 MCP,很多任务其实用内置工具就能完成,硬上 MCP 反而增加复杂度。
4.3 MCP 连接配置的实操细节
MCP 的配置在不同客户端里不太一样。以 VS Code 为例,你需要在设置里找到 MCP 相关的配置项,把 MCP Server 的地址和认证信息填进去。有些 MCP Server 是本地进程,通过 stdio 通信;有些是远程服务,通过 HTTP 或 WebSocket 通信。配置的时候要看清文档,别把通信方式搞错了。
{ "mcpServers": { "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp"] }, "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"] } } }注意:MCP Server 的权限范围要严格控制。文件系统类的 MCP 一定要限定可访问目录,不然 AI 可能读写到你不想让它碰的文件。
5. 把 Claude Code 当调度器用的实操路径
5.1 环境准备:从安装到跑通第一个任务
如果你还没装 Claude Code,先把基础环境搭起来。安装方式根据系统不同有差异,Windows、macOS、Linux 各有各的步骤。装完之后第一件事是确认版本,因为调度相关的能力在不同版本里差异比较大。
# 确认安装成功 claude --version # 查看当前配置 claude config list装好之后,建议先跑一个简单任务验证链路通畅。比如让它读一个文件、改一个函数、跑一下测试。这一步的目的是确认基础能力没问题,再去试调度相关的功能。很多人一上来就搞复杂任务,结果出了问题分不清是环境问题还是调度问题。
5.2 任务拆解:什么样的任务适合交给调度器
不是所有任务都适合调度。我的判断标准是三条:任务能拆成多个独立子任务、子任务之间有明确的依赖关系、子任务可以并行执行。三条都满足,才值得上调度器。如果任务本身就是线性的、不可拆的,那用普通模式反而更快。
举个例子,"给整个项目补单元测试"就适合调度:可以按模块拆,每个模块的测试独立,模块之间可以并行。而"修复一个具体的 bug"就不太适合:bug 的定位和修复通常是线性的,拆了反而增加协调成本。
5.3 子代理的配置与上下文传递
调度器模式下,每个子代理都需要明确的上下文。这个上下文包括:任务目标、输入文件、约束条件、输出格式。上下文传递做得好不好,直接决定子代理能不能干对活。
我的经验是,给子代理的上下文要"够用但不冗余"。给太少,它不知道要干什么;给太多,它的注意力被稀释,反而容易跑偏。一个比较实用的做法是,把上下文分成"必须知道"和"可以参考"两类,必须知道的直接放进 prompt,可以参考的放在文件里让它自己按需读取。
5.4 结果汇总与冲突处理
多个子代理并行跑完之后,结果汇总是个麻烦事。如果两个子代理改了同一个文件,就会有冲突。Claude Code 用 worktree 隔离,理论上每个子代理改的是自己 worktree 里的文件,不会直接冲突。但合并回主分支的时候,冲突还是可能发生。
处理冲突的策略有两种:一种是让调度器自动合并,能合就合,合不了就标记出来让人处理;另一种是让子代理在提交前先同步主分支的最新改动,减少冲突概率。我倾向于后者,因为自动合并虽然省事,但一旦合错了,排查成本很高。
6. 实测中遇到的坑与排查思路
6.1 子代理"跑飞"了怎么办
我在测试调度模式的时候遇到过一次子代理跑飞的情况:给它一个"重构模块"的任务,它改着改着开始改不相关的文件,最后提交了一堆莫名其妙的改动。排查下来发现是上下文里没有明确限定改动范围,子代理就"自由发挥"了。
解决办法是在任务描述里加明确的边界,比如"只允许修改 src/user/ 目录下的文件"、"不要改动任何配置文件"、"不要新增依赖"。这些约束看起来啰嗦,但能大幅降低跑飞的概率。
6.2 任务卡住不返回的排查链路
另一个常见问题是任务卡住。子代理提交了任务,但迟迟不返回结果。这时候排查链路是这样的:
- 先看 worktree 目录,确认子代理是不是还在跑
- 看进程列表,确认相关进程是否存活
- 看日志,确认最后一步卡在哪里
- 如果是 MCP 调用卡住,检查 MCP Server 是否正常响应
# 查看 worktree 状态 git worktree list # 查看相关进程 ps aux | grep claude # 查看最近的日志 tail -f ~/.claude/logs/latest.log大部分卡住的情况都是 MCP Server 无响应或者网络超时导致的。如果是 MCP 的问题,重启 MCP Server 通常能解决。
6.3 上下文丢失与状态不一致
调度模式下,子代理之间的上下文是隔离的。这带来一个副作用:子代理 A 知道的背景,子代理 B 可能不知道。如果任务之间有隐含的依赖,就容易出现状态不一致。
比如子代理 A 改了接口签名,子代理 B 还在用旧签名写调用代码。两个都跑完了,合并的时候才发现对不上。避免这个问题的办法是,在拆任务的时候把接口约定先固定下来,作为共享上下文传给所有子代理。
6.4 资源竞争与限流
并行任务多了之后,资源竞争就来了。CPU、内存、磁盘 IO、网络带宽,都是有限的。如果同时开十个子代理,每个都在跑测试、装依赖、编译代码,机器很容易被拖垮。
我的做法是给调度器设一个并发上限,比如同时最多跑三个子代理。这个上限根据机器配置来定,配置高的可以多开,配置低的就少开。Claude Code 的调度器应该支持配置并发数,具体参数可以查文档。
7. 这套设计对 Agent 开发的启发
7.1 调度能力是 Agent 从玩具到工具的分水岭
我观察了很多 Agent 项目,发现一个规律:能干活的和不能干活的,差别往往不在单个 Agent 的智能程度,而在调度能力。一个只会单步执行的 Agent,再聪明也只能做简单任务;一个有调度能力的 Agent,即使单个步骤不那么完美,也能通过编排完成复杂任务。
Claude Code 这次把自己改成调度器,本质上是在补这块能力。它不再追求"一步到位",而是追求"分步可靠"。这个思路对做 Agent 开发的人很有参考价值:与其把单个 Agent 做得无比强大,不如把调度框架做扎实,让多个普通 Agent 协作完成复杂任务。
7.2 Supervisor 模式的适用边界
Supervisor 模式不是万能的。它适合任务可拆、子任务独立、结果可合并的场景。如果任务本身是高度耦合的,拆开反而增加协调成本,那就不适合用 Supervisor。
判断标准可以简化为:拆开之后,子任务之间的通信成本是否低于并行带来的收益。如果通信成本高,就不拆;如果通信成本低,就拆。这个判断需要结合具体任务来做,没有一刀切的答案。
7.3 从 Claude Code 看 Agent 框架的演进方向
从这次改动能看出几个趋势:一是 Agent 框架正在从"单代理"向"多代理"演进;二是隔离机制(worktree、沙盒)越来越重要;三是标准化接口(MCP)成为能力扩展的主流方式;四是调度逻辑从硬编码向可配置演进。
这些趋势对做 Agent 框架的人有直接参考意义。如果你在设计 Agent 系统,建议把这几个方向纳入考虑:支持多代理协作、提供隔离机制、实现标准化工具接口、把调度逻辑做成可配置的。
8. 一些实操建议和注意事项
最后分享几个我在实际使用中总结的点。第一,不要一上来就用调度模式跑复杂任务,先用简单任务验证链路,确认没问题再上复杂的。第二,worktree 的磁盘占用要定期清理,不然时间长了会堆积。第三,MCP 工具的权限要严格控制,尤其是文件系统和网络相关的。第四,子代理的任务描述要写清楚边界,宁可啰嗦也不要含糊。第五,并发数要根据机器配置来设,不要贪多。
还有一个容易被忽略的点:调度模式下的日志比普通模式重要得多。因为任务跑起来之后你看不到中间过程,出问题了只能靠日志排查。所以建议把日志级别调高一点,保留足够的信息。如果日志太多影响性能,可以只保留关键节点的日志。
这套东西我还在持续摸索,有些地方的理解可能还不够深。但整体上,Claude Code 这次从执行者向调度者的转变,方向是对的,设计思路也值得借鉴。如果你也在做 Agent 相关的东西,建议花点时间研究一下它的调度机制,应该会有收获。