1. Codex 本地跑不起来?先搞懂 config.toml 沙盒与审批到底在管什么
Codex 是 OpenAI 推出的本地编码代理,能在你的终端里读代码、改文件、跑命令。它跟普通聊天模型最大的区别是:它真的会动你的磁盘。所以 Codex 设计了两套控制机制——沙盒(sandbox)和审批(approval)。沙盒决定 Codex 技术上能碰到什么,审批决定它越界前要不要停下来问你。这两者配合不好,就会出现两种极端:要么 Codex 什么都干不了,一直弹确认;要么它悄悄改了不该改的文件,你事后才发现。
这篇聚焦config.toml里沙盒模式与审批策略的配置,围绕local proxy failed、401这类常见报错展开。我会给出可直接复制的config.toml片段和AGENTS.md示例,并演示怎么一步步验证沙盒和审批行为是否真的生效。适合已经在用 Codex CLI、但被权限配置卡住的人。
先说清楚一个容易混的点:Codex 自己访问网络和沙盒里的命令访问网络是两回事。Codex 自带网页搜索工具,默认走缓存索引;而沙盒里执行的curl、pip install这类命令,默认在workspace-write模式下是断网的。很多人配了web_search = "live"却发现pip还是装不上,就是把这两个网络搞混了。
沙盒级别有三个:read-only只能看不能改;workspace-write能在工作区内读写和执行常规命令,这是本地开发的默认低摩擦模式;danger-full-access完全放开,文件系统和网络边界都没了。工作区包含当前目录和/tmp这类临时目录,但项目下的.git、.codex、.agent三个目录是保护目录,写之前仍然要问。
审批级别也有三档:untrusted对不在信任集合里的命令都要问;on-request默认在沙盒内跑,越界才提示;never不在审批处停留。理解这几个组合,是排查一切权限报错的基础。
2. 接入前的准备:TaoToken 的 Base URL、Key 与 Model ID 三件套
在动config.toml之前,先把模型接入这条链路打通。Codex 支持自定义模型提供商,通过model_providers配置块指定base_url和env_key。这里我用 TaoToken 作为接入端点来演示,因为它兼容 OpenAI 的接口格式,配置方式和官方文档一致。
你需要准备三样东西,我称之为三件套:Base URL、API Key、Model ID。Base URL 填https://taotoken.net/api,注意这个地址不带任何查询参数。API Key 在控制台的 API Keys 页面生成,生成后只显示一次,记得立刻保存。Model ID 填你实际要调用的模型标识,比如gpt-5.1这类。
关键点在于env_key这个字段。它不是让你把 Key 直接写进去,而是指定一个环境变量的名字,Codex 运行时去读这个环境变量的值。很多人第一次配的时候直接把 Key 填在env_key后面,结果报 401,就是因为这个字段的语义被误解了。
正确的做法是在终端里设置环境变量。Linux 或 macOS 下用export OPENAI_API_KEY="你的Key",Windows PowerShell 下用$env:OPENAI_API_KEY="你的Key"。设置完可以用echo $OPENAI_API_KEY确认一下有没有生效。如果你想让它在每次开终端时自动加载,就写进~/.bashrc或~/.zshrc。
如果你还没生成 Key,可以去控制台的 API Keys 页面创建:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=codex_config_guide 。生成后建议先在一个临时终端里 export 测试,确认能通再写进配置文件。
接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=codex_config_guide ,里面有完整的字段说明。如果你只是想先验证模型能不能通,可以用模型对话页面发一条消息试试:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=codex_config_guide 。这一步能排除掉 Key 本身的问题,避免后面把接入错误误判成沙盒问题。
3. 可复制的 config.toml 与 AGENTS.md 配置片段
配置文件的位置和优先级要先搞清楚。Codex 的解析顺序从低到高是:内置默认设置、系统配置(Unix 上是/etc/codex/config.toml)、用户配置~/.codex/config.toml、项目配置.codex/config.toml、Profile、--config命令行覆盖。优先级越高的越晚读取,直接覆盖之前的值。项目配置只有在项目被标记为受信任时才会参与解析,这一点后面排障会用到。
下面是一份可以直接抄的~/.codex/config.toml,我按接入加沙盒加审批的顺序组织:
# 模型接入三件套 model = "gpt-5.1" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "OPENAI_API_KEY" # 沙盒与审批 approval_policy = "on-request" sandbox_mode = "workspace-write" [sandbox_workspace_write] network_access = false writable_roots = [] # 网络搜索(Codex 自身的搜索工具,与沙盒命令网络无关) web_search = "cached" # 项目根目录标志 project_root_markers = [".git", ".hg", ".sl"] # 日志 log_dir = "/absolute/path/to/codex-logs" [features] multi_agent = true这份配置的意图是:沙盒内随便读写,越界操作走审批,沙盒命令默认断网。如果你确实需要沙盒里的命令联网,把network_access改成true,但要知道这意味着 Codex 执行的curl能访问外网。
AGENTS.md是给 Codex 的项目上下文指令。它会在每次会话启动时按顺序加载:先全局~/.codex/AGENTS.override.md或~/.codex/AGENTS.md,再从项目根目录向下遍历到当前工作目录,每个目录检查AGENTS.override.md、AGENTS.md以及project_doc_fallback_filenames里的备用名。每个目录最多加载一个文件,空文件跳过。
一个实用的AGENTS.md示例:
# 项目约定 ## 代码风格 - Python 使用 black 格式化,行宽 100 - 提交前必须跑 pytest ## 禁止操作 - 不要修改 migrations/ 目录下的历史迁移文件 - 不要执行 git push,推送由人工完成 ## 常用命令 - 测试:pytest -q - 类型检查:mypy src/在config.toml里可以调整加载行为:
project_doc_fallback_filenames = ["TEAM_GUIDE.md", ".agents.md"] project_doc_max_bytes = 65536project_doc_fallback_filenames的顺序是严格的,TEAM_GUIDE.md优先级高于.agents.md。project_doc_max_bytes控制所有加载上下文的总大小上限。
4. 逐步验证沙盒与审批是否真的生效
配完不等于生效,必须动手验证。我按从接入到沙盒到审批的顺序,给你一套可复现的验证动作。
第一步,验证模型接入。在终端里确认环境变量已设置,然后启动 Codex:
export OPENAI_API_KEY="你的Key" codex进入交互界面后,随便问一句让它读当前目录的文件。如果返回 401,说明 Key 或env_key有问题,先回到第 2 节检查。如果报local proxy failed,通常是base_url写错或网络不通,检查地址是不是https://taotoken.net/api,有没有多写斜杠或路径。
第二步,验证沙盒的读边界。在read-only模式下,让 Codex 尝试创建一个文件:
codex -c sandbox_mode="read-only"然后输入「在当前目录创建一个 test.txt」。它应该拒绝或请求审批,而不是直接创建。如果它直接创建成功了,说明沙盒没生效,检查是不是有更高优先级的配置覆盖了。
第三步,验证workspace-write的写边界。切回workspace-write,让它创建文件,应该能成功。再让它写工作区外的路径,比如/etc/test.txt,应该被拦下或请求审批。
第四步,验证审批策略。把approval_policy设成untrusted,然后让 Codex 跑一个不在信任集合里的命令,比如whoami。它应该弹审批。再设成never,同样的命令应该直接执行或直接拒绝,不会停下来问你。
第五步,验证AGENTS.md是否加载。直接问 Codex:「Summarize the current instructions.」如果它复述出你AGENTS.md里的约定,说明加载成功。注意 0.120.0 有个已知 bug,/status可能显示没加载AGENTS.md,但实际是加载了的,用这个提问法验证更可靠。
第六步,验证沙盒命令网络。在network_access = false下,让 Codex 执行curl https://example.com,应该失败。改成true后重试,应该能通。这一步能帮你区分是 Codex 搜索的问题还是沙盒命令网络的问题。
5. 常见报错排查:401、local proxy failed、reading choices 与 OAuth
排障的核心思路是:先分清是接入层的问题还是沙盒层的问题。接入层的报错通常跟 Key、Base URL、Model ID 有关;沙盒层的报错通常跟权限、路径、审批有关。
401 Unauthorized 是最常见的。原因基本是三类:env_key指定的环境变量没设置或拼错;Key 本身失效或复制时带了空格;base_url指向的端点不认这个 Key。排查时先在终端echo $OPENAI_API_KEY确认变量有值,再用模型对话页面单独测一次 Key 是否有效。如果对话页面能通、Codex 报 401,那就是config.toml里env_key的名字和实际环境变量名对不上。
local proxy failed通常出现在base_url配置有问题时。检查地址是不是完整的https://taotoken.net/api,有没有漏掉协议头,有没有多余的路径。如果你在model_providers里配了http_headers或env_http_headers,也要确认这些头没有冲突。
reading choices这类报错一般出现在流式响应解析阶段。可能是stream_max_retries或stream_idle_timeout_ms设置不合理,也可能是中间网络不稳定。可以先调大重试次数:
[model_providers.taotoken] request_max_retries = 4 stream_max_retries = 10 stream_idle_timeout_ms = 300000OAuth 相关报错多出现在用官方账号登录的场景。如果你走的是自定义 provider 加 API Key 的路线,一般不会碰到 OAuth。如果碰到了,检查是不是有残留的登录态在干扰,清理后重新用 Key 接入。
还有一个隐蔽的坑:项目配置.codex/config.toml只有在项目受信任时才生效。如果你在项目里放了配置但没生效,检查~/.codex/config.toml里有没有设置projects.<path>.trust_level。没设的话,项目配置会被忽略,你改的东西自然不起作用。
沙盒相关的报错,比如「operation not permitted」,通常是writable_roots没包含目标路径。如果你需要 Codex 读写工作区外的目录,把它加进去:
[sandbox_workspace_write] writable_roots = ["/path/to/another/dir"]审批相关的困惑,比如「为什么它一直问我」,多半是approval_policy设成了untrusted。想减少打扰就改成on-request,想完全不问就never,但要清楚never意味着越界操作直接失败而不是执行。
6. 长期编码与 Agent 场景下的配置建议
如果你只是偶尔用 Codex 改改代码,上面这套配置够用了。但如果你打算把它当成日常编码代理,甚至跑多代理协作,有几个配置值得调。
多代理场景下,[agents]块控制并发和嵌套:
[agents] max_threads = 6 max_depth = 1max_threads是最多同时开多少个子代理,默认 6。max_depth是子代理嵌套深度,默认 1,也就是子代理不能再开子代理。调大这两个值会显著增加资源消耗和审批请求的数量,建议先用默认值跑一段时间再决定。
子代理的审批有个细节:在交互式 CLI 里,批准请求可能从非活动线程冒出来,覆盖层会显示源线程标签,你可以按o打开那个线程再决定。在非交互式流程里,需要新批准的操作会直接失败,错误反馈给父工作流。所以如果你在 CI 或脚本里跑 Codex,approval_policy要设成never,否则会卡住。
长期使用建议把log_dir指到一个固定位置,方便回溯:
log_dir = "/absolute/path/to/codex-logs"也可以用命令行临时覆盖:codex -c log_dir=./.codex-log。日志里具体有哪些字段官方没完整说明,但排查问题时翻一翻通常能找到线索。
如果你需要更稳定的编码代理体验,可以考虑 Coding Plan,它在并发和额度上更适合长期跑:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=codex_config_guide 。配合AGENTS.md把项目约定写清楚,Codex 的行为会稳定很多。
最后提醒一个我踩过的坑:web_search别默认开live。Codex 在明确需要搜索时才该联网,否则它会到处搜,既慢又费额度。设成cached或disabled,需要时再临时开。沙盒命令的网络访问同理,network_access = false是更安全的默认值,真要装依赖时再开,装完关掉。