20 倍算力的瓶颈
我买了 Claude Max plan,最贵的那个档位。官方宣称有 20 倍的 Opus 模型用量。
用下来我发现,瓶颈根本不在算力。
Claude Code 的使用过程是这样的:它写一段代码,你 review 一下,觉得没问题就让它继续。它再写一段,你再看一下。每一步都需要人手动确认。这意味着不管 Opus 用量给你多少倍,你的产出上限取决于你能多快地做 code review。
还有一个更恼人的问题:context 太长之后,session 的质量会明显下降。命名开始随意,逻辑开始混乱,有时候写出来的东西跟前面的代码互相矛盾。这时候你只能开一个新的 session,但新 session 对之前的上下文一无所知,又得重新建立理解。
说白了,20 倍的算力被两个东西卡死了:人的交互带宽,和 context 窗口的物理限制。
所以我需要一个系统,把人从循环里摘出来。
我想解决什么问题
两个。
上下文膨胀导致代码质量下降
用 Claude Code 写过项目的人应该都有体感:session 刚开始的时候,代码质量很好,逻辑清晰,命名规范。但随着对话越来越长,上下文窗口塞满了几十轮的对话历史,质量开始肉眼可见地下降。命名变随意,边界情况被忽略,有时候甚至重写之前写过的逻辑。
这不是 Claude 变笨了。是上下文窗口的物理限制。当窗口里塞了太多东西,模型的注意力被稀释了,就像你在一个吵得要死的会议室里试图写代码。
每次都需要人验收
Claude Code 写完一段代码,你得自己 review,确认没问题才能让它继续。如果你一直盯着倒也行。但我想要的是:把需求丢给它,出去吃个饭回来看结果。中间不需要我参与。
这意味着系统需要有自我验证的能力。不是 Claude 自己说”我觉得写得不错”,而是有一个独立的、看不到实现过程的 agent 来做 code review,给出客观的判断。
面临的挑战
这两个问题看起来各自独立,但解法其实指向同一个方向:多 agent 编排。
用多个短 session 替代一个长 session 解决上下文膨胀,用独立的 Reviewer agent 替代人工验收。但引入多 agent 之后,新的问题来了:
谁来管理这些 agent? 任务怎么拆,按什么顺序执行,前一个任务的产出怎么传给后一个?需要一个调度者。
调度者自己的上下文会不会膨胀? 如果调度者是一个长驻的 Claude session,跑几十轮循环之后,它自己的上下文也炸了。问题又回来了。
状态存在哪? 如果每个 agent 都是独立的短 session,它们之间怎么传递信息?不可能靠”记忆”,因为每个 session 启动时是干净的。
子 agent 怎么调用? 最初我想的是轮询:分发任务后每隔几秒检测子 agent 是否完成。但很快发现轮询引入了定时器管理、状态竞争、延迟浪费等一堆复杂度。最终选择了同步阻塞调用,通过 claude -p 启动子 agent,调用本身就是阻塞的,子 agent 完成后命令返回结果,Orchestrator 直接拿到产出进入下一步。简洁、可靠、无需定时器。
用户怎么介入? 系统在自动跑,但遇到需要人做决定的情况(比如一个任务反复失败),怎么通知用户、等待回复、拿到回复后继续?
解决方案
四个角色
我设计了四个角色,每个都有明确的职责边界:
| 角色 | 类比 | 职责边界 |
|---|---|---|
| Architect | 架构师 | 只规划,不写代码。输出任务列表和技术决策文档 |
| Orchestrator | 项目经理 | 只调度,不创造。读状态 → 分派 → 更新状态 → 退出 |
| Implementer | 程序员 | 只执行分配的任务,不扩大范围 |
| Reviewer | 代码审查员 | 独立审查,看不到 Implementer 的推理过程,只看产出 |
Architect(架构师) 只在项目启动和异常升级时出场。把需求拆成带依赖关系和验收标准的任务列表。关键约束:绝对不写代码。一旦它开始写代码,注意力就浪费在细节上了,规划质量反而下降。写完计划就退场。
Orchestrator(调度者) 是整个系统的心跳。但它不是一个持续运行的 agent,而是一个被定时唤醒的无状态函数(这个设计后面会解释)。每次醒来做一件事:读状态 → 派活 → 等结果 → 审核 → 更新状态 → 退出。它越笨越好,越机械越稳定。
Implementer(执行者) 是干活的。每次启动只看到当前任务的描述、验收标准、和精确筛选过的相关文件。不知道项目全貌,也不需要知道。有一个重要的约束:不扩展范围。任务说”实现用户登录”,它不应该顺手把”忘记密码”也做了。越界 = 引入调度者不知道的变更 = 状态管理炸掉。
Reviewer(审核者) 做独立的 code review。它拿到任务需求和 Implementer 的代码产出,但看不到 Implementer 的推理过程。这很重要:如果 Reviewer 能看到 Implementer 是怎么想的,它会被带着走,失去独立判断。就像真实团队中,code review 只看 PR diff,不看开发者的内心独白。返回三种结论:通过、需修改(附具体意见)、需重做。
无状态 Orchestrator
调度者的上下文膨胀问题,我的解法是:让它根本不存在于内存中。
核心哲学四个字:召之即来、完事就走。
Orchestrator 是一个 Cowork scheduled task,每 5 分钟唤醒一次。每次唤醒都是一个全新的 Claude session,干净的上下文。它的全部”记忆”在磁盘上的 state.json 里。读文件、做决策、调子 agent、写文件、退出。下次唤醒再来。
这意味着:
- 每次执行都有干净的上下文窗口,不存在质量退化
- 所有记忆都在文件系统中,而非 Claude 的对话历史里
- Orchestrator 崩溃不会丢失状态,
state.json就是恢复点 - 多个项目可以并行运行,互不干扰
但有一个问题:每次唤醒都是全新的 Claude 实例,上一个周期发生了什么?如果不做处理,新的 Orchestrator 只能从任务状态中推断,很多”软信息”就丢了。比如”上一轮 Reviewer 差点就通过了,只是测试覆盖率不够”或者”task-04 的依赖刚完成,下一轮应该优先处理”。
所以我加了一个 orchestrator_notes 字段。每个周期结束时,Orchestrator 写一两句话的摘要,告诉”下一个自己”发生了什么、接下来该关注什么。本质上是一个跨实例的短期记忆。不是完整的上下文传递(那会重蹈上下文爆炸的覆辙),而是一张精炼的便签纸。
状态文件是唯一的 truth
所有 agent 之间的信息传递只通过文件系统。state.json 里记录了一切:任务列表和每个任务的状态、Reviewer 的历次反馈、Orchestrator 留给下次唤醒的备忘、并发锁(orchestrator_running + orchestrator_last_run)、用户交互队列。
我特意把 status(项目在任务生命周期中的位置)和 should_run(自动执行的开关)设计成正交的。这个区分很重要:用户想”暂停”的时候,不应该丢失任务进度。如果只有一个 status 字段,“暂停”只能用一个额外的状态值(比如 paused),会和任务生命周期纠缠在一起。
分成两个维度之后就清晰了:
| status | should_run | 含义 |
|---|---|---|
| running | true | 正常运行 |
| running | false | 用户暂停(kill),任务保留但不执行 |
| completed | false | 项目完成 |
| waiting_for_user | true | 等待用户输入,Orchestrator 仍会唤醒但跳过工作 |
kill 只改 should_run,不碰 status。resume 反之。两个维度互不干扰。
.ap/ 在项目目录内
最初我把所有 AP 项目的状态集中存放在 ~/Projects/autopilot/ 下。但很快发现问题:项目和 autopilot 系统耦合太紧,无法灵活地把一个已有项目纳入管理,而且项目在磁盘上分散各处,集中目录不自然。
所以改成了项目本地化:状态文件住在项目根目录的 .ap/ 下面,和代码在一起,就像 .git/ 属于项目本身一样。
my-project/
├── .ap/
│ ├── state.json
│ ├── context/
│ │ ├── architecture.md
│ │ └── role-prompts.md
│ └── logs/
├── src/
└── package.json
一个全局注册表 ~/.ap/registry.json 记录所有 AP 项目的路径,给 ap status 命令用。这个决策直接催生了 ap adopt 命令,让已有项目可以直接纳入 AP 管理。
显式激活
一个重要的产品决策:AP 绝不自动启动。
即使项目目录下有 .ap/,即使用户描述的改动很大,AP 也不会自作主张地接管。原因很简单:AP 是重量级工作流,误触发的代价很高。用户可能只是想快速修个 bug,不需要四角色编排。
触发规则:
- 用户明确说
ap setup、ap status等命令,立即触发 - 用户描述大型改动但没提 AP,建议使用 AP,等待确认,绝不自启
- 用户做小改动,直接帮忙,不提 AP
异步用户交互
Orchestrator 是短命的,等不了用户。所以当它需要人做决定时(比如一个任务被 Reviewer 打回三次),它把问题写进 state.json,设状态为 waiting_for_user,然后正常退出。后续每次唤醒检查有没有回复,没有就跳过,有了就继续。用户通过 ap interact 回答问题。
工作原理
把上面的东西串起来,完整的流程分三个阶段。
启动
执行循环
收尾
所有任务完成后,跑一次全量测试 + lint + 类型检查。全过就写 summary,标记 completed。有失败就生成修复任务,继续循环。
已有项目
除了从零 setup,还有 ap adopt,把一个已有代码库纳入 AP。区别在于 Architect 规划前会先并行启动几个子 agent 深度阅读代码库,理解现有架构和 convention,然后基于这些理解来规划新工作。所有历史上下文(架构决策、模块边界、接口约定)都保留着,新的 Implementer 能直接读到,不需要重新发现。
关键设计总结
- Orchestrator 无状态。每次唤醒都是全新的 Claude session,上下文永远干净。彻底解决了 context 爆炸导致代码质量下降的问题。
- Reviewer 按需唤醒。针对每个任务临时启动一个 Reviewer,只给它任务需求和代码产出,不给多余的上下文。简洁的上下文确保了代码审核的准确度。
- 可打断、可交互。执行过程中随时可以
ap kill暂停,用ap interact回答系统的提问,用ap resume继续。人始终在回路中,但不需要一直盯着。 - 可接入老项目。
ap adopt命令让已有代码库直接纳入 AP 管理,Architect 会先深度阅读现有代码再规划,不是从零开始。 - 多项目并行。每个项目的状态独立存在于自己的
.ap/目录,一台电脑上可以同时跑多个 AP 项目,互不干涉。
限制
- 太 heavy 了。四角色编排、定时唤醒、状态文件管理,对于”改个 bug”或者”加个按钮”这种小事来说是杀鸡用牛刀。AP 适合的是需要拆成多个任务的中大型改动。
- token 消耗巨大。每个任务至少要跑一轮 Implementer + Reviewer,失败重试还要翻倍。这个项目存在的意义就是把我的 Claude Max 20 倍 plan 压榨到极致。如果你用的是按量付费,账单会很刺激。
未来计划
- Eco 模式。不是所有任务都需要 Opus。计划加一个 eco 模式,对简单任务用更轻量的模型,复杂任务才上 Opus,在质量和 token 消耗之间找平衡。
- Web 看板。现在看项目状态只能用
ap status命令行查看。计划做一个 web 看板,在浏览器里实时查看各项目状态、任务进度、审查历史,手机上也能看。