Guardian Review¶
Guardian review 是 Codex 对 on-request/granular approval 的自动审查层。它不是替代 sandbox,也不是简单规则列表;它会为具体工具动作构造一个受控的审查子会话,让专门的 reviewer model 判断是否可以自动批准。
它解决的问题¶
传统 agent CLI 有两种不理想的审批体验:
- 所有高风险动作都弹给用户,频繁打断。
- 给模型过大的自动权限,风险被转移到执行后。
Guardian 的折中是:当 approval policy 允许请求审批,并且 approvals_reviewer == AutoReview 时,把 approval request 先交给 guardian reviewer。它的原则是 fail closed:超时、会话失败、解析失败都会阻止执行,只有显式 allow 才放行。
路由条件¶
入口在 codex-rs/core/src/guardian/review.rs:
matches!(
turn.approval_policy.value(),
AskForApproval::OnRequest | AskForApproval::Granular(_)
) && approvals_reviewer == ApprovalsReviewer::AutoReview
这意味着 Guardian 只接管本来会进入审批路径的请求。更早的 ARC、权限 profile、sandbox 仍然可以先阻断动作。
审查合同¶
Guardian 要返回严格 JSON,对应 GuardianAssessment:
| 字段 | 含义 |
|---|---|
risk_level |
low/medium/high/critical |
user_authorization |
用户是否已授权该类操作 |
outcome |
allow/reject 等审查结果 |
rationale |
审查理由 |
guardian_output_schema 会约束输出结构,parse_guardian_assessment 负责解析。如果输出 malformed,执行失败关闭。
Transcript 裁剪¶
Guardian 不把完整历史塞进审查 prompt,而是构造紧凑 transcript:
| 常量 | 数值 | 用途 |
|---|---|---|
GUARDIAN_MAX_MESSAGE_TRANSCRIPT_TOKENS |
10_000 |
message transcript 总预算 |
GUARDIAN_MAX_TOOL_TRANSCRIPT_TOKENS |
10_000 |
tool transcript 总预算 |
GUARDIAN_MAX_MESSAGE_ENTRY_TOKENS |
2_000 |
单条 message 上限 |
GUARDIAN_MAX_TOOL_ENTRY_TOKENS |
1_000 |
单条 tool 上限 |
GUARDIAN_MAX_ACTION_STRING_TOKENS |
16_000 |
待执行动作描述上限 |
GUARDIAN_RECENT_ENTRY_LIMIT |
40 |
最近条目数量上限 |
这套预算体现了安全审查里的上下文工程:要保留用户意图、近期工具结果和具体动作,但不能把审查本身拖成另一个完整 agent turn。
Trunk 与 ephemeral review¶
GuardianReviewSessionManager 会维护一个可复用的 trunk review session。复用条件由 GuardianReviewSessionReuseKey 决定,它包含 model/provider、context window、reasoning 配置、permissions、instructions、cwd、mcp servers、sandbox exe、features 等会影响审查行为的字段。
如果 trunk 空闲且 reuse key 一致,就复用 trunk;如果 trunk 忙,或 key 不一致,会 fork 出 ephemeral review:
| session kind | 使用场景 |
|---|---|
TrunkNew |
首次创建 trunk |
TrunkReused |
trunk 可复用且空闲 |
EphemeralForked |
trunk 忙或配置不匹配时的临时审查 |
trunk 成功完成后会刷新 fork snapshot。这样下一次 ephemeral review 可以从最近已提交的 guardian rollout 快照启动,而不是从零开始。
超时、重试和熔断¶
Guardian 有多个保护层:
| 机制 | 代码位置 | 作用 |
|---|---|---|
GUARDIAN_REVIEW_TIMEOUT = 90s |
guardian/mod.rs |
审查 deadline |
GUARDIAN_REVIEW_MAX_ATTEMPTS = 3 |
guardian/review.rs |
审查失败重试上限 |
| fail closed | run_guardian_review |
timeout/session/parse error 都阻止执行 |
| denial circuit breaker | GuardianRejectionCircuitBreaker |
同一 turn 拒绝过多时中断 turn |
拒绝熔断阈值是:
| 常量 | 数值 |
|---|---|
| 连续拒绝 | 3 |
| 最近窗口拒绝 | 50 次审查中 10 次拒绝 |
熔断触发时,Codex 会发送 GuardianWarning,然后 abort 当前 turn。这个设计防止 agent 在被拒绝后不断变体尝试,形成策略绕行。
拒绝后的开发者消息¶
当 guardian reject 一个动作时,Codex 会生成一段明确指令:
The agent must not attempt to achieve the same outcome via workaround,
indirect execution, or policy circumvention.
这段信息作为后续模型上下文的一部分,让 agent 明确知道“不能换个写法继续做同一件事”。这比只返回工具错误更强,因为它改变了后续推理约束。
与 Review Task 的关系¶
codex-rs/core/src/tasks/review.rs 是用户可触发的 /review 风格任务,用 sub-agent 产出 structured review output。它和 Guardian 共享“子会话审查”的思想,但目标不同:
| 机制 | 触发 | 目标 | 权限 |
|---|---|---|---|
| Guardian Review | 工具审批请求 | 判断具体动作是否自动放行 | fail closed,继承父配置并受限 |
| Review Task | 用户进入 review mode | 审查代码变更并输出 findings | 禁用 web search、collab、multi-agent,审批永不请求 |
Review Task 在退出时会把 review output 作为 developer message 记录到 rollout,确保后续 turn 能读到审查结论。
可学习的设计点¶
- 自动审批不是规则硬编码,而是“专用模型 + 严格 schema + 失败关闭”。
- trunk reuse 降低频繁审批的延迟,同时用 reuse key 精确失效。
- fork snapshot 让并发审查既能共享上下文,又不会互相污染。
- denial circuit breaker 把“安全拒绝”升级为“停止当前 turn”,避免策略绕行。
- 审查输出会转化成后续开发者上下文,而不是仅影响当前工具调用。
关键源码¶
| 主题 | 文件 |
|---|---|
| guardian 入口与常量 | codex-rs/core/src/guardian/mod.rs |
| approval review flow | codex-rs/core/src/guardian/review.rs |
| review session manager | codex-rs/core/src/guardian/review_session.rs |
| approval request formatting | codex-rs/core/src/guardian/approval_request.rs |
| prompt/schema/parse | codex-rs/core/src/guardian/prompt.rs |
| review task | codex-rs/core/src/tasks/review.rs |