当 AI 学会修 Bug:SWE-agent + Claude Code 实战演练

摘要

在传统软件开发中,修复一个 GitHub Issue 通常需要开发者手动定位代码、理解问题、编写修复并补充测试。随着大语言模型(LLM)的进步,AI 代理(Agent)已经能够自动化完成这一流程。本文通过一个最小化 Demo,展示 SWE-agent 结合 Claude Code 的核心工作流:AI 自动读取 Issue 描述、修复代码中的除零错误、添加缺失的单元测试,并运行 pytest 验证修复。你将看到如何用不到 200 行代码模拟一个完整的 AI 驱动 Bug 修复流程,理解 Agent 在代码库中自主决策、修改和执行测试的底层逻辑。

问题背景:从 Issue 到 Fix 的自动化之梦

作为一名后端开发者,你一定经历过这样的场景:凌晨两点,GitHub 上突然冒出一个 Issue,描述了一个边界条件导致的崩溃。你揉揉眼睛,打开 IDE,开始定位代码、理解上下文、写修复、补测试、跑 CI…… 一套流程下来,半小时过去了。

如果 AI 能替你做这些呢?不是简单地生成代码片段,而是像一个真正的开发者一样:阅读 Issue → 理解问题 → 定位代码 → 修改文件 → 补充测试 → 验证结果。这就是 SWE-agent 和 Claude Code 想要解决的问题。

SWE-agent 是普林斯顿大学 NLP 组开发的一个开源框架,它让 LLM 能够与代码仓库交互——浏览文件、编辑代码、运行命令。Claude Code 则是 Anthropic 推出的编程助手,擅长代码理解和生成。两者结合,就形成了一个能自主完成软件工程任务的 AI 代理。

但理想很丰满,现实往往更骨感。我们不妨先从一个最小的 Demo 开始,看看这个流程到底是怎么运转的。

技术方案:SWE-agent + Claude Code 的核心工作流

SWE-agent 的核心设计思想是:将代码仓库操作抽象为 Agent 可执行的“工具”。这些工具包括:

  • read_file(path) — 读取文件内容
  • edit_file(path, old_str, new_str) — 定位并替换代码
  • run_command(cmd) — 在 shell 中执行命令
  • submit() — 提交最终修复

Claude Code 则负责理解自然语言描述的 Issue,并调用这些工具完成任务。整个流程可以概括为:

  1. Issue 解析:Agent 读取 Issue 描述,提取关键信息(如 bug 表现、期望行为)
  2. 代码探索:Agent 浏览仓库结构,定位相关文件
  3. 修复实施:Agent 修改代码,修复 bug
  4. 测试补充:Agent 添加或修改测试用例,覆盖边界条件
  5. 验证执行:Agent 运行测试,确保修复有效

在我们的 Demo 中,为了简化演示,我们直接模拟了这个流程的核心步骤,而不是依赖完整的 SWE-agent 框架。这样做的好处是:你能清晰地看到每一步在做什么,而不必被复杂的 Agent 调度逻辑干扰。

核心实现解析:手写一个最小化 AI 修复流水线

项目结构

Demo 包含三个核心文件:

1
2
3
4
5
.
├── main.py # 入口:创建仓库、模拟修复、运行测试
├── calculator.py # 有 bug 的计算器模块
├── test_calculator.py # 缺少边界测试的测试文件
└── issue.md # 模拟的 GitHub Issue

第一步:创建有 Bug 的代码库

main.py 中的 create_mock_repo() 函数负责在临时目录中生成一个最小化的 Python 项目。关键代码是 calculator.py 中的 divide 函数:

1
2
3
4
def divide(a, b):
if b == 0:
return None # bug: should raise ValueError
return a / b

这是一个经典的错误设计:除零时返回 None 而不是抛出异常。这会导致调用方无法区分“除零”和“正常计算结果为 None”的情况,引发难以追踪的 bug。

同时,test_calculator.py 中缺少了对除零场景的测试:

1
2
3
def test_divide():
assert divide(10, 2) == 5
# Missing test for division by zero

第二步:模拟 Agent 读取 Issue

issue.md 的内容模拟了一个真实的 GitHub Issue:

1
2
3
4
5
6
7
8
9
## Bug Report

The `divide` function in `calculator.py` returns `None` when dividing by zero.
It should raise a `ValueError` with the message "Cannot divide by zero".

## Expected Behavior

```python
divide(10, 0) # Should raise ValueError: Cannot divide by zero
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Agent 会读取这个文件,理解问题所在。在我们的 Demo 中,`main.py` 直接打印了 Issue 内容,模拟了 Agent 的“阅读理解”步骤。

### 第三步:修复 Bug

接下来是修复环节。Agent 需要找到 `calculator.py` 中 `divide` 函数的实现,并将 `return None` 替换为 `raise ValueError("Cannot divide by zero")`。

在完整 SWE-agent 中,这通过 `edit_file` 工具实现。我们的 Demo 直接使用文件操作模拟:

```python
def fix_calculator():
with open('calculator.py', 'r') as f:
content = f.read()

