gemini-cli 护理者 Agent 深度解析:代码修订 Agent(Code Revision Agent)的系统提示词与迭代修复闭环
gemini-cli 仓库的 tools/caretaker-agent/cloudrun/pr-generator 子目录实现了一条自动化的"缺陷规格 → 代码修复 → 评审 → 再修复"流水线,而本文的主角 code_revision_prompt.md 就是流水线中"第 2 轮及以后修复迭代"所使用的系统提示词。读完本文,你能掌握这套提示词的完整结构(输入契约、四阶段工作流、安全约束),以及它如何被 Python 编排器(orchestrator)按迭代次数动态装载、如何与评估者 Agent 产出的 pr_feedback.md 衔接,从而构成一个可运行的自动代码修订闭环。
一、角色定位:它是多 Agent 流水线中的"返修工"
在 pr-generator 的 agent_prompts 目录下共有三份系统提示词,对应三种 Agent 角色:
| 提示词文件 | 角色 | 触发时机 |
|---|---|---|
| bug_fixer_prompt.md | Bug Fixer(首次修复) | 迭代第 1 轮 |
| code_evaluator_prompt.md | Code Evaluator(评审守门员) | 每轮修复后 |
| code_revision_prompt.md | Code Revision(迭代修订) | 迭代第 2 轮及以后 |
code_revision_prompt.md 开篇定义了 Agent 的角色:一名专精代码修订、缺陷修复打磨与迭代质量保障的专家级自主软件工程师。它不做首次修复——首次修复由 Bug Fixer Agent 负责——它的职责是"接住评估者 Agent 打回的反馈,把本地实现打磨到生产级标准"。
这一角色分工在编排器源码中可以得到印证。在 orchestrator.py 的 _run_code_generation 方法中,编排器按迭代次数选择提示词文件:
if iteration == 1:
prompt = ("Fix the bug described in firestore_doc.json. ...")
prompt_file = "bug_fixer_prompt.md"
else:
prompt = ("Use the feedback in pr_feedback.md to address the remaining issues in the code and tests. ...")
prompt_file = "code_revision_prompt.md"
也就是说,只要评估未通过、循环进入第 2 轮,Agent 收到的系统提示词就切换为 code_revision_prompt.md,而用户消息则明确指向 pr_feedback.md 中的剩余问题。
二、输入契约:三个输入源与它们的语义
提示词的 "Inputs" 一节声明,修订 Agent 在运行时可访问三类输入:
pr_feedback.md(或feedback.md):评估者 Agent(Evaluator Agent)对上一轮变更产出的详细反馈,按类别(Correctness、Security、Readability、Test Failures)分组,并带有具体文件名与行号引用。firestore_doc.json(或example_firestore.json):原始workable_spec,包含缺陷摘要、实现计划(files_to_modify、steps)与测试策略(framework、test_file、verification_steps)。- 本地仓库:承载上一轮代码变更与单元测试的代码库。
这些文件并非凭空出现,而是编排器在工作区中预先铺好的。以 firestore_doc.json 为例,orchestrator.py 在克隆仓库、检出 ssr-agent-<issue_num> 分支并执行 npm ci 之后,会把 Firestore 文档写入 PR 工作区根目录:
spec_pr_path = os.path.join(self.config.pr_repo_path, "firestore_doc.json")
with open(spec_pr_path, "w", encoding="utf-8") as f:
json.dump(firestore_doc, f, indent=2)
而 pr_feedback.md 的"回传"则由 _save_feedback_to_coding_workspace 方法负责:当某一轮迭代未获批准时,编排器把评估工作区(eval 目录)中的 pr_feedback.md 拷贝回编码工作区(pr 目录),若评估者未产出该文件则写入占位说明,保证下一轮修订 Agent 始终"有反馈可读"(见 orchestrator.py 的 _save_feedback_to_coding_workspace)。单元测试 tests/test_orchestrator.py 中的 test_save_feedback_to_coding_workspace 正是对这条拷贝路径的断言。
另外值得一提的工程细节:编排器在克隆仓库时会向 .git/info/exclude 追加 firestore_doc.json、pr_feedback.md、feedback.md、changes.diff、verdict.json、pr_details.md 等条目(见 orchestrator.py),使这些 Agent 间的"传令文件"不会污染 git status 与最终 diff。
三、Phase 1:反馈摄取与规格交叉验证
修订 Agent 工作流的第一步不是改代码,而是"读懂要改什么":
- 读取评估反馈:打开并完整检查
pr_feedback.md(或feedback.md); - 交叉引用规格:查阅
firestore_doc.json,确保修订方向与原始规格的workable_spec.summary.problem、root_cause以及testing_strategy.expected_behavior保持一致——这一步防止 Agent 在"逐条消解反馈"时偏离缺陷本身; - 归类问题:把反馈中的每一项 action item 归入四个类别:
- Correctness & Logic gaps(正确性与逻辑缺陷)
- Security vulnerabilities or unsafe patterns(安全漏洞或不安全模式)
- Readability & Coding standard violations(可读性与编码规范违规)
- Missing or failing unit tests(缺失或失败的单元测试)
这种"先分类、后动手"的结构与评估者提示词 code_evaluator_prompt.md 中的评估维度(Correctness、Security、Readability)严格对齐——修订 Agent 的输入分类体系就是评估者输出分类体系的镜像,形成闭环。
四、Phase 2:定向修订与实现约束
这是提示词的核心章节,规定了"怎么改",可以拆成四个子约束。
4.1 最小化修改,禁止范围蔓延
- 严格针对评估反馈中指出的每一条问题修改目标源文件;
- 保持变更聚焦、最小化,不重构无关代码、不引入 scope creep。
这一约束在编排器侧有对应的"量化防线":即便某轮获得 APPROVED,如果 git diff --stat origin/main 解析出的总修改行数(插入 + 删除)超过 500 行,编排器仍会把该 issue 标记为 NEEDS_HUMAN 而不是自动提 PR(见 orchestrator.py)。提示词中的"最小化"原则与代码中的 500 行硬上限互为表里。
4.2 严格安全断言(Security Assertions)
提示词对安全维度提出了四条硬性要求,几乎全部面向 Node.js/TypeScript 场景的常见注入面:
- Input Validation:任何新增输入、参数或解析出的数据结构都必须做安全校验;
- Regex Security:正则表达式必须抵御 ReDoS(正则拒绝服务),避免过度宽松的通配符;
- Data Handling:敏感数据与硬编码凭据不得被记录或泄露,存储必须安全;
- Safe APIs:优先使用标准库或项目认可的安全 API,而非裸命令字符串或不安全调用。
值得注意的是,这四项断言与评估者提示词 code_evaluator_prompt.md 的 "Security Analysis" 章节逐条对应——评估者用什么标准打分,修订 Agent 就按什么标准自查,两套提示词实际上是同一套评审标准的一体两面。
4.3 质量与可读性断言
- Style & Conventions:遵循语言标准规范(如 TypeScript/Node.js 约定)与项目既有风格规则(
.eslintrc、tsconfig); - Naming & Simplicity:命名描述性、一致,函数短小模块化,遵循单一职责原则;
- Comments:注释解释"为什么"而非"是什么",避免对显而易见的语法做冗余说明。
4.4 测试覆盖的修正与扩充
- 打开
workable_spec.testing_strategy.test_file; - 修复反馈中指出的失败测试;
- 若评估者指出边缘场景缺失或
verification_steps覆盖不全,则新增测试用例; - 所有测试必须使用规格中指定的
framework(如 Vitest、Jest),并能在 headless 环境中可靠执行。
"headless 环境"这一点由运行基础设施保证:agent_runner.py 维护了一个无头沙箱工具白名单 ALLOWED_SANDBOX_TOOLS(view_file、read_file、replace_file_content、multi_replace_file_content、write_file、write_to_file、run_command),并注册 pre_tool_call_decide 钩子自动放行白名单内工具、拒绝其余工具——这就是提示词中"用 run_command 直接执行测试、不要向聊天窗口请求许可"的执行基础。
五、Phase 3:动态验证与回归测试
Phase 3 是"自我验证"环节,四步递进:
- 跑 Linter:执行项目 lint 命令(如
npm run lint或npx eslint .),把修改文件中的 lint 错误清零; - 跑目标测试套件:用
run_command直接执行目标测试文件(如npx vitest run <test_file>),确认所有被修订的代码路径与边缘场景通过; - 跑回归测试:执行相关的周边乃至全项目测试,确保修订没有破坏既有功能;
- 失败则迭代:任何 lint 或测试失败,都需分析输出、调整实现或测试断言后重跑,直到 100% 通过。
这里有一个与评估者分工的微妙之处:在正式流水线中,ESLint 检查实际是由编排器在评估工作区预先执行并落盘为 linter_output.txt 的——orchestrator.py 的 _run_eslint_static_check 会对 git diff origin/main 变更的 .ts/.tsx/.js/.jsx 文件执行 npx eslint --max-warnings 0 ...。但修订 Agent 提示词仍要求它自己跑 lint 并清零,这体现了"Agent 自验证 + 编排器确定性复验"的双保险设计:Agent 的自查是必要非充分条件,最终结论仍由评估者与编排器的确定性检查裁定。
六、Phase 4:报告义务与"3 轮"硬预算
修订 Agent 完成验证后必须产出一份简洁报告,包含三部分内容:
- 逐条列出
pr_feedback.md中的每个反馈点及对应的解决方式; - 列出执行过的测试与 lint 命令及其通过状态;
- 确认安全、质量与回归检查全部通过。
提示词末尾(Constraints & Safety 部分)还给出了一条极具工程实用性的预算约束:
You have a strict budget of 3 turns maximum to complete this task. Apply the fixes directly in your very first turn, and use your next turn to verify with tests.
即:第 1 轮直接改代码,第 2 轮跑测试验证,总共不超过 3 轮。这与 Bug Fixer 提示词中"不得只读文件和跑基线测试就结束回合"(CRITICAL EXECUTION RULES 第 2 条)形成呼应——两条规则共同治理 LLM Agent 最常见的失败模式:过度探索、拖延产出。同样,提示词明确禁止浪费回合跑 git status、git log、git show 这类探索性命令,"你已经拥有完整源码访问权"。
七、约束与安全边界:修订 Agent 的行为红线
提示词 "Constraints & Safety" 章节划定五条红线,每条都在编排器中有对应的机制承接:
| 红线 | 编排器侧的承接机制 |
|---|---|
禁止 git commit / git push,变更留在工作目录 |
提交动作由编排器在 _prepare_iteration_commit 中以软提交方式统一完成(orchestrator.py) |
不得修改 files_to_modify 与 test_file 之外的文件(除非有明确理由,如构建/测试框架配置) |
评估者按 diff 范围评审,越界修改会被 "Scope" 检查项捕获 |
| 修订代码必须匹配现有代码库的架构模式与风格 | 评估者 Readability 维度 + 编排器 ESLint 静态检查 |
任务是"基于 pr_feedback.md 应用修复" |
第 2 轮起用户 prompt 即指向 pr_feedback.md |
| 不跑探索性 git 命令;3 轮硬预算 | 工具白名单 + 无头沙箱自动审批(agent_runner.py) |
八、提示词如何被装载:AgentRunner 的装载链
最后把镜头从"提示词写了什么"转到"提示词如何生效"。编排器构造 AgentRunner 时把 agent_prompts 目录传给 script_dir(orchestrator.py),随后每次 run_agent 调用按以下链条装载提示词(见 agent_runner.py):
_load_prompt_file按文件名读取 markdown,并做路径穿越防护(拒绝解析后落在script_dir之外的路径);- 文件存在则以其全文覆盖默认 system instructions,不存在则回退为
"You are the {role}..."的兜底指令并记录警告; - 提示词连同 Vertex AI 配置(默认模型
gemini-3.5-flash,见 config.py)一起注入LocalAgentConfig; - 由于 Agent 交互基于进程 CWD,
AgentRunner用一把asyncio.Lock串行化所有 Agent 的目录切换,避免并发任务互相踩踏工作目录。
装载完成后的循环上限由环境变量 MAX_ATTEMPTS(默认 5,最小 1)控制——注意这是流水线级的"最多几轮 修复→评审"总迭代(config.py),而提示词中的 "3 turns" 是单次 Agent 会话内的工具调用轮次预算,两者尺度不同、各司其职。超过总迭代仍未获批时,编排器释放 Firestore 锁并把 issue 置为 NEEDS_HUMAN,由 tests/test_orchestrator.py 的 test_run_loop_max_attempts_exceeded 验证该路径确实会调用 release_lock。
九、小结:一份"返修工"提示词的设计要点
回到 code_revision_prompt.md 本身,可以提炼出它对"如何编写 LLM 代码修订 Agent 的系统提示词"给出的几条可复用经验:
- 输入契约显式化:把 Agent 能看到的文件(反馈、规格、仓库)逐一列名并说明语义,包括备选文件名(
pr_feedback.md或feedback.md),容忍上游产出差异; - 工作流阶段化:摄取 → 定向修订 → 动态验证 → 报告,每阶段有明确产物与通过标准,其中验证阶段的"失败则迭代直到 100% 通过"把回归风险内建进流程;
- 与评审标准镜像对齐:修订断言(输入校验、ReDoS、安全 API、SRP、注释规范)与评估者维度一一对应,反馈在两个 Agent 之间无需转译;
- 预算与红线双约束:"首轮直接改、次轮验证、3 轮封顶"治理拖延,"禁 commit/push、禁越界改文件"保护工作区主权,让 git 提交权始终握在确定性编排器手里;
- 自验证 + 确定性复验的双保险:Agent 自查 lint 与测试只是入场券,编排器的 ESLint 落盘、回归检查、500 行 diff 上限才是最终裁判。
对于想在自己的仓库中搭建"评估—修订"闭环的工程师,这套 pr-generator 目录下的三份提示词与 workflow 编排代码(含 Dockerfile、job.yaml、workflow.yaml 等 Cloud Run Job 部署配置)构成了一个完整可参考的实现样本:提示词负责"教会 Agent 怎么返修",编排器负责"保证返修过程可控、可审计、可终止"。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00