核心概念精讲:Prompting、Sandboxing 与 Approval
Codex 不是一个被动的代码补全工具——它是一个自主编码智能体。要驾驭这个智能体,你需要理解三个基石概念:Prompting(如何下达指令)、Sandboxing(智能体的技术边界在哪里)、Approval(何时需要人类确认)。三者协同构成了 Codex 的 "自主性-安全性" 平衡框架。
本篇核心收获:
- 掌握 Codex 提示词的结构化写法:目标、上下文、约束、输出格式
- 理解沙箱的三种模式及其平台原生实现机制
- 掌握审批策略的三档行为差异与运行时切换
- 理解 Rules 的命令级精细控制能力
- 建立「沙箱定义边界 + 审批控制暂停」的协同心智模型
一、Prompting:与 Codex 智能体对话的艺术
Codex 的工作模式是一个循环:接收提示词 → 调用模型 → 执行动作(读文件、编辑代码、运行命令)→ 观察结果 → 继续循环,直到任务完成或被取消。提示词的质量直接决定了这个循环的效率和准确性。
1.1 高质量提示词的结构
官方 Codex Prompting Guide(Cookbook)提炼了一个经过内部评估优化的提示词结构:
| 要素 | 说明 | 示例 |
|---|---|---|
| Goal(目标) | 一句话说清 "完成" 意味着什么,要具体 | "为 /api/users 端点添加分页支持,返回 { data, total, page, pageSize }" |
| Context(上下文) | 代码所在的环境:框架、语言版本、目录结构、已有模式 | "项目使用 Spring Boot 3.2 + MyBatis-Plus,分页参考 OrderController 的实现" |
| Constraints(约束) | 模型必须遵守的规则:性能、安全、命名、禁止事项 | "不引入新依赖,SQL 必须使用参数化查询,方法命名遵循现有 camelCase 风格" |
| Output(输出格式) | 你期望的交付物形式 | "直接修改文件并运行 mvn test 验证,不要只给计划" |
| Examples(示例) | 一个好的示例胜过一页说明 | "参考 GET /api/orders?page=1&size=20 的请求/响应格式" |
| Edge Cases(边界) | 你已知的失败模式 | "page 参数小于 1 时应返回 400,pageSize 超过 100 时限制为 100" |
Codex 被训练为一个自主的高级工程师——给出方向后,它会主动收集上下文、规划、实现、测试、迭代。默认期望是交付可运行的代码,而不仅仅是计划。 如果你不确定如何拆分任务,可以先让 Codex 提出一个方案。
1.2 任务分解策略
Codex 处理复杂任务的能力远超简单补全,但仍然遵循 "小任务优于大任务" 的原则:
- 可验证性:包含复现步骤、验证方式、lint/pre-commit 检查指令,让 Codex 能自我验证
- 渐进式分解:不确定怎么拆?先问 Codex:"分析这个需求,给我一个分步实现计划"
- 并行化思维:Codex 支持多线程并行工作(尤其是 Codex App),读密集型任务可以拆成多个独立线程
# ❌ 模糊的大任务
"重构整个认证模块"
# ✅ 分步的小任务
"Step 1: 将 AuthService 中的 JWT 生成逻辑抽取到 JwtTokenProvider 类
Step 2: 添加 Token 刷新端点 POST /api/auth/refresh
Step 3: 为新端点编写集成测试,覆盖过期 Token 和无效 Token 场景"1.3 上下文管理
Codex 的所有信息必须装入模型的上下文窗口内。窗口大小因模型而异,Codex 会监控并报告剩余空间。
- 手动上下文:在提示词中引用相关文件和图片。IDE 扩展会自动包含打开的文件列表和选中的文本范围
- 自动上下文:Codex 在工作过程中会自动收集文件内容、工具输出,以及已完成/待完成事项的记录
- Compaction(上下文压缩):长时间任务中,Codex 会自动通过摘要压缩上下文,丢弃不相关的细节。通过反复压缩,Codex 可以在多步骤复杂任务上持续工作数小时
Codex 会自动从 ~/.codex/ 以及从仓库根目录到当前目录的每一层,枚举并注入 AGENTS.md
文件。这些文件作为持久化的项目级指令,相当于 "永远生效的提示词"。详见本系列第 08 篇。
1.4 图片输入:从截图到代码
Codex 支持多模态输入——你可以在提示词中附加截图、设计稿、UI 原型图,实现 "视觉到代码" 的工作流。
使用方式:
- CLI:
codex -i screenshot.png "按照这个截图实现页面" - IDE 扩展:在 Chat 面板中拖拽或粘贴图片
- Codex App:直接在输入框中粘贴图片
典型场景:
- 将 Figma 设计稿截图转换为前端组件代码
- 提供 Bug 截图,让 Codex 定位并修复 UI 问题
- 附加架构图,让 Codex 理解系统拓扑后生成代码
Cookbook 特别强调:前端任务要避免 "AI 泥巴味"——不要千篇一律的 Inter/Roboto 字体、紫白配色、暗色模式。应该追求有意图的、大胆的界面设计。如果是在现有项目中工作,则保持现有设计系统的风格一致性。
1.5 Web 搜索:cached vs live
Codex 内置了 Web 搜索工具,默认在本地任务中启用。搜索结果可以帮助 Codex 查阅 API 文档、了解框架用法、获取最新信息。
| 模式 | 行为 | 适用场景 |
|---|---|---|
cached(默认) | 使用 OpenAI 维护的预索引缓存,不直接抓取实时网页 | 查阅 API 文档、框架用法。降低 prompt injection 风险 |
live | 实时抓取最新网页数据(等同 --search 参数) | 需要最新的 release notes、changelog 等实时信息 |
disabled | 完全关闭 Web 搜索工具 | 离线环境或安全敏感项目 |
配置方式:
# config.toml
web_search = "cached" # 默认值
# web_search = "live" # 等同 --search
# web_search = "disabled"即使是 cached 模式,Web 搜索结果仍应视为不可信内容。live 模式下 prompt injection 风险更高——恶意网页可能包含误导性指令。当使用 --yolo 或 danger-full-access 沙箱时,Web 搜索会自动切换为 live 模式。
二、Sandboxing:智能体的技术边界
沙箱是让 Codex 能够自主工作的前提——它定义了一个受约束的执行环境,Codex 可以在边界内自由行动,而不需要每一步都停下来请求确认。
2.1 沙箱的本质
沙箱作用于 Codex 派生的所有子进程,不仅限于 Codex 自身的文件操作。当 Codex 运行 git、包管理器、测试框架等工具时,这些命令都继承相同的沙箱边界。
核心思想:在明确的限制内给予智能体自主权。你不是在信任智能体的意图,而是在信任它运行在强制执行的限制之内。
2.2 三种沙箱模式
| 模式 | 文件访问 | 命令执行 | 网络访问 |
|---|---|---|---|
read-only | 只读,不能编辑任何文件 | 需审批才能运行命令 | ❌ 关闭 |
workspace-write(默认) | 工作区内可读写 | 常规本地命令自动执行 | ❌ 默认关闭 |
danger-full-access | 无文件系统限制 | 无限制 | ✅ 开启 |
--full-auto=workspace-write+on-request→ 低风险自动化预设,仍有沙箱保护- Full Access =
danger-full-access+never→ 移除所有保护,仅在可控环境中使用
workspace-write 模式的保护路径:
即使在默认的 workspace-write 模式下,以下路径始终被保护为只读:
<workspace>/.git(无论是目录还是 gitdir 指针文件,解析后的 Git 目录也受保护)<workspace>/.agents<workspace>/.codex- 保护是递归的——上述路径下的所有内容都不可写
2.3 平台原生实现
Codex 在每个操作系统上使用原生的安全机制来强制执行沙箱策略,而不是简单的软件层模拟:
| 平台 | 技术栈 | 实现机制 |
|---|---|---|
| macOS | Seatbelt 策略 + sandbox-exec | 动态构建 Seatbelt 策略文件(.sbpl),默认 deny-by-default,显式允许 PTY、基本系统调用和安全 sysctl。写入仅允许声明的 writable roots。网络规则仅在策略启用网络时追加 |
| Linux | Bubblewrap + seccomp | 默认使用 bubblewrap 管道配合 seccomp 过滤。use_legacy_landlock 可回退到旧版 Landlock 路径。托管代理模式下,出站流量通过 proxy-only bridge 路由,构建失败则关闭网络 |
| WSL | 继承 Linux 沙箱 | IDE 扩展支持直接在 WSL 中运行,继承 Linux 沙箱语义。VS Code 设置 chatgpt.runCodexInWindowsSubsystemForLinux = true |
| Windows | Windows 原生沙箱 | 使用 elevated(推荐)或 unelevated 模式。sandbox_private_desktop = true(默认)提供额外隔离 |
在容器化环境中,如果宿主机或容器配置不支持 Landlock/seccomp,沙箱可能无法工作。此时应让 Docker 容器本身提供隔离,然后在容器内使用 --sandbox danger-full-access 运行 Codex。
2.4 writable_roots:扩展可写范围
当 Codex 需要访问工作区之外的目录时(例如共享库路径、monorepo 的其他包),可以通过 writable_roots 扩展可写范围,而不需要移除整个沙箱:
[sandbox_workspace_write]
writable_roots = [
"/home/user/shared-libs",
"/opt/project/packages/common"
]这比直接切换到 danger-full-access 安全得多——你精确控制了额外开放的路径。
2.5 network_access:网络访问控制
默认情况下,workspace-write 模式关闭网络访问。需要时(如 npm install、pip install),Codex 会通过审批流程请求网络权限。
如果你的工作流频繁需要网络(如持续安装依赖),可以在配置中显式开启:
[sandbox_workspace_write]
network_access = true开启网络意味着子进程可以访问任意外部服务。结合 prompt injection 风险,恶意内容可能导致智能体下载并执行不可信代码。仅在你信任工作区内容时开启。
Codex Cloud 的网络模型不同:
云端环境使用两阶段模型——Setup 阶段可以访问网络(安装依赖),Agent 阶段默认离线。Secrets 仅在 Setup 阶段可用,Agent 阶段开始前被清除。
三、Approval Policy:何时暂停,何时放行
审批策略决定了 Codex 在遇到沙箱边界时的行为:是自动尝试、请求确认,还是直接失败。
3.1 三档审批策略
| 策略 | 行为 | 适用场景 |
|---|---|---|
untrusted | 仅已知安全的只读命令自动执行;任何可能修改状态的命令都暂停等待审批 | 高安全需求场景,或初次使用 Codex 时建立信任 |
on-request(默认) | 在沙箱内自由工作;需要越界时(如编辑工作区外文件、访问网络)才请求审批 | 日常开发的最佳平衡点,推荐使用 |
never | 永不暂停请求审批。Codex 在当前权限范围内尽力完成任务 | CI/CD 管道、自动化脚本等非交互环境 |
常见组合速查:
| 意图 | 命令行参数 | 效果 |
|---|---|---|
| Auto 预设(推荐) | --full-auto 或不加参数 | 工作区内自由读写和执行,越界时请求审批 |
| 安全只读浏览 | --sandbox read-only -a on-request | 只能读文件和回答问题,编辑/执行/网络都需审批 |
| CI 只读(非交互) | --sandbox read-only -a never | 只能读文件,永不暂停审批 |
| 自动编辑 + 审批命令 | --sandbox workspace-write -a untrusted | 可读写文件,但执行不可信命令前需审批 |
| 完全无限制(危险) | --yolo | 无沙箱、无审批(不推荐) |
3.2 /permissions:运行时切换
你不需要重启 Codex 就能改变权限级别。在 CLI 会话中使用 /permissions 命令即可实时切换:
- Codex App 和 IDE 扩展中,权限选择器位于输入框下方
- CLI 中使用
/permissions切换模式 /status可以查看当前工作区包含哪些目录
Codex 的智能推荐:
- 版本控制项目:启动时推荐
Auto(workspace-write + on-request) - 非版本控制目录:启动时推荐
read-only - 某些场景下,Codex 会以
read-only启动,直到你通过/permissions显式信任工作目录
3.3 Granular Approval:精细化审批
除了三档全局策略,Codex 还支持颗粒化审批,让你对不同类型的审批分别控制:
approval_policy = { granular = {
sandbox_approval = true, # 沙箱越界:交互式审批
rules = true, # Rules 匹配:交互式审批
mcp_elicitations = true, # MCP 工具调用:交互式审批
request_permissions = false, # 权限请求:自动拒绝
skill_approval = false # Skill 脚本:自动拒绝
}}3.4 MCP 与 App 工具的审批
Codex 的审批不仅限于 Shell 命令。对于 MCP 服务器和 App 连接器的工具调用:
- 标记为有副作用的工具调用会触发审批
- 标记为
destructive的工具调用始终需要审批,即使同时标记了 read-only
四、Rules:命令级的精细控制
当沙箱和审批策略的粒度不够时,Rules 提供了命令前缀级别的 allow / prompt / forbid 控制。
4.1 Rules 文件格式
Rules 使用 Starlark 语法(类 Python,但无副作用),文件位于 .codex/rules/ 目录下:
# ~/.codex/rules/default.rules
# 允许 git status 和 git diff 自动执行
prefix_rule(
pattern = ["git", ["status", "diff"]],
decision = "allow",
justification = "Safe read-only git commands",
)
# 运行 npm publish 前必须确认
prefix_rule(
pattern = ["npm", "publish"],
decision = "prompt",
justification = "Publishing to npm registry requires review",
)
# 禁止执行 rm -rf
prefix_rule(
pattern = ["rm", "-rf"],
decision = "forbidden",
justification = "Dangerous: use git clean instead",
match = ["rm -rf /tmp/build", "rm -rf node_modules"],
)4.2 决策优先级
当多条 Rules 同时匹配一个命令时,Codex 采用最严格优先原则:
forbidden > prompt > allow
这意味着即使你 allow 了 git add,如果另一条 rule forbid 了出现在同一 bash -lc 调用中的 rm -rf /,整个调用仍会被拒绝。
4.3 Shell 复合命令的安全处理
Codex 对 bash -lc "git add . && rm -rf /" 这类复合命令有特殊处理:
- 可安全拆分时(仅包含纯文字、
&&、||、;、|):Codex 使用 tree-sitter 解析,拆分为独立命令分别评估 - 不可安全拆分时(包含重定向、变量替换、通配符、控制流):整个调用作为一条命令评估
这防止了危险命令藏在安全命令后面偷偷执行。
4.4 Smart Approvals
当 Smart Approvals 启用时(默认开启),Codex 会在你遇到需要审批的命令时自动建议一条 prefix_rule。审查并接受后,该规则会写入 ~/.codex/rules/default.rules,后续同类命令自动放行。
4.5 测试 Rules
# 测试一条规则如何应用于特定命令
codex execpolicy check --pretty \\
--rules ~/.codex/rules/default.rules \\
-- gh pr view 7888 --json title,body,comments输出 JSON 格式的匹配结果,包含最严格的决策和所有匹配规则的 justification。
五、三者协同:Codex 的自主性-安全性框架
理解了三个概念之后,最关键的是理解它们如何协同工作:
协同逻辑总结:
- Sandboxing 定义技术边界——Codex 能触碰什么(文件、网络、目录)
- Approval Policy 定义暂停时机——越界时是自动处理、请求确认还是直接失败
- Rules 提供精细例外——在全局策略之上,对特定命令单独放行或禁止
- Prompting 驱动整个循环——高质量的提示词减少越界需求,让智能体在沙箱内就能完成更多工作
- 新项目:
read-only+on-request→ 先让 Codex 分析代码,建立理解 - 建立信任后:
workspace-write+on-request(默认 Auto 模式)→ 日常开发 - 定义 Rules:对常用命令
allow,对危险命令forbidden→ 减少审批疲劳 - 自动化场景:
workspace-write+never→ CI/CD 或脚本化执行 - 仅在可控环境中:
danger-full-access+never→ Docker 容器内的全自动任务