作者将 500 个 PHP 脚本分配给 10 个子 Agent 并行迁移,结果发现瓶颈不在并发数量而在任务定义的模糊性——子 Agent 对同一指令的理解偏差导致大量返工。
这个想法是把文件分成批次,分配给小型模型处理。
Main Agent
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Agent 1 Agent 2 Agent 3
50 files 50 files 50 files
│ │ │
└─────────────┼─────────────┘
▼
Migration
每个 agent 收到的指令本质上是一样的:
用新的结构化日志替换 使用正确的 channel 保留业务逻辑 完成分配的文件
文件之间是独立的,所以这个方法看起来合理。
但每个 agent 做的远不止实际的迁移工作。
它还在重新发现代码库、搞清楚什么需要改、决定 channel 名称,以及跟踪自己的进度。
这种重复的工作才是真正的成本。
问题主要不在代码改动本身,而在于围绕改动所做的周边工作。
Problem 1: Tracking completed work
用多个 agent,就需要有人知道:
哪些文件是待处理的 哪些正在被处理 哪些应该跳过
这就是工作流状态。
JSON 文件、数据库或任务队列是为这种场景设计的。LLM 上下文不是。
Problem 2: Finding what actually needs to change
每个 agent 都需要自己发现日志语句。
这个过程大致是:
Open file
↓
Understand file
↓
Search for logging
↓
Find legacy calls
↓
Inspect context
↓
Decide what to change
↓
Perform migration
但如果一个简单的命令已经能告诉我们:
ExampleScript.py:42
ExampleScript.py:87
ExampleScript.py:131
ExampleScript.py:164
那让十个不同的模型上下文去发现同样的位置,就几乎没什么价值了。
这是工具该做的事。
Problem 3: Channel generation consumed reasoning
每个脚本需要一个唯一的 channel。
ExampleScript.py
↓
example_channel
这是我本来不应该委托给模型的又一个决策。
Channel 生成可以是确定性的:
file path
↓
channel generator
↓
validated channel map
一旦生成,channel 就可以直接交给模型。
没必要让模型对每个文件都重新考虑命名规范和唯一性。
这是我思维转变的关键点。
500 个独立文件
但这未必意味着:
500 个独立的推理问题。
这是两件不同的事。
迁移本身大部分是:
Find legacy logging
↓
Replace with known API
↓
Use known channel
↓
Preserve everything else
工作重复了数百次,但推理模式大致相同。
现在对比一个调试问题:
Why did API latency increase?
├── Database?
├── Cache?
├── Network?
├── AWS infrastructure?
└── Application code?
这些是真正不同的推理路径。
这才是 sub-agent 变得有用的时候:
Problem
│
┌──────────┼──────────┐
▼ ▼ ▼
Agent A Agent B Agent C
Database Network Application
│ │ │
└──────────┼──────────┘
▼
Synthesis
每个 agent 可以独立调查一个实质性假设。
这才是有意义的并行。
在我的迁移中,我在并行化工作,而不是推理。
显而易见的改进是把确定性工作移到模型外部。
不要让 agent 去发现一切,而是先对代码库进行预处理。
Repository
│
▼
Preprocessing
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Inventory Log locations Channel map
│ │ │
└──────────────┼──────────────┘
▼
index.json
│
▼
Single Claude Code
│
▼
Migration
│
▼
Verification
预处理阶段确定:
哪些文件包含 legacy logging 哪些文件不包含 logging legacy 调用在哪里 每个文件属于哪个 channel 哪些已经完成了
{
"file": "ExampleScript.py",
"status": "pending",
"legacy_log_count": 4,
"channel": "example_channel"
}
现在模型不需要去发现问题。
它拿到的是已经发现的问题。
Explore the repository and migrate this file.
模型可以收到:
File:
ExampleScript.py
Channel:
example_channel
Legacy logging locations:
47
82
119
153
Expected migrations:
4
Task:
Replace the identified legacy logging statements
with the structured logging implementation.
Do not modify business logic.
Do not change the assigned channel.
Do not modify unrelated code.
模型现在专注于真正需要推理的部分:
如何用新的 API 表达这个已有的日志语句,同时保留其含义?
其他一切都已确定。
这是一个好得多的任务边界。
对于这个迁移,单个 Claude Code 会话有一些简单的优势:
一个共享的迁移上下文 没有重复的指令 没有 agent 间的协调 外部状态用于跟踪进度 确定性工具处理确定性工作
工作流变成了:
index.json
│
▼
Next pending file
│
▼
Prepare file context
│
├── locations
├── channel
└── rules
│
▼
Single agent
│
▼
Verification
│
┌─────┴─────┐
▼ ▼
PASS FAIL
│ │
▼ ▼
completed review
这并不比多 agent 系统缺乏技术含量。
只是更好地匹配了问题本身。
这段经历引出了一个更好的问题。
"我有多少任务?"
"我有多少独立的推理问题?"
这个区别让有用的场景清晰多了。
对于架构调查,不同的 agent 可以探索不同的领域:
Agent A → AWS architecture
Agent B → database architecture
Agent C → observability
Agent D → security
主 agent 然后可以汇总发现。
Competing debugging hypotheses
对于性能问题:
Performance issue
│
┌────────────┼────────────┐
▼ ▼ ▼
Database Network Application
hypothesis hypothesis hypothesis
│ │ │
└────────────┼────────────┘
▼
Synthesis
每个 agent 调查一个不同的解释。
Independent code reviews
一个变更可以从不同角度审查:
Agent A → correctness
Agent B → security
Agent C → performance
Agent D → maintainability
这些 agent 不是简单地做同样的工作。每个有各自不同的分析目标。
Independent feature implementation
如果一个系统有明确分离的组件:
API
Worker
Infrastructure
Observability
且它们的接口已经定义好了,不同的 agent 可以独立工作。
重要的条件是低耦合。
Sub-agent 不是免费的并行线程。
每个额外的 agent 都带来自己的:
Single agent:
shared context
+
sequential reasoning
N agents:
N × context
+
N × reasoning
+
coordination
+
synthesis
所以只有当节省的推理大于引入的开销时,并行才有用。
一个有用的思考方式是:
Sub-agent benefit = parallel reasoning saved - duplicated context
- coordination cost - synthesis cost
如果差值很小,增加 agent 基本上就是增加机械复杂度。
在创建 sub-agent 之前,问自己:
Is the task deterministic?
用脚本或工具。
Does it require substantial reasoning?
单个 agent 通常就够了。
Is the reasoning independent?
放在一个会话里。
Would a fresh context provide meaningful value?
Sub-agent 可能是值得的。
一个简单的决策树:
Is it deterministic?
│
┌─────┴─────┐
YES NO
│ │
TOOL Substantial
reasoning?
│
┌────┴────┐
NO YES
│ │
SINGLE AGENT Independent?
│
┌─────┴─────┐
NO YES
│ │
SINGLE SUB-AGENTS
SESSION
这次迁移改变了我对 agent 编排的思考方式。
五百个文件仍然可以代表一种推理模式。
在十个 agent 之间复制相同的 context 有成本。
在调用模型之前找到相关信息,可以比增加更多 worker 节省更多精力。
模型不应该记住数百个文件的状态。
Channel 生成、分类、搜索、计数和验证可以自动化。
更多的 agent 不自动意味着更快或更便宜。
不是维护工作流状态。
不是执行确定性工具可以更可靠执行的搜索。
最大的教训不是:
"不要使用 sub-agent。"
不要仅仅因为工作可以分解就并行化。当推理可以分解时,才并行化。
一百个确定性转换可能更适合用脚本处理。
一百个小推理任务可能仍然更适合用一个上下文充足的 agent 处理。
五个困难的独立调查可能正好适合五个 sub-agent。
任务数量只是问题的一部分。
推理的结构应该决定架构。
我最初的假设是:
500 files
↓
many agents
↓
faster migration
更好的方法原来是:
500 files
↓
deterministic preprocessing
↓
external state
↓
bounded context
↓
single agent
↓
deterministic verification
教训不是 sub-agent 不好。而是并行应该有原因。
在生成另一个 agent 之前,问自己:
独立的推理在哪里?
如果没有多少独立推理,更多的 agent 可能只是意味着更多的 context、更多的 token、更多的协调,以及之后更多的清理工作。
当 sub-agent 让你能够同时探索不同的实质性推理路径时,才使用它们。
否则,更少但边界更清晰的 agent 通常会胜出。