首页
/ gemini-cli 自动修 Bug 流水线解析:Bug Fixer Agent 系统提示词设计与源码级实现

gemini-cli 自动修 Bug 流水线解析:Bug Fixer Agent 系统提示词设计与源码级实现

2026-09-06 17:43:34作者:虞亚竹Luna

在 gemini-cli 仓库的 tools/caretaker-agent 目录下,运行着一条“GitHub Issue → 自动定位 → 自动修复 → 自动评测 → 自动提交 PR”的无人值守流水线(caretaker-agent)。本文以该流水线中 PR 生成器(pr-generator)的第一轮编码智能体系统提示词 bug_fixer_prompt.md 为主体,完整拆解它对“自动修 Bug 的 Coding Agent”的角色约束、输入规范、四阶段工作流与安全边界,并结合 orchestrator.pyagent_runner.py 等源码,说明这份提示词是如何被装载进无头(headless)沙箱、与工具白名单和迭代循环协同工作的。读完后你将掌握:一份面向自动化代码修改场景的系统提示词应该如何设计其“强制动作、输入契约、验证闭环与越权护栏”,以及这类 Agent 在 Cloud Run 环境中运行的完整机制。

提示词在 PR 生成流水线中的位置

pr-generator 由一个 Python 工作流目录驱动,入口是 worker.py:它初始化 Config 并启动 Orchestrator 状态机。状态机按轮次循环:

  • 第 1 轮:调用 Coding Agent,系统提示词文件正是 bug_fixer_prompt.mdorchestrator.py 第 341-351 行);
  • 第 2 轮及以后:若评测未通过,则改用 code_revision_prompt.md 读取上一轮反馈 pr_feedback.md 进行定向修订;
  • 每轮代码生成后,由 code_evaluator_prompt.md 定义的 Evaluator Agent 输出 verdict.json 判定 APPROVEDNEEDS_REVISION

也就是说,bug_fixer_prompt.md 是这条“生成—评测—修订”迭代环的起点提示词,它面对的输入是上游 triage 阶段产出的“可执行缺陷规格”(workable_spec),产出则是对目标仓库的真实文件修改。

角色定义:以测试驱动和防回归为目标的自主工程师

提示词开篇的 Role 一节给出的定位是:

You are an expert autonomous software engineer specializing in bug resolution, test-driven development, and regression prevention.

即“专长于缺陷解决、测试驱动开发(TDD)与回归防护的专家级自主软件工程师”。任务目标被明确限定为三步:接收 bug 规格 → 在本地仓库应用修复 → 实现完备测试并验证。值得注意的是角色措辞中反复出现 autonomous(自主)——这意味着 Agent 运行在无人值守环境中,不可能停下来向人提问。这一前提正是后面“CRITICAL EXECUTION RULES”中“不得只看不改”“不得请求许可”等硬性规则的由来。

三条关键执行规则:对抗 LLM 的“只读惰性”

提示词中最具工程价值的是 CRITICAL EXECUTION RULES 一节,它针对 LLM Agent 常见的三类失败模式设置了强约束:

  1. 强制文件编辑(MANDATORY FILE EDITS):必须使用文件编辑工具(replace_file_contentmulti_replace_file_contentwrite_file)修改 workable_spec.implementation_plan.files_to_modify 中列出的文件,并向 workable_spec.testing_strategy.test_file 添加新的测试断言;
  2. 禁止“看完即止”(DO NOT STOP AFTER VIEWING OR BASELINE TESTS):绝不允许在仅读取文件或仅运行未修改的基线测试后就结束会话,必须在本地工作区产生具体文件修改;
  3. 立即应用编辑(APPLY EDITS IMMEDIATELY):打开并查看目标文件后,应立即用编辑工具应用修复与测试断言,随后用 run_command 验证。

这三条规则与运行环境的源码实现形成了精确呼应。agent_runner.py 第 38-65 行 定义了无头沙箱的工具白名单与自动批准钩子:

