1. 为什么你的 Codex 总是“失忆”:AGENTS.md 与 skills 协同的真实场景
Codex 这类命令行 AI 编码代理,最让人抓狂的不是它不会写代码,而是它每次开新对话就像换了个人:昨天刚讲清楚的项目结构、命名规范、测试命令,今天全部归零。你不得不把同一段背景描述复制粘贴第五遍,然后看着它又一次把src/utils写成src/common。这个问题的根源在于上下文窗口——当对话变长,你只能开新会话,而新会话对之前的一切一无所知。
解决思路不是把上下文塞得更满,而是把“项目知识”从对话里剥离出来,落到文件系统上。Codex 提供了两层机制:项目级的AGENTS.md负责长期记忆,skills/目录负责可复用的操作技能。前者告诉 Codex“这个项目是什么、怎么跑、有哪些坑”,后者告诉它“遇到某类任务时按什么流程做”。两者配合,才能让 Codex 在真实仓库里稳定干活,而不是每次从零猜。
这篇教程面向想把 Codex 用进日常开发的工程师。我会给出可直接复制的AGENTS.md模板、.codex/skills的目录结构、一个自定义 skill 的完整写法,以及初始化仓库后如何用一次任务验证 Codex 确实读到了配置、确实执行了 skill。全程围绕 git 仓库展开,因为 Codex 的沙箱机制和版本管理是绑在一起的。
先说清楚 Codex 的沙箱边界:它把整个项目文件夹当作沙箱,不能修改沙箱外的文件,默认也不联网。这意味着你的AGENTS.md和 skills 必须放在项目目录内,Codex 才能读到。理解这一点,后面的配置才不会白写。
2. 前置准备:TaoToken 接入 Codex 的 Base URL 与 Key 配置
在写AGENTS.md之前,得先让 Codex 能正常发请求。Codex 支持自定义模型端点,这里用 TaoToken 作为接入层,把 Base URL 指向它的 API 地址,再配上 Key 和 Model ID,三件套缺一不可。
先拿 Key。打开 https://taotoken.net/api-keys ,登录后创建一个新的 API Key,复制出来。注意 Key 只在创建时完整显示一次,丢了就重新建一个。这个 Key 后面要写进 Codex 的配置文件,不要提交到 git 仓库里。
Base URL 用https://taotoken.net/api,注意这里不加任何查询参数。Model ID 根据你要用的模型填,比如claude-sonnet-4-5或gpt-5-codex这类编码向模型,具体以控制台模型列表为准。如果你不确定选哪个,可以先在 https://taotoken.net/models 用对话方式试一下,确认模型能正常响应再写进配置。
Codex 的配置分两层:全局配置在~/.codex/config.toml,项目级配置在仓库根目录的.codex/config.toml。全局配置放 Key 和默认模型,项目配置放项目特有的模型覆盖和沙箱策略。这样多个项目可以共用同一个 Key,又各自独立。
一个容易踩的坑是:Codex 读取配置的优先级是项目级覆盖全局级,但AGENTS.md的读取是“项目根目录 + 全局~/.codex/AGENTS.md”叠加。也就是说,你可以在全局AGENTS.md里写个人偏好(比如“注释用中文”“提交信息用 conventional commits”),在项目AGENTS.md里写项目规范,Codex 会同时读两份。
配置写完后,用一条最小请求验证连通性。在终端里执行codex exec "print hello",如果返回正常文本而不是 401 或连接错误,说明 Base URL 和 Key 都对了。这一步别跳过,否则后面 skill 不生效时你分不清是配置问题还是 skill 写法问题。
3. 可复制配置:AGENTS.md 模板与 .codex/skills 目录结构
这一节给可直接落地的文件内容。先建AGENTS.md,放在仓库根目录。模板如下,按你的项目替换占位内容:
# 项目:my-service ## 技术栈 - 语言:TypeScript 5.x + Node.js 20 - 框架:Fastify - 测试:Vitest - 包管理:pnpm ## 目录约定 - src/routes:HTTP 路由,一个文件一个资源 - src/services:业务逻辑,不直接碰数据库 - src/repos:数据访问层,SQL 只出现在这里 - tests:与 src 同构的测试文件 ## 常用命令 - 安装:pnpm install - 开发:pnpm dev - 测试:pnpm test - 类型检查:pnpm typecheck - 格式化:pnpm format ## 编码规范 - 禁止 any,用 unknown + 类型守卫 - 错误统一用 AppError 类,不抛裸 Error - 提交信息遵循 conventional commits ## 注意事项 - 不要修改 migrations 目录下的历史文件 - 新增环境变量必须同步更新 .env.example这份模板的关键是“可执行”:命令要能直接跑,目录约定要具体到文件职责,规范要能判断对错。Codex 读完后,你让它加一个路由,它会知道去src/routes而不是随便建文件。
接下来是 skills 目录。项目级 skill 放在.codex/skills/下,每个 skill 一个子目录,目录名就是 skill 名。结构如下:
.codex/ config.toml skills/ add-route/ SKILL.md db-migration/ SKILL.mdSKILL.md是 skill 的入口文件,用 frontmatter 声明元信息,正文写执行步骤。一个add-routeskill 的完整写法:
--- name: add-route description: 为 Fastify 项目新增一个 HTTP 路由,包含路由文件、service、测试 --- # 新增路由 当用户要求新增一个 API 路由时,按以下步骤执行: 1. 在 src/routes/ 下新建 <resource>.ts,导出 Fastify 插件 2. 在 src/services/ 下新建 <resource>.service.ts,写业务逻辑 3. 在 tests/routes/ 下新建 <resource>.test.ts,覆盖 200 和 400 两个分支 4. 在 src/app.ts 中注册新路由插件 5. 运行 pnpm test 确认通过 命名规则:资源名用复数小写,如 users、orders。 错误处理:参数校验失败返回 400,用 AppError 包装。注意 frontmatter 里的name必须和目录名一致,description要写清楚“什么时候用这个 skill”,Codex 靠它判断是否触发。正文用编号步骤,每步都是可执行动作,不要写“考虑一下”“酌情处理”这种模糊表述。
项目级config.toml里可以指定模型和沙箱策略:
model = "claude-sonnet-4-5" approval_policy = "on-request" [sandbox] mode = "workspace-write"workspace-write表示允许在项目目录内写文件,但不出沙箱。approval_policy = "on-request"表示高风险操作会先问你。这两个参数配合,既能干活又不会乱来。
4. 验证请求:初始化仓库后跑一次任务确认 skill 生效
配置写完必须验证,否则你不知道 Codex 到底读没读到。验证分三步:初始化 git、跑一个触发 skill 的任务、检查结果。
第一步,初始化仓库并提交初始状态。Codex 的很多能力依赖 git,比如它用工作树做备份、用 diff 展示改动。执行:
git init git add . git commit -m "chore: init project with codex config"提交后,Codex 在沙箱里做的修改可以通过git diff查看,出问题也能git checkout回滚。
第二步,跑一个明确会触发add-routeskill 的任务。在项目根目录执行:
codex exec "新增一个 GET /health 路由,返回 {status:'ok'},按项目规范写测试"观察 Codex 的输出。如果配置正确,它应该:先读取AGENTS.md(输出里会提到项目技术栈)、识别出这是“新增路由”任务从而加载add-routeskill、按 skill 里的步骤依次创建文件。你可以用codex exec --verbose看到它读取了哪些文件。
第三步,检查产物。执行git status看新增了哪些文件,应该包括src/routes/health.ts、src/services/health.service.ts、tests/routes/health.test.ts,以及src/app.ts的修改。然后跑pnpm test,确认测试通过。如果文件位置对、测试过,说明 skill 生效了。
如果 Codex 没按 skill 走,先检查.codex/skills/add-route/SKILL.md的 frontmatter 是否合法,再检查description是否足够明确。Codex 匹配 skill 靠语义相似度,描述太泛(比如只写“处理路由”)可能匹配不上。
验证通过后,你可以把这个流程固化成习惯:每次给 Codex 派任务前,先确认AGENTS.md是最新的,skill 目录没有语法错误。这样长期用下来,Codex 的表现会稳定很多。
5. 常见报错排查:401、local proxy failed 与 skill 不触发
用 Codex 接 TaoToken 时,报错集中在几类。逐个说清楚现象和修法。
401 Unauthorized:最常见。现象是codex exec直接返回 401,或者提示invalid api key。原因通常是 Key 没写对、Key 过期、或者配置文件路径不对。检查顺序:先确认~/.codex/config.toml里的 Key 和 https://taotoken.net/api-keys 上显示的一致;再确认 Base URL 是https://taotoken.net/api而不是别的路径;最后确认没有多余空格或换行。如果用的是环境变量OPENAI_API_KEY,注意 Codex 可能优先读配置文件,两者冲突时以配置文件为准。
local proxy failed / connection refused:现象是请求发不出去,提示本地代理失败。这通常是因为系统里设了 HTTP_PROXY 或 HTTPS_PROXY 环境变量,而 Codex 尝试走代理但代理没开。检查env | grep -i proxy,如果有输出,临时 unset 掉再试。另一个可能是 Base URL 写成了http://而不是https://,改成 https 即可。
reading choices: unexpected end of JSON input:现象是 Codex 收到响应但解析失败。原因一般是模型返回了非 JSON 格式,或者响应被截断。先确认 Model ID 写对了,不存在的模型可能返回错误页而不是 JSON。再确认没有在 Base URL 后面手动加/v1之类的路径,TaoToken 的 API 地址已经包含了正确路径。
skill 不触发:现象是 Codex 正常干活,但没按 skill 里的步骤走。检查三点:SKILL.md的 frontmatter 是否用---包裹且name与目录名一致;description是否包含任务关键词;skill 目录是否在.codex/skills/下而不是~/.codex/skills/(项目级和全局级位置不同)。如果都对了还不触发,试着在任务描述里直接提 skill 名,比如“用 add-route skill 新增路由”。
OAuth 相关报错:如果你之前用 OAuth 登录过 Codex,配置里可能残留了旧的认证方式。现象是提示 token 无效或需要重新登录。解决方法是删掉~/.codex/auth.json,改用 API Key 方式。注意auth.json和config.toml是两套机制,用 Key 就不要再留 OAuth 的 token。
排查时养成看 verbose 输出的习惯:codex exec --verbose "任务"会打印它读取的配置文件、加载的 skill、发出的请求。大部分问题看日志就能定位。
6. 长期使用建议:把 Codex 接进日常编码与 Agent 工作流
配置跑通只是开始,真正省时间的是把它接进日常流程。几个实践建议。
第一,AGENTS.md要随项目演进更新。每次你发现 Codex 犯了个“本不该犯”的错,比如把测试写到错误目录,就把这条规则补进AGENTS.md。它相当于给 Codex 的项目说明书,越用越准。
第二,skill 按任务类型拆分,不要写一个万能 skill。add-route、db-migration、fix-lint各管一件事,描述清晰,触发准确。skill 之间可以互相引用,比如add-route里写“测试写法参考 test-conventions skill”。
第三,用 git 工作树并行跑任务。Codex 支持在同一个仓库的不同工作树里同时干活,互不干扰。命令是git worktree add ../my-service-feature2,然后在那个目录里开新的 Codex 会话。适合同时推进多个 feature 的场景。
第四,长期编码或 Agent 类任务,可以考虑用 Coding Plan 把额度固定下来,避免按次计费的不确定性。入口在 https://taotoken.net/coding-plan ,适合每天都要用 Codex 干活的开发者。
第五,模型选择上,编码任务优先用编码向模型,复杂重构再用大模型。切换模型改config.toml里的model字段即可,不用改其他配置。
最后提醒一点:Codex 是助手不是替代品。它写的代码你要 review,它跑的测试你要确认。把AGENTS.md和 skills 配好,是为了让它少犯低级错误,把精力留给真正需要判断的地方。配置一次,长期受益,这个投入是值得的。