本章摘要 编写一个能写出
Hello World的脚本很容易,但构建一个能在一个百万行代码库中修复竞态条件(Race Condition)Bug 的 Agent 却极具挑战。 本章将从“软件工程”而非单纯“代码生成”的视角,系统拆解 Coding Agent 的架构。我们将深入探讨如何利用 Repo Map 解决上下文限制,如何设计非破坏性的文件修改协议,以及如何构建 TDD(测试驱动开发) 闭环来确保代码不仅能运行,而且是正确的。 学习目标
- 架构认知:理解 Coding Agent 的核心不是 LLM,而是“境交互循环”(Environment Interaction Loop)。
- 上下文工程:掌握利用 AST(抽象语法树)和 Call Graph(调用图)压缩代码库的方法。
- 工具设计:学会设计
search_and_replace等鲁棒的编辑工具,而非脆弱的行号编辑。- 闭环验证:建立“复现-修复-回归”的自动化测试策略。
在多模态 Agent 的语境下,Coding Agent 的输入往往是一个含糊的 Issue(可能包含报错截图、日志片段、用户描述),输出则是一个经过验证的 Pull Request (PR)。
我们将 Coding Agent 的能力划分为 L1~L4 四个层级:
ls, grep, find,理解跨文件依赖,定位问题所在,并处理多个文件的修改。本章重点关注 L3 和 L4。
一个成熟的 Coding Agent 工作流是一个有状态的决策图:
[Start: GitHub Issue]
|
v
[Phase 1: Exploration & Context] <-----------------------+
| 1. Read Issue Description |
| 2. List Files (Repo Tree) |
| 3. Search Keywords (Grep/Symbol Search) |
| 4. Build "Mental Model" of relevant code |
+-----+--------------------------------------------------+
|
v
[Phase 2: Reproduction (The "Red" State)] <-------------+
| 1. Create reproduction_script.py |
| 2. Run script -> Capture STDOUT/STDERR |
| 3. ANALYZE: Does it fail as expected? |
| (No -> Go back to Exploration) |
+-----+--------------------------------------------------+
|
v
[Phase 3: Coding & Patching (The "Fix" State)] <--------+
| 1. Read Implementation Details (Source Code) |
| 2. Plan Modification (Think Step) |
| 3. Apply Edit (Tool Call) |
| 4. Handle Edit Errors (e.g., Linter/Syntax) |
+-----+-------------------------------------------------+
|
v
[Phase 4: Validation (The "Green" State)]
| 1. Run reproduction_script.py (Expect Pass) |
| 2. Run Existing Tests (Regression Check) |
| 3. Visual Verification (If UI related) |
+-----+-------------------------------------------------+
|
+---> [Success] ---> Submit PR
|
+---> [Fail] ------> Return to Phase 3 (Refine)
最大的工程挑战在于 Token 预算。直接把所有文件塞进 context window 是不可行的(既贵又会降低模型注意力)。我们需要一种有损压缩但保留语义结构的表示方法。
Repo Map 是一种通过静态分析生成的代码摘要。它只保留“路标”,隐去“风景”。
压缩规则 (Rule of Thumb):
class 和 def 定义行。... 或 pass。ASCII 示意图:原始代码 vs. Repo Map
[原始代码 main.py (100行)] [Repo Map 表示 (5行)]
import utils
class Server: class Server:
def __init__(self, port): def __init__(self, port): ...
self.port = port def start(self): ...
self.log = []
# ... 20 lines ... def helper_func(x: int) -> bool: ...
def start(self):
print("Starting...")
# ... 50 lines logic ...
不要预加载。Agent 应该像人类在 IDE 中一样,点击哪个文件,才加载哪个文件的内容。
read_file(path)。read_file(path, start_line, end_line),禁止全量读取。对于未知的库或巨大的项目,使用 embedding 检索:
工具的设计直接决定了 Agent 的修改成功率。最糟糕的设计是 overwrite_file(重写整个文件),最好的设计是基于上下文的 patch。
| 工具名 | 关键参数 | 设计意图与工程细节 |
|---|---|---|
ls / list_files |
path |
探索目录结构。Gotcha: 必须限制递归深度,防止打印出 node_modules 的几万个文件。 |
search |
query, file_pattern |
类似 grep -n。让 Agent 找到关键词所在的行号。 |
read |
path, start_line, end_line |
关键特性: 输出必须带行号(Line Numbers),方便后续引用。 |
edit_replace |
path, search_block, replace_block |
推荐: 类似 sed 但更智能。Agent 提供“要查找的几行代码(作为锚点)”和“替换后的代码”。系统自动匹配锚点并替换。 |
run_cmd |
command, timeout |
执行 Shell 命令。安全限制: 只能在沙箱内运行,禁止网络请求(除非是白名单)。 |
create_file |
path, content |
用于创建新的测试脚本或新模块。 |
初学者常设计 edit_line(file, line_number, new_content)。
context。对于前端或 GUI 任务,需要增加:
capture_screenshot(url/path): 返回图片的 base64。get_render_tree(): 返回简化版的 DOM 树或 Accessibility Tree。visual_diff(img1, img2): 辅助工具,返回两张图的差异热力图(虽然 VLM 可以自己看,但工具辅助更精确)。Agent 极其容易产生幻觉——它以为代码是对的,但实际上跑不通。必须用解释器作为“物理定律”来约束它。
在修改任何业务代码前,强制 Agent 必须先写一个 Test Case。
reproduce_issue.py。当 edit 工具调用失败,或测试运行报错时,Agent 需要进入 ReAct 循环:
修改代码最怕“破坏了其他地方”。
function_A 后,Agent 应该主动调用 search("function_A") 查找所有调用方。find_references 工具。PR 不仅仅是代码,还有描述。
每道题包含提示(Hint),答案默认折叠。