当 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,并调用这些工具完成任务。整个流程可以概括为:
Issue 解析 :Agent 读取 Issue 描述,提取关键信息(如 bug 表现、期望行为)
代码探索 :Agent 浏览仓库结构,定位相关文件
修复实施 :Agent 修改代码,修复 bug
测试补充 :Agent 添加或修改测试用例,覆盖边界条件
验证执行 :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 return a / b
这是一个经典的错误设计:除零时返回 None 而不是抛出异常。这会导致调用方无法区分“除零”和“正常计算结果为 None”的情况,引发难以追踪的 bug。
同时,test_calculator.py 中缺少了对除零场景的测试:
1 2 3 def test_divide (): assert divide(10 , 2 ) == 5
第二步:模拟 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 ) print ("\n[1/4] Creating mock repository..." ) create_mock_repo() print ("\n[2/4] Reading issue..." ) read_issue() print ("\n[3/4] Fixing bug..." ) fix_calculator() print ("\n[4/4] Adding test..." ) add_test() 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 复杂:
大型代码库 :Agent 需要快速定位相关文件,而不是遍历所有代码
多文件修改 :一个 bug 可能涉及多个模块的联动修改
上下文理解 :Agent 需要理解代码的架构设计,避免引入新问题
安全与权限 :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 的时代已经来了。你准备好了吗?