Agent.Space 博客

用 Claude Code 或 Codex 修 Bug:一个可运行的完整例子

用四个测试复现 URL 拼接 Bug,给 Claude Code 或 Codex 明确的修复任务,再检查最小补丁与实际输出。附完整代码和提示词。

让编码 Agent 修 Bug,最好从一个能复现的失败开始,以一个能验证的改动结束。把预期行为、失败例子和修改边界交给 Claude Code 或 Codex,然后自己检查测试与 diff。

下面是一个完整小练习。我们在 2026 年 10 月 8 日使用 Bun 1.3.14 本地运行:原实现通过一个用例、失败三个;修正后四个全部通过。这是下方代码的运行结果,不是 Claude Code 或 Codex 的能力跑分,被测补丁也不是模型生成的结果。

Bug:搜索链接被拼错了

假设一个工具函数给绝对 URL 添加搜索参数,约定如下:

  • 把 q 设置为传入字符串,替换已有 q;
  • 保留其他查询参数和片段标识;
  • 把搜索词编码为参数值。

原始 searchLink.ts 实现太简单:

ts
export function searchLink(base: string, query: string): string {  return `${base}?q=${query}`;}

https://example.test/search?q=coffee 看起来没问题。但 URL 已有 ?sort=date、带着 #results,或者搜索词含有 & 时,结果就会出错。

用四个检查复现

在真实项目之外创建临时练习目录,保存上面的函数,以及下面这个 searchLink.test.ts:

ts
import { expect, test } from "bun:test";import { searchLink } from "./searchLink";
test("adds a simple query", () => {  const url = new URL(searchLink("https://example.test/search", "coffee"));  expect(url.searchParams.get("q")).toBe("coffee");});
test("keeps sort and replaces the old query", () => {  const url = new URL(searchLink(    "https://example.test/search?sort=date&q=old", "coffee",  ));  expect(url.searchParams.get("sort")).toBe("date");  expect(url.searchParams.getAll("q")).toEqual(["coffee"]);});
test("keeps the fragment", () => {  const url = new URL(searchLink("https://example.test/search#results", "coffee"));  expect(url.searchParams.get("q")).toBe("coffee");  expect(url.hash).toBe("#results");});
test("keeps special characters inside the query value", () => {  const query = "coffee & tea + 奶";  const url = new URL(searchLink("https://example.test/search", query));  expect(url.searchParams.get("q")).toBe(query);  expect([...url.searchParams.keys()]).toEqual(["q"]);});

运行:

sh
bun test searchLink.test.ts

原始版本预期为 1 pass、3 fail。保留这次输出。如果结果不同,先检查复制的文件和运行时,再让 Agent 修复。

给 Agent 一个有边界的任务

把失败的练习文件和以下提示词交给它:

text
修复 searchLink.ts,让四个已有测试通过。先运行测试,根据实际输出解释失败。保留无关查询参数和片段标识。q 必须只有一个值,并正确保留特殊字符。
除非发现测试存在具体错误,否则只修改工具函数。使用运行时标准 URL API,不增加依赖。不要通过放宽断言来获得通过结果。补丁后运行同一条测试命令,并展示 diff。

Claude Code 的官方最佳实践强调为 Agent 提供验证工作的方式。这里真正重要的是可观察的行为约定,而不是某句提示词本身。

用于真实仓库时,沿用项目已有测试工具与约定。可以先按接手已有代码库的流程找到它们,再开始修改。

检查修正后的实现

满足这个练习约定的一种实现是:

ts
export function searchLink(base: string, query: string): string {  const url = new URL(base);  url.searchParams.set("q", query);  return url.href;}

再次运行同一条命令。我们的本地结果是 4 pass、0 fail。

这个改动利用已有 URL 结构,不再附加第二个 ? 或把查询参数放进片段。searchParams.set 替换已有 q,同时保留其他参数。测试比较解码后的值,因为等价的 URL 序列化可能使用不同的空格编码方式。

函数有意只接受绝对 URL。相对 URL 需要额外的基准地址与行为约定;这里没有处理。它还可能规范化序列化结果,所以不要直接用于必须逐字节保留原文的签名 URL。

四个测试通过,证明了什么?

它证明这四个用例在被测运行时满足工具函数约定。它不能证明界面真的调用该函数、服务器按预期解释 q,或所有输入都被支持。

用于真实搜索功能时,还需要在浏览器提交表单、查看生成的 URL,并核对展示结果。只有功能确实需要时,再补充相对 URL、空值等行为检查。

如果 Agent 没有运行命令就报告成功,要求它补齐证据。如果命令在加载测试前就失败,先处理环境错误。这两种情况都不能直接变成模型能否修 Bug 的结论。

在一个 Workspace 里练习

在 Agent.Space 创建临时练习项目,放入两个文件,选择当前可用的 Claude Code 或 Codex 配置,发送有边界的任务。检查保存的函数、测试输出与 diff,再把方法用于生产项目。具体准备步骤见 Claude Code Workspace 指南。

如果比较两个配置,分别提供独立的原始失败文件。让第二个 Agent 读取第一个已经修好的代码,不构成比较。更完整的评估方式见编码 Agent 回归评估指南。