
1. 从一次配置不生效的排查说起如果你正在用 Codex 做本地 Agent 开发大概率遇到过这种场景明明在配置文件里改了模型参数重启之后行为却完全没变或者项目根目录放了一份AGENTS.md但 Agent 就是看不见里面的指令。我第一次碰到这个问题时花了整整一个下午在日志里翻找最后才发现是配置优先级搞反了——全局配置把项目级配置给覆盖了。Codex 的本地自定义 Agent 与模型配置核心其实就三件事TOML 配置文件怎么写、AGENTS.md 放在哪、以及当多处配置冲突时谁说了算。这三件事听起来简单但真正踩过坑的人都知道细节里全是门道。TOML 的字段层级、AGENTS.md 的加载范围、模型配置的优先级链条任何一环理解偏差都会导致改了没反应或者行为诡异。这篇内容适合三类人刚装好 Codex 想跑通第一个自定义 Agent 的新手、被配置优先级坑过的中级开发者、以及想给团队统一 Agent 行为规范的工程负责人。我会从实际排查链路出发把 TOML 结构、AGENTS.md 机制、优先级规则讲透并给出可以直接抄的配置模板和验证方法。全程按为什么这么设计来讲而不是只丢一堆字段让你背。在开始之前先明确一个概念Codex 这里的Agent指的是在本地通过配置文件定义的一套行为单元它包含模型选择、工具权限、系统提示词、上下文加载规则等。而模型配置则是决定这个 Agent 调用哪个模型、用什么参数、走哪个端点的部分。两者通过 TOML 和 AGENTS.md 两个载体来落地理解它们的协作方式是关键。2. TOML 配置文件的结构与字段逻辑2.1 为什么选 TOML 而不是 JSON 或 YAMLCodex 用 TOML 作为主配置格式这个选择不是随便定的。JSON 不支持注释配置里想写个这行是干嘛的都做不到YAML 缩进敏感一个空格错位就整个解析失败而且深层嵌套时容易出歧义。TOML 刚好卡在中间支持注释、层级用[section]明确划分、数据类型直观对配置文件这种人写机器读的场景非常合适。实际用下来TOML 最大的好处是可读性和可维护性。团队协作时新人打开配置文件能一眼看懂结构不用去猜缩进层级。而且 TOML 的[table]语法天然适合表达某个 Agent 的某类配置这种嵌套关系。2.2 核心配置区块拆解一份典型的 Codex 本地配置通常包含以下几个区块。我按实际使用频率排序# 全局默认模型配置 [model] provider openai name gpt-4o temperature 0.7 max_tokens 4096 # Agent 定义 [agents.default] description 通用开发助手 model gpt-4o instructions_file AGENTS.md # 工具权限 [tools] allow_shell true allow_file_write true allowed_paths [./src, ./tests] # 端点配置 [provider.openai] base_url https://api.example.com/v1 api_key_env OPENAI_API_KEY这里每个字段都有讲究。[model]区块定义的是兜底配置当某个 Agent 没有单独指定模型时就用这里的。temperature控制输出随机性做代码生成建议 0.2-0.4做创意类任务可以到 0.8。max_tokens要根据模型上下文窗口留余量别设成窗口上限否则长对话容易截断。[agents.xxx]是 Agent 定义区每个子表就是一个独立 Agent。instructions_file指向该 Agent 的系统提示词文件这就是 AGENTS.md 的入口。[tools]区块控制 Agent 能干什么allowed_paths是安全边界强烈建议显式列出允许访问的目录而不是图省事写[/]。[provider.xxx]定义模型服务端点。api_key_env用环境变量名而不是直接写密钥这是基本安全习惯。把密钥硬编码进配置文件一旦文件进了版本库就是事故。2.3 字段类型与常见写法陷阱TOML 的类型系统比想象中严格。字符串必须用引号布尔值是小写true/false数组用方括号。我见过最常见的错误是把temperature 0.7写成temperature 0.7字符串和浮点数在某些解析器里不会自动转换结果就是配置静默失效。另一个坑是数组的追加语义。有些配置项在多层配置合并时是追加而不是覆盖比如allowed_paths。如果你在全局配了[./src]在项目级又配了[./tests]最终生效的可能是两个路径的并集而不是你以为的覆盖。这个行为在不同版本里可能有差异验证方法永远是看实际生效结果而不是猜。提示改完 TOML 后先用配置校验命令跑一遍别直接启动 Agent。语法错误在启动时可能只报一行模糊的错定位起来很痛苦。2.4 一个可直接复用的多 Agent 配置模板下面这份模板是我在实际项目里沉淀下来的包含一个通用 Agent、一个专注代码审查的 Agent、一个文档生成 Agent[model] provider openai name gpt-4o temperature 0.3 max_tokens 8192 [agents.general] description 通用开发助手 instructions_file agents/general.md model gpt-4o [agents.reviewer] description 代码审查专用 instructions_file agents/reviewer.md model gpt-4o temperature 0.1 [agents.writer] description 文档生成 instructions_file agents/writer.md model gpt-4o temperature 0.6 [tools] allow_shell true allow_file_write true allowed_paths [./src, ./docs, ./tests] [provider.openai] base_url https://api.example.com/v1 api_key_env OPENAI_API_KEY注意reviewer的temperature设成了 0.1因为代码审查要的是稳定、可复现的判断不需要发散。writer设成 0.6文档需要一定的表达灵活性。这种按 Agent 职责差异化配置参数是让 Agent 真正好用的关键而不是所有 Agent 共用一套参数。3. AGENTS.md 的加载机制与作用范围3.1 AGENTS.md 到底解决什么问题TOML 负责机器怎么跑AGENTS.md 负责Agent 怎么想。前者是结构化配置后者是自然语言指令。把系统提示词单独抽成 Markdown 文件好处有三一是提示词可以写得很长很详细不受 TOML 字符串转义的折磨二是 Markdown 天然支持标题、列表、代码块写复杂指令时结构清晰三是提示词文件可以独立做版本管理和评审。AGENTS.md 的内容通常包括Agent 的角色定位、工作流程、输出格式要求、禁止事项、可用工具说明。它不是随便写写就行的写得好的 AGENTS.md 和写得差的Agent 表现能差出一个量级。3.2 文件位置决定加载范围这是最容易踩坑的地方。AGENTS.md 的加载遵循就近原则但具体行为取决于你放在哪放置位置作用范围典型用途项目根目录整个项目项目级通用规范子目录该目录及子目录模块级特殊规则用户配置目录所有项目个人全局偏好Agent 专属路径单个 Agent特定 Agent 指令项目根目录的 AGENTS.md 是最常见的。当 Agent 在项目里工作时会自动加载根目录的这份文件作为基础指令。如果你在某个子目录也放了 AGENTS.md进入该目录工作时子目录的规则会叠加或覆盖根目录的规则——具体是叠加还是覆盖取决于实现版本必须实测确认。我个人的经验是根目录放通用规范子目录只在确实需要特殊行为时才放。滥用子目录 AGENTS.md 会导致行为难以预测排查问题时你都不知道当前生效的是哪一份。3.3 一份高质量 AGENTS.md 的写法很多人写 AGENTS.md 就是几句话你是一个编程助手请帮我写代码。这种指令等于没写。好的 AGENTS.md 应该像给新员工的入职手册具体、可执行、有边界。# 角色 你是一名资深后端工程师专注于 Python 服务开发。 # 工作流程 1. 收到需求后先复述你的理解确认无误再动手 2. 修改代码前先说明你要改哪些文件、为什么 3. 每次只做一件事不要一次性大改 # 输出规范 - 代码块必须标注语言 - 涉及文件路径时使用相对路径 - 不确定的地方明确说不确定不要编造 # 禁止事项 - 不要删除现有测试 - 不要修改配置文件中的密钥相关字段 - 不要执行网络请求类命令这份指令的价值在于可验证。Agent 是否复述了理解、是否说明了改动范围、是否标注了语言都是可以检查的。模糊的指令无法验证也就无法改进。3.4 指令冲突时的处理思路当 TOML 里的配置和 AGENTS.md 里的指令出现矛盾时比如 TOML 说allow_shell false但 AGENTS.md 里写你可以执行 shell 命令以谁为准答案是以 TOML 为准。TOML 是硬性约束AGENTS.md 是软性引导。工具权限、路径限制这类安全相关的配置永远由结构化配置说了算自然语言指令不能突破这个边界。这个设计很合理——如果提示词能绕过权限控制那权限控制就形同虚设了。理解这一点后你就知道该怎么分工安全边界、模型参数、工具开关放 TOML角色设定、工作流程、输出风格放 AGENTS.md。两者各司其职不要混着写。4. 配置优先级谁覆盖谁怎么验证4.1 优先级链条的完整梳理Codex 的配置优先级从高到低大致是这样的命令行参数启动时显式传入的优先级最高项目级配置项目目录下的 TOML 和 AGENTS.md用户级配置用户主目录下的全局配置系统级默认内置的兜底值这个链条的逻辑是越具体越优先。项目级比用户级具体所以项目级覆盖用户级。命令行参数最具体所以最高。但实际使用中合并策略比优先级本身更复杂。有些字段是整体覆盖有些是深度合并有些是追加。比如模型名是整体覆盖工具权限可能是合并路径列表可能是追加。这就是为什么我明明改了配置却没生效——你以为的覆盖实际是合并。4.2 一个真实的排查链路说个我实际遇到的案例。当时项目里配了temperature 0.2但 Agent 输出明显很发散感觉像 0.8 的效果。排查过程是这样的第一步确认项目级配置有没有被加载。在项目根目录跑配置查看命令输出里temperature显示的是 0.2说明项目配置读到了。第二步检查用户级配置。打开用户主目录的配置文件发现里面也有一份[model]区块temperature 0.8。问题来了——两份配置都有temperature到底哪个生效第三步实测验证。把项目级的temperature改成 0.1重启 Agent输出依然发散。这说明用户级配置覆盖了项目级和预期的优先级链条相反。第四步查文档和版本说明。发现当前版本对[model]区块的处理是用户级优先只有[agents.xxx]区块才是项目级优先。这是个版本相关的行为差异。第五步解决方案。把temperature从全局[model]挪到具体 Agent 的配置里因为 Agent 级配置的优先级是明确的。改完后行为符合预期。这个案例的教训是不要假设优先级规则在所有配置区块里都一致。不同区块可能有不同的合并策略唯一可靠的办法是实测。4.3 验证配置生效的标准方法与其猜不如建立一套验证流程。我现在的习惯是改配置前先记录当前行为比如跑一个固定输入看输出改配置后用同样的输入再跑一次对比差异确认改动生效如果没生效逐层排查命令行 → 项目级 → 用户级 → 默认值对于模型参数这类不好直接观察的配置可以临时设一个极端值来验证。比如把temperature设成 0 和 1输出差异会非常明显一眼就能看出配置有没有生效。验证完再改回正常值。注意验证时用固定输入别用随机输入。输入变了输出差异就分不清是配置导致的还是输入导致的。4.4 优先级设计的工程意义为什么要有这么复杂的优先级因为不同场景需要不同的控制粒度。个人开发者可能希望全局配一套顺手的参数个别项目再微调。团队协作时项目级配置要能强制统一行为不能被个人全局配置覆盖。CI 环境里命令行参数要能临时覆盖一切方便做测试。理解了这层设计意图配置冲突时你就知道该往哪一层放想影响所有项目就放用户级想只影响当前项目就放项目级想临时测试就用命令行。放对层级比调对参数更重要。5. 模型配置的实战细节与常见故障5.1 模型选择与参数搭配模型配置不是填个名字就完事。不同任务对模型能力的要求不同参数搭配也不同。下面是我总结的常见场景配置场景推荐 temperaturemax_tokens说明代码生成0.2-0.44096-8192要稳定不要发散代码审查0.0-0.24096要可复现的判断文档撰写0.5-0.78192需要表达灵活性需求分析0.3-0.54096平衡准确与发散头脑风暴0.8-1.04096要的就是多样性max_tokens的设置有个经验法则不要超过模型上下文窗口的 1/4。因为输入也要占空间如果输出上限设得太高长对话时输入空间被挤压反而容易出问题。比如 128K 窗口的模型输出上限设 8192 到 16384 比较稳妥。5.2 端点配置与密钥管理[provider.xxx]区块里base_url和api_key_env是两个关键字段。base_url指向模型服务地址api_key_env指定从哪个环境变量读密钥。密钥管理有个铁律永远不要把密钥写进配置文件。正确做法是配置文件里只写环境变量名密钥通过环境变量注入。这样配置文件可以安全地进版本库密钥则通过 CI 的 secret 管理或本地的 shell 配置来提供。# 本地开发时在 shell 配置里设置 export OPENAI_API_KEYyour-key-here # CI 环境里通过平台的 secret 机制注入如果团队多人协作建议在 README 里明确列出需要设置哪些环境变量新人照着配就行不用去翻配置文件猜。5.3 配置改了没反应的六种可能这个故障太常见了我把它拆成六种可能按排查顺序排列配置文件路径不对Codex 读的是特定路径下的配置你改的文件可能根本不是它读的那个语法错误导致静默失败TOML 解析失败时有些实现会回退到默认值而不报错优先级被覆盖你改的层级被更高优先级的配置盖住了缓存未刷新某些实现会缓存配置需要重启或显式刷新字段名拼写错误temprature和temperature差一个字母就失效版本行为差异不同版本对同一字段的处理可能不同排查时按这个顺序走能覆盖绝大多数情况。其中第 2 和第 3 是最隐蔽的因为都不报错只是行为不对。5.4 多环境配置的组织方式实际项目通常有开发、测试、生产多套环境模型配置也不同。我的组织方式是基础配置放config.toml包含所有环境共用的部分环境差异放config.dev.toml、config.prod.toml等启动时通过参数指定用哪套这样避免了在单个文件里写一堆条件判断也方便不同环境独立演进。关键是基础配置里不要写环境相关的值比如具体的base_url这些都应该在环境配置里覆盖。6. 把配置管起来团队协作与版本管理6.1 哪些该进版本库哪些不该配置文件的版本管理有个清晰的分界线该进版本库的TOML 结构、AGENTS.md 内容、环境变量名列表、配置模板、README 说明。不该进版本库的真实密钥、个人偏好配置、本地路径相关的绝对路径、临时调试配置。判断标准很简单这个文件换个人、换台机器还能用吗能用就进版本库不能用就加进.gitignore。6.2 团队统一 Agent 行为的做法团队协作时最大的痛点是每个人的 Agent 行为不一致导致同样的任务输出质量参差不齐。解决办法是把 Agent 配置当成代码来管理AGENTS.md 走代码评审改动要有人 reviewTOML 配置有明确的 owner不能随便改关键配置项在 README 里说明设计意图定期回顾配置清理过时项我见过做得好的团队会把 AGENTS.md 的改动和代码改动绑定改代码逻辑的同时更新 Agent 指令保证两者同步。这种做法虽然麻烦但长期看省了很多沟通成本。6.3 配置变更的可追溯性配置改了行为变了出问题时怎么定位答案是让配置变更可追溯。具体做法每次改配置都写清楚改了什么、为什么改提交信息别写update config这种废话。如果团队用 issue 跟踪把配置变更和对应的 issue 关联起来。这样半年后回头看能知道某个参数为什么是现在这个值。对于关键参数可以在配置文件里用注释记录决策背景# temperature 设为 0.2 是因为代码审查需要稳定输出 # 2024-01 调整原值 0.5 导致审查意见过于发散 temperature 0.2这种注释看起来啰嗦但排查问题时能救命。6.4 新人上手的配置检查清单给团队新人一份配置检查清单能省掉大量答疑时间[ ] 环境变量是否设置echo $OPENAI_API_KEY验证[ ] 配置文件路径是否正确[ ] TOML 语法是否通过校验[ ] AGENTS.md 是否在预期位置[ ] 跑一个最小测试用例确认 Agent 能正常响应[ ] 检查配置优先级确认没有意外的覆盖这份清单覆盖了 90% 的新人配置问题。把它写进 README新人自助排查团队效率能提升不少。7. 我在实际使用中沉淀的几条经验配置这件事文档能告诉你的永远是是什么真正值钱的是踩过坑之后才知道的东西。分享几条我自己的体会。第一条改配置前先备份。听起来很基础但我真的见过有人把一份能用的配置改废了又没备份最后只能从头重建。配置文件不大复制一份的成本几乎为零但能省掉大麻烦。第二条一次只改一个变量。同时改三个参数行为变了你都不知道是哪个导致的。科学实验的对照原则在配置调试里同样适用。第三条极端值验证法。怀疑某个配置没生效时把它设成极端值比如 temperature 设 0 或 1跑一次看输出。差异明显就说明生效了没差异就说明没生效。这个方法比看日志快得多。第四条AGENTS.md 要短而精。我一开始写 AGENTS.md 恨不得写两千字结果 Agent 反而抓不住重点。后来精简到几百字只保留最关键的规则效果反而更好。指令太多模型会顾此失彼。第五条优先级问题优先怀疑层级放错。遇到改了没反应先别怀疑代码先检查配置放对层级没有。大部分时候问题就出在这。最后再分享一个小技巧如果你不确定某个配置项的正确写法去看官方示例或者社区里别人分享的配置比对着文档猜字段名快得多。配置这东西抄一份能跑的再改成自己需要的比从零写高效得多。