多 Agent 并行听起来很美,但如果把同一个 Bug 同时交给 3 个 Agent,它们会互相补位,还是制造冲突?本文设计一个可复现实验:同一问题、同一代码库、三个隔离 worktree、三个不同策略的 Agent,最后比较修复质量、改动范围、测试通过率和合并成本。

Lab 001:让 3 个 Agent 同时修同一个 Bug,会发生什么?

多 Agent 并行听起来很美,但如果把同一个 Bug 同时交给 3 个 Agent,它们会互相补位,还是制造冲突?本文设计一个可复现实验:同一问题、同一代码库、三个隔离 worktree、三个不同策略的 Agent,最后比较修复质量、改动范围、测试通过率和合并成本。

三个 Agent 同修一个 Bug 实验流程图
三个 Agent 同修一个 Bug 实验流程图

一、实验目标

本实验不是为了证明“多 Agent 一定更好”,而是观察它们在同一任务下的行为差异:

观察点 说明
修复路径 Agent 会选择最小修改、重构、还是补测试后修复
改动范围 是否越改越大,触碰无关模块
验证质量 是否新增回归测试,是否运行正确测试
冲突成本 三份结果能否合并,是否互相覆盖
人工决策 人类最终如何选择和组合结果

二、实验架构

mermaid
flowchart TD
  A["同一个 Bug 报告"] --> B["创建 3 个 git worktree"]
  B --> C["Agent A: 最小修复"]
  B --> D["Agent B: 重构修复"]
  B --> E["Agent C: 测试优先"]
  C --> F["收集 diff / 测试 / 成本"]
  D --> F
  E --> F
  F --> G["冲突分析"]
  G --> H["选择最佳补丁或合并方案"]

三、实验样例 Bug

选择一个足够真实但可控的 Bug:订单金额使用浮点数导致边界值计算错误。

python
# app/billing/discount.py
def final_price(price: float, discount_rate: float) -> float:
    discounted = price * (1 - discount_rate)
    return round(discounted, 2)

失败测试:

python
# tests/test_discount.py
from app.billing.discount import final_price


def test_final_price_rounding_boundary():
    assert final_price(19.995, 0) == 20.00

失败日志:

text
E       assert 19.99 == 20.0
E        +  where 19.99 = final_price(19.995, 0)

四、Agent 策略设计

给三个 Agent 不同的系统指令,观察策略差异。

yaml
agents:
  minimal_fix:
    name: "Agent A"
    model: "claude-sonnet"
    instruction: "只做最小必要修改,避免重构,必须补充回归测试。"
    worktree: "../lab-agent-a"

  refactor_fix:
    name: "Agent B"
    model: "gpt-4.1"
    instruction: "允许重构 billing 金额计算模块,统一金额类型,保持接口兼容。"
    worktree: "../lab-agent-b"

  test_first:
    name: "Agent C"
    model: "codex"
    instruction: "先补充失败测试和边界测试,再实现修复。"
    worktree: "../lab-agent-c"

参数说明

参数 说明
instruction 控制 Agent 的修复风格
worktree 隔离执行目录,避免互相覆盖
model 可固定同一模型,也可测试不同模型
acceptance 统一验收标准,避免比较不公平

五、实验脚本

bash
#!/usr/bin/env bash
set -euo pipefail

BASE_BRANCH="${BASE_BRANCH:-main}"
BUG_PROMPT_FILE="${BUG_PROMPT_FILE:-prompts/rounding-bug.md}"

git fetch origin "$BASE_BRANCH"

for name in agent-a agent-b agent-c; do
  git worktree remove --force "../lab-$name" 2>/dev/null || true
  git worktree add "../lab-$name" "$BASE_BRANCH"
done

run_agent() {
  local dir="$1"
  local strategy="$2"
  (
    cd "$dir"
    codex exec "$(cat "$BUG_PROMPT_FILE")

策略: $strategy
验收:
- tests/test_discount.py 必须包含 19.995 边界值
- pytest tests/test_discount.py -q 必须通过
- 输出修改摘要和剩余风险"
  )
}

run_agent "../lab-agent-a" "最小修复" &
run_agent "../lab-agent-b" "允许重构" &
run_agent "../lab-agent-c" "测试优先" &
wait

六、结果记录模板

yaml
result:
  agent: "Agent A"
  strategy: "minimal_fix"
  changed_files:
    - "app/billing/discount.py"
    - "tests/test_discount.py"
  lines_added: 18
  lines_deleted: 3
  tests:
    command: "pytest tests/test_discount.py -q"
    passed: true
    duration_seconds: 1.8
  behavior:
    touched_unrelated_files: false
    added_regression_test: true
    used_decimal: true
  cost:
    input_tokens: 12400
    output_tokens: 2100
    estimated_usd: 0.08
  reviewer_notes:
    - "改动最小,适合直接合并"

七、评分矩阵

维度 权重 评分标准
正确性 35% 测试通过,边界值正确
改动范围 20% 修改文件越少、越聚焦分越高
测试质量 20% 是否补充有效回归测试
可维护性 15% 是否引入清晰类型和命名
合并成本 10% 是否容易 cherry-pick 或合并

示例评分:

text
Agent A: 88 分,最小修复,合并成本最低
Agent B: 76 分,设计更完整,但触碰范围偏大
Agent C: 84 分,测试最好,但实现略保守

八、冲突分析代码

bash
for name in agent-a agent-b agent-c; do
  echo "=== $name ==="
  git -C "../lab-$name" diff --stat
  git -C "../lab-$name" diff --name-only
done

git -C ../lab-agent-a diff > /tmp/agent-a.patch
git -C ../lab-agent-b diff > /tmp/agent-b.patch
git -C ../lab-agent-c diff > /tmp/agent-c.patch

如果要比较三个补丁是否修改同一函数,可以用:

bash
for patch in /tmp/agent-*.patch; do
  echo "$patch"
  grep -n "^@@ " "$patch"
done

九、实验结论

这个实验通常会得到三个很现实的结论:

  1. 多 Agent 并行适合探索方案,不适合盲目自动合并。
  2. “测试优先”的 Agent 往往更可靠,但不一定最省 Token。
  3. 人类 Reviewer 的角色会从“亲自修 Bug”变成“选择和组合补丁”。

十、复现实验检查清单

  • 同一个 base commit
  • 同一个 Bug prompt
  • 独立 worktree
  • 统一验收命令
  • 固定结果记录模板
  • 保留 diff、测试日志、Token 成本
  • 人工评审时隐藏 Agent 名称,降低偏见

总结

多 Agent 并行不是让多个 Agent 抢着改同一份代码,而是用并行探索降低不确定性。真正有价值的流程是:隔离执行、统一验证、结构化评分、人工选择最佳补丁。