Skill-Agent 协作架构篇:从单 Skill 到 Multi-Agent 编排¶
核心结论:当一个 Skill 同时承载的任务维度过多时,高优先级任务会系统性压制低优先级任务的执行——即使 Skill 明确禁止跳过也无效。这是 LLM 的结构性限制,不能通过加强提示词消除,只能通过架构手段解决。解法是 Skill-Agent 协作:将重度 Skill 拆分为聚焦单一维度的垂直 Skill,各由独立 Agent 在隔离上下文中执行;配合 Grep-Gated 执行协议,将 75% 的检查项转为规则驱动的预扫描,进一步降低维度内的概率性遗漏。
目录¶
17. 注意力稀释:架构问题,不是提示词问题¶
17.1 注意力稀释的规律(以代码审查 Skill 为例)¶
单 Skill 同时处理多个维度时,高优先级任务会天然抢占模型注意力,导致低优先级任务被系统性遗漏——这不是偶发错误,而是可复现的结构性失效,代码审查场景尤为典型。
以 Go 代码审查为例,以下代码交给 go-code-reviewer Skill 处理:
func getBatchUser(ctx context.Context, userKeys []*UserKey) ([]*User, error) {
userList := make([]*User, 0)
var wg sync.WaitGroup
for i, u := range userKeys {
if u == nil { continue }
wg.Add(1)
go func() {
defer wg.Done()
user, err := redis.GetGuest(ctx, u.Id)
if err != nil {
log.WarnContextf(ctx, "no found guest user: %v", u)
continue
}
userList = append(userList, user)
}()
}
return userList, nil
}
Skill 发现了 4 个 High 级并发缺陷(编译错误、数据竞争、goroutine 泄漏、循环变量捕获),但漏报了一个 Medium 级性能问题:
// 实际代码(错误)
userList := make([]*User, 0)
// 应该写成(已知上界 len(userKeys),应预分配容量)
userList := make([]*User, 0, len(userKeys))
这完全符合 Skill 的 Performance checklist 中"Slice Pre-allocation"检查项。Skill 本身也明确规定:
Execute ALL checklist categories regardless of how many High findings have already been identified
但模型仍然漏报了。人工指出遗漏后,模型立即识别并承认:
"当 4 个 High 级别的并发缺陷占据了注意力后,我在走 Performance checklist 时不够仔细,错误地将这个问题归入了'可忽略的小问题'而没有正式报告。"
关键发现:问题不在于模型"不会"——指出后立即承认,说明它具备识别能力。问题在于单次调用中同时处理 5 个审查维度,High 级别 Findings 天然更"吸引"注意力,压缩了模型分配给其他维度的认知资源。
17.2 根因:上下文窗口的注意力竞争¶
单 Agent 加载重度 Skill 时,上下文窗口承载了所有维度的知识、全部代码,以及已发现的 Findings:
[单个 Agent 的上下文窗口]
┌─────────────────────────────────────────┐
│ go-code-reviewer SKILL.md(全量知识) │
│ ├── 安全规则(SQL 注入、XSS...) │
│ ├── 并发规则(竞态、死锁、泄漏...) │
│ ├── 性能规则(预分配、N+1...) │ ← 被挤压
│ ├── 错误处理规则(wrap、nil check...) │ ← 被挤压
│ └── 质量规则(命名、结构...) │ ← 被挤压
│ │
│ 已发现的 Findings: │
│ ├── [High] REV-001 编译错误 ←────────┐ │
│ ├── [High] REV-002 数据竞争 ←────────┤ │ 注意力集中在这里
│ ├── [High] REV-003 goroutine 泄漏 ←──┤ │
│ └── [High] REV-004 循环变量捕获 ←────┘ │
│ │
│ Performance checklist: │
│ Slice Pre-allocation → ??? (未检查) │ ← 注意力不足
└─────────────────────────────────────────┘
Anthropic 的内部研究对这一现象提供了量化支撑:在 BrowseComp 浏览能力评测中,token 使用量单独解释了 80% 的性能差异(三个因素合计解释 95%,另外 15% 由工具调用次数和模型选择贡献),核心原因是每个 Agent 在干净的上下文窗口中执行,token 使用效率更高——这正是上下文污染(Context Rot)会拉低单 Agent 性能的直接证据。(来源:How we built our multi-agent research system,Anthropic Engineering Blog,2025-06-13)
这不是提示词写法的问题,是架构问题。 已尝试的缓解措施如下:
| 缓解措施 | 效果 | 局限 |
|---|---|---|
| 在 Skill 中强调"不可跳过 checklist" | 部分有效 | 规则本身也在同一上下文中竞争注意力 |
| 写入 Memory"High findings 不能跳过其余 checklist" | 下次有帮助 | 无法根本解决单上下文多维度的注意力竞争 |
| 增加 checklist 的强制性语言 | 有限改善 | LLM 的注意力机制是概率性的,无法仅靠指令稳定覆盖 |
这些措施仅能把执行遗漏概率从高降为中,无法消除。迭代篇(§15-16)已记录这一上限:在规则层的最终修复率约为 67%,仍有系统性残差。本篇给出架构层的根本解法。
17.3 为什么 Multi-Agent 是正确方向¶
17.3.1 Multi-Agent 的精确定义与四大机制¶
Multi-Agent 架构是指多个 AI Agent 在明确的角色分工和协作协议下,协同完成一个复杂任务。每个 Agent 拥有独立的上下文窗口、专用的工具集和清晰的职责边界。
这与软件工程中的微服务演进高度类似:
| 软件演进 | AI Agent 演进 |
|---|---|
| 单体应用代码库太大,难以维护 | 单体 Agent 上下文窗口积累太多,性能下降 |
| 单点故障影响全局 | 单个维度失误影响整条审查链路 |
| 无法独立扩展模块 | 无法为不同任务选择最优模型 |
| 职责边界模糊 | Agent 角色混乱导致输出质量下降 |
就像单体应用最终需要被拆分为微服务一样,单体 Agent 在任务足够复杂时,也需要被拆分为多个专职 Agent。
Multi-Agent 对 Go 代码审查场景的四大优势机制:
| 优势 | 机制 | 对本场景的意义 |
|---|---|---|
| 专注的上下文窗口 | 每个 sub-Agent 在全新、干净的上下文中运行,不受其他维度 Findings 污染 | 并发审查发现 4 个 High 不会影响性能审查对 make([]*User, 0) 的敏感度 |
| 深度专业化 | 每个 Agent 的系统提示聚焦单一领域,工具集精简 | Security Agent 只看安全缺陷;Performance Agent 只看性能问题——无需兼顾其他 |
| 多视角质量保障 | 多个 Agent 独立评估,彼此不知道其他 Agent 的 Findings | 并发、错误、性能审查各自独立得出结论,交叉验证相互强化 |
| 灵活的模型配置 | 主会话(编排 Skill)用强模型做分诊和汇总,Workers 用快速模型执行审查 | 主会话负责分诊 + 去重,Workers 使用 Haiku/Sonnet 控制成本 |
第一个优势直接对应本文的核心问题:当单个上下文窗口同时持有多个高严重度 Findings 时,模型对低优先级检查项的覆盖率会系统性下降。这是提示词难以修复的结构性缺陷——Multi-Agent 通过让每个维度在独立上下文中运行,显著降低了跨维度的注意力竞争。
17.3.2 实证数据:Anthropic + AgentCoder¶
Anthropic 多 Agent 研究系统实测(来源:How we built our multi-agent research system,Anthropic Engineering Blog,2025-06-13): - Claude Opus 4(Lead)+ Claude Sonnet 4(Workers)的多 Agent 系统,在内部研究评测中比单 Agent Opus 4 性能高出 90.2% - 在 BrowseComp 评测中,token 使用量单独解释了 80% 的性能差异——关键不在于模型更强,而在于每个 Agent 在干净的上下文中专注完成单一任务
AgentCoder 学术研究(来源:https://arxiv.org/pdf/2312.13010): - 多 Agent 代码生成(Programmer + Test Designer + Test Executor)在 HumanEval 上达到 96.3% pass@1,单 Agent SOTA 为 90.2% - 使用更少的 token(56.9K vs 138.2K)达到更高的准确率,证明专业化分工可以同时提升质量和效率
这组数据揭示了一个反直觉的结论:Multi-Agent 的优势不来自"用了更多算力",而来自让每个 Agent 在干净的上下文中做更专注的事。
17.3.3 架构换模型:降低对顶尖推理模型的依赖¶
§17.3.2 的实证数据指向一个值得单独提炼的结论:Multi-Agent 架构不仅仅是"用便宜的模型做同样的事"——而是用更便宜的模型,做更好的事。
| 配置 | 模型 | 审查质量(基准案例) | 漏报数 |
|---|---|---|---|
| 单 Agent | Opus 4 | 4 High,漏报 1 Medium | 1 |
| Multi-Agent Orchestrator-Workers | Sonnet 4 Workers + Sonnet Lead | 全部捕获 13/13 | 0 |
为什么更便宜的模型 + 更好的架构能超越更强的模型 + 单 Agent?
根因在于任务结构与模型能力的匹配度。Opus 在单一聚焦任务上的表现确实优于 Sonnet——但当它被要求在同一个上下文中同时覆盖 5 个独立维度时,注意力稀释会系统性拉低它在每个维度上的实际发挥。而 Sonnet 在只负责一个维度(如仅审查并发问题)时,专注度接近满状态,不受跨维度注意力竞争的影响。
换一种说法:对于多维度任务,Sonnet × N 个聚焦 Agent 的组合效能,可以超过 Opus × 1 个泛化 Agent。
成本权衡:
| 维度 | 单 Opus Agent | Multi-Agent Sonnet Workers |
|---|---|---|
| 单次推理成本 | 高(Opus 约为 Sonnet 定价的 5–10 倍) | 低(每个 Worker 用 Sonnet/Haiku) |
| 总 token 消耗 | 低(单次调用) | 高(多个并行 Agent 累计) |
| 整体账单 | 中 | 中(token 更多但单价更低,近似持平) |
| 审查质量 | 有注意力稀释风险 | 更全面、更稳定 |
多 Agent 并行虽然累计 token 消耗更高,但每次推理调用使用的是更低价位的模型。两者相抵,整体账单往往近似持平,而质量却显著提升。
核心洞察:这一结论改变了模型选型的思路框架。传统问法是"我应该用哪个最强的模型?"——更好的问法是"我的任务架构,能否把模型从需要同时擅长多件事,改造成只需专精一件事?"如果能,次优模型配合优质架构往往优于顶尖模型配合平凡架构。
对于遭遇注意力稀释的场景,这意味着:你不需要等待更强大的下一代模型来解决漏报问题——架构重构是在现有模型上更可控、更可预期的解法。
17.4 编排模式选型:为什么是 Orchestrator-Workers¶
明确了 Multi-Agent 的优势之后,下一个问题是:选哪种编排模式?
Anthropic 定义了五种基础编排模式。逐一评估它们对 Go 代码审查场景的适用性:
| 模式 | 核心机制 | 对本场景的评估 | 适用? |
|---|---|---|---|
| 模式一:Prompt Chaining | 线性步骤序列,上一步输出是下一步输入 | 安全/并发/性能各维度之间没有依赖关系,不是顺序问题 | ✗ |
| 模式二:Routing | 分类输入,路由到某一个专门处理器 | 一次审查需要同时覆盖多个维度,而不是选择其中一个 | ✗ |
| 模式三:Parallelization | 多路并行,子任务预先固定 | 接近需求,但子任务固定,每次必须跑所有分支,无法按内容裁剪 | △ |
| 模式四:Orchestrator-Workers | 中央编排者动态分解任务,按需调度 Workers | 在当前场景下最匹配——审查维度随代码内容动态决定 | ✓ |
| 模式五:Evaluator-Optimizer | 生成→评估→改进的迭代循环 | 代码审查是诊断任务,不是迭代生成任务 | ✗ |
模式三与模式四的关键区别是本次选型最需要厘清的点。两者都支持并行,差异在于子任务的来源:
Parallelization(模式三):
代码 → [固定派发: Security + Performance + Quality + Logic + ...] → 汇总
子任务在设计时确定,每次审查都跑完整的 N 路
Orchestrator-Workers(模式四):
代码 → [Lead Agent 分析 diff] → 动态决策 → 按需派发 K 路(K ≤ N)→ 汇总
子任务在运行时确定,根据代码内容决定需要哪些维度
对 Go 代码审查而言,需要派发哪些 Agent 取决于被审查代码的内容:
- 代码只改了变量名 → 只需 Quality + Logic(2 个 Agent)
- 代码引入了
go func+sync.WaitGroup→ 还需 Concurrency + Error(4 个) - 代码包含
make([]*T, 0)+ 批量函数名 → 还需 Performance(5 个) - 代码有
_test.go变更 → 还需 Test(6 个)
这种"内容驱动的维度选择"无法在设计时预知,必须由编排者在运行时根据输入动态决策——这正是 Anthropic 对 Orchestrator-Workers 适用场景的定义:"无法提前预测需要哪些子任务,需要 Orchestrator 根据输入动态决策"。
如果强行用 Parallelization,代价是每次审查都启动所有 7 个 Agent,一次 5 行变量名修改也要承担全量 Agent 的 token 消耗和延迟,性价比严重失衡。分诊本身就是 Orchestrator 最核心的价值。
18. Skill-Agent 协作架构:设计、实施与验证¶
选型已定,进入实施阶段。 §17 识别了注意力稀释问题,§17.3 确立了 Multi-Agent 方向,§17.4 在五种模式中选出了 Orchestrator-Workers。本章以
go-code-reviewer→ 7-Agent 编排体系为贯通案例,回答下一个问题:如何把选型落地为一套可运行、可验证、可复用的架构? 所涉及的设计原则(垂直拆分、主会话负责编排、按需分诊、Grep-Gated 协议)不局限于代码审查场景,适用于任何遭遇注意力稀释的重度 Skill。
18.1 三种架构对比(决策矩阵)¶
| 架构 | 特点 | 已知问题 | 推荐度 |
|---|---|---|---|
| A:单 Skill | 1 个 Agent 加载全量审查知识,一次调用完成所有维度 | 注意力稀释;High Findings 系统性压制其他维度;已证实漏报 | 基础场景 |
| B:Multi-Agent 无 Skill | 7 个垂直 Agent 仅靠提示词,无 Skill 加载;主会话负责编排 | 上下文干净,但缺少领域审查规则;只能依赖 AI 通用知识;可能漏掉项目特定规则 | 不推荐 |
| C:Multi-Agent + 垂直 Skill | 主会话加载 go-review-lead Skill 负责分诊与汇总;7 个垂直 Agent 各自加载领域 Skill | 设计和维护成本略高 | ✅ 推荐 |
架构 C 的核心原则:
原则一:每个 Agent 只加载一个维度的 Skill。Performance Agent 的上下文中主要只有性能相关知识和待审查代码,没有其他维度的规则,也不接收其他 Agent 的 Findings。这会显著提高它把注意力放在 Performance checklist 上的概率。
原则二:主会话(编排角色)不审查代码。主会话加载 go-review-lead Skill 后扮演编排角色,只做分诊和汇总,不加载任何垂直审查 Skill,不直接分析代码逻辑。若主会话自己也做审查,它的发现会影响对其他 Agent 结果的汇总判断——和重度 Skill 是同一个问题。
原则三:垂直 Agent 通过 skills: 字段在启动时自动加载领域知识。Agent 定义文件是轻量的(几十行提示词),审查知识保存在独立的 Skill 文件中,Agent 通过 frontmatter 中的 skills: 字段声明所依赖的 Skill——平台在 Agent 启动时自动注入完整 Skill 内容,无需运行时手动调用 Skill() 工具。不存在内容重复,Skill 文件可被多个 Agent 复用。
原则四(平台约束 + 工程决策):编排逻辑必须以 Skill 形式封装,在主会话执行。
结论先行,推理如下:
平台约束:subagent 不能生成 subagent
→ 编排必须在主会话执行
→ 选项 A:每次用临时 prompt 编排?
→ 否:流程太复杂 + 不可复用
→ 选项 B:封装为 Skill,主会话调用
→ 是:复杂度可控 + 标准化 + 可复用
→ Skill 是唯一合适的载体
两层决策各有一个不可绕开的理由:
第一层:为什么编排不能由 subagent 执行(即不能配置为 .claude/agents/ 中的 agent 定义)? Claude Code 明确规定子代理不能生成子代理("Subagents cannot spawn other subagents")。如果把 go-review-lead 配置为 agent 定义文件,它被调用时会作为子代理运行,此时它对 Agent 工具发出的并行调用请求将被平台静默忽略——7 个垂直 Agent 退化为串行调用或根本不被派发。
第二层:排除 agent 定义后,为什么不直接在主会话用 prompt 来编排,而必须封装成 Skill? 理由有两个:
-
复杂度不可接受:编排流程是流水线+并行的混合模式——作用域识别→审查深度选择→编译预检→四阶段分诊→动态派发 N 个垂直 Agent 并行审查→去重汇总。把这个流程写成临时 prompt,篇幅将远超可接受范围,且极难维护。
-
无法复用:每次发起代码审查都要重新提供这段复杂 prompt。这是一个标准化流程,应当封装,而不是每次重写。
更深一层的洞察:把编排逻辑封装为 Skill,不只是工程上的务实决策——它正是 Skill-Agent 协作架构在本架构中的直接体现,且同时呈现在两个层次:
| 层次 | 角色 | 模式 |
|---|---|---|
| 宏观 | 主会话调用编排 Skill → Skill 派发 7 个子代理并行 → Skill 去重汇总 → 主会话展现 | Skill 编排 Agents |
| 微观 | 每个子代理加载自己专属的垂直审查 Skill 来执行任务 | Agent 依赖 Skill |
两个层次都在运行同一个 Skill-Agent 协作模式,架构在自身内部自洽:编排用的是 Skill,执行也用的是 Skill,而连接二者的是 Agent。这不是巧合, 而是一以贯之的 Skill-Agent 协作架构思想。
完整架构全景(主会话 Skill 编排 + 7 个垂直 Agent):
PR Diff / 代码片段
│
↓
[主会话 + go-review-lead Skill]
职责:分诊 + 派发 + 汇总
加载 go-review-lead Skill
不加载垂直审查 Skill
不直接审查代码
│
Phase 1-4: 分诊
grep + 模式匹配,判断涉及哪些维度
│
┌────────┬────────┬───────┼───────┬────────┬────────┐
↓ ↓ ↓ ↓ ↓ ↓ ↓
[Security][Concurr][Perf] [Error] [Quality] [Test] [Logic]
Agent Agent Agent Agent Agent Agent Agent
│ │ │ │ │ │ │
加载安全 加载并发 加载性能 加载错误 加载质量 加载测试 加载逻辑
Skill Skill Skill Skill Skill Skill Skill
│ │ │ │ │ │ │
独立审查 独立审查 独立审查 独立审查 独立审查 独立审查 独立审查
└────────┴────────┴───────┴───────┴────────┴────────┘
│
↓
主会话汇总
合并 Findings + 去重 + 按严重度排序
│
↓
最终报告
实证验证:简化方案为何不可行¶
架构 C(7-Agent + 垂直 Skill)在直觉上可能显得过重——毕竟最好的架构不是最复杂的,而是最简单、最合适的。在最终确定该方案之前,我们实验性地尝试了两种更简单的替代路径,数据给出了否定答案。
实验一:单 Agent + Grep-Gated 协议
假设:在 go-code-reviewer 单 Agent 上下文中引入 Grep-Gated 执行协议(88 个 checklist 项,其中 66 个 grep-gated)+ 编译预检,就能机械性地消除注意力稀释,不需要 Multi-Agent 的上下文隔离。
结果:检出率 62%,与原始单 Agent 完全持平。Grep-Gated 协议有效减少了模型随意跳过机械检测项的情况,但没有解决核心问题——当上下文中同时存在多个维度的 checklist 时,High 级别发现仍会在语义分析阶段系统性地压制 Medium 级别发现。
实验二:3-Agent 精简编排
假设:Security、Concurrency、Error 三个维度在业务上高度关联,可以合并到同一子代理上下文中处理,在降低 token 成本的同时保持足够的检出率。
将 7-Agent 拆分为 3 个子代理:Security+Concurrency+Error 合并为一个,Performance+Quality 合并为一个,Logic+Test 合并为一个。
结果:检出率降至 69%,漏掉 4/13 个问题——4 个 High 级别的并发 bug 在合并上下文中压制了 Medium 级别的 Nil *User 错误,与最初单 Agent 里 High 并发压制 Medium 性能问题的机制完全相同。业务上"关联"的维度,在注意力竞争上与不相关的维度没有本质区别。
数据汇总
| 方案 | 检出率 | 重复率 | Token 成本 |
|---|---|---|---|
| 原始单 Agent | 8/13 (62%) | 0% | ~$0.03 |
| 单 Agent + Grep-Gated | 8/13 (62%) | 0% | ~$0.03 |
| 3-Agent 精简编排 | 9/13 (69%) | ~15% | ~$0.05 |
| 7-Agent 优化(推荐方案) | 15/15 (100%) | 31.6% | ~$0.08 |
核心机制
两次实验共同揭示了一个反直觉的规律:注意力稀释的驱动因素是严重度差异,而非主题相关性。只要一个上下文中同时存在 High 和 Medium 级别的发现,High 就会在语义分析阶段系统性地压制 Medium——无论这两个发现属于哪个业务维度。
由此得出:每个维度独立一个上下文,是消除注意力稀释的最小充分条件。少一个维度的隔离就会复现压制机制,漏报随之出现。
关于表中数字的说明:
-
15/15 与 §18.5 中的 13/13 不矛盾:13 是进入第三轮验证时基于前两轮已知问题集的"预期 Findings 数";第三轮完成后,7-Agent 架构又在同一基准代码中识别出 2 个前两轮未被捕获的新 Finding(含 §18.5 末尾摘录报告中的 REV-008 和 REV-009),使基准案例的最终总数升至 15。§18.1 汇总表中的 15/15 反映的是迭代完成后的最终检出结果;§18.5 中的 13/13 反映的是第三轮进入时的预期目标。
-
31.6% 的计算方式:将 7 个 Agent 各自上报的 Finding 条数加总(含跨 Agent 重复上报同一问题的条数),记为 N_total;去重后得到 unique Finding 数,记为 N_unique。重复率 = (N_total - N_unique) / N_total。以当前基准案例为例:7 个 Agent 合计上报约 22 条 Findings,去重后得到 15 个 unique Findings,重复率 = (22 - 15) / 22 ≈ 31.6%。3-Agent 精简方案中约 11 条上报对应 9 个 unique Findings,重复率 ≈ 18%(表中取 ~15% 为近似值)。
31.6% 的跨 Agent 重复率不是浪费——它是多维度并行覆盖必然产生的代价,也是保证正确性的结构性冗余。7-Agent 架构不是过度设计,而是恰好满足需求的最简有效方案:如无必要,勿减实体。
18.2 Skill 拆分指南(以 go-code-reviewer 为例)¶
拆分判断标准:
| 信号 | 是否应该拆分 |
|---|---|
| Skill 的 checklist 覆盖 3 个以上独立维度 | 是——维度间会互相抢注意力 |
| 单次审查经常产生 5+ 个 High Findings | 是——High Findings 越多,其他维度被挤压越严重 |
| 审查后用户经常指出"这个应该发现但没发现" | 是——典型的注意力稀释症状 |
| Skill 只覆盖 1 个维度,且 checklist < 15 项 | 否——上下文负担不大,单 Agent 足够 |
目录结构(以 go-code-reviewer 为例):
skills/
├── go-security-review/SKILL.md # SQL 注入、XSS、密钥泄露、权限
├── go-concurrency-review/SKILL.md # 竞态、goroutine 泄漏、死锁、WaitGroup
│ └── references/go-concurrency-patterns.md
├── go-performance-review/SKILL.md # 预分配、N+1、索引、内存
│ └── references/go-performance-patterns.md
├── go-error-review/SKILL.md # 错误包装、资源关闭、panic 处理
├── go-quality-review/SKILL.md # 命名、结构、lint 规则、注释规范
├── go-test-review/SKILL.md # 测试覆盖率、断言质量、测试隔离
└── go-logic-review/SKILL.md # 业务逻辑、边界条件、nil、错误传播
# go-review-lead 以 Skill 形式运行在主会话,不在 .claude/agents/ 中
# 主会话通过 Skill 工具加载 skills/go-review-lead/SKILL.md
.claude/agents/ # 仅包含 7 个垂直 Worker Agent
├── go-security-reviewer.md # 加载 go-security-review
├── go-concurrency-reviewer.md # 加载 go-concurrency-review
├── go-performance-reviewer.md # 加载 go-performance-review
├── go-error-reviewer.md # 加载 go-error-review
├── go-quality-reviewer.md # 加载 go-quality-review
├── go-test-reviewer.md # 加载 go-test-review
└── go-logic-reviewer.md # 加载 go-logic-review
checklist 上限原则:每个垂直 Skill 的 checklist 项不超过 15 条。如果超过,说明该维度还可以继续拆分。这一上限来自本文所记录的案例实践:在独立上下文中,15 条以内的单维度 checklist 未观察到明显的维度内注意力稀释;超过后,同维度内的 High Finding 开始对 Medium 级别项产生压制(本文 §18.5 轮次 2 的维度内稀释即为一例)。15 应视为经验起点,而非已验证的通用常数——不同模型版本、代码体量和 Skill 提示词结构均可能影响这一阈值,使用时应结合实际漏报率判断是否需要进一步拆分。
如果垂直 Skill 的 checklist 已超过 15 条,建议按以下路径决策:
-
先观察,再拆分:触发进一步拆分的依据是可重现的漏报症状,而不是条目数量本身。先通过实际审查验证是否已出现可观察的漏报,再决定是否拆分——过早拆分会引入不必要的架构维护成本。
-
按严重度分层,而非按主题细分:§18.1 实证验证表明,注意力稀释的驱动因素是严重度差异,而非主题相关性。如果超量的 checklist 中包含 High 级别项,将 High/Critical 项与 Medium/Low 项拆分到两个独立 Skill,往往比继续按技术主题细分更有效。
-
先 grep 化,再评估拆分必要性:Grep-Gated 协议将机械检测项从模型注意力预算中解放出来,等效延迟触发"超载"临界点。如果当前 checklist 中还有可 grep 化但尚未配置 pattern 的项,先完善覆盖——可能在不拆分的情况下消除漏报。
18.3 分诊机制(go-review-lead Skill 在主会话中执行)¶
两级分诊¶
分诊分两个层次,层次之间成本差异悬殊:
Level 1:文件类型分诊(无需 LLM,用 grep 即可)
# 有 .go 文件变更? → 进入 Level 2
# 有 _test.go 变更? → 派发 go-test-reviewer
# 有 go.mod 变更? → 派发 go-security-reviewer(依赖审查)
# 有 .sql / migration? → 派发 go-security-reviewer
Level 2:内容分诊(Haiku 快速扫描 diff,约 $0.001/次)
diff 包含 go func / channel / sync → Concurrency Agent
diff 包含 make([] + 零容量 → Performance Agent
diff 包含 sql.Rows / tx.Begin → Error + Security + Performance Agent
函数名含 Batch / Multi / GetAll → Performance Agent
Level 1 不消耗 token。两级合计每次分诊成本可忽略不计。
四阶段分诊逻辑(Phase 1–4)¶
| Phase | 扫描对象 | 典型触发规则 |
|---|---|---|
| Phase 1:Import 扫描 | 所有变更文件的 import 块 | "sync" → Concurrency;"database/sql" → Security + Error + Performance |
| Phase 2:Diff Pattern 扫描 | 仅新增/修改行 | make(\[\] 零容量 + append( 共现 → Performance;go func → Concurrency |
| Phase 3:文件路径 heuristic | 变更文件的路径和函数名 | auth/、handler/ → Security;函数名含批量语义 → Performance |
| Phase 4:变更范围评估 | diff 整体结构 | 新增 .go 文件 → 强制派发 Error;go.mod 变更 → 对新依赖重跑 Phase 1 |
无兜底派发原则:若某 Agent 未被任何阶段触发,则跳过并明确记录原因——而不是无差别地全量启动。这是分诊机制最核心的价值。
成本对比¶
| 方案 | 简单风格 PR | 复杂并发 PR | 全方位重构 |
|---|---|---|---|
| 全量 7 Agent(无分诊) | ~$0.16 | ~$0.16 | ~$0.16 |
| 分诊 + 按需派发 | ~$0.02 | ~$0.07 | ~$0.10 |
| 原始单 Skill | ~$0.03 | ~$0.03(但漏报) | ~$0.03(但漏报) |
按需调度在简单 PR 上节省约 80% 成本,在复杂 PR 上成本与全量启动持平,但审查质量显著优于单 Skill 方案。
注:以上成本为近似估算,基于 Claude Haiku 4.5 / Sonnet 4.6 的 2026-03 官方定价,实际成本还受代码量(token 数)影响,仅作数量级参考。
18.4 Grep-Gated 执行协议(核心执行机制)¶
问题本质的重新认识¶
首轮 Multi-Agent 架构(§18.5 轮次 2)暴露了一个根本性的设计失误:把模型当成了人类代码审查员。人类审查员读 checklist,然后用"眼睛"扫代码,靠注意力和经验发现问题。模型也在被迫做同样的事——用"注意力"扫描 checklist,然后在代码中寻找匹配。这种方式的问题在于,模型的注意力是概率性分配的;而 grep 对显式模式的检出更接近规则驱动的机械扫描。
模型不是人,它有工具可以用。
工程解法:工具辅助检测(tool-assisted detection)+ 模型判断(model judgment)。对于有明确语法特征的 checklist 项,让模型先用 grep 机械扫描,再对 HIT 结果做语义确认。只有真正需要推理的语义项,才交给模型全量分析。
执行流程(分步说明)¶
对每个 sub-agent,执行流程变为:
1. 通过 Skill 工具加载对应领域 Skill(checklist + 规则 + grep pattern)
2. 识别目标文件(或将裸代码片段写入 $TMPDIR/review_snippet.go)
3. 对所有 grep-gated checklist 项,按 Skill 中提供的 pattern 执行 grep
4. grep HIT → 模型做语义确认(true positive vs false positive)
5. grep MISS → 自动标记 NOT FOUND,跳过语义分析,不上报主会话
6. 无 grep pattern 的项(纯语义项)→ 模型全量推理
7. 只上报 FOUND 项
8. Execution Status 中包含审计行:Grep pre-scan: X/Y items hit, Z confirmed
主会话汇总各 sub-agent 的报告后,根据审计行核查覆盖率,而不是盲目信任"没报告 = 没问题"。
覆盖率统计¶
7 个 Skill、86 条 checklist 项,其中 65 条(75%)可 grep 化:
| Skill | 总条数 | Grep 化 | 纯语义 |
|---|---|---|---|
| go-concurrency-review | 14 | 13 | 1 |
| go-performance-review | 12 | 10 | 2 |
| go-error-review | 12 | 12 | 0 |
| go-security-review | 16 | 14 | 2 |
| go-quality-review | 12 | 8 | 4 |
| go-test-review | 10 | 8 | 2 |
| go-logic-review | 10 | 0 | 10 |
| 合计 | 86 | 65 (75%) | 21 (25%) |
在当前设计中,75% 的检查项转化为了规则驱动的预筛选,模型的注意力可以更多集中在剩余 25% 的语义项上。
宽门槛设计原理¶
Grep-Gated 协议的 pattern 设计采用宽门槛策略:宁有 HIT 假阳性,不漏 MISS 假阴性。
go\s+func这一 pattern 同时触发 6 个并发审查项,产生大量 HIT- false positive 交给模型在语义确认阶段过滤,成本可接受
- MISS 会直接跳过语义分析,一旦漏检就不再有任何机会补救
这种不对称性决定了 pattern 宁宽勿严:漏检的代价(遗漏真实 bug)远大于误触发的代价(多一次语义确认)。
复合 pattern 设计:缺失保护检测¶
对于"应该有 A 但没有 B"的缺失类问题,使用复合 pattern:
# CONC-14: 无界 goroutine 创建(有并发但无限流控制)
grep pattern:go\s+func
AND NOT:SetLimit|semaphore|maxConcurrency|worker.*pool
# PERF-01: Slice 未预分配(有 make 但无容量参数)
grep pattern:make\(\[\][^]]+,\s*0\) → 检测零容量
AND NOT:第三个参数存在
复合 pattern 使"缺少防护"类问题可被 grep 机械检出,而不再依赖模型注意力去发现"不存在的东西"——这恰恰是注意力最容易疏漏的场景。
go-logic-review 的特殊处理¶
go-logic-review 覆盖业务逻辑、边界条件、合同违反、nil 安全等问题,这些问题没有稳定的语法特征,无法用 grep 预筛选。该 Skill 的所有 10 条 checklist 项均为纯语义分析,使用专用执行模板:
## Execution Order
After invoking the skill:
1. Identify target files (from dispatch prompt)
2. All checklist items are semantic-only — no grep pre-scan applicable
3. Apply full model reasoning to each item
4. Report FOUND items only
5. Include: `Semantic-only skill: 10/10 items evaluated`
这是协议的合理边界:grep 只适用于有语法特征的问题,强行 grep 化语义项会产生大量无意义 MISS,反而降低覆盖率的可信度。
18.5 三轮迭代验证¶
用同一段 getBatchUser 代码(§17.1 所示)进行三轮完整验证,每轮在上一轮的架构基础上改进。
三轮对比总览¶
| 指标 | 轮次 1:单 Skill | 轮次 2:Multi-Agent v1 | 轮次 3:Multi-Agent + Grep-Gated |
|---|---|---|---|
| 架构 | 1 Agent + 重度 Skill | 7 Worker Agent + 主会话 Skill 编排 | 7 Worker Agent + 主会话 Skill 编排 + Grep-Gated 协议 |
| 派发 Agent 数 | 1 | 4(跳过 performance) | 5(含 performance) |
| High Findings | 4 | 7 | 7 |
| Medium Findings | 1(漏报 1) | 2(漏报 4+) | 6 |
| Slice Pre-allocation | ❌ 未发现 | ❌ 未发现(performance 未被分诊) | ✅ REV-009 正式上报 |
| Unbounded Goroutines | ❌ 仅在 Residual Risk | ⚠️ 有时遗漏 | ✅ REV-008 正式上报 |
| 总 Findings 捕获 | 8/9(漏 1) | 不稳定 | 13/13 |
轮次 1:单 Skill 的失效¶
单 Skill 调用发现了 4 个 High 并发缺陷,但 Slice Pre-allocation 漏报。模型事后承认原因是 Performance checklist 的注意力被 High Findings 挤压——注意力稀释问题由此确认为架构层根因,触发本次改造。
轮次 2:Multi-Agent v1 的新问题¶
完成第一阶段改造后,架构已切换为主会话 Skill 编排 + 7 个 Worker Agent。由于尚未引入 Grep-Gated 协议,且原始分诊 heuristic 仍不完整,验证暴露了两个新问题:
问题一:分诊盲区。go-review-lead 的 Phase 2 原始触发条件只对"已有 capacity 参数的 make"触发,而 make([]*User, 0) 恰好是没有 capacity 的情况——规则反向匹配失败,go-performance-reviewer 被直接跳过。代码以裸片段提交也导致 Phase 3 的文件路径 heuristic 无效。
问题二:维度内注意力稀释。即便 go-concurrency-reviewer 被正确分诊并派发,当上下文中存在多个 High 级别的编译错误和数据竞争时,"无界 goroutine 创建"这类 Medium 级别的问题仍会被模型降低优先级,最终只出现在 Residual Risk 中,而不是作为正式 Finding 上报。
架构已经将不同审查维度隔离到独立上下文,但在同一个 Agent 的上下文内,多个 High 级别 Findings 仍然会压制 Medium 级别的项。注意力稀释问题在垂直维度内部依然存在。第一轮架构改造的汇总报告如下(摘录关键差异部分):
- Skipped skills: go-performance-reviewer (no hot-path loops or DB patterns)
← 分诊盲区导致跳过
Residual Risk:
2. Unbounded goroutine spawning: ... Not flagged as a finding since expected
batch size is unknown ... ← 未正式上报,藏在 Residual Risk 中
Summary: 7 High / 2 Medium / 1 Low.
轮次 3:Multi-Agent + Grep-Gated 的验证通过¶
针对分诊盲区,修正 Phase 2 触发条件(同时检测零容量 make),并在 Phase 3 补充批量语义函数名 heuristic(getBatchUser 直接命中)。针对维度内注意力稀释,引入 Grep-Gated 执行协议。
验证结果:在当前基准案例中,13 个预期发现均被捕获,未观察到新的遗漏。 此外,7-Agent 架构在同一代码中进一步识别出 2 个前两轮未被发现的 Finding(REV-008 无界 goroutine、REV-009 Slice 未预分配均完整上报),使基准案例的最终总捕获数升至 15——即 §18.1 汇总表中的 15/15 (100%)。
slice pre-allocation 的完整轨迹:
| 轮次 | 状态 | 原因 |
|---|---|---|
| 轮次 1(单 Skill) | 未发现 | Performance checklist 注意力被 4 个 High 挤压 |
| 轮次 2(Multi-Agent v1) | 未发现 | performance Agent 未被分诊;维度内注意力竞争仍影响其他 Medium 问题 |
| 轮次 3(Multi-Agent + Grep-Gated) | REV-009 [Medium] 正式上报 | make([]*User, 0) 被 grep pattern 机械命中,无法被注意力稀释 |
最终报告(摘录):
- Dispatched: go-concurrency-reviewer, go-performance-reviewer,
go-error-reviewer, go-quality-reviewer, go-logic-reviewer
- Triage: make([]*User, 0) + append( + getBatchUser 批量语义命中 Phase 2+3
[Medium] Missing Slice Pre-allocation — Repeated Reallocation in Batch Hot Path
- ID: REV-009 (original: PERF-001)
- Evidence: userList := make([]*User, 0) — zero capacity, no second argument.
Grep hit: make([]*User, 0) at L10. Function name getBatchUser signals batch hot path.
- Recommendation: userList := make([]*User, 0, len(userKeys))
[Medium] Unbounded Goroutine Spawning — Resource Exhaustion Under Large Batches
- ID: REV-008 (original: CONC-005)
- Evidence: goroutine count scales linearly. No SetLimit, semaphore, or worker pool
present. Grep: go\s+func HIT AND NOT SetLimit|semaphore MISS.
Summary: 7 High / 6 Medium — 13/13 expected findings captured.
改进闭环完整成立:单 Skill 注意力稀释 → Multi-Agent 架构改造 → 分诊盲区修复 → Grep-Gated 协议引入 → 13/13 全部捕获。
18.6 完整实现参考¶
本章描述的 Multi-Agent 架构已作为可运行文件发布在本仓库,可直接部署到 Claude Code 环境:
| 内容 | 路径 | 说明 |
|---|---|---|
| Orchestrator Skill | skills/go-review-lead/SKILL.md | 主会话编排逻辑:分诊规则、汇总格式、报告规范(以 Skill 形式运行,不在 agents/ 目录中) |
| 7 个垂直审查 Skill | skills/go-{concurrency,performance,error,security,quality,test,logic}-review/SKILL.md | 各维度的 checklist、Grep-Gated pattern、输出格式 |
| 7 个 Agent 定义文件 | outputexample/go-review-lead/agents/ | 可直接复制到 .claude/agents/ 的垂直 Worker Agent 定义文件(不含 go-review-lead) |
| 部署指引 | outputexample/go-review-lead/README.md | 安装步骤、前置条件、用法说明(英文) |
执行过程如下所示:
Step 1 — 作用域识别 + 审查深度选择 + 编译预检:主会话读取 diff,识别变更文件类型(Go 源码 / 测试文件 / 配置),选择审查深度(Strict / Standard),并运行编译预检。编译失败直接上报为 REV-001/REV-002,不阻断后续流程。

Step 2 — 分诊 + 并行派发:go-review-lead Skill 对 diff 执行模式匹配(sync import、go func、make([]、_test.go 等),据此决定需要激活哪些维度的 Worker Agent,并在同一条响应中并行派发所有选定 Agent。

Step 3 — 整合子代理审查结果:7 个 Worker Agent 并行完成各自维度的审查后,主会话收集所有返回结果,按 Finding ID 去重(跨维度重复上报的同一问题合并为一条,取较高严重度),并提取各 Agent 的 Execution Status 行。

Step 4 — 最终审查报告:主会话按严重度排序,输出标准化 Markdown 报告,包含 Executive Summary、Finding 列表(每条带维度标签和证据)、Execution Status 矩阵、Residual Risk 说明。

18.7 常见问题¶
Q:跨维度问题(如无界 goroutine = 并发 + 性能)如何处理?
允许两个 Agent 从各自角度同时报告同一问题。主会话在汇总时去重合并,取较高严重度,合并证据。交叉报告比遗漏好——去重的成本远低于漏报的代价。REV-008(无界 goroutine)正是由 Concurrency Agent 从并发维度正式上报,兼有 Performance 语义,两者合并为一条 Finding,严重度取较高的 Medium。
Q:所有重度 Skill 都应该拆分吗?
不是。判断标准:覆盖 3 个以上独立维度、单次经常产生 5+ 个 High Findings、或用户反复反馈漏报,才值得拆分。如果 Skill 只有单个维度且 checklist < 15 条,上下文负担不大,单 Agent 足够,不需要引入 Multi-Agent 的设计和维护成本。
Q:go-review-lead Skill 应该让主会话用什么模型运行?
Sonnet 足够。分诊(模式匹配)和汇总(合并排序)不需要深度推理。用 Opus 做分诊是过度配置。垂直审查 Agent 用 Sonnet,特别复杂的架构级审查可以考虑 Opus。
Q:Lead 应该配置为 Skill 还是 .claude/agents/ 中的 Agent 文件?
必须是 Skill,不能是 agent 定义文件。原因是平台的硬约束。
Claude Code 官方文档在多处明确规定:子代理不能生成子代理("Subagents cannot spawn other subagents. If your workflow requires nested delegation, use Skills or chain subagents from the main conversation.")。其后果是:
| 调用方式 | Lead 运行在 | 能否派发 Worker | 实际结果 |
|---|---|---|---|
主会话加载 go-review-lead Skill | 主对话(非子代理) | ✅ 可以 | 7 个 Worker 并行运行 |
主会话启动 go-review-lead Agent | 子代理 | ❌ 不可以 | Agent 工具调用被平台忽略,并行步骤跳过 |
正确的部署方式:不要在 .claude/agents/ 中创建 go-review-lead.md。主对话通过 Skill 加载 go-review-lead 后,由主对话本身执行分诊和 Worker 派发。7 个垂直审查 Agent(.claude/agents/go-*-reviewer.md)保留为 agent 定义,它们是被主对话派发的 Worker,自身不再派发子任务。
Q:Grep-Gated 的 grep MISS 会不会漏掉真实问题?
会,这是协议的已知权衡。grep MISS 代表 pattern 未命中,自动标记 NOT FOUND 并跳过语义分析。因此 pattern 的设计至关重要——宽门槛原则(宁多 HIT 不漏 MISS)和复合 pattern(有 A 且无 B)是两个核心设计手段,用于最大化覆盖率同时保持 pattern 的稳定性。
18.8 降级与错误处理¶
Multi-Agent 架构引入了额外的故障点——单 Skill 只会整体失败,而 7 个 Worker Agent 并行时,任何一个都可能出现超时、Skill 加载失败或返回格式错误。
| 故障类型 | 主会话处理方式 |
|---|---|
| sub-agent 超时(> 120s) | 标记该维度为 SKIPPED (timeout),继续汇总其他维度结果 |
| sub-agent 返回空 Findings | 正常,视为该维度无发现,在 Execution Status 中记录 0 findings |
| sub-agent 返回格式错误 | 标记为 PARSE_ERROR,在 Residual Risk 中注明"X 维度未完成,建议单独重跑" |
| Skill 文件缺失(加载失败) | sub-agent 自行报告错误,主会话在 Execution Status 中注明 |
核心原则:部分成功优于全量失败。 主会话应始终输出当前已有的发现,而不是因为一个 Agent 失败就放弃整份报告。
如果关键维度(如 Concurrency)的 Agent 失败,在报告尾部加注:
[Residual Risk] go-concurrency-reviewer did not complete (timeout).
Concurrency dimension not covered in this review — recommend re-running
with: "使用 go-concurrency-reviewer agent 审查 <file>"
18.9 成本模型与适用范围¶
适用范围:
| 场景 | 推荐架构 | 原因 |
|---|---|---|
| 单维度 Skill,checklist < 15 条 | 单 Skill | 无注意力竞争,无需多 Agent 开销 |
| 多维度 Skill,已观察到漏报 | Multi-Agent + 垂直 Skill | 跨维度注意力竞争,需要隔离上下文 |
| 高频轻量审查(如变量名修改) | 分诊后按需派发(2–3 Agent) | 成本约 $0.02,远低于全量启动 |
| 关键路径全量审查 | 全量 7 Agent | 成本约 $0.10–0.16,质量最优 |
成本结构:
- 分诊成本(Level 1 grep + Level 2 Haiku):约 $0.001/次,可忽略
- 每个 Worker Agent(Haiku,单文件):约 $0.005–0.015
- 主会话汇总(Sonnet):约 $0.01–0.02
- 典型完整审查(5 个 Worker):约 $0.05–0.10
适用范围的边界:
本文的结论强度应限定在以下范围内:Go 代码审查场景;以 getBatchUser(并发/goroutine 类)为主案例,以 ListLayout(安全/ORM/设计类)为跨域追加案例;当前 7 个垂直 Skill + go-review-lead Skill(主会话编排)实现;当前 Grep-Gated checklist 覆盖率(65/86,约 75%)。
尚未充分验证的场景包括:其他编程语言、超大 diff、跨文件复杂依赖、不同模型版本下的稳定性,以及多案例上的误报率和漏报率统计曲线。
如果 Skill 只有单个维度且 checklist < 15 条,不必升级为 Multi-Agent 架构——单 Agent 在上下文负担可控时,是更简单、更低成本的选择。架构升级的触发条件是可观察的漏报症状,而不是维度数量的绝对阈值。
本篇关键结论回顾:注意力稀释是 LLM 在单上下文多维度场景下的结构性限制,提示词强化只能缓解,无法根本解决。Skill-Agent 协作架构通过两个正交手段解决这一问题:Multi-Agent(Orchestrator-Workers 模式)消除跨维度注意力竞争;Grep-Gated 协议将 75% 的检查项转为规则驱动的预扫描,降低维度内的概率性遗漏。两者结合,在
go-code-reviewer的基准案例中实现了 13/13 的完整捕获。§17.4 逐一评估了五种编排模式对代码审查场景的适用性,从技术上论证了 Orchestrator-Workers 是唯一同时满足"支持并行"和"子任务内容驱动"两个条件的选择;同一套评估框架可直接复用于其他任务类型的模式选型。