# 定位并替换 bug 代码
old = ' return None # bug: should raise ValueError'
new = ' raise ValueError("Cannot divide by zero")'

content = content.replace(old, new)

with open('calculator.py', 'w') as f:
f.write(content)

print("✅ calculator.py fixed")

这里的关键是:Agent 必须精确地定位到需要修改的代码行。在真实场景中,Agent 会先读取整个文件,然后找到 divide 函数定义的位置,再执行替换。

第四步:补充测试

修复完成后,Agent 需要为除零场景添加测试。这同样需要精确的代码定位——找到 test_divide 函数末尾,追加新的测试用例:

1
2
3
4
5
6
7
8
9
10
11
def add_test():
with open('test_calculator.py', 'a') as f:
f.write('''

def test_divide_by_zero():
import pytest
with pytest.raises(ValueError, match="Cannot divide by zero"):
divide(10, 0)
''')

print("✅ test_calculator.py updated")

注意这里使用了 pytest.raises 来验证异常抛出,这是 Python 测试中的标准做法。

第五步:运行验证

最后一步是执行测试,验证修复是否有效:

1
2
3
4
5
6
7
8
9
10
11
def run_tests():
result = subprocess.run(
[sys.executable, '-m', 'pytest', 'test_calculator.py', '-v'],
capture_output=True,
text=True
)
print(result.stdout)
if result.returncode == 0:
print("🎉 All tests passed!")
else:
print("❌ Some tests failed")

完整的 main.py 流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def main():
print("=" * 60)
print("SWE-agent + Claude Code Demo")
print("=" * 60)

# Step 1: Create mock repo
print("\n[1/4] Creating mock repository...")
create_mock_repo()

# Step 2: Read issue
print("\n[2/4] Reading issue...")
read_issue()

# Step 3: Fix bug
print("\n[3/4] Fixing bug...")
fix_calculator()

# Step 4: Add test
print("\n[4/4] Adding test...")
add_test()

# Run tests
print("\n" + "=" * 60)
print("Running tests...")
print("=" * 60)
run_tests()

if __name__ == '__main__':
main()

运行效果:从 Issue 到绿标

执行 python main.py 后,你会看到类似以下的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
============================================================
SWE-agent + Claude Code Demo
============================================================

[1/4] Creating mock repository...

[2/4] Reading issue...
## Bug Report

The `divide` function in `calculator.py` returns `None` when dividing by zero.
It should raise a `ValueError` with the message "Cannot divide by zero".

[3/4] Fixing bug...
✅ calculator.py fixed

[4/4] Adding test...
✅ test_calculator.py updated

============================================================
Running tests...
============================================================
============================= test session starts ==============================
platform darwin -- Python 3.11.5, pytest-7.4.0, pluggy-1.2.0
rootdir: /var/folders/xx/.../T/tmpabc123
collected 5 items

test_calculator.py::test_add PASSED [ 20%]
test_calculator.py::test_subtract PASSED [ 40%]
test_calculator.py::test_multiply PASSED [ 60%]
test_calculator.py::test_divide PASSED [ 80%]
test_calculator.py::test_divide_by_zero PASSED [100%]

============================== 5 passed in 0.02s ===============================
🎉 All tests passed!

整个过程不到 1 秒,AI 就完成了从理解 Issue 到提交修复的全流程。所有 5 个测试全部通过,包括新添加的除零边界测试。

总结与展望

通过这个 Demo,我们看到了 AI 驱动软件工程的核心流程:Issue 理解 → 代码定位 → 修复实施 → 测试补充 → 验证执行。虽然我们的实现是模拟的,但它揭示了 SWE-agent 和 Claude Code 背后的核心思想——将软件开发任务分解为 Agent 可执行的原子操作。

真实场景中的挑战

当然,现实世界远比这个 Demo 复杂:

  1. 大型代码库:Agent 需要快速定位相关文件,而不是遍历所有代码
  2. 多文件修改:一个 bug 可能涉及多个模块的联动修改
  3. 上下文理解:Agent 需要理解代码的架构设计,避免引入新问题
  4. 安全与权限:Agent 需要被限制在安全的执行环境中

未来方向

SWE-agent 已经在 SWE-bench 基准测试中展现了令人印象深刻的能力——在真实 GitHub Issue 上的修复成功率超过 12%(相比 GPT-4 的 1.7%)。随着 Claude Code 等更强大的代码模型出现,这个数字正在快速提升。

对于开发者来说,这意味着什么?不是失业,而是解放。AI 可以处理那些重复性的、模式化的 Bug 修复和测试编写,让我们把精力集中在架构设计、系统优化和业务创新上。

下一步,你可以尝试

  • 将 Demo 扩展为真正的 SWE-agent 配置
  • 尝试用 Claude Code 修复真实项目中的 Issue
  • 思考如何将 AI 代理集成到你的 CI/CD 流水线中

AI 修 Bug 的时代已经来了。你准备好了吗?