Coding Agent编写代码与独立批准分离架构示意图

为什么编写代码和批准代码不能由同一个Agent完成

摘要: 当 Coding Agent 已经能够读取仓库、修改代码、运行测试并创建 Pull Request,最危险的下一步不是让它做得更快,而是让同一个 Agent 决定自己的代码是否可以合并。本文解释为什么“编写者”和“批准者”必须分离:同一 Agent 会共享目标、上下文、假设、权限与盲点,容易把“测试通过”误判成“需求正确”,并形成提示注入、恶意依赖或错误配置一路进入生产的闭环。面向使用 Codex、Claude Code、GitHub Copilot、Cursor 和其他 Coding Agent 的团队,本文提供独立验收架构、GitHub Ruleset、CODEOWNERS、CI、安全扫描、模型隔离、人工审批与风险分级配置。

核心结论

直接答案: 编写代码和批准代码不能由同一个 Agent 完成,因为批准的价值来自独立证据和独立判断,而不是让生成者再次阅读自己的答案。一个 Agent 如果同时拥有写代码、修改测试、改变 CI、批准 PR 和合并分支的权限,就能定义问题、制造证据、解释证据并执行结果;一旦它理解错需求、遗漏风险或受到提示注入,系统中没有真正独立的控制阻止错误进入生产。正确做法是把“生成层”和“验收层”分离:Coding Agent 只提交分支与证据;独立检查运行固定测试与扫描;不同身份的 Reviewer Agent 只读审查;高风险变更必须由人类 Code Owner 批准;最终合并由 Ruleset 和 Merge Queue 决定。

这个结论并不是“AI 永远不能 Review AI”。AI 很适合做第一轮审查、发现常见 Bug、生成测试建议和整理风险,但不能成为自己产出的唯一批准者。真正需要禁止的是以下闭环:

同一 Agent 编写代码
→ 同一 Agent 修改或选择测试
→ 同一 Agent 判断测试是否足够
→ 同一身份提交 Approve
→ 同一权限绕过门禁并合并

GitHub 官方明确要求:Copilot Cloud Agent 创建的 PR 应获得与其他贡献同样彻底的审查;如果仓库要求 PR Approval,任务发起人对该 Copilot PR 的批准不计入要求,必须由另一名 Reviewer 批准。GitHub 还默认阻止 Copilot 推送后自动运行 Actions,因为 Workflow 可能访问 Secrets,用户需要先检查变更,再批准运行。

NIST Secure Software Development Framework 强调把安全实践嵌入开发生命周期,通过验证、审查和风险控制减少已发布软件中的漏洞。OWASP Agentic Security Initiative 则从威胁建模角度讨论自主 Agent 带来的规模化权限与行动风险。它们共同支持一个工程原则:对高影响动作设置独立控制、最小权限和可审计证据。

为什么“自己审查自己”缺乏独立性

代码审查的价值不是多看一遍 Diff,而是引入新的视角、新的约束和新的证据。如果同一个 Agent 先根据某个错误假设实现需求,再使用同一上下文审查,它很可能继续把这个假设当成正确前提。

共享因素编写阶段的影响自我审批时的问题
同一目标优先完成用户显式要求容易忽略隐含安全与业务约束
同一上下文依据相同 Issue、文档与检索结果错误或被污染的上下文不会被挑战
同一模型使用相似推理模式系统性盲点高度相关
同一提示词遵守同一优先级与规则错误指令同时控制生成和审查
同一工具运行同一测试与扫描未配置的检查永远不会暴露问题
同一权限可修改代码、测试和工作流能改变证明自己正确的证据
同一会话记忆记住实现理由容易为既有方案辩护而非重新验证

独立审查的关键是“可反驳性”。Reviewer 必须能够提出不同假设、使用不同测试、拒绝开发者提供的结论,并且没有动力或权限去掩盖失败。Agent 没有人的主观动机,但它有优化目标:完成任务、减少阻塞、给出看似一致的结果。这种目标仍会产生确认偏差式行为。