# Permitted tool allowlist for headless sandbox operations
ALLOWED_SANDBOX_TOOLS = {
    # Reading tools
    "view_file",
    "read_file",
    # File writing & editing tools
    "replace_file_content",
    "multi_replace_file_content",
    "write_file",
    "write_to_file",
    # Command execution
    "run_command",
}

if hooks is not None:
    @hooks.pre_tool_call_decide
    def auto_approve_all_tools(context, tool_call) -> str:
        """Only auto-approves safe, allowlisted tools in headless mode."""
        if tool_call.name in ALLOWED_SANDBOX_TOOLS:
            return "PROCEED"
        return "REJECT"

从源码结构看,提示词中点名的 replace_file_contentmulti_replace_file_contentwrite_filerun_command 恰好都落在白名单内:白名单内工具被 pre_tool_call_decide 钩子自动放行(无人点击“允许”),名单外工具一律 REJECT。这解释了为什么提示词需要反复强调“必须用编辑工具落盘”——因为无头环境里不存在人工确认,Agent 若只停留在“阅读 + 思考”层面,会话就会被白白消耗掉。

输入规范:workable_spec 字段契约

提示词规定 Agent 会收到一个包含 workable_spec 的 JSON 载荷,需要提取的关键字段如下:

字段路径 含义 提示词中的用途
workable_spec.implementation_plan.files_to_modify 目标文件清单 限定必须修改的文件范围
workable_spec.implementation_plan.steps 详细修复步骤说明 修复实施的逐步指令
workable_spec.testing_strategy.framework 测试框架(如 Vitest、Jest、Pytest) 决定新测试用什么框架编写
workable_spec.testing_strategy.test_file 测试应添加/更新的测试文件 测试断言的落点
workable_spec.testing_strategy.verification_steps 需要验证的具体断言/场景 测试用例的设计依据

这份规格并非凭空传给 Agent。在 orchestrator.py 第 215-221 行,Orchestrator 会把校验通过的 Firestore 文档原样落盘为 PR 工作区根目录下的 firestore_doc.json——这正是提示词 Phase 1 要求解析的文件。规格中的另一个顶层字段 issue_idorchestrator.py 第 159 行)与 github_metadata(owner/repo/issue_number)则用于后续的锁校验、分支命名与 PR 创建。

工作流详解:四个阶段如何落地

Phase 1:摄入与验证(Ingestion & Validation)

  1. 解析 JSON 输入(即 firestore_doc.json),从 workable_spec 中提取全部相关细节;
  2. 验证本地环境:确认自己位于目标仓库根目录;确认 files_to_modify 列出的文件存在;检查 test_file 是否存在,若不存在则计划创建它。

对应的环境准备由 Orchestrator 在 Agent 启动前完成(orchestrator.py 第 102-143 行):克隆或同步 origin/main、设置 bot 的 git 身份、把 firestore_doc.json/pr_feedback.md/changes.diff 等管线产物写入 .git/info/exclude 以免污染 git status,再 git checkout -B ssr-agent-<issue_num> origin/main 切出特性分支,并以 NODE_OPTIONS="--max-old-space-size=4096" npm ci --no-audit --no-fund --maxsockets 3 安装依赖(orchestrator.py 第 200-213 行)。所以提示词里“确认位于仓库根目录”这条,实际上由外层 AgentRunner 的工作目录切换保证:run_agent 通过 working_directory 上下文管理器 将进程 CWD 切到 repo_path,并用全局 asyncio.Lock 串行化,因为 os.chdir 是进程级操作。

Phase 2:实施(MANDATORY FILE EDITS)

  1. 应用代码修改:使用 replace_file_contentwrite_file,严格依照 steps 修改 files_to_modify 中的文件;不重构无关代码,保持改动最小化并聚焦于该 bug;
  2. 实现测试:打开(或创建)test_file,添加与 verification_steps 对齐的新测试用例,确保使用指定 framework,测试需整洁、可读,必要时对外部依赖做 mock。

这里“最小化改动”原则与外层状态机形成闭环:_prepare_iteration_commitorchestrator.py 第 372-397 行 实际位于 orchestrator.py)对每轮工作区做 git add . && git reset --soft origin/main 后生成 diff;若第 1 轮没有任何改动,会直接抛 OrchestrationError("Failed to generate any code changes in the first iteration.") 终止本次任务。换言之,“只看不改”不仅浪费一次迭代,还会让整次 Job 失败。

Phase 3:验证与校验(Verification & Validation)

提示词对验证阶段的命令选择做了非常具体的规定:

  • 只跑目标测试:只运行 test_file 中的测试来验证修复;
  • 明确禁项:不要运行 npm run preflight
  • 推荐命令形式(以 Vitest 为例):
    • npx vitest run <path/to/test_file>
    • npm test -w <workspace> -- <path/to/test_file>
  • 零失败要求:目标测试文件内所有用例必须全部通过;
  • 失败迭代:若失败,分析错误输出 → 用文件编辑工具修正实现或测试 → 重跑目标测试 → 循环直至干净通过。

只跑目标测试而非全量套件,是受计算资源约束的工程决策:整个 Job 容器限额为 2 CPU / 8Gi 内存、超时 3600 秒(见 job.yaml)。确定性回归检查则由 Orchestrator 在评测通过后另行执行——_run_regression_checksorchestrator.py 第 530-574 行)在评测沙箱中执行 npm run cleannpm ci,并对 test:ci 类失败通过 PreflightFilter 的白名单规则判断是否可豁免。

Phase 4:报告(Reporting)

  • 概述所做修改并列出被修改的文件;
  • 列出运行的测试及其通过/失败状态;
  • 确认未检测到回归。

这一节对应的是 Agent 会话结束时的文本输出,最终会被 AgentRunner.run_agent 收集进 full_output(按 step_index 排序拼接 content 与 thoughts,见 agent_runner.py 第 234-247 行),供上层日志追溯。

约束与安全边界

提示词末尾的 Constraints & Safety 三条规则,划定了 Coding Agent 的行为边界:

  • 不得运行 git commitgit push 或任何修改远程仓库的命令,改动只留在工作目录;
  • 不得修改 files_to_modifytest_file 之外的文件,除非有明确理由(例如测试框架所需的包配置更新);
  • 新代码必须匹配现有代码库的风格与模式。

这些约束与白名单机制互为表里:即便 Agent 试图 git pushrun_command 虽在白名单内可以执行,但外层 Orchestrator 才是真正掌握 git 远程操作的一方——它使用内存中的 http.extraHeader 认证头推送分支并调用 GitHubClient 创建 PR(orchestrator.py 第 647-691 行)。把“改代码”与“推代码”分离给两个信任层级,是该流水线安全设计的核心:Agent 永远只是工作区的编辑者,而非发布者。

提示词的装载与执行机制

从源码看,这份 Markdown 提示词的运行链路如下:

  1. Orchestrator.__init__script_dir 指向 agent_prompts 目录(orchestrator.py 第 75-82 行);
  2. 第 1 轮调用时传入 system_prompt_file="bug_fixer_prompt.md"AgentRunner._load_prompt_file 读取文件内容作为 system_instructions,并做路径穿越防护(agent_runner.py 第 99-121 行);若文件缺失则回退到默认指令并记 warning;
  3. LocalAgentConfig(vertex=True, project=..., location=..., model=..., system_instructions=..., workspaces=[repo_path]) 组装本地 Agent 配置,默认模型为 gemini-3.5-flash(由 config.pyMODEL_NAME 环境变量控制,job.yaml 中亦有同一默认值);
  4. 任务级 prompt 由 Orchestrator 动态拼接(orchestrator.py 第 342-350 行),内容与提示词中 CRITICAL 规则高度一致——强制编辑、禁止只读收场、headless 沙箱中用 run_command 直接执行测试命令、不要在聊天中请求许可。

