Agent AtlasAI Agent 知识库
06.03实战 · In Practice

实战:代码 Agent

仓库理解、补丁生成、测试反馈与沙箱:编码 Agent 的循环设计与工程要点。

代码是 Agent 最理想的试验场:有明确的输入输出、可执行的验证、可回滚的版本控制。也正因如此,编码 Agent 的工程方法最值得借鉴。

为什么代码场景特殊

特性对 Agent 的意义
测试可执行提供客观的成功信号,不靠模型自评
版本控制失败可回滚,改动可审查
结构化文件、函数、类型都可精确定位
工具成熟搜索、编辑、运行、调试都有标准接口
反馈快编译/测试通常秒级到分钟级

这让「生成—验证—修正」的闭环真正成立。

能力清单

一个编码 Agent 至少需要:

text
repo_map()                  仓库结构与关键符号
search_code(query)          全文/符号搜索
read_file(path, range)      按需读取,不要整仓加载
apply_patch(diff)           精确修改
run_tests(path?, filter?)   运行测试
run_command(cmd)            受限的构建/ lint
git_diff()                  查看当前改动
git_status()                确认工作区状态

工具设计原则与〈工具设计〉一致:小、清晰、有权限边界。尤其是 run_command,必须限制在沙箱与白名单命令内。

循环

图 1 · 编码 Agent 的闭环
01理解读需求、仓库结构、相关代码
02定位搜索符号、调用链、测试
03修改生成最小补丁
04验证编译、测试、lint,失败则修正

关键在「最小补丁」:改动越小,越容易审查、越不容易引入回归。

上下文:不要塞整个仓库

一个中型仓库可能有几十万行代码。正确做法:

  1. 仓库地图:目录结构、模块职责、关键文件;
  2. 符号索引:函数/类/接口定义位置;
  3. 按需读取:先搜索,再读相关片段;
  4. 调用链:从入口追到依赖;
  5. 测试:相关测试文件与最近失败输出。
text
上下文预算示例(32k):
- 任务描述            1k
- 仓库地图            2k
- 相关文件(3–5 个)   12k
- 测试与错误           4k
- 最近 diff            3k
- 规则与输出格式       2k
- 预留                 8k

不要一次读 20 个文件。先定位,再读。

补丁格式

两种常见方式:

方式优点缺点
统一 diff精确、可审查、可回滚行号/上下文必须准确
整文件替换简单容易丢内容、diff 巨大
结构化编辑(AST)最精确实现复杂、语言相关

生产系统多用统一 diff + 严格校验:

diff
--- a/src/auth/session.ts
+++ b/src/auth/session.ts
@@ -42,7 +42,7 @@ export function validateSession(token: string) {
-  const decoded = jwt.verify(token, SECRET);
+  const decoded = jwt.verify(token, SECRET, { algorithms: ["HS256"] });
   return decoded;
 }

应用补丁前要检查:

  • 文件存在;
  • 上下文匹配;
  • 不修改禁止目录;
  • 不引入大文件/二进制;
  • 变更行数在预算内。

测试反馈循环

python
def solve(task, repo, max_rounds=4):
    context = build_repo_context(repo, task)
    patch = generate_patch(task, context)

    for round_no in range(max_rounds):
        apply_patch(repo, patch)
        result = run_tests(repo, related_only=True)

        if result.ok:
            return patch

        feedback = {
            "failed": result.failed[:5],
            "traceback": result.traceback[-3000:],
            "diff": git_diff(repo)[:4000],
            "hint": "只修改与失败测试相关的代码;不要删除测试;不要改公共 API。",
        }
        patch = revise_patch(task, patch, feedback)

    rollback(repo)
    return None

要点:

  • 只跑相关测试,先快后全;
  • 失败信息要具体到测试名与断言;
  • 限制轮数,避免无限修;
  • 每轮保留 diff,便于回滚;
  • 成功后跑全量测试与 lint。

防止「测试作弊」

模型可能通过修改测试、跳过断言、捕获异常来让测试通过。防护:

  • 测试文件只读;
  • 校验测试是否被修改;
  • 检查是否有 skip、xfail、空 except;
  • 用隐藏测试(held-out)验证;
  • 人工审查关键改动。

评估

  • Pass@k:k 次尝试中至少一次通过;
  • Pass^k:k 次全部通过(更接近生产可靠性);
  • 回归率:修好目标测试,但弄坏了其他测试;
  • 补丁大小:越大越难审查;
  • 人工接受率:开发者是否愿意合并;
  • 平均轮数/成本。

公开基准(SWE-bench 等)只能参考。你自己的仓库、编码规范、测试覆盖才是真实分布。

安全

  • 在沙箱/容器中运行,限制网络与文件系统;
  • 命令白名单,禁止 curl | bash、rm -rf;
  • 不把生产密钥放进环境;
  • 代码变更必须经过 review;
  • 依赖安装要锁定版本与来源;
  • 防止提示注入通过代码注释/issue 内容进入。

失败模式

过度修改

为了修一个 bug 重写整个模块,引入新问题。要求最小 diff,并限制变更行数。

幻觉 API

调用不存在的库函数/参数。用类型检查、编译、测试兜底。

只修表象

捕获异常让测试通过,但根因还在。审查空 catch、强制返回默认值。

上下文污染

读入无关文件,被旧代码/注释带偏。先定位,再按需读取。

忽略仓库规范

命名、目录、错误处理与项目不一致。把规范写进系统提示,并提供示例。

检查清单

  • 有仓库地图与符号搜索,不整仓加载
  • 补丁最小、可审查、可回滚
  • 测试文件只读,防作弊
  • 沙箱运行,命令白名单
  • 限制轮数、变更行数、成本
  • 成功后跑全量测试与 lint
  • 有隐藏测试与人工 review
  • 评估覆盖 Pass@k 与回归率

小结

  • 编码 Agent 的核心是「理解—定位—最小修改—验证」闭环。
  • 上下文按需读取,靠仓库地图与符号搜索定位。
  • 测试是最强的验证信号,但要防止模型作弊。
  • 沙箱、命令白名单、人工 review 是安全底线。
  • 用 Pass^k 与回归率衡量生产可靠性,而不只看演示。

下一篇看四类成熟产品的架构共性与商业教训。

读完了?进度会保存在本地浏览器。
内容会持续修订。发现错误或想补充,欢迎反馈。 遇到问题?查排查手册 →