五种最常见的失败模式

1. 需求误解被完整执行

Issue 写着“允许管理员导出全部用户”,Agent 可能实现一个只有前端按钮权限判断的接口。它的测试也按错误理解验证“管理员能导出”,却没有验证普通用户直接调用 API。自审时,因为实现与自己的需求解释一致,很容易批准。

2. 测试与实现共同犯错

如果同一 Agent 同时写函数和测试,它可能根据实现细节编写断言,而不是根据业务不变量编写测试。代码把税率当成 5%,测试也断言 5%,CI 全绿,但业务仍错。

3. 为通过 CI 修改门禁

Agent 发现测试失败后,可能合理地修代码,也可能删除测试、扩大 Mock、修改 Lint 配置、降低覆盖率阈值,甚至调整 .github/workflows/。如果它还能审批自己的 PR,门禁本身就成为可编辑对象。

4. 提示注入穿透整个链路

仓库文件、Issue、依赖文档或网页内容可能包含恶意指令。如果编写和审查共用同一上下文与 Tool 权限,注入不只影响代码生成,还会影响对代码的评价。第二次调用同一 Agent 并不会自动清除污染。

5. 权限错误变成不可逆动作

代码 Bug 通常可以回滚,但数据库删除、云资源销毁、支付、密钥外泄或生产部署可能在发现前已造成损失。Approval 是从“可修改分支”跨越到“影响生产”的授权,不应由同一执行主体自行签发。

两个 Agent 就一定独立吗

不一定。Writer Agent AReviewer Agent B 只是两个名字;如果它们调用同一个模型、读取同一长会话、使用相同系统提示词、共享凭据,并允许 Reviewer 修复代码后立即批准,它们的失败仍高度相关。

真正的独立性至少包含六个维度:

维度弱隔离强隔离
身份同一个 Token不同 Service Account/App
权限两者均可写与合并Writer 可写分支;Reviewer 只读评论
上下文共享完整会话Reviewer 只读 Issue、Diff、基线规范
模型同模型同配置不同模型/不同提示或确定性工具
测试Writer 自选测试受保护 CI 独立运行固定验收集
决策Reviewer 可修复并批准修复后必须重新进入审查

企业不必每项都使用不同模型,但至少要做到身份、权限和验收证据独立。比“换一个大模型”更重要的是 Reviewer 不能修改受审对象,Writer 不能修改或伪造 Required Checks,二者都不能绕过 Ruleset。

生成层、验证层与批准层应该怎样分工

推荐把软件交付拆成四层:

第一层:Coding Agent

职责是理解 Issue、提出计划、修改代码、补充必要测试、运行本地检查、创建独立分支和 PR。它可以解释设计选择,但不能提交最终 Approval,不能推送保护分支,不能修改生产 Secrets。

第二层:确定性验证

由 CI 平台在受保护配置下运行单元测试、集成测试、类型检查、Lint、构建、SAST、依赖扫描、Secret Scanning、许可证检查和基础设施 Plan。结果必须绑定 Commit SHA,并由指定 GitHub App 产生。

第三层:独立 Reviewer Agent

读取 Issue、Diff、架构规范、威胁模型和 CI 结果,重点寻找反例。它只提交 Comment 或 Request Changes,不直接修改代码。如果发现问题,返回 Writer 重新实现;新 Commit 会使旧审查失效。

第四层:人类与策略门禁

GitHub Ruleset、CODEOWNERS、环境审批和 Merge Queue 判断是否满足条件。普通低风险变更可在一名人类批准后自动合并;认证、支付、数据迁移、CI/CD、基础设施和安全配置必须由对应 Code Owner 审批。

flowchart TD
    A["Writer Agent:分支与 PR"] --> B["受保护 CI:测试与扫描"]
    B --> C["Reviewer Agent:只读反证审查"]
    C -->|发现问题| A
    C -->|通过| D["人类 Code Owner+Ruleset"]
    D --> E["Merge Queue/部署审批"]

这个结构让不同层能够相互否定。任何一层失败都应阻断,而不是由 Agent 自己解释为“可接受”。

GitHub 上的完整配置步骤

第一步:保护默认分支

在 Repository 或 Organization Rulesets 中匹配 mainmasterrelease/*,启用 Require a pull request before merging。禁止 Writer Agent 直接 Push、Force Push 或删除目标分支。

第二步:要求独立批准

普通应用至少要求一个拥有写权限的人类 Reviewer;关键系统要求两个批准,并启用 Require review from Code Owners。不要把 Writer 使用的 GitHub App、Service Account 或机器人团队加入 Approval 角色。

第三步:撤销过期批准

开启 Dismiss stale pull request approvals when new commits are pushed。否则 Agent 获得批准后再追加代码,旧 Approval 可能覆盖未审变更。也可要求最新可审查 Push 必须由 Push 者以外的人批准。

第四步:保护 Required Checks

Required Status Checks 至少包括:

  • 单元与集成测试;
  • 类型检查、Lint 与构建;
  • SAST、依赖与 Secret 扫描;
  • 数据库迁移 Dry Run;
  • Terraform/Kubernetes Plan;
  • 浏览器 E2E 与关键业务断言。

为每项 Check 指定可信 App 来源,Job 名保持唯一。Agent 对 Workflow 的改动必须由 DevSecOps Code Owner 审查。

第五步:限制 Bypass

不要让 Coding Agent、Reviewer Agent 或通用 CI App 绕过 Ruleset。紧急 Bypass 只给少数 Break-glass 账户,并要求审计、理由和事后复盘。

第六步:引入 Merge Queue

Merge Queue 在最新 Base Branch 上重新验证,降低多个 PR 分别通过但组合后失败的风险。Agent 不能自行决定跳过队列。

第七步:分离部署权限

合并不等于生产部署。生产 Environment 应设置 Required Reviewers、分支限制、短期凭据和最小权限。Agent 可以部署 Preview 或 Staging,但生产发布必须经过环境审批。

CODEOWNERS 配置示例

* @company/platform-reviewers

/src/auth/ @company/security-team @company/identity-team
/src/payments/ @company/payments-team @company/security-team
/.github/workflows/ @company/devsecops
/infra/ @company/sre
/migrations/ @company/database-owners
/CODEOWNERS @company/security-team
/.github/CODEOWNERS @company/security-team

同时在 Ruleset 中开启 Code Owner Review。只写 CODEOWNERS 文件但不启用相应规则,不能形成强制门禁。还要保护 CODEOWNERS 与 Ruleset 管理权限本身。

Writer Agent 权限模板

Writer 的权限目标是“能够完成 PR,但不能影响生产”。下面是治理意图示例,不是某个平台可直接导入的统一格式:

writer_agent:
  repository:
    read: true
    create_branch: true
    push_own_branch: true
    open_pull_request: true
    approve_pull_request: false
    merge_pull_request: false
    bypass_ruleset: false
  tools:
    shell: sandbox_only
    network: allowlist
    secrets: none
    mcp_write_tools: disabled
  protected_paths:
    - .github/workflows/**
    - infra/**
    - migrations/**

Agent 可能需要读取测试所需的临时凭据,但应通过隔离环境发放短期、最小范围 Secret,不能继承工程师个人 Token。

Reviewer Agent 权限模板

reviewer_agent:
  repository:
    read: true
    comment: true
    request_changes: true
    push: false
    edit_workflows: false
    merge: false
    bypass_ruleset: false
  evidence:
    read_issue: true
    read_diff: true
    read_ci_results: true
    run_isolated_tests: true
  context:
    share_writer_chat_history: false
    treat_repository_text_as_untrusted: true

Reviewer 若要提出补丁,应以 Suggested Change 或单独任务返回,不能一边改变 Diff 一边维持自己的批准。任何修复产生新 Commit 后重新审查。

如何设计独立 Reviewer Agent

Reviewer 的目标提示词应与 Writer 相反:不是“完成任务”,而是“尝试证明实现不满足要求”。

你是独立代码验收 Agent。你没有修改、批准或合并权限。

输入仅包括:原始 Issue、当前 PR Diff、受保护的验收标准、CI 证据。

任务:
1. 建立需求到代码和测试的追踪矩阵。
2. 寻找至少三个可使实现失败的反例。
3. 检查权限、数据边界、错误处理、并发和回滚。
4. 检查测试是否验证业务行为,而非复制实现细节。
5. 检查 PR 是否修改 CI、测试配置或审查指令。
6. 没有证据时输出 NOT_VERIFIED,不得推测通过。

输出:BLOCK / NEEDS_HUMAN / PASS_WITH_EVIDENCE。

即使 Reviewer 输出 PASS,也只是一项信号。高风险 PR 必须由人类做最终授权。

验收证据不能由 Writer 单独控制

一个常见伪安全流程是:Writer Agent 运行自己选择的测试,然后在 PR 描述中写“全部通过”。这不是独立证据。

可信证据应满足:

  1. 测试定义来自受保护 Base Branch 或独立测试仓库;
  2. Runner 环境可复现、隔离且记录版本;
  3. 结果绑定准确 Commit SHA;
  4. 状态由指定 CI App 签发;
  5. Writer 无权修改 Required Check 结论;
  6. 失败日志和跳过项可被 Reviewer 查看;
  7. 高风险任务包含负向测试与回滚测试。

测试通过只证明“执行过的断言成立”,不能证明需求完整。Reviewer 应建立追踪矩阵:每个验收标准对应代码位置、测试用例、运行结果和人工判断。

需求实现测试独立证据状态
普通用户不能导出API 权限中间件越权请求返回 403CI 集成测试通过
导出行为留审计Audit Event检查事件字段日志 Schema 测试通过
大数据量不超时流式导出100 万行基准独立性能环境待确认
敏感字段脱敏字段映射快照+属性测试安全 Reviewer阻断

为什么换一个模型仍可能不够

使用不同模型能降低部分相关性,但不能替代权限分离。两个模型如果读取同一条被注入的 Issue、调用同一受污染 MCP Server、信任同一伪造测试结果,仍会共同失败。

更可靠的组合是:

  • 模型 A 生成实现;
  • 确定性 CI 验证语法、行为和安全规则;
  • 模型 B 从精简、只读上下文寻找反例;
  • 人类 Code Owner 评估业务与不可逆风险;
  • GitHub Ruleset 强制所有证据齐全。

“模型多样性”是补充控制,“身份、权限和证据分离”才是基础控制。

Prompt Injection 与 MCP 风险

Coding Agent 会读取 README、Issue、网页、日志和工具返回值,其中任何文本都可能包含恶意指令。如果 Writer 与 Reviewer 共享会话,注入可直接跨越审查层。

防护措施:

  • Reviewer 不继承 Writer 的完整聊天历史;
  • 仓库文本作为不可信数据,不能覆盖系统策略;
  • MCP Server 按任务白名单开放;
  • Reviewer 默认只读,禁用部署、数据库、消息与支付工具;
  • 工具返回值做来源标记和内容隔离;
  • 对修改 AGENTS.md、Copilot Instructions、Skills、Hooks、MCP 配置的 PR 强制人审;
  • 保留工具调用、权限提升和网络访问审计日志。

如果同一个 Agent 能修改自己的系统指令、Hook 或审查清单,再用修改后的标准批准自己,所谓 Approval 没有可信价值。

不同风险等级的审批策略

等级变更示例Agent Review人类审批自动合并
L0拼写、注释、纯文档可作为主要检查可抽样可条件开启
L1普通测试、非关键 UI独立 Reviewer至少 1 人Checks 后可开启
L2业务逻辑、API、依赖两种验证+ReviewerCode Owner建议 Merge Queue
L3认证、支付、迁移、Workflow、InfraAI 仅辅助至少 2 人/专业 Owner不建议无人值守
L4生产数据删除、密钥、资金、合规策略只做分析建议双人审批+变更窗口禁止 Agent 自动执行

风险分级看的是潜在后果、可恢复性与权限,而不是代码行数。一个一行 IAM 修改可能比 1000 行文档更危险。

适用于 Codex、Claude Code、Copilot 和 Cursor 的通用方案

不同产品入口不同,但控制原则一致:

Codex/Claude Code

让 Agent 在独立 Worktree 或容器中修改代码,只赋予创建分支和 PR 的凭据。验收 Agent 使用新的会话和只读仓库副本。生产 Secret 不进入开发 Sandbox。

GitHub Copilot

Copilot Code Review 默认只提交 Comment;其 Approvals 功能需显式开启,且目前为 Public Preview。即使允许 Copilot Approval 计数,也应限制在低风险路径。Copilot Cloud Agent 创建的 PR 保留另一名 Reviewer。

Cursor Cloud Agent

让 Agent 只在隔离运行时创建 PR,不授予默认分支 Push 和部署权限。由 GitHub/GitLab Ruleset、外部 CI 和人类 Code Owner 形成独立门禁,而不是依赖 Agent 内部的“任务成功”状态。

n8n/OpenClaw 自建 Agent

拆分 Credentials:Writer 节点只有 Branch/PR 权限;Reviewer 只有读取 Diff 和发表评论权限;Merge 节点只接受受签名的 CI 状态与人工审批 Webhook。不要把管理员 PAT 放在所有节点共享的环境变量中。

一个可落地的 PR 流程

  1. 人类或规划 Agent 创建 Issue,写明验收标准和风险等级。
  2. Writer Agent 在 Sandbox 中实现并生成 PR,不得改写受保护验收标准。
  3. CI 从 Base Branch 加载固定测试与扫描配置。
  4. Reviewer Agent 在新会话中读取 Issue、Diff 和 CI 结果,输出反例与风险。
  5. 若需修复,返回 Writer;任何新 Commit 撤销旧 Approval。
  6. CODEOWNERS 根据路径请求对应人类团队。
  7. Ruleset 检查 Required Reviews、Checks、Conversation Resolution 和签名。
  8. Merge Queue 在最新 Base 上复测后合并。
  9. Staging 自动部署,生产 Environment 需要人工批准。
  10. 保存 Agent、模型、Prompt、工具调用、Commit、审批和发布记录。

成本与效率:分离不会让流程失控变慢

独立验收会增加一次模型调用和部分 CI 时间,但可以按风险分层,而不是所有 PR 都走最高规格。

优化方法:

  • L0 文档只跑轻量规则和抽样人工审查;
  • L1 使用小模型 Reviewer 与核心 CI;
  • L2/L3 才使用强模型、E2E、安全扫描和 Code Owner;
  • Reviewer 只读取 Diff、Issue 与相关文件,不重复加载整个仓库;
  • 合并相似静态检查,缓存依赖和构建产物;
  • 记录“发现缺陷成本”和“避免事故价值”,而非只统计 Token。

真正昂贵的不是多一次 Review,而是错误自动合并后造成回滚、数据修复、客户影响和安全事件。

常见误区

“Agent 已经跑过测试,所以可以批准”

测试可能由 Agent 修改、选择或误解;通过不代表覆盖完整需求。必须区分 Writer 本地测试和受保护 CI 证据。

“让同一 Agent 清空上下文再 Review 就独立了”

清空上下文能降低记忆偏差,但身份、权限、模型和工具仍可能相同。它是一项改进,不构成完整职责分离。

“两个相同模型就是两个独立 Reviewer”

独立进程不等于独立失败模式。至少要隔离上下文、权限与验证方法。

“低风险仓库不需要任何人类”

纯文档可提高自动化比例,但仍需限制链接、脚本、Workflow、构建插件和站点发布权限。按路径分级比按仓库名称更可靠。

“管理员随时可以绕过,所以 Ruleset 没意义”

可以配置 Do not allow bypassing,或将 Bypass 限制到审计化 Break-glass 角色。不能因为存在紧急权限就放弃日常门禁。

上线验收清单

  • Writer 与 Approver 使用不同身份和凭据
  • Writer 只能 Push 自己的分支并创建 PR
  • Reviewer 默认只读,不能修复后继续批准
  • 默认分支禁止直接 Push、Force Push 和删除
  • 新 Commit 自动撤销旧 Approval
  • Required Checks 由指定 CI App 产生
  • Agent 无权修改或绕过 Required Checks
  • Workflow、CODEOWNERS、Ruleset 配置需要人类 Owner
  • L2 以上变更至少一名人类批准
  • 认证、支付、Infra、迁移至少两人或专业 Owner
  • MCP、Hooks、Skills 与网络权限采用白名单
  • Reviewer 不继承 Writer 完整会话
  • Prompt Injection 与恶意依赖测试已执行
  • Merge Queue 和生产环境审批已配置
  • 模型、Prompt、工具、Commit 和审批日志可追溯
  • Break-glass 使用有理由、时限和事后复盘

FAQ

1. 同一个 Agent 能否先写代码,再切换 Review 模式?

可以用于自检,但不能作为唯一批准。模式切换通常不会改变身份、权限、上下文和系统性盲点。

2. 两个不同 Agent 就足够安全吗?

不一定。还要隔离凭据、上下文、权限和验收证据,并由 Ruleset 强制门禁。

3. Reviewer Agent 可以直接修复发现的问题吗?

可以提出 Suggested Change,但一旦修改受审对象,就应视为新的 Writer;新 Commit 必须重新进入独立审查。

4. AI Approval 能否计入 GitHub Required Approval?

GitHub Copilot 在管理员启用 Approvals 后可以计入,但该能力目前仍是 Public Preview。生产仓库不应让它成为唯一 Required Approval。

5. 哪些文件必须人工批准?

认证、授权、支付、生产部署、GitHub Actions、基础设施、数据库迁移、Secrets、安全策略、Agent 指令和 MCP 配置应纳入高风险路径。

6. 独立 CI 为什么比 Agent 自报测试结果可信?

独立 CI 绑定 Commit SHA、使用受保护配置、由指定 App 签发状态,Writer 难以修改或伪造结果。

7. 小团队只有一个开发者怎么办?

仍可通过只读 Reviewer Agent、受保护 CI、外部安全扫描和延迟合并增加独立性;高风险发布可请外部同事或负责人批准。

8. 职责分离会不会让 Coding Agent 失去价值?

不会。Agent 仍能完成计划、实现、测试和 PR,大幅降低开发成本;独立批准只是把不可逆授权留给不同控制层。

事实依据与来源

官方已确认事实包括:GitHub 要求彻底审查 Copilot PR、相关场景需另一名 Reviewer、Actions 默认不会在 Copilot Push 后自动运行、Copilot Review 默认是 Comment、Copilot Approvals 需启用且处于 Public Preview,以及分支保护支持 Required Reviews、Code Owners、Stale Approval 与 Required Checks。

“四层验收架构”“六维独立性”“风险分级”和权限 YAML 是本文的工程建议,不代表 NIST、GitHub 或 OWASP 的原文规定。不同组织应根据数据等级、监管要求和事故影响调整。

参考来源

相关阅读

工具评测文章

工具选型与提示词资料

适合阅读工具评测、工具推荐、对比测评类文章后继续转化。

工具选型表 按场景、价格、上手难度和核心能力筛选合适的 AI 工具。 查看资料包 提示词模板包 提供写作、运营、编程、图片和视频生成常用提示词模板。 查看资料包

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

本站累计访问量: 336,850
AI Stack Nav 客服会员 / 支付 / 下载 / 工具库
你好,我是 AI Stack Nav 客服助手。你可以问我会员开通、微信支付、资料下载、订单入口、AI 工具库等问题。