依赖方面,requirements.txt 声明了 google-antigravity>=0.1.0google-cloud-firestoregoogle-genai 等核心包;Dockerfile 基于 python:3.11-slim,从官方 node:20-slim 镜像拷入 Node 20(因为 Agent 需要执行 npx vitest 等 npm 命令),以非 root 用户运行 workflow/worker.py

迭代上限、500 行护栏与人工兜底

bug_fixer_prompt.md 的“失败即迭代”策略有明确的上界,均由源码中的确定性逻辑执行:

  • 最大轮数MAX_ATTEMPTS 环境变量(默认 5,最小 1,见 config.py 第 41-44 行);
  • 并发双锁:任务启动前经 db_interface.py 的 Firestore 事务获取 15 分钟锁(lock.holder + lock.expires_at),状态置为 COMMIT_GENERATIONgeneration_attempts >= 2 时直接转 NEEDS_HUMAN
  • 改动规模护栏:即使 Evaluator 给出 APPROVED,若 git diff --stat origin/main 统计的增删行数超过 500 行,同样转入 NEEDS_HUMANorchestrator.py 第 272-288 行);
  • 失败兜底:Workflow 层(workflow.yaml)捕获 Job 异常后将 Firestore 文档状态改写为 NEEDS_HUMAN 并清空锁字段;Cloud Run Job 自身配置 maxRetries: 2job.yaml)。

这套“提示词自律 + 白名单强制 + 状态机兜底”的三层防线,正是该提示词设计的深层逻辑:LLM 的输出不可完全信任,因此每一条提示词中的关键规则(必须编辑、禁止 push、限定测试命令)在 Orchestrator、工具钩子或 Firestore 状态机中都有对应的确定性执行者。

与评测/修订提示词的分工

理解 bug_fixer_prompt.md 的边界,需要对照同目录的另两份提示词:

  • code_evaluator_prompt.md:评测者明确“不得自己修代码”,只依据 changes.diff 与规格做正确性、安全性(含 ReDoS、敏感信息泄漏检查)、可读性评审,读取 Orchestrator 预先生成的 linter_output.txt(不得自行跑 linter),最终输出 verdict.json,并按严格格式(## Commit Message / ## PR Description 两级标题,供 Orchestrator 正则解析)写出 pr_details.mdpr_feedback.md
  • code_revision_prompt.md:修订者以 pr_feedback.md 为驱动做定向精修,且被限制在“最多 3 个回合”内完成,要求第一轮就直接应用修改。

三者构成清晰的职责切分:Bug Fixer 负责首轮“从规格到实现”、Evaluator 负责独立审查、Revision Agent 负责按反馈收敛,而文件级交互(firestore_doc.jsonchanges.diffverdict.jsonpr_feedback.mdpr_details.md)全部被写进 git exclude,避免污染 diff。

小结

bug_fixer_prompt.md 表面上是一份 90 余行的系统提示词,实际上是一份“无头编码 Agent 的操作契约”:它用 CRITICAL 规则消灭 LLM 的只读惰性,用 workable_spec 字段表锁定输入输出契约,用四阶段工作流规范“摄入—实施—验证—报告”的闭环,用安全约束把 Agent 关在“工作区编辑者”的角色里。而真正让这份契约可信的是仓库中的配套实现——agent_runner.py 的工具白名单钩子、orchestrator.py 的迭代状态机、db_interface.py 的 Firestore 双锁与状态转移,以及 job.yaml/workflow.yaml 定义的资源与重试边界。对希望自建“自动修 Bug Agent”的团队而言,这套“提示词设计 + 确定性护栏”的分工方式,以及 agent_promptsworkflowtests(含 test_orchestrator.py 等测试)的目录组织,都是可直接参考的工程范式。

登录后查看全文
热门项目推荐
相关项目推荐