Skip to content

Instantly share code, notes, and snippets.

@acmerfight
Last active September 12, 2026 15:16
Show Gist options
  • Select an option

  • Save acmerfight/74b63fab714d04096c86bf12f7d7d9aa to your computer and use it in GitHub Desktop.

Select an option

Save acmerfight/74b63fab714d04096c86bf12f7d7d9aa to your computer and use it in GitHub Desktop.
关掉等待工具,Codex 反而更省 token|Astra low 三对实验:结论、官方 API 费用、最终配图、原始数据与复现方法

关掉等待工具,Codex 反而更省 token:Astra low 三对实验

作者:@yaogangqiang · 实验日期:2026-09-12

这是分享文章的实验配套页:结论、过程、逐对结果与复现方法放在一起。下文只统计本次 Astra 的六次正式运行,不合并其他模型或先前的探索实验。

结论先说

在本次“等待文件出现”的任务里,关闭原生 clock.sleep 后,Astra low 的三个运行都用了更少的模型响应、总输入和输出 token,并且更早回复。

三次等待阶段合计,开启组相比关闭组:

指标 关闭 OFF 开启 ON 开启相对关闭
模型响应 93 133 +43.0%
输入 token(含缓存) 1,374,342 2,155,491 +56.8%
输出 token(已含推理输出) 5,021 10,838 +115.9%
按 Astra Fast API 单价计算的费用 $4.6955 $7.3066 +55.6%

分享文案中的 43%、57%、116% 是表中百分比取整。费用的 $4.70 → $7.31、+55.6% 使用同一等待阶段口径,按官方 API 价格分别计算非缓存输入、缓存输入和输出;缓存输入的官方单价就是非缓存输入的十分之一,不是假设折扣。

Astra low:开启 clock.sleep 后,三次等待合计 API 费用高出 55.6%,关闭 $4.70、开启 $7.31;第二对费用方向相反。

日志里更值得关注的是策略变化: 开启组反复“检查 → sleep → 再检查”;关闭组自己写 shell 程序持续监控,把频繁检查交给本地进程。

六次都成功读取文件,随机校验值和修改时间均通过核验。开启组实际调用了原生 sleep 67 次,全部正常结束。六轮都只有 一个 turn,自动续跑为零

边界也放在前面: 只有一个任务、一个模型档位、三对样本;第二对开启组的 API 费用反而低 3.2%。这次没有测试 sleep 被新消息打断的价值,也不能推断所有任务都该关闭它。

1. 为什么做这个实验?

Relux 的分析讨论了 Codex 等待过程中的开销,并提到 clock.sleep 能缓解其中一部分。于是我提出一个更窄的问题:

在同一个文件等待任务中,仅改变原生 clock.sleep 的可用性,模型会怎样选择等待策略,响应、token、费用和交付延迟会发生什么变化?

这是一组补充观察,不是对 Relux 文中所有场景的复现或反驳。本次六轮没有发生 Goal 自动续跑。

Codex 原始 PR #28429说明的设计理由包括让等待可以被用户新消息或 mailbox 输入提前打断。这与“外部文件一出现就唤醒模型”不同;本实验没有向模型发送文件完成通知。

2. 实验怎样运行?

相同任务,独立文件,真实等待

每轮都从一个新任务和空目录开始,给模型完全相同的提示:

开启 goal:等待当前目录的 done.txt 文件出现;文件出现后实际读取它,告诉我文件内容和文件的修改时间,然后完成 goal 并停止。文件将由已经启动的外部程序创建;不要自行创建或修改它,不要查看外部程序的实现或干预它,不要使用子 agent。

外部程序先启动,等待真实 600 秒后,原子生成 done.txt,里面有随机校验值和 UTC 时间。

  • 模型不知道要等多久,提示里没有“10 分钟”。
  • 没有要求模型使用 sleep、shell,或者最小化 token;等待策略由它自己选。工作目录名也不提示等待时长。
  • 中途没有人工提醒、完成通知或人为续跑。
  • 每个条件使用独立生成器,各自计时、各自生成文件。

这样,模型需要实际等待和读取文件,不能仅凭猜测回复内容。

固定条件

项目 固定值或规则
客户端 Codex CLI 0.154.0
模型和推理档位 GPT-6 Astra / low;不是对默认 medium 的测试
请求服务档位 priority,对应 Fast
Goal 两组均开启,无 Goal token budget
实验规模 3 对,每对 2 个条件并发;共 6 次正式运行
外部等待 每轮真实 600 秒
任务输入 相同任务提示、空目录、同一客户端模型目录快照
工具差异 只改变原生 clock.sleep 的可用性;两组均可运行 shell

两组使用同一 CLI、模型、推理档位、服务档位、提示和客户端模型目录快照。clock.curr_time 保持相同。每对有效功能开关的唯一差异是 sleep_tool

# 开启条件
features.sleep_tool = { enabled = true, mode = "always_on" }

# 关闭条件:只把 enabled 改成 false
features.sleep_tool = { enabled = false, mode = "always_on" }

always_on 用于明确控制实验中的工具可用性;这不是对所有用户默认设置的调查。先用两个独立探针验证“开时能调用,关时没有工具”,探针不计入正式样本。

三对依次进行,每对两个条件并发,但启动时间不完全相同;第一对先关后开,第二、三对先开后关。顺序在运行前按 seed 2026091202 和平衡方案确定。脚本和协议在正式实验前用本地哈希冻结,没有公开预注册或第三方时间戳

不因为模型选了其他工具、没有使用 sleep、报错或完成较慢而剔除样本。六个预定样本全部保留。每轮有 900 秒、300 万累计输入 token、3 万输出 token、80 turns 的保护上限。

工具定义会随可用性变化,后续上下文也会随模型行为发展。这里比较的是工具可用性对端到端行为的影响,不是强制执行相同命令后比较 sleep 函数本身的性能。

统计口径

  • 主要指标: 预先确定为外部生成器启动至文件生成之间完成的模型响应数。
  • 等待阶段: 按完成事件的时间归属整个响应及其用量,不把跨越边界的单次响应按秒拆分;包含建立 Goal 等步骤,不能把全部计数都称为浪费。
  • 模型响应: 一个独立完成的 response ID,不等于用户提问数、turn 数或工具调用数。
  • 最终回复延迟: 从每轮自己的文件生成时刻,到该轮最终回复;不是整个任务耗时。
  • 费用: 实验完成后,用已记录 token 和官方 API 单价计算的派生指标;不是预先指定的主要指标。

响应和 token 从逐响应事件独立复算,并与服务端累计用量核对。事件边界使用记录的 UTC 时间;外部程序确实等待约 600 秒,另以单调时钟核验。第二对两种时钟的跨度约差 0.198 秒,这一记录保留在完整报告中。

3. 每一对结果是什么?

下表并列比较的两组数字均按“关闭 / 开启”排列。 回复延迟分别从各自文件生成时刻计算;费用只覆盖等待阶段。

配对(关闭 case / 开启 case) 等待阶段模型响应 最终回复延迟,秒 API 费用,美元 开启费用相对关闭
1(case-01 / case-02) 31 / 58 6.28 / 13.27 $1.559640 / $3.381420 +116.8%
2(case-04 / case-03) 35 / 38 7.23 / 16.76 $1.916036 / $1.853904 -3.2%
3(case-06 / case-05) 27 / 37 6.19 / 55.30 $1.219824 / $2.071256 +69.8%

第二对关闭组虽然响应更少,但非缓存输入更多:38,802 对 23,989 token,因此费用方向与响应次数不同。不能把“响应更少”直接写成“每一对都更便宜”。

三对是描述性结果,不据此声称统计显著性、总体平均效果或普遍收益。逐轮 token 分项见 results.csv,逐轮费用见 costs.json

4. 两组实际怎样等待?

我们能观察到行为差异;模型为什么偏好某个策略,现有日志不能确证。

模型选择的两种等待流程

开启组:模型反复参与检查和等待。 它调用命令检查文件;没有出现,就调用 clock.sleep;时间到了,再决定检查文件和下一次等多久。本次实际等待间隔在 10–50 秒之间。

关闭组:先写一个持续监控的小程序。 程序内部每 1–2 秒检查文件,出现后读取并输出。模型仍然会查看终端状态,所以模型响应没有降到零;但程序内部的每一次检查,都不需要单独调用模型。

下面只是帮助理解的伪代码;每轮实际命令保存在证据包的 evidence/case-*/tool-calls.csv

开启组:
  模型检查文件
  → 没有:模型调用 clock.sleep
  → 等待结束:模型再次检查

关闭组:
  模型启动一个程序:
    while 文件不存在:
      等待 1–2 秒
    读取文件并输出
  模型通过终端工具等待/查看程序结果,随后回复

注意:关闭的是原生 clock.sleep,并没有禁止 shell 的 sleep 或普通程序等待。两组都能运行 shell。这个实验比较的是“多提供这一个工具,会怎样影响模型的行为”。

第三对:文件出现后,为什么又睡了 45 秒?

这一轮有一个很直观的过程。以下为开启组的真实 UTC 日志:

时间 发生了什么
13:14:17.173 检查返回:文件还没出现
13:14:19.649 外部程序记录文件已生成
13:14:21.268 模型依据先前结果,调用 45 秒 sleep
13:15:06.289 sleep 正常结束
13:15:10.021 读取命令返回文件内容和修改时间

文件在“检查”和“开始睡眠”之间出现了。睡眠没有接到新输入,就按设定时长结束。开启组最终在文件生成后 55.30 秒回复;配对关闭组是 6.19 秒

这是检查间隔带来的延迟;日志没有显示 sleep 工具执行失败。

两组最终回复延迟相差约 49.11 秒。45 秒是其中一次实际 sleep 的时长,不等于全部相对延迟。六轮没有工具解析错误或命令非零退出。

5. API 费用怎样计算?

三次等待合计:关闭 $4.6955 → 开启 $7.3066,开启高出 55.6%。 若以开启组为基准,关闭则节省 35.7%。百分比的分母不同,不能混用。

计算使用 2026-09-12 核对的 OpenAI 官方价格。实验请求的服务档位是 priority,官方现称 Fast mode,所以下表采用对应的 Fast 公开单价。费用由记录用量按统一的官方 API 单价计算。

类别 每百万 token 单价 关闭:token 开启:token 关闭:美元 开启:美元
非缓存输入 $20 80,262 106,211 $1.6052 $2.1242
缓存输入 $2 1,294,080 2,049,280 $2.5882 $4.0986
输出(已含推理输出) $100 5,021 10,838 $0.5021 $1.0838
三次等待合计 $4.6955 $7.3066
Fast API 费用(美元)
= 非缓存输入 × 20 / 1,000,000
+ 缓存输入   ×  2 / 1,000,000
+ 输出       × 100 / 1,000,000

开启相对关闭的增幅
= (7.306580 / 4.695500 - 1) × 100%
= 55.6081% ≈ 55.6%

这里没有将全部输入按原价计算,也没有把 reasoning token 再加一次。六轮日志中的 cacheWriteInputTokens 均为零;如果另一次实验出现缓存写入,需按对应写入价格单独处理。逐响应核验的最大输入是 20,894 token,低于 272K 的长上下文加价门槛;不能用多次请求的累计输入来判断是否触发该门槛。Astra 计价规则

缓存输入是官方定价的十分之一,不是假设折扣。 第二对的反向结果已在逐对表中完整列出。

若统一采用 Standard 单价(非缓存输入 $10、缓存输入 $1、输出 $50 / 百万 token),同一批等待用量折算为关闭 $2.347750、开启 $3.653290,涨幅仍为 55.6%。若统计整轮任务,包括文件生成后的读文件和最终回复,Fast API 费用为关闭 $5.032740、开启 $7.833848,开启高出 55.7%。正文主要比较始终采用等待阶段口径。

