尧图精选

Codex本地Agent配置详解:模型、TOML与AGENTS.md优先级

🕒 发布时间:2026/10/1 7:12:07 📁 来源:尧图网络
在本地跑 Codex 的朋友应该都有同感装好 CLI 只是开始真正让它按你的想法干活绕不开模型配置、TOML 文件和 AGENTS.md 这三件事。我最初只是想给 Codex 换一个成本更低的模型结果顺手把本地自定义 Agent 的整套配置逻辑摸了一遍期间还踩了 cc switch local proxy failed while handling codex endpoint /responses 这个坑最后才搞明白 model、provider、wire_api 三者之间是怎么协同的AGENTS.md 的优先级规则又是怎么定死的。这篇就把配置项之间的关系、第三方模型的接入流程、以及本地指令的优先级一次讲透。适合刚接触 Codex CLI、或者已经能跑通但想深度定制的朋友也欢迎已经踩过坑的来对照验证。1. 先搞清楚本地自定义 Agent到底自定义了什么1.1 Codex CLI 和网页版 Agent 的本质区别Codex CLI 是跑在终端里的编码代理往大了说它就是你本地自定义 Agent 的载体。网页版 Agent 的模型、工具、运行环境全在服务端你只能在界面里发指令很难干预它的决策细节而 Codex CLI 的工作循环是在本地发生的——它读取本地文件、执行终端命令、按指令规划步骤每一步你都能看到。这个差别意味着自定义的空间完全不同你可以换掉它的模型、定义它的行为规范、甚至通过配置文件给它接上不同的模型供应商。换句话说Codex CLI 的本地属性让它从一个 AI 工具变成了一台可以由你装配的 Agent 工作机。不过这里要泼一盆冷水本地自定义并不等于无限自由。Codex CLI 的输出质量 模型能力 指令约束 环境权限 三者相乘。模型换得再好如果 AGENTS.md 写得一团糟它照样会在代码风格、文件组织上放飞自我反过来你再怎么精心设计指令基础模型能力不够推理照样会跑偏。所以下面聊配置的时候我会一直强调模型、指令、权限要一起看。1.2 本地配置的三层结构具体到落地本地自定义 Agent 主要动三样东西用户级全局配置~/.codex/config.toml存放模型、API 密钥、默认行为等所有项目共用。项目级配置项目根目录下的codex.toml或.codex/config.toml专属于当前仓库可以用--config显式指定。指令文件AGENTS.md一份给 Agent 看的员工手册。全局版放在~/.codex/AGENTS.md项目版放在仓库根目录子目录里也可以放小范围的补充版。初次接触很容易把这三层搞混尤其是项目级配置和指令文件的边界。我自己的理解是config.toml 管的是用什么模型、连哪个 API、权限怎么给AGENTS.md 管的是面对这个项目时你的工作方式、代码规范、哪些事坚决不能做。一个是硬件装配一个是价值观输出。1.3 你能自定义的四个变量如果把这套体系再抽象一层任何本地 Agent 其实都在你手里这四个变量上滑动模型用 OpenAI 官方模型还是 DeepSeek、Qwen、Kimi 这些兼容 OpenAI 协议的第三方模型。供应商模型跑在哪家的 API 上base_url 指向哪里、拿哪个环境变量做密钥。指令通过 AGENTS.md 注入项目背景、编码规范、行为边界。工作流CLI 的参数、沙盒权限、MCP 工具、环境变量传递。这四个变量排列组合起来就能得到差异很大的行为。我见过有人把 Codex 配成只读代码审查员也有人配成能自动跑测试并修复失败用例的流水线工人还有人在同一台机器上同时维护三套 config对应不同项目风格。这些都不是魔法就是把上面四个变量的优先级和值调好了而已。2. config.toml 里能写什么model、model_provider 与 wire_api 的三方关系2.1 配置文件怎么被加载Codex CLI 默认读~/.codex/config.toml。如果你在项目根目录放了codex.tomlCLI 会把它和用户级配置做合并项目级覆盖用户级命令行参数优先级最高能直接盖过文件里的同名字段比如codex --model gpt-5会覆盖配置文件里的 model 字段。这个优先级顺序我实测是稳定生效的排查我改了配置怎么不生效的问题第一件事永远是确认有没有更高层级的配置在覆盖你。小技巧不确定当前生效的是什么跑codex --show-config或者看 CLI 启动时的调试输出它会打印最终合并结果比自己翻文件猜靠谱得多。2.2 最简配置一个 model 字段就够了如果你用官方模型不走任何第三方config.toml 里甚至可以只有一行model gpt-5登录方式也简单先codex login走 OpenAI 账号或者用环境变量OPENAI_API_KEY。但相信我只要是折腾本地自定义 Agent 的人用不了两天就会碰到我想换更便宜的模型这个需求于是 model 字段背后的坑就来了。2.3 model_provider 打开的自定义空间换第三方模型的时候光写model deepseek-chat是不够的。Codex 需要一个供应商描述来知道这个模型该往哪里发请求、用哪个密钥、走什么协议。在 config.toml 里的写法是model deepseek-chat model_provider deepseek [model_providers.deepseek] name deepseek base_url https://api.deepseek.com/v1 env_key DEEPSEEK_API_KEY wire_api chat这里有几个字段要逐个说清楚name供应商名字自己起只要能对应上就行。base_urlAPI 的根地址。Codex 会在后面拼接具体的端点路径。env_key告诉 Codex 从哪个环境变量读取密钥而不是硬编码在配置文件里。这是好习惯因为 config.toml 一旦误提交到 Git 仓库密钥就全裸奔了。wire_api这是最容易踩坑的字段也是我接下来要单独讲的。2.4 wire_apiresponses 还是 chat决定你能不能连通OpenAI 自己的模型走的是 Responses 协议端点通常是/responses而绝大多数第三方模型包括 DeepSeek、很多开源模型的托管 API只兼容 OpenAI 的 Chat Completions 协议端点是/v1/chat/completions。Codex 默认假设模型供应商支持 Responses 协议。如果你没设置wire_api它会按/responses路径发请求第三方服务根本不认识这个路径直接报错。解决办法就是显式声明协议wire_api chat设置之后Codex 会改用 Chat Completions 协议和第三方 API 通信。我把这两者的区别整理成了表格方便对照项目Responses 协议Chat Completions 协议典型端点/responses/v1/chat/completions原生支持OpenAI 官方模型大多数兼容 OpenAI 接口的第三方配置字段wire_api responseswire_api chat常见场景默认配置、官方模型DeepSeek、Qwen 等第三方接入简而言之model 决定选谁model_provider 决定去哪连wire_api 决定用什么语言说话。三者配合错任何一个结果都是连不通或者返回格式解析失败。3. 接 DeepSeek 的完整链路配置、报错再到 cc-switch 管理3.1 为什么我选 DeepSeek 作为本地 Agent 的默认模型选择第三方模型的目的不外乎两点成本、可用性。DeepSeek 的 token 单价低中文和代码能力在开源模型里属于第一梯队上下文窗口也够日常项目用。对我这种要长时间开着 Codex 跑任务的人来说成本优势非常明显。另外把模型从官方账号切到第三方 API登录态的管理也更直接不存在账号登录过期导致的工作流中断。要特别说明的是第三方模型不是免费的午餐。DeepSeek 虽然便宜但它在某些复杂推理任务上和 OpenAI 旗舰模型还有差距。我的建议是粗活累活代码格式整理、按模板生成文件、测试用例补写交给第三方高难度重构再切回官方模型。这就是为什么后面要聊 cc-switch 这种配置切换工具。3.2 从零到能对话的完整配置接 DeepSeek 的步骤其实很短但每一步都有讲究。这是我的完整操作从 DeepSeek 开放平台拿到 API key。写入环境变量export DEEPSEEK_API_KEY你的key建议写进 shell 的配置文件比如~/.zshrc。在~/.codex/config.toml里配置供应商和默认模型model deepseek-chat model_provider deepseek [model_providers.deepseek] name deepseek base_url https://api.deepseek.com/v1 env_key DEEPSEEK_API_KEY wire_api chat随便在终端跑一个任务cd /tmp codex 用 Python 写一个读取 CSV 的小工具。正常情况下看到 Codex 开始拆解任务、逐文件操作就算通了。但如果你和我一样是在已有其他配置的基础上改的大概率会撞上下面这个报错。3.3 cc switch local proxy failed while handling codex endpoint /responses 完整排查这是我在这篇文章里最想写的坑。现象是切换配置之后Codex 每次发请求都在处理/responses端点时失败报错里还带了一句 cc switch local proxy failed。先说报错里的 local proxy 指什么它一般指你配置里指定的本地端点转发服务也就是 base_url 指向的那个进程。很多人在自建 API 网关或者调试流量时会引入一个本地转发层Codex 的请求先到这个本地服务再由它转给真正的模型 API。这个转发层一旦没起来、端口配错、或者它自己不认/responses路径你就会看到这类报错。我当时的排查链路是这样的建议你也按顺序来确认 base_url 指向的服务在线。如果 base_url 写的是http://127.0.0.1:端口先看那个进程有没有在跑。我那次就是切配置时把端口改掉了转发服务听着老端口Codex 自然连不上。直接 curl 验证端点。curl http://127.0.0.1:端口/responses看看返回什么。这能把网络不通和协议不匹配快速分开。检查 wire_api 是否匹配供应商。Codex 默认走responses路径如果你的转发层背后是只支持 chat 的第三方 API就得在 config.toml 里写wire_api chat。否则即使服务在线它也不认识/responses这个请求。看转发层日志。本地转发服务通常会打印收到的请求路径和转发目标一眼就能看出 Codex 实际请求的是哪个端点、转发目标是不是配错了。我这次问题最终落在 wire_api 上。配置里残留的旧供应商声明把协议撑成了默认的 responses而本地转发层和后端都只支持 chat请求自然死在中途。把wire_api chat显式写好之后报错立刻消失。另外也建议给转发层加一条路由把/responses请求转换成 chat 协议的请求这样两边都舒服。一个小提醒如果你根本没有自建任何转发服务却在 config.toml 里看到了127.0.0.1开头的 base_url那大概率是从某个教程或切换工具里继承来的残留配置直接改成官方 API 地址即可。3.4 用 cc-switch 管理多套模型配置本地自定义 Agent 一旦跑起来你会发现自己可能有两三套配置一套连官方、一套连 DeepSeek、可能还有一套连内部模型。手动改 config.toml 很容易改乱这时候 cc-switch 这类工具就有用了。cc-switch 是一个管理 Codex / Claude Code 配置切换的小工具它做的事情本质上是把你要的 provider、model、base_url、env_key 组合存成一套配置预设需要时一键切换帮你重写对应的配置文件。用完它之后你会感觉换模型从编辑文件变成点按钮。使用时有两点注意。第一cc-switch 切换时会重写~/.codex/config.toml如果你在里面写了自定义的复杂配置比如多个 provider 或沙盒设置切换前最好先备份或者把自定义部分也补录进 cc-switch 的预设里。第二切换完务必检查最终生成的配置里有没有多余的 base_url 或没用的环境变量残留避免出现上一节那种端口、路径不匹配的诡异报错。4. AGENTS.md 的优先级项目规矩和全局规矩打架时听谁的4.1 AGENTS.md 是给 Agent 看的员工手册AGENTS.md 的作用不是给人类看的文档而是给 Agent 读的指令文件。你希望 Codex 在项目里怎么工作、遵守什么规范、什么操作绝对禁止、常用命令是什么都可以写进去。它和 README.md 的区别就在这里README 描述项目是什么AGENTS.md 描述 Agent 在项目里怎么干活。Codex 启动时会自动加载 AGENTS.md不需要你在提示词里引用它。官方约定的路径有全局和项目两种全局~/.codex/AGENTS.md作用于所有项目。项目仓库根目录的AGENTS.md以及各级子目录里的AGENTS.md。4.2 加载顺序和优先级规则关于 AGENTS.md最容易被误解的就是优先级问题。我最早以为文件越多越好所有规则都会生效实践下来完全不是这样。Codex 的加载规则大致是从当前工作目录开始逐级向上找 AGENTS.md然后再加上用户全局的 AGENTS.md。多条规则之间是合并关系并不冲突的约束会全部生效。同一条约束出现冲突时越靠近当前工作目录、描述越具体的文件优先。也就是说项目根目录的规则优先生效于~/.codex/AGENTS.md子目录的规则又优先生效于项目根目录。这个就近优先的原则非常好用。举个例子全局 AGENTS.md 里写死Python 代码统一用空格缩进但某个项目根目录的 AGENTS.md 规定该项目统一用 Tab 缩进那么 Codex 在这个项目里就会按 Tab 干活因为它读到的最近指令把更通用的指令覆盖掉了。但要注意覆盖不是无条件的。涉及安全红线的规则比如不得直接执行删除关键目录的命令即便只出现在某一个层级的 AGENTS.md 里Codex 也会很谨慎地遵守。这类约束不会被更大范围但更弱的规范冲掉。我的理解是安全提醒属于模型内置的强约束文件里的普通风格偏好在弱约束层面互相覆盖。4.3 冲突实例全局说左项目说右再补一个实战里经常看到的冲突场景。假设全局 AGENTS.md 写了IMPORTANT - 所有提交信息必须使用英文而某仓库的 AGENTS.md 写了- commit message 统一使用中文描述结果会怎样实测下来项目级会赢Codex 提交时写中文。因为项目文件离任务更近对整个任务的上下文有更强的约束力。如果你想让某条规则无论如何都生效我的经验是在文字层面做足功夫比如用大写IMPORTANT开头、写明这是不可覆盖的强制规则并且同时在项目级文件里再写一遍。多层级重复声明比单层级的权重声明更可靠。4.4 一份能让你少走弯路的 AGENTS.md 模板说了一堆规则不如给一份我能直接复制的模板。我给常用项目写 AGENTS.md 时结构基本固定# AGENTS.md ## 项目背景 这是一个基于 Python 3.12 的 CLI 工具仓库使用 uv 管理依赖。 ## 编码规范 - Python 代码使用 4 空格缩进行宽 100。 - 类型标注必须完整函数必须有 docstring。 - 禁止引入未经验证的新依赖。 ## 常用命令 - 运行测试uv run pytest tests/ - 代码格式化uv run ruff format . - 类型检查uv run mypy src/ ## 重要约束 IMPORTANT - 不允许修改 tests/ 下的文件来迎合实现。 - 任何重构必须先运行测试再给出结论。 - 删除文件前必须列出来交给用户确认。这份模板里最重要的是最后一段重要约束。别小看它模型对先运行测试再下结论删除前确认这类强约束的遵守程度决定了 Agent 到底是帮你干活还是给你添乱。模板本身不复杂但每次花五分钟把这段写好后面能省下大量收拾残局的时间。5. 组装一个完整的本地实战 Agent从配置文件到运行复盘5.1 目标做一个代码审查 Agent理论讲了不少做一个完整的实战项目才有感觉。我最近给一个旧仓库定制了一个代码审查 Agent需求是审查未提交的 diff按照仓库既有风格提意见最终输出一份 markdown 报告。这个过程正好把前面讲到的模型、TOML、AGENTS.md 全部用上。分工是这样的模型和供应商审查任务不需要特别深的推理成本要低选 DeepSeek。AGENTS.md定义审查清单、禁止事项、报告输出格式。config.toml把模型、供应商、协议串起来。命令行用codex 开始审查这类固定话术触发。5.2 完整配置与启动方式~/.codex/config.toml长这样model deepseek-chat model_provider deepseek [model_providers.deepseek] name deepseek base_url https://api.deepseek.com/v1 env_key DEEPSEEK_API_KEY wire_api chat项目根目录的AGENTS.md浓缩版# AGENTS.md ## 审查任务说明 审查每次请求时的 git diff重点关注 - 变更是否符合项目现有架构分层。 - 是否缺少单元测试或测试是否只覆盖正例。 - 是否引入不必要的全局状态。 ## 上报格式 - 问题清单按 严重 / 建议 两级分类。 - 每条意见必须给出文件路径与行号。 - 结尾给出总体结论可以合并 / 需要修改后合并。 ## 重要约束 IMPORTANT - 不要直接修改代码只输出审查报告。 - 如果 diff 为空直接说明无事可做不要猜测。启动方式很简单export DEEPSEEK_API_KEYxxx cd 项目目录 codex 审查当前工作区的改动输出 markdown 报告5.3 运行复盘我实际撞到的几个问题配置跑通不等于万事大吉。我把实测过程中最有代表性的问题列出来这些都是你们大概率也会碰到的。codex auth token is unavailable这个报错几乎可以肯定是认证信息没被读到。排查顺序先确认环境变量真的存在echo $DEEPSEEK_API_KEY再看 config.toml 里的env_key名字是否和它完全一致最后确认没有别的配置把环境变量覆盖掉。我自己有一次是大小写写错了Codex 读不到折腾了十分钟。agent execution terminated due to error这个通常是 Agent 在执行某个终端命令时出错并终止了任务比如 pytest 找不到模块、目录权限不足。解决办法是看它执行到哪一步失败了然后给它更明确的工作目录或恢复指令。不要急着换模型多半不是模型问题而是任务上下文没说清。显示更新 agent 沙盒Codex 的沙盒机制如果提示更新把 CLI 升级到最新版就行。沙盒的作用是隔离 Agent 执行的命令避免它对系统造成不可控的影响建议日常使用保持沙盒开启。在 config.toml 里可以设置权限边界一般用只读或工作区可写两档就够了除非你明确需要 Agent 安装依赖、修改系统配置否则不要轻易给完全访问权限。并发和限流问题本地同时开多个 Agent 会话时第三方 API 通常不限制并发但要注意两点一是 token 消耗会快速上涨二是部分 API 有 RPM/TPM 限制容易在峰值时触发 429。我的做法是写一个非常小的队列脚本一次只让两个会话在跑高优先级的任务插队。对多数人的日常使用人工控制一次只开一两个会话反而是最有效的。5.4 稳定运行后的参数调优跑稳定之后我开始做减法。第一个发现是 AGENTS.md 别写太长。模型确实会读但动辄几十条的规范会稀释重点它更倾向于遵守开头和结尾的规则。我最后把审查项目的 AGENTS.md 压缩到二十多行效果反而更好。第二个发现是让 Agent 先做计划再动手。在任务里加一句先列出执行步骤分步进行比直接让它一股脑做完要稳定得多。这个习惯对推理能力中等偏上的模型都有效DeepSeek 也不例外。第三个发现是本地自定义 Agent 的稳定性瓶颈往往在 API 端点的稳定性而不是模型本身。响应超时、连接重置这类问题重试一两次通常就好了。代码审查这种任务重试成本很低放心大胆重跑。折腾完这一整套我的感想是Codex 本地自定义 Agent 的门槛不在模型选择而在配置体系的完整性。TOML 决定它能不能连上正确的模型AGENTS.md 决定它会不会用正确的方式工作优先级规则决定两者冲突时谁说了算。这三件事理顺了自定义 Agent 其实就是把好用的模型 清晰的指令 合适的权限组合起来的体力活。我现在的习惯是每接入一个新模型先写一小段基线问题集去试再用 cc-switch 固化一套配置每进入一个新项目先把项目 AGENTS.md 写好再让 Agent 介入。如果你也打算深度定制建议从一个小而具体的场景比如帮我按规范审查代码入手先跑通再慢慢加规则。这套流程我已经用了几个项目稳定性和可控性都达到了能日常使用的水平。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →