作者:@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 价格分别计算非缓存输入、缓存输入和输出;缓存输入的官方单价就是非缓存输入的十分之一,不是假设折扣。
日志里更值得关注的是策略变化: 开启组反复“检查 → sleep → 再检查”;关闭组自己写 shell 程序持续监控,把频繁检查交给本地进程。
六次都成功读取文件,随机校验值和修改时间均通过核验。开启组实际调用了原生 sleep 67 次,全部正常结束。六轮都只有 一个 turn,自动续跑为零。
边界也放在前面: 只有一个任务、一个模型档位、三对样本;第二对开启组的 API 费用反而低 3.2%。这次没有测试 sleep 被新消息打断的价值,也不能推断所有任务都该关闭它。
Relux 的分析讨论了 Codex 等待过程中的开销,并提到 clock.sleep 能缓解其中一部分。于是我提出一个更窄的问题:
在同一个文件等待任务中,仅改变原生
clock.sleep的可用性,模型会怎样选择等待策略,响应、token、费用和交付延迟会发生什么变化?
这是一组补充观察,不是对 Relux 文中所有场景的复现或反驳。本次六轮没有发生 Goal 自动续跑。
Codex 原始 PR #28429说明的设计理由包括让等待可以被用户新消息或 mailbox 输入提前打断。这与“外部文件一出现就唤醒模型”不同;本实验没有向模型发送文件完成通知。
每轮都从一个新任务和空目录开始,给模型完全相同的提示:
开启 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 秒,这一记录保留在完整报告中。
下表并列比较的两组数字均按“关闭 / 开启”排列。 回复延迟分别从各自文件生成时刻计算;费用只覆盖等待阶段。
| 配对(关闭 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。
我们能观察到行为差异;模型为什么偏好某个策略,现有日志不能确证。
开启组:模型反复参与检查和等待。 它调用命令检查文件;没有出现,就调用 clock.sleep;时间到了,再决定检查文件和下一次等多久。本次实际等待间隔在 10–50 秒之间。
关闭组:先写一个持续监控的小程序。 程序内部每 1–2 秒检查文件,出现后读取并输出。模型仍然会查看终端状态,所以模型响应没有降到零;但程序内部的每一次检查,都不需要单独调用模型。
下面只是帮助理解的伪代码;每轮实际命令保存在证据包的 evidence/case-*/tool-calls.csv:
开启组:
模型检查文件
→ 没有:模型调用 clock.sleep
→ 等待结束:模型再次检查
关闭组:
模型启动一个程序:
while 文件不存在:
等待 1–2 秒
读取文件并输出
模型通过终端工具等待/查看程序结果,随后回复
注意:关闭的是原生 clock.sleep,并没有禁止 shell 的 sleep 或普通程序等待。两组都能运行 shell。这个实验比较的是“多提供这一个工具,会怎样影响模型的行为”。
这一轮有一个很直观的过程。以下为开启组的真实 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 的时长,不等于全部相对延迟。六轮没有工具解析错误或命令非零退出。
三次等待合计:关闭 $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 单价,不计税费、地区附加费、合同优惠或本地进程运行成本。
这组数据支持的观察: 在本任务的三对 Astra low 运行中,原生 sleep 的可用性伴随着不同的自选等待策略;开启组每对响应、总输入、输出更多且回复更晚,合计 API 费用也更高。
尚未验证的推论: 默认 medium 或更高推理档位、其他模型、不同任务、更长等待、更多重复次数,以及被用户新消息打断时,是否仍会如此。也没有测试“保留工具,但提示模型优先写监控程序”。
这三对来自同一天、一个模型档位、一条中文提示。客户端目录快照不能锁定服务端权重、路由或缓存;并发和启动顺序等也可能影响结果。没有做显著性检验,不声称首次发现,不把本结果解释成工具失效或所有等待都应关闭 sleep。
“模型越强,是否越该信任它自身,只在频繁出错时才加工具或 prompt 干预?”可以作为由本次观察引出的思考,不是本实验已经证明的结论。
| 文件 | 用途 |
|---|---|
| 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 |
下载 astra-clock-evidence.zip、calculate-costs.py 和 costs.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.json 和 evidence/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,不自动获取新价。
原实验环境是 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.csv、summary.json、verification.json 和 runs/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 校验。
- Relux:Why Codex burns a weekly limit in a day while the agent waits for the tide:本实验的讨论起点,场景与本实验不完全相同。
- Codex 原始 sleep PR #28429:新输入可打断等待的设计背景。
- Microsoft SentinelBench:相关的长时监控与等待工具研究,不作为本次结果的证明。
- OpenAI API Pricing:本次费用计算使用的官方单价。



