1. 为什么 Codex CLI 的 Agent Loop 值得单独拆开看很多人第一次用 Codex CLI会把它当成一个「能跑命令的 ChatGPT」。你输入一句「帮我把这个项目跑起来」它回你一段命令你复制粘贴报错了再问它它再给一段。这个用法没错但你其实只用了它 10% 的能力。真正让 Codex CLI 区别于普通对话模型的是它内部那套 Agent Loop模型不是一次性给你答案而是在一个循环里反复做「思考 → 行动 → 观察结果 → 再思考」的小决策直到任务收敛。我试过把一个 Node 项目直接丢给它只说「跑起来并补一个 README」。它没有一口气输出几十行命令而是先ls看目录再读package.json然后尝试npm start看到缺依赖的报错后自己决定npm install再跑一次最后才写 README。整个过程你能在终端里看到它每一步的 Tool Call 和真实输出。这就是 Agent Loop 的价值把「一次性答题」拆成「多轮可验证的小步骤」。这篇文章面向想读懂 Codex Agent 内部机制的开发者。我会把 Agent Loop 的完整运转链路拆开Prompt 怎么构造、模型怎么决定下一步、Tool Call 怎么被解析执行、结果怎么塞回上下文继续循环。然后给出可复制的 Agent Loop 配置片段带你做一次 Tool Call 触发验证最后说明怎么把 Codex 的auth.json改到 TaoToken 统一通道方便你观察请求到底走向哪里。如果你之前只停留在「问一句答一句」这篇能帮你把 Codex CLI 真正当成一个本地软件代理来用。2. Agent Loop 的五步链路与 Prompt 驱动 Tool Call 机制2.1 目标与过程分离用户输入只是「终点」在 Codex CLI 里你输入的那句话不是直接变成模型的思考内容它的角色更接近「任务目标」。系统会把目标和过程分开目标是稳定的过程是动态的。你说「补一个 README」系统只知道终点是「有一个 README」至于先看目录还是先跑测试完全由后续每一轮循环决定。这个设计的好处是模型不需要在信息不足的情况下硬猜路径。它每一轮只回答一个问题「在当前信息条件下我下一步该做什么」这个「下一步」通常只有两种可能要么还需要更多信息或行动输出一个 Tool Call要么信息够了直接输出最终回答循环结束。2.2 Prompt 是模型看世界的全部信息这是最容易被低估的一步。对模型来说它并不知道「刚刚发生了什么」除非你把信息放进 Prompt。所以每一轮 Agent Loop 都会重新构造一个 Prompt里面通常包含系统设定你是一个 coding agent可以改文件、跑命令、可用工具列表shell、文件读写、测试运行、用户目标、以及到目前为止发生过什么跑了什么命令、输出是什么、有没有报错。关键点在于「重新构造」。第一轮你还没看过项目结构第二轮你已经知道有哪些文件第三轮你已经看到测试报错。如果 Prompt 不更新模型会永远以为自己什么都不知道。所以 Agent Loop 的一个核心动作就是把刚刚发生的现实结果翻译成模型能理解的文字再塞回 Prompt。2.3 Tool Call 是模型「想干活」的表达方式模型本身不会执行命令。它只能输出文字或结构化指令。当它说「我需要运行 ls 看看目录」时系统会解析这个输出发现这是一个 tool call然后在真实环境里执行命令收集真实输出。这一步把「建议」变成了「现实动作」。这里有个反直觉的点工具执行完模型并不会自动「知道结果」。你必须把执行结果转成文本比如「你刚刚运行了 ls输出是src/ package.json」再加入 Prompt发起下一轮推理。这一步完成后新的一轮 Loop 才开始。2.4 循环如何收敛为决策循环的结束条件不是写死的而是由模型决定的。当模型判断信息已经足够它会输出最终回答Agent Loop 结束。这就是为什么 Agent 必须是一个「死循环」你不知道要循环多少轮不知道什么时候信息才足够只能一轮一轮试。结束条件由模型在每一轮里动态判断。用一个最小代码结构来体现这个本质class SimpleAgent: def __init__(self, llm): self.llm llm self.history [] def run(self, goal): while True: prompt self.build_prompt(goal) response self.llm(prompt) if response[type] final: print(response[text]) break if response[type] tool_call: result self.execute_tool(response) self.history.append(result) def build_prompt(self, goal): return {goal: goal, history: self.history} def execute_tool(self, call): if call[name] shell: return os.popen(call[command]).read()这段代码不是生产级但它 100% 体现了 Agent Loop 的本质Agent 不是模型而是调度者history是现实世界发生过的文本化记录while True是因为结束条件由模型决定。理解了这五步你再看 Codex CLI 的终端输出就能对上号了。3. 可复制的 Codex Agent Loop 配置片段与 auth.json 改造3.1 Codex CLI 的配置文件位置Codex CLI 的配置通常放在用户目录下的.codex文件夹里。核心文件有两个config.toml负责模型和运行参数auth.json负责认证信息。你要观察请求走向重点就是这两个文件。先看config.toml的一个可复制片段路径按你的实际安装位置调整# ~/.codex/config.toml model gpt-5-codex model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY [agent] max_turns 30 auto_execute false这里的max_turns就是 Agent Loop 的最大轮数防止死循环跑飞。auto_execute false表示每个 Tool Call 执行前需要你确认调试阶段建议保持 false方便你观察每一步。3.2 auth.json 改造到 TaoToken 统一通道auth.json是 Codex 读取认证信息的地方。要把它改到 TaoToken 统一通道你需要写入 Base URL、Key 和 Model ID 三件套。一个可复制的auth.json结构如下{ auth_mode: apikey, providers: { taotoken: { base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model: gpt-5-codex } }, default_provider: taotoken }注意base_url用https://taotoken.net/api不要带多余路径。api_key从 TaoToken 控制台的 API Keys 页面获取。model填你要用的模型 ID和config.toml里的model保持一致。如果你用的是环境变量方式也可以在 shell 里设置export TAOTOKEN_API_KEYsk-你的TaoToken密钥然后在config.toml里通过env_key TAOTOKEN_API_KEY引用。两种方式选一种即可不要同时配导致冲突。3.3 三件套对照表配置项值说明Base URLhttps://taotoken.net/api统一通道入口不带 UTMAPI Keysk-...从控制台 API Keys 获取Model IDgpt-5-codex与 config.toml 保持一致改完之后Codex CLI 的每一次模型请求都会走 TaoToken 通道。你可以在终端里观察请求日志确认 Agent Loop 每一轮的 Prompt 和 Tool Call 都经过这个入口。这样调试时你能清楚看到「模型看到了什么、决定了什么、执行了什么」。4. 一次 Tool Call 触发验证从 Prompt 到执行结果4.1 准备一个会报错的最小项目验证 Agent Loop 最好的方式是给它一个需要多轮才能解决的任务。新建一个目录放一个会报错的 Node 项目mkdir codex-loop-demo cd codex-loop-demo cat package.json EOF { name: codex-loop-demo, version: 1.0.0, scripts: { start: node index.js } } EOF cat index.js EOF const express require(express); const app express(); app.get(/, (req, res) res.send(ok)); app.listen(3000); EOF这个项目npm start会报错因为没装express。正好用来观察 Codex 怎么一轮轮推进。4.2 启动 Codex 并输入目标在项目目录里启动 Codex CLIcodex然后输入目标「把这个项目跑起来确认首页能返回 ok」。注意你只给目标不给步骤。4.3 观察每一轮的 Tool Call你会看到类似这样的循环输出。第一轮模型决定先看目录[tool_call] shell: ls -la [result] package.json index.js第二轮它读package.json和index.js判断这是 Node 项目尝试运行[tool_call] shell: npm start [result] Error: Cannot find module express第三轮它根据报错决定装依赖[tool_call] shell: npm install express [result] added 1 package第四轮再跑一次[tool_call] shell: npm start [result] Server listening on 3000第五轮它判断任务完成输出最终回答循环结束。整个过程你能清楚看到 Prompt 里累积的history如何驱动每一轮的决策。这就是 Agent Loop 从 Prompt 到 Tool Call 再到收敛的完整链路。4.4 验证请求走向如果你想确认请求确实走了 TaoToken 通道可以在 Codex 启动时打开详细日志或者在 TaoToken 控制台的请求记录里查看。每一轮模型推理都会对应一条请求记录包含模型 ID 和时间戳。对照终端里的轮次你就能把「本地看到的 Tool Call」和「通道里的请求」一一对应起来。5. 本篇常见报错排查401、local proxy failed 与 reading choices5.1 401 Unauthorized这是最常见的认证错误。出现401通常有三个原因auth.json里的api_key填错或过期base_url写成了带多余路径的地址环境变量和配置文件里的 Key 冲突。排查顺序先确认base_url是https://taotoken.net/api不带尾部斜杠和多余路径再确认 Key 是从控制台 API Keys 页面复制的完整字符串最后检查是不是同时配了环境变量和auth.json导致读取了旧的那个。改完重启 Codex CLI 再试。5.2 local proxy failed这个报错通常出现在 Codex 尝试连接本地代理或自定义端点时。如果你在config.toml里配了model_provider但auth.json里的default_provider名字对不上就会出现local proxy failed。检查两处的 provider 名称是否完全一致比如都叫taotoken。另一个可能是base_url指向了一个不可达的地址。确认网络能正常访问https://taotoken.net/api并且没有在中间层配了额外的转发规则。5.3 reading choices 相关报错当模型返回的结构和 Codex 期望的格式不匹配时会出现reading choices类的解析错误。这通常是因为model字段填了一个不支持结构化输出的模型 ID或者通道返回的响应格式和 Codex 的解析器不兼容。排查方法确认config.toml和auth.json里的model完全一致并且是 Codex 支持的模型 ID。如果换了模型后出现这个错先换回默认模型验证通道是否正常再逐步替换。5.4 OAuth 相关报错如果你之前用的是 OAuth 登录方式切到 API Key 模式后可能残留旧的认证状态。出现 OAuth 报错时检查auth.json里的auth_mode是否设成了apikey。如果还有旧的 token 缓存清掉后重新写入三件套。5.5 三件套检查清单报错优先检查修复动作401Base URL Key确认https://taotoken.net/api和完整 Keylocal proxy failedprovider 名称config.toml 与 auth.json 保持一致reading choicesModel ID两处 model 字段一致且受支持OAuthauth_mode改为apikey并清理旧缓存每次改完配置重启 Codex CLI 让新配置生效。调试阶段建议保持auto_execute false这样每个 Tool Call 你都能看到出问题也容易定位。6. 把 Agent Loop 用起来从观察到调优读懂 Agent Loop 之后你调 Codex CLI 的方式会变。以前你可能会写很长的 prompt试图一次性说清所有步骤现在你只需要给清楚目标让循环自己展开。目标越明确模型每一轮的决策越聚焦收敛越快。max_turns是个值得调的参数。设太小复杂任务还没跑完就中断设太大遇到死循环会浪费请求。一般项目调试设 20 到 30 比较合适简单任务设 10 就够。如果你发现模型在某一轮反复执行同一个命令说明 Prompt 里的history可能没有正确更新或者工具返回的结果格式让模型无法理解这时候要检查 Tool Call 的输出解析。想观察请求走向把auth.json改到 TaoToken 统一通道后每一轮模型推理都会在控制台留下记录。你可以对照终端里的轮次看模型每一轮到底收到了什么 Prompt、返回了什么决策。这个对照过程比读任何文档都更能帮你理解 Agent Loop 的真实运转。如果你还没拿到 Key先去控制台创建一个然后按第 3 节的片段把config.toml和auth.json配好。配完之后用第 4 节的最小项目跑一遍亲眼看到 Tool Call 一轮轮触发、循环最终收敛你对 Codex Agent 的理解就不再停留在概念层面了。