以上使用公开 API 单价,不计税费、地区附加费、合同优惠或本地进程运行成本。

6. 可以得出什么结论?

这组数据支持的观察: 在本任务的三对 Astra low 运行中,原生 sleep 的可用性伴随着不同的自选等待策略;开启组每对响应、总输入、输出更多且回复更晚,合计 API 费用也更高。

尚未验证的推论: 默认 medium 或更高推理档位、其他模型、不同任务、更长等待、更多重复次数,以及被用户新消息打断时,是否仍会如此。也没有测试“保留工具,但提示模型优先写监控程序”。

这三对来自同一天、一个模型档位、一条中文提示。客户端目录快照不能锁定服务端权重、路由或缓存;并发和启动顺序等也可能影响结果。没有做显著性检验,不声称首次发现,不把本结果解释成工具失效或所有等待都应关闭 sleep。

“模型越强,是否越该信任它自身,只在频繁出错时才加工具或 prompt 干预?”可以作为由本次观察引出的思考,不是本实验已经证明的结论

7. 下载与复现

文件 用途
astra-clock-evidence.zip 原实验归档:六轮脱敏事件、工具记录、生成器日志、协议、原始分析和复现脚本
results.csv 六轮结果汇总
calculate-costs.py 对已发布用量按固定 API 单价计算费用
costs.json 每轮与合计、等待阶段与整轮、Fast 与 Standard 的费用结果
第一张高清图 / 第二张高清图 最终版英文 PNG,2000 × 2000
x-final-graphics.zip 两张 PNG、矢量 SVG、图注和说明
SHA256SUMS.txt 当前 Gist 正文和附件的 SHA-256

A. 核对已有实验与费用:不调用模型

下载 astra-clock-evidence.zipcalculate-costs.pycosts.json 到同一个目录。需要 Python 3.11 或以上,不需要第三方 Python 库。

原实验 ZIP 的 SHA-256:

5946e815d45ef4a86f000e661619c1a8b49f0eb27b31fa61733579e60ac1ebc2

从下载目录执行:

unzip astra-clock-evidence.zip -d astra-clock-evidence
cd astra-clock-evidence
python3 recount_public.py

预期是六个 case-*,每个都有 "all_pass": true。脚本从公开事件独立复算整轮和等待期响应与 token、turn、自动续跑、sleep 调用,以及随机校验值读取和最终回复状态,共 6 × 9 = 54 项检查。文件修改时间等额外审计见 verification.jsonevidence/case-*/audit.json

仍在解压目录中,校验归档内文件哈希:

python3 - <<'PY'
import hashlib, json
from pathlib import Path
manifest = json.loads(Path('SHA256SUMS.json').read_text())
bad = [name for name, expected in manifest.items()
       if hashlib.sha256(Path(name).read_bytes()).hexdigest() != expected]
if bad:
    raise SystemExit(f'Hash mismatch: {bad}')
print(f'OK: {len(manifest)} files match')
PY

再回到下载目录,复算费用并与 Gist 结果比较:

cd ..
python3 calculate-costs.py astra-clock-evidence --output-dir cost-recalculated
python3 - <<'PY'
import json
from pathlib import Path
expected = json.loads(Path('costs.json').read_text())
actual = json.loads(Path('cost-recalculated/costs.json').read_text())
if actual != expected:
    raise SystemExit('Cost results differ')
print('OK: cost results match')
PY

费用脚本使用十进制运算,分别输出每轮、每组、等待阶段、整轮任务的结果;还检查记录中的缓存写入和逐响应输入长度。价格固定为 2026-09-12,不自动获取新价。

B. 在自己的账号重新运行

原实验环境是 macOS/POSIX、Python 3.11+、已登录的 Codex CLI 0.154.0。Windows 原生环境没有验证。模型访问权限不足时不能复现这组 Astra 实验;不要静默换模型。

先下载并解压证据 ZIP,然后从下载目录进入:

cd astra-clock-evidence

如果已有正确版本的 Codex,可跳过安装。也可以把这个版本安装到当前研究目录里,避免替换全局版本:

# 仍在解压后的 astra-clock-evidence 目录;需要 Node.js / npm
npm install --prefix ./cli-runtime @openai/codex@0.154.0
export PATH="$PWD/cli-runtime/node_modules/.bin:$PATH"
codex --version
# 预期:codex-cli 0.154.0

# 尚未登录时再运行
codex login

运行者自己的 ~/.codex/models_cache.json 中须有 gpt-6-astra 条目;必要时先启动一次 Codex,确认账号可选择 Astra 后退出。脚本使用你自己的模型目录快照,原实验完整目录没有公开。

接下来,复制到一个不存在的新目录。目录名不要提示开关条件或等待时长:

python3 prepare_reproduction.py ../session-study-new
cd ../session-study-new

# 先做工具可用性探针,再冻结本次复制实验的哈希
python3 study.py --probe
python3 verify_preflight.py

# 仅在探针通过后运行;会调用真实模型并消耗账号用量
python3 study.py

# 运行结束后分析并核验
python3 analyze_study.py
python3 verify_final.py

三对约需 30–45 分钟,另加模型和初始化开销。不要缩短外部生成器的 600 秒,不要中途提醒模型文件已生成,也不要失败后覆盖或只保留漂亮结果。想重跑时创建另一个新目录。

成功完成后,查看 results.csvsummary.jsonverification.jsonruns/case-*/derived/复现的是实验方法,不保证再次得到相同数字。

脚本不修改全局配置,但会读取本机 Codex 配置。它显式关闭原环境的四个 MCP server,以及 apps/plugins/memories/multi_agent。其他机器可能还有额外 MCP、hooks、技能或配置,需要检查并记录,保证两组一致。不要在含研究说明或仓库指令的工作目录内直接让模型执行本实验。

两个常见失败:Codex version drift 表示 PATH 中版本不对;找不到模型目录或 Astra 条目表示本地目录/账号条件未满足。解决后应在新目录重做探针,不要绕过验证继续正式实验。

若要重画原始图表,另安装 matplotlib 后运行 plot_study.py。原中文绘图脚本使用 macOS 的 STHeiti Light.ttc,其他系统需换成可用中文字体;绘图不是运行和复算实验的前置条件。

公开数据的范围

原实验 ZIP 保持不变,保留实验完成时的分析和旧图;本 Gist 正文、费用附件与两张英文图是面向本次分享整理的版本。费用是在原始用量上新增的分析,没有改写执行记录。

公开事件经过允许名单筛选和路径脱敏,不包含认证信息、完整模型目录、完整 RPC 日志、系统/开发者提示或内部推理内容。原始私有文件哈希与脱敏副本哈希不是同一个概念;脱敏文件应使用公开包自己的 SHA256SUMS.json 校验。

相关材料

ae107ebbc02d14f665de3a322818d5bac8973990b66e9bc536ae26e221482458 00-README.md
7d90181fa8efa46a1d84608c328312a48d12f6d0c36ec1d79aeb6173db69c5b5 01-x-result.png
87120ae05780e3c1f349e0b410b682ed07c56c5dfc3a397d02773544f80751d7 02-x-behavior.png
5946e815d45ef4a86f000e661619c1a8b49f0eb27b31fa61733579e60ac1ebc2 astra-clock-evidence.zip
37148a238c85374957e118cb54b2524616203d4b3e89278aceeabc82083ec3ef calculate-costs.py
d1faf75971b562d4eec3b596129dcba7cf13047a9d5dbcdfcfe3dfbccfb2d64c costs.json
79ba5aa993597a2dd7c32a077d252937b063e57b04acdedd77e35d4db4f80bf3 results.csv
9d774829aa98b29a059c3d4694a773b9c20239ac6179ef3d796ba101ebb83be2 x-final-graphics.zip
This file has been truncated, but you can view the full file.
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment