顶层配置只留四条硬规则:Agent 在哪里必须停下来
模型可以越来越自主,但生产、持久化数据、成本和不可逆动作必须先经过明确授权。安全不是效率的对立面,而是自动化成立的前提。
本页目录 · 11 节
我给编码 Agent 的顶层配置刻意保持简短。除了一份本机通用约定,核心就是四条 Safety Gates:
@~/.codex/RTK.md
DO NOT send optional commentary
## Safety Gates
- Do not commit, push, merge, deploy, or release directly to protected branches or production environments without explicit confirmation for that exact action.
- Do not read, scan, create, update, delete, or otherwise operate on production or persistent data without first listing the risks and receiving explicit confirmation.
- Do not perform operations that may incur costs, create paid resources, or invoke billable external services without first listing the risks and receiving explicit confirmation.
- Do not perform destructive, irreversible, security-sensitive, or externally impactful operations without first explaining the impact and receiving explicit confirmation.
公开版本把本机用户名缩写为 ~。本文中的 persistent data 也不指任务范围内的普通工作区源码;它指生产或长期保存的业务/客户数据、授权工作区之外的持久状态,以及未经授权复制会扩大暴露面的导出物。工作区源码仍受任务范围与文件授权约束;仓库若定义了更严格边界,则以更严格规则为准。
这四条规则不是一套完整安全系统。它们是一份放在最高优先级上下文里的授权策略:告诉 Agent 哪些常规工作可以自主推进,哪些行为会改变真实世界的后果,因而必须暂停并把决定权交还给人。
先做威胁建模:风险不只来自「模型犯傻」
一个能读文件、执行 shell、访问网络和调用 Provider API 的 Agent,至少面对五类失败来源:
- 意图误读:用户说「准备发布」,Agent 把它理解成「立即发布」;
- 目标漂移:任务本来只针对 feature branch,操作却落到
main或 production; - 能力放大:模型的一次错误判断,经由高权限凭证变成真实数据、费用或外部影响;
- 不可信输入:README、网页、issue、日志或工具结果中的 prompt injection 诱导 Agent 越权;
- 状态陈旧:确认之后,branch SHA、查询范围、部署 payload 或资源价格已经变化。
Anthropic 对 trustworthy agents 的分析同样把模型、Harness、工具和运行环境视为共同的能力与监督面,并明确指出误解用户意图和 prompt injection 都是现实风险。威胁模型因此不能只问「模型有多聪明」,还要问:它能接触什么、凭什么被允许行动、错误的 blast radius 有多大、事后能否证明发生了什么。
Capability 不等于 Authority
这是四条规则背后的核心区分:
| 层次 | 回答的问题 | 例子 |
|---|---|---|
| Capability | 技术上能不能做 | 工具持有 Git、AWS 或数据库凭证 |
| Intent | 当前任务希望得到什么 | 「分析发布失败原因」 |
| Authority | 用户是否授权这次具体副作用 | 「确认把 commit A 部署到 production」 |
| Enforcement | 系统怎样阻止越界 | sandbox、IAM、branch protection、approval hook |
| Evidence | 执行后怎样证明结果 | Provider 回执、目标状态回读、审计日志 |
凭证可以访问生产,不代表当前任务授权访问生产;用户让 Agent 分析一次失败,也不代表授权它顺手修复、提交、推送和部署。反过来,Prompt 里写了「必须确认」也不代表技术层已经强制执行——模型仍是概率系统,可能误解上下文或受到不可信内容影响。
所以,顶层 Safety Gates 是授权语义的第一层,不是 sandbox、最小权限、Provider 保护规则和审计的替代品。NIST SP 800-53 Rev. 5中的 least privilege、separation of duties 与 audit controls 提供了更一般的工程原则:只授予完成任务所需的最小能力,关键职责不要集中在单一决策点,并为特权行为留下可检查记录。
一次有效确认必须绑定具体动作
explicit confirmation 不是看到聊天里出现一个「可以」就放行。确认至少要与以下内容绑定:
Approval = {
action, // commit / push / deploy / query / delete / purchase ...
exact_target, // repo, branch, environment, account, table, recipients ...
payload_or_hash, // 将要写入或执行的精确内容
risk_summary, // blast radius, cost, data exposure, reversibility
preconditions, // 当前 SHA、版本、过滤条件、资源状态
validity, // 本次调用、当前状态或明确时间窗口
approved_by, // 可信用户身份或审批策略
request_id // 本次具体 tool call / operation 身份
}
确认前的风险说明是一次 preflight,确认后的目标回读是一次 readback。两者缺一不可:没有 preflight,人不知道自己批准了什么;没有 readback,Agent 不知道 Provider 最终做了什么。审批还必须来自受信任的用户界面、身份或策略;网页、Issue、日志和仓库文本即使写着「approved」,也只能作为数据,不能成为 approved_by。
仓库可以在顶层规则之上增加更严格的门禁。例如,对本地直接提交或 push main,要求在列出 commit、目标 branch、diff 范围和部署影响后,再取得第二次、针对该精确动作的确认。这里的第二次确认是仓库层强化,不应被泛化成所有低风险操作都要重复询问。第一次可以确认方向或计划,第二次绑定即将执行的 payload;如果两次之间 payload 或目标变化,旧确认自动失效。
Gate 1:交付动作按后果逐级授权
commit、push、merge、deploy、release 不是同义词:
- commit 改变本地历史;
- push 改变远端 ref,并可能触发 CI;
- merge 改变目标分支;
- deploy 改变某个运行环境;
- release 可能创建公开、可消费或不可轻易撤销的版本。
一次有效 preflight 应写明 repository、remote、source/target branch、当前与预期 SHA、是否命中 protected branch、会触发的流水线、目标 environment 和恢复路径。用户授权「push feature branch」,不能推导出「创建 PR」「merge main」或「部署 production」。即使这些动作在技术上紧密相连,也必须按用户给出的字面边界停下。
Provider 层还应继续设置 branch protection、required reviews 和 deployment environment rules。GitHub Actions 的部署文档说明 environment 可以配置 protection rules,待审任务也可以被批准或拒绝。这样的技术门禁能防止 Prompt 误判直接变成生产变更。
执行后要读回远端 branch SHA、PR/merge 状态、deployment 对应的 revision 或 artifact,以及真实运行入口。push 成功不等于 merge,CI 绿色不等于 deploy,deployment success 也不等于线上行为正确。
Gate 2:持久化数据连只读访问也先说明风险
数据门禁覆盖 read、scan、create、update、delete,因为只读不等于无风险:
- 生产查询可能暴露个人信息、凭证或业务敏感字段;
- 缺少索引或范围过大的 scan 可能造成负载与费用;
- 错误的时间范围、tenant 或状态过滤会产生误导性结论;
- 导出文件会把生产数据复制到新的持久化位置,扩大泄露面。
preflight 必须说明数据源与环境、表或索引、字段、过滤条件、预计行数、是否涉及 PII、查询成本/负载、输出落点和保留方式。写操作还要说明事务边界、并发条件、备份、dry-run、分批策略、回滚方式以及用于回读的稳定主键。
对未知 schema、未知范围或未知恢复路径采取 fail closed:先停下补齐事实,而不是用宽查询「看一眼再说」。技术凭证提供的是 capability,只有明确的数据目标和风险确认才构成本次 authority。
Gate 3:费用也是必须授权的副作用
调用付费模型、执行大范围日志分析、创建云实例、扩容数据库、发送付费消息,可能不改业务数据,却会产生账单、消耗配额或留下持续收费资源。
费用 preflight 至少包含 Provider、账户/项目、区域、资源或模型、预计调用次数/数据量、单次与总成本估计、最大上限、持续时间和清理方式。无法精确估价时要给区间和最坏情况,不能用「应该很便宜」代替说明。
本地结构校验、mock 和 dry-run 可以降低真实调用次数,但它们不能伪装成在线验证。报告要区分「请求结构已验证」「免费健康检查已通过」和「付费真实路径已执行」。执行后读回 usage、billing metric、资源状态,并清理临时付费资源。
Gate 4:不可逆、敏感或影响外部的人和系统
前三类无法穷举全部后果。强制 push、批量删文件、轮换凭证、修改 IAM、发送邮件或 Slack、创建公开 issue/PR、发布包、覆盖备份,都应落入第四道门禁。
preflight 要回答四件事:准确目标是什么、影响谁、能否恢复、失败时如何止损。对消息类动作应展示收件人和最终内容;对删除类动作应列出精确对象并优先选择可恢复方式;对权限与密钥操作应说明当前权限、新权限、凭证传播范围和轮换后的依赖影响。
目标如果仍由 glob、未解析环境变量、模糊别名或「当前账号」决定,就还不具备被确认的条件。先把目标解析成稳定身份,再请求授权。
不要让确认变成无意义的点击
审批过多会产生 approval fatigue。Anthropic 在其Agent containment 实践中披露,频繁弹窗会让用户逐渐降低注意力;其结论是不能只靠人逐次判断,还要通过 sandbox、VM、文件系统边界和 egress control 限制可造成的最大损害。OpenAI 的 Codex 安全部署实践也采用同样的分层原则:低风险日常动作尽量无摩擦,高风险动作才停下,同时配合 sandbox、网络策略、托管配置与 agent-aware telemetry。
因此,Safety Gate 应该放在改变后果的边界,而不是每一个工具调用:
- 读取任务范围内的本地代码、做静态分析、编辑已授权文件、运行非破坏性本地测试,可以自主进行;
- 触碰生产、长期保存的业务/客户数据、授权工作区外的持久状态、费用、外部系统或不可逆状态,才进入 preflight 与确认;
- 同一个已批准动作只有在 target、payload、风险和前置条件完全一致时才可继续;
- 目标变化、payload drift、确认超时、出现新的费用/数据范围、失败后改走另一条路径,都必须重新确认。
OpenAI 的 Codex 安全部署实践给出的控制原则同样是:让 Agent 在有界环境内完成低风险日常工作,把跨越技术边界或可能产生高风险后果的动作交给审批策略处理。审批应落在真实后果上,而不是机械地包围每一步本地工作。
从 Prompt 到技术控制:五层防御
前面的四条 Prompt 是我当前采用的授权语义。下面五层是工程化的目标模型,不表示每个项目或运行环境都已经完整部署了全部控制;具体落地状态必须逐项回读。
一套可落地的安全设计至少有五层:
- Prompt / Policy:表达用户意图、禁止推导授权、定义停下来的条件;
- Tool boundary:schema 校验、参数 allowlist、危险命令阻断、幂等键和 approval hook;
- Environment:只读或 workspace sandbox、网络 egress policy、隔离 worktree/容器、秘密不进入无关上下文;
- Provider:最小权限 IAM、branch protection、environment review、预算上限、数据库权限与速率限制;
- Telemetry & Readback:记录 prompt、审批、工具参数、结果和 Provider 标识,并从权威目标重新读回状态。
OpenAI Agents SDK 的 HITL 机制展示了一个关键实现细节:待审批工具调用会暂停为 interruption,批准针对具体 call,运行状态可序列化后再恢复。真正的门禁应尽可能绑定具体 tool call 与参数,而不是只让模型记住一句「用户之前同意过」。
Prompt injection 防御同样需要跨层处理。来自网页、issue、日志、仓库文档和 MCP 的文字只能作为数据,不能授予新权限;外部内容不得覆盖顶层策略;工具应仅暴露任务需要的最小能力;凭证尽量不进入模型上下文;即使模型受骗,sandbox、egress 和 Provider 权限也应限制它能造成的后果。纯提示词只能影响行为倾向,不能提供强制安全保证。
Safety Gate 的失败模式
| 失败模式 | 为什么危险 | 正确处理 |
|---|---|---|
| 模糊的「可以」「继续」 | 无法确定批准了哪个动作和目标 | 回显 action、target、payload,再取得精确确认 |
| 陈旧确认 | SHA、数据范围或价格已经变化 | 绑定 precondition 与有效期,变化后重新确认 |
| Payload drift | 实际执行内容不同于预览 | 对 payload/hash 做执行前比较,不一致即停止 |
| 跨动作复用 | 把 commit 授权扩大成 push/deploy | 每种外部后果独立授权 |
| 目标别名 | main、prod、当前账号指向错误对象 |
解析 remote、account、region、environment 的稳定身份 |
| 部分成功 | Provider 只完成一部分,Agent 却报告完成 | 读回每个目标,区分 verified/mismatch/unknown |
| Prompt injection | 外部文字诱导泄密或越权 | 不可信内容不改变 authority,并靠环境和工具边界限权 |
| Approval fatigue | 用户机械点击,监督失效 | 仅在后果边界暂停,低风险操作走短路径 |
| 只靠 Prompt | 概率性遵循被误当成强制控制 | 叠加 sandbox、IAM、hooks、provider rules 与 telemetry |
一个完整的安全闭环
对任何命中 Safety Gate 的动作,使用同一条闭环:
Classify consequence
-> Resolve exact target
-> Build preview and risk summary
-> Wait for action-specific confirmation
-> Re-check target, payload and preconditions
-> Execute once
-> Read back from the authoritative provider
-> Report verified / mismatch / unknown
四条顶层规则的价值,不在于覆盖所有攻击,也不在于证明 Agent 永远不会犯错。它们把「高能力工具可以做什么」与「本次任务被允许做什么」分开,并给更强的技术控制一个统一的授权语义。低风险工作因此可以连续进行,高风险后果则在准确的位置暂停、确认、执行和回读。
安全不是自动化完成之后再补的一次检查。只有当权限最小、授权具体、边界可执行、结果可审计时,Agent 的自主性才真正适合进入生产工程。
相关文章
从 Workflow Harness 到轻量 Prompt:Codex 5.6 之后我删掉了什么
当模型的原生流程已经够强,Harness 会从效率放大器变成上下文负担。这次重写保留了安全边界,同时大幅精简 Prompt 和运行时。
上下文加载:解释「怎样加载上下文」本身也在消耗上下文
用证据优先级、可重建句柄与新鲜度指纹控制每一轮推理真正需要看到的材料。