Codex 实际发送给模型的内容(10分钟阅读)

TLDR AI 工具

摘要

一篇技术深度文章,记录并分析了 Codex CLI 发送给模型的精确 HTTP 请求,测量了 token 数量,以及指令、工具和上下文是如何打包的。

一位开发者将 Codex 指向一个自定义本地服务器,记录下它为一条 16 字符提示词生成的请求。他们测量了在加载指令、暴露工具、读取文件、运行命令、接收图像以及压缩历史记录时,哪些内容发生了变化。该实验并未调用外部模型。本文详细介绍了实验的发现。
查看原文
查看缓存全文

缓存时间: 2026/08/05 13:32

# Codex 实际发送给模型的内容 来源:https://www.0xkato.xyz/what-codex-actually-sends-to-the-model - 首页 (https://www.0xkato.xyz/) - 博客 (https://www.0xkato.xyz/blog) - 研究 (https://www.0xkato.xyz/projects) - 关于 (https://www.0xkato.xyz/about) - 作品集 (https://github.com/0xkato/Portfolio/tree/main) Codex 实际发送给模型的内容 2026 年 8 月 4 日,星期二 - 10 分钟阅读 我录制了 Codex 为一个 16 字符提示词生成的请求,然后测量了它在加载指令、暴露工具、读取文件、运行命令、接收图像以及压缩历史记录时的变化。 当我输入 "Reply with pong." 时,提示词只有 16 个字符。 Codex 发送的请求却是 42,980 字节。 在本地用 o200k\_base 编码为 JSON 后,大约相当于 9,435 个 token。其中包装提示词约占 25 个 token,即 0.3%。其余部分都来自 Codex 本身:指令、工具定义、权限、技能元数据、环境上下文和请求框架。 这些 token 数量是本地估算值,并非 API 用量或计费数据。捕获到的请求体本身是精确的。 文件读取和命令输出会在之后被加入。当累积的历史记录变得过大时,Codex 可以将其通过另一个模型请求发送,用一个摘要替换它,然后继续执行。 ## 我如何录制请求 Codex 支持自定义模型提供商。我将其指向一个本地 HTTP 服务器,该服务器保存每个请求,对敏感标头进行脱敏,并返回固定的假响应。该实验没有调用任何外部模型。 `` Codex 客户端 → 本地录制器 → 确定性假响应 ↑ 请求在此处被保存 `` 录制器展示的是客户端发送了什么。它无法展示真实提供商在收到请求后可能做出的更改、任何输入是否会被缓存,或它将如何计费。 我测量了两项内容: - 原始请求字节数:HTTP JSON 正文在脱敏前的大小。 - 近似文本 token 数:脱敏后的 JSON 在本地用 o200k\_base 编码的结果。 测试使用的是 Codex CLI 0.145.0 及 gpt-5.6-sol 模型。 ## 第一个请求 我在一个空的临时 Git 仓库中启动了 Codex,禁用了项目指令,并将 CODEX\_HOME 指向一个空目录。 请求仍然描述了五个内置系统技能,因此这是一个隔离主目录的基线,而不是最小化可能的请求。 有三项内容占据了 9,435 个 token 中的 7,696 个: 包含内容 | 序列化大小 | 本地估算值 --- | --- | --- additional\_tools 开发者条目 | 四个顶级工具条目 | 16,741 字符 | 3,942 tokens 开发者消息 | 主要 Codex 指令 | 17,730 文本字符 | 3,729 tokens 用户消息 | Reply with pong. | 16 文本字符 | 25 tokens 这四个工具条目分别是 exec、wait、request\_user\_input 和一个协作命名空间。它们代表的动作不止四个。collaboration 包含六个子工具,而 exec 描述了命令执行、打补丁、图像检查、计划更新以及其他嵌套工具。 在这次运行中,Codex 将工具条目和基础指令放在了 input 数组中,而不是使用顶层的 instructions 和 tools 字段。 ## 项目指令 Codex 从仓库根目录到它启动的目录构建其项目指令链。它在每一级查找 AGENTS\.md,将更靠近的指令放在后面。 我创建了一个根级和一个子级的 AGENTS\.md,每个包含 100 个唯一标记。 - 从仓库根目录启动会发送全部 100 个根标记,且不发送子标记。 - 从子目录启动会发送全部 200 个标记。 - 从根目录启动后运行 ls child 不会添加子级指令。 启动目录决定了自动指令链。显式读取子文件仍然可以将其内容作为普通工具历史记录添加进来。 在大小测试中,我使用了合成的高熵标记而不是自然语言。每个标记是一个类似 PAIRED\_AGENTS\_1000\_0001 的字符串,o200k\_base 会将其自行拆分为 11 个 token。普通散文词汇则不会。下表显示指令会被完整传输——这并不代表你自己的 AGENTS\.md 会花费这么多。 更大的文件会直接改变第一个请求: 原始请求字节数 | 本地估算值 | 与基线的差异 --- | --- | --- 隔离主目录基线 | 42,980 | 9,435 | — 250 个合成 AGENTS 标记 | 48,927 | 11,965 | +5,947 字节;+2,530 tokens 1,000 个合成 AGENTS 标记 | 67,177 | 20,465 | +24,197 字节;+11,030 tokens 在一个包含 250 个标记的两请求追踪中,全部 250 个标记出现在两个请求中。 ## 技能分两个阶段加载 仓库中 \.agents/skills/ 下的技能最初只贡献其名称、描述和路径。它们的 SKILL\.md 正文在被读取之前不会出现。 每个合成技能有一个 12 词的描述和一个包含唯一标记的 200 词正文。 - 一个技能为第一个请求增加了 481 字节和约 125 个 token。 - 十个技能增加了 4,810 字节和约 1,250 个 token。 - 没有任何正文标记出现在两个请求的第一个中。 我测试了一个包含三个工具的本地 MCP 服务器,以及两个共计七个工具的本地服务器。 在仅初始运行的测试中,两个请求均为 46,582 字节和约 10,410 个本地 token。二者都不包含自定义工具名称或描述。相反,exec 接口获得了通用的 MCP 发现指南。禁用已配置的服务器后,请求恢复到了隔离主目录基线。 在我让 exec 打印匹配的延迟工具条目后,描述出现了: 保留的描述标记 | 增加的字节数 | 增加的本地估算值 --- | --- | --- 一个服务器,三个工具(每个 40 个标记) | 120 | 5,894 | 1,522 tokens 两个服务器,七个工具(三个 40 标记,四个 60 标记) | 360 | 15,970 | 4,210 tokens 一个服务器白名单仅一个工具(40 个标记) | 40 | 2,288 | 578 tokens 这些差异将发现后的请求与同一追踪中的第一个请求进行比较,后者在另一次运行中为 46,589 字节和 10,410 个本地 token。 我还创建了一个包含 5,000 个标记的工具描述。截断后,其保留的首尾样本仍包含 1,046 个标记。下一个请求增长了 40,607 字节和约 9,631 个本地 token。 按配置观察到的请求大小 按配置观察到的请求大小 MCP 发现将延迟的工具描述移入历史记录 MCP 发现将延迟的工具描述移入历史记录 ## 一个编码任务,逐个请求查看 我创建了一个带有配置错误的小型 Python 测试项目:一个显式的 false 值被用户默认值替换。任务是: > 修复导致显式 false 值被用户默认值替换的配置优先级错误。添加一个回归测试并运行相关的测试套件。 这个追踪衡量的是请求增长,而非模型推理。动作是预先确定的。 动作完成在其之前 | 原始字节数 | 本地估算值 --- | --- | --- 0 | 初始任务 | 44,189 | 9,815 1 | 搜索 | 45,289 | 10,114 2 | 文件读取 | 46,278 | 10,368 3 | 初始测试 | 46,959 | 10,529 4 | 添加回归测试 | 47,635 | 10,701 5 | 回归测试失败 | 48,832 | 10,968 6 | 第二次检查 | 49,953 | 11,254 7 | 应用修复 | 50,471 | 11,386 8 | 测试套件通过 | 51,170 | 11,554 9 | 验证差异 | 52,389 | 11,889 最终请求比第一个请求大 8,200 字节和约 2,074 个 token。搜索结果、文件内容、测试、失败信息、补丁和最终差异都保留给了后续轮次。 一次错误修复期间的上下文增长 一次错误修复期间的上下文增长 ## 文件在读取后才会进入请求 我创建了五个带有唯一标记的无害文件:一个普通源文件、一个被忽略的文件、一个假的 \.env、一个被忽略的 20,000 行日志,以及一个在 AGENTS\.md 中被提及名称的文件。 它们的内容都没有出现在第一个请求中。 运行 rg --files -uu 添加了它们的文件名,而不是内容。在显式读取之后,普通文件、被忽略的文件、假的 \.env 和被忽略的日志都出现在后续请求中。 原始字节数 | 本地估算值 --- | --- 文件操作之前 | 43,500 | 9,617 文件名列表之后 | 45,040 | 10,092 读取普通文件之后 | 45,445 | 10,196 读取被忽略文件之后 | 45,846 | 10,303 读取假 \.env 之后 | 46,250 | 10,418 读取大型被忽略日志之后 | 87,561 | 20,350 读取被提及文件之后 | 87,983 | 20,461 大型日志在下一个请求之前被截断为首尾样本。 Codex 不会自动上传仓库。但 \.gitignore 并不会阻止显式读取,也不会阻止由此产生的工具输出进入后续请求。 ## 终端输出保留在历史记录中 十行和一百行的命令结果被逐字保留到后续请求中。一个 10,000 行的结果被截断为首尾样本,但请求仍然从 43,337 字节和约 9,584 个 token 增长到了 88,480 字节和 25,835 个 token。 重复的输出不会被去重。ANSI 格式化的文本和失败的 Python 堆栈跟踪也会保留在历史记录中。 ## 图像以数据 URL 形式传输 一张合成的 32×32 PNG 以 442 字符的 data:image/png;base64,... URL 出现在请求中。 随后我附加了一张更大的合成渐变 PNG。Codex 在传输前对其进行了调整大小并重新编码。捕获到的 71,666 字符数据 URL 解码后是一张 1600×1600 的 PNG。一个包含两张图像的请求同时包含两个数据 URL。 原始请求体大小分别为:小图像 43,955 字节,变换后的大图像 115,265 字节,两张图像一起 115,886 字节。对 base64 进行本地文本 token 化并不是图像 token 计算,因此我没有用它来估算成本。 ## 压缩会将历史记录通过另一个请求发送 针对 OpenAI 或 Azure,Codex 通过专用端点进行压缩。针对自定义提供商(如我的录制器),它会自行构建摘要请求。这就是我捕获的路径,它有两个阶段。首先,Codex 将累积的历史记录连同摘要提示词一起发送。然后,它围绕保留的用户消息和返回的摘要重建对话。代码位于压缩请求 (https://github.com/openai/codex/blob/bb5054fe47abe73ecbbd454751066a28c89f4bb9/codex-rs/core/src/compact.rs#L112-L140) 和 历史替换 (https://github.com/openai/codex/blob/bb5054fe47abe73ecbbd454751066a28c89f4bb9/codex-rs/core/src/compact.rs#L241-L385) 路径中。 我通过合成用量强制触发了它:报告 13,000 个输入 token、20,000 个 token 的上下文窗口和 12,000 个 token 的压缩阈值。 这产生了三个请求: - 初始请求:42,030 字节和约 9,378 个 token。包含普通工具和用户请求。 - 压缩请求:68,375 字节和约 21,408 个 token。包含累积的历史记录、一个大型保留的工具结果和一个摘要提示词。普通工具列表为空。 - 恢复后的请求:42,646 字节和约 9,500 个 token。普通工具和原始用户消息回来了。原始工具调用和输出被替换为合成摘要。 压缩移除了什么、保留了什么 压缩移除了什么、保留了什么 恢复后的请求比压缩请求小 25,729 字节和约 11,908 个 token。摘要故意写得很简短。 这展示了历史记录是如何被替换的,而非真实模型会如何进行摘要。压缩之后,某个细节可能只能通过生成的摘要存续,而不再是原始的消息或工具输出。 ## 什么穿过了机器边界 有些信息在任何工具使用之前就已存在:Codex 指令、可见的工具接口、被发现的 AGENTS\.md 链、技能元数据、环境上下文和用户提示词。 其他信息只在某次动作之后才出现:读取后的文件内容、命令后的终端输出、发现后的 MCP 描述,以及附加后的图像。 未读取的仓库文件、被忽略的文件和假的 \.env 不会自动出现。提示词是种子。请求是工作状态。 什么可以离开机器 什么可以离开机器 ## 这个实验没有测量什么 - 跨所有 Codex 版本、模型、操作系统或产品形态的通用最小请求。 - 自主模型推理。多轮工作流使用了固定的假响应,因此真实会话每轮携带的内容比这些追踪显示的多。 - 模型生成的压缩摘要的质量。 - 提供商侧的转换、缓存命中、计费或模型内部机制。 配套的工件包包含录制器、脱敏的请求体、分析文件、测试和图源。 非常欢迎反馈。如果你对其中任何内容感兴趣,请在 X (https://x.com/0xkato) 上联系我。我喜欢结交新朋友。

相似文章

解析Codex代理循环

OpenAI Blog

# 解析Codex代理循环 来源:[https://openai.com/index/unrolling-the-codex-agent-loop/](https://openai.com/index/unrolling-the-codex-agent-loop/) [Codex CLI⁠\\(在新窗口中打开\\)](https://developers.openai.com/codex/cli)是我们的跨平台本地软件代理,旨在在你的机器上安全高效地运行,生成高质量、可靠的软件更改。自从我们首次推出以来,我们已经学到了大量关于如何构建世界一流软件代理的知识[自从我们首次启动

数据科学团队如何使用 Codex

OpenAI Blog

本指南来自 OpenAI Academy,解释了数据科学团队如何利用 Codex 加速分析工作流程,包括根本原因分析、业务影响报告以及处理模糊请求。

@sitinme: 一个挺实用的 Codex 使用小技巧: Codex 在执行任务时,经常会自己在后台搜索、打开网页、检查内容。虽然效率挺高,但有时候我其实更希望看到它正在做什么,尤其是需要我参与判断的时候。 以前我每次都要单独告诉它: 用浏览器或者 Com…

X AI KOLs Timeline

分享一个使用 Codex 的技巧,通过配置 AGENTS.md 文件来控制 Codex 在执行任务时显示其操作过程,提高交互可见性和协作效率。