前言
8 月 30 日,OpenAI Codex 工程负责人 Tibo(Thibault Sottiaux)发帖宣布:团队逐条排查了数千份用户报告,修复了 8 类会"额外消耗额度"的问题,并为所有 Codex 和 ChatGPT Work 付费用户重置了使用额度------按使用方式不同,同等额度预计可多支撑 10%~50%。
额度重置是安抚措施,真正有价值的是那份 8 类问题清单。它等于 OpenAI 公开承认:一个月活 2000 万的 Agent 产品,在控制面(谁在花钱、花在哪、怎么停)上踩遍了几乎所有典型的坑。
这份清单是一份免费的故障模式教材。本文把它拆成四族故障、四条设计原则、一套回归测试,最后给一个可以直接移植到你项目里的"Agent 预算守卫"。
一、事件回顾:一次罕见的"官方自曝"
时间线:

量化数字(官方与多方信源一致):个别异常的 /goal 任务曾消耗一周额度的 15%~70% ;旧版 Computer History 在部分场景每周最多吃掉 约五分之一 额度;后台记忆进程曾因停止条件永远无法满足而运行多达 15000 次。
二、为什么"少发消息"救不了你的额度
很多人对 Agent 额度的直觉是"我发了多少条消息"。OpenAI 官方帮助文档明确:用量不只取决于消息数或时长,而取决于 token 量、模型选择、任务/上下文规模、本地或云端执行、Fast mode、上下文压缩、工具调用,以及后台任务(reviews、automations、subagents、terminals、memories)。
用户侧证据(社区报告,个案仅供参考):有 Pro 用户分析本地日志,发现 codex-auto-review 约占其记录用量的 75%------消耗发生在用户根本看不见的地方。
三个常见误区:
| 误区 | 真相 | | --- | --- | | "我少发几条消息就行" | 后台任务(记忆/自动化/评审)不经过你的消息计数 | | "上下文压缩是省 token 的" | 压缩本身是一次 LLM 调用;压缩策略有 Bug 时反而反复计费 | | "子任务用便宜模型更省钱" | 子 Agent 若意外升级到高成本模型(Bug ⑤),成本会反向爆炸 |
三、8 个 Bug 的分类学:四族故障模式
把 8 个 Bug 平铺罗列没有信息量,归类之后规律立刻浮现。
A 族 · 上下文管理(Bug ①⑥⑧) :压缩残留旧图导致反复压缩、Computer History 重复总结、MCP 结果重复编码或截断后重取。共同点:同一信息被多次编码、多次计费。
B 族 · 后台任务(Bug ②④⑦) :Memory Worker 停止条件永不满足(跑了 15000 次)、自动化运行频率高于配置、普通对话意外触发后台请求。共同点:后台执行体缺少硬终止条件或频率上限。
C 族 · 执行控制(Bug ③) :/goal 任务越过终止条件继续运行或反复重试,个别消耗周额度 15%~70%。共同点:自主循环没有预算熔断。
D 族 · 模型选择(Bug ⑤) :子 Agent 异常升级调用高成本模型。共同点:模型路由缺乏显式声明与约束。

这个分类的意义在于:修好 8 个具体 Bug 只能救 OpenAI 的用户,理解 4 族模式才能救你自己的 Agent 项目。
四、四条设计原则:从别人的事故里学架构
原则一:幂等压缩(治 A 族)
对被压缩/总结/编码的内容做内容寻址(hash 去重):同一段内容在会话全生命周期只总结一次,总结结果缓存复用。压缩后清理旧载荷时,必须原子性地"删除旧内容 + 记录已总结标记",两者缺一就会出现 Codex 的 Bug ①(旧图残留 → 下一轮再压缩一次)。
原则二:后台任务两阶段终止(治 B 族)
后台任务的停止条件必须是可满足的状态,而不是"永不触发"的循环判断(Bug ② 的 15000 次就是这么来的)。两阶段终止:第一阶段停止接受新工作,第二阶段等待在途任务收尾;外加一个看门狗(watchdog)------超过最大存活时间强制回收。automations 的调度频率必须以用户配置为硬上限,配置变更时旧任务要重新校准。
原则三:预算熔断器(治 C 族)
任何自主循环(goal、重试、探索)在启动前必须声明 token 预算;运行中累计消耗逼近阈值时先降级(缩小搜索空间/降低频率),越过阈值即硬熔断并汇报。熔断检查必须发生在"发出下一次请求之前"------等响应回来再检查,钱已经花出去了。这正是 Bug ③ 消耗 70% 周额度的根源:终止条件检查在循环边界上失效。
原则四:模型路由白名单(治 D 族)
子 Agent 的模型选择必须显式声明在任务描述符里,且只能从白名单中选;任何"自动选择更强模型"的逻辑默认关闭。D 族 Bug 的本质是隐式授权:主 Agent 调子 Agent 时没有传递成本约束,子 Agent 的"聪明选择"变成了账单炸弹。
五、把事故清单变成回归测试
社区(zeronoise)给出的建议值得直接采纳:把 8 类故障模式当作回归测试套件,在任何无人值守的 Agent 任务上线前跑一遍。
|
| 测试场景 | 断言 | | --- | --- | --- | | 1 | 图片密集会话触发多次压缩 | 同一图片只被编码一次;token 增量有上界 | | 2 | 带 /goal 的任务设置一个必然可达的停止条件 | 任务在条件满足后 N 步内终止 | | 3 | 后台记忆任务运行到最大存活时间 | 看门狗强制回收,无僵尸进程 | | 4 | 自动化任务以自定义频率调度 | 实际触发频率 ≤ 配置频率 | | 5 | 子 Agent 任务描述符 | 模型选择 ∈ 白名单;无隐式升级 | | 6 | 返回超大结果的 MCP 工具 | 结果只编码一次;截断后有标记,不重取 | | 7 | 普通对话轮次 | 无计划外后台请求产生 | | 8 | 记录每次请求的模型与 token 数 | 账单可按任务/来源归因 |
度量三件套:token 增量(分请求记录)、模型选择日志、任务是否按预期终止。没有这三个度量,上面的断言无从谈起------这就引出实战项目。
六、实战项目:写一个 Agent 预算守卫
四个原则浓缩成一个约百行的可移植中间件。接口只做三件事:计量(meter)、限流(enforce)、汇报(report)。
bash
# budget_guard.py --- Agent 预算守卫(可直接移植的最小实现)
from dataclasses import dataclass, field
from enum import Enum
import time
class GuardAction(Enum):
ALLOW = "allow" # 放行
DOWNGRADE = "downgrade" # 逼近阈值:降级(提示缩小上下文/换便宜模型)
BLOCK = "block" # 熔断:禁止发起新请求
# 模型路由白名单:治 D 族(隐式升级)
MODEL_WHITELIST = {
"planner": ["cheap-model"], # 规划类子任务只允许便宜模型
"worker": ["cheap-model", "pro-model"],
"reviewer": ["cheap-model"],
}
MODEL_COST_PER_1K = {"cheap-model": 0.002, "pro-model": 0.02}
@dataclass
class BudgetGuard:
token_budget: int # 任务级 token 总预算(治 C 族)
usd_budget: float # 任务级美元预算
watchdog_timeout_s: float = 600 # 看门狗:治 B 族(后台失控)
used_tokens: int = 0
used_usd: float = 0.0
ledger: list = field(default_factory=list) # 流水:治"账本不透明"
started_at: float = field(default_factory=time.time)
def check_model(self, role: str, model: str) -> str:
"""发请求前校验模型白名单,非法请求自动降级到白名单最便宜项。"""
allowed = MODEL_WHITELIST.get(role)
if allowed is None:
raise ValueError(f"未注册的任务角色: {role}")
if model not in allowed:
return allowed[0] # 拒绝隐式升级,显式降级
return model
def precheck(self, est_tokens: int, model: str) -> GuardAction:
"""关键点:检查发生在发请求之前,而不是收响应之后。"""
ratio = (self.used_tokens + est_tokens) / self.token_budget
cost = est_tokens / 1000 * MODEL_COST_PER_1K[model]
if time.time() - self.started_at > self.watchdog_timeout_s:
return GuardAction.BLOCK # 看门狗超时,硬熔断
if self.used_usd + cost > self.usd_budget:
return GuardAction.BLOCK # 美元预算熔断
if ratio >= 1.0:
return GuardAction.BLOCK # token 预算熔断
if ratio >= 0.8:
return GuardAction.DOWNGRADE # 80% 水位:降级运行
return GuardAction.ALLOW
def record(self, role: str, model: str, tokens: int) -> None:
"""每次请求后记账------流水是透明计费的地基。"""
self.used_tokens += tokens
self.used_usd += tokens / 1000 * MODEL_COST_PER_1K[model]
self.ledger.append({
"ts": time.time(), "role": role, "model": model,
"tokens": tokens, "cum_tokens": self.used_tokens,
"cum_usd": round(self.used_usd, 4),
})
def report(self) -> str:
"""按角色/模型归因的账单摘要------治 A/B 族的'看不见的消耗'。"""
by_role: dict = {}
for e in self.ledger:
by_role.setdefault(e["role"], 0)
by_role[e["role"]] += e["tokens"]
lines = [f"总消耗: {self.used_tokens} tokens / ${self.used_usd:.4f}"]
for role, tk in by_role.items():
lines.append(f" {role}: {tk} tokens ({tk/max(self.used_tokens,1):.0%})")
return "\n".join(lines)
6.1 集成演示:接进一个最小 Agent 循环
bash
def agent_loop(guard: BudgetGuard, goal: str, max_iters: int = 50):
for i in range(max_iters):
model = "pro-model"
model = guard.check_model("worker", model) # 白名单校验
est = 2000 # 粗估本次请求 token
action = guard.precheck(est, model) # 发请求前检查
if action == GuardAction.BLOCK:
print(f"[熔断] 第{i}轮:预算耗尽或看门狗超时,终止")
break
if action == GuardAction.DOWNGRADE:
model, est = "cheap-model", est // 2 # 降级运行
# response = call_llm(model, goal, ...) # 你的 LLM 调用
response_tokens = 1800 # 演示用假数据
guard.record("worker", model, response_tokens)
# ... 处理响应、判断 goal 是否达成(终止条件必须可达!)
else:
print("[警告] 达到最大迭代仍未终止------检查终止条件是否可满足")
print(guard.report())
6.2 项目讲解:三个设计决策
-
为什么
precheck在发请求前? 对应原则三。收到响应再检查等于"先花钱再对账",对失控循环毫无约束力。Codex 的/goalBug 正是循环边界上的检查失效 -
为什么要按角色/模型记账(ledger)? 对应"账本透明"。用户社区最集中的诉求是"按任务/来源归因"------
report()的输出就是你排查"额度去哪了"的第一手证据 -
为什么
check_model返回降级模型而不是抛异常? 对应原则四的工程化表述:白名单违规应当显式降级并记录,而不是让整条任务链失败------成本控制和可用性要同时成立
七、观点:额度透明度是下一个产品分水岭
OpenAI 在公告中承诺后续"在应用中进一步展示额度去向"。我认为这个承诺比额度重置更重要:
-
Agent 产品的竞争正从"能力"转向"能力 × 成本 × 可控性"三角。 单点跑分的天花板效应越来越明显,而"敢把账本给用户看"会成为企业采购的硬指标------企业要的是可预算、可审计、可熔断
-
成本工程不是附加功能,是控制面的一等公民。 Codex 这 8 个 Bug 全部出在控制面(压缩/后台/循环/路由),没有一个出在"代码写得不对"上。这说明 Agent 可靠性工程的主战场已经转移
-
给开发者的三条行动清单:① 无人值守任务上线前,跑一遍第五节的 8 条回归测试;② 任何自主循环都接预算熔断(本文 BudgetGuard 可以直接抄);③ 从今天起记录每次 LLM 请求的角色/模型/token 流水------没有流水,一切成本优化都是盲人摸象
一句话收束:这次事件最大的启示不是"OpenAI 也会犯错",而是------当 Agent 开始自主花钱,控制面设计就和中枢能力同等重要。8 个 Bug 是别人交过的学费,四条原则和一套测试是你能省下的学费。
参考资料
-
Tibo(@thsottiaux)官方公告,2026-08-29/30(经多方信源转述)
-
爱范儿:《Codex 修复 8 类额度异常,付费用户同等额度预计可多用 10%~50%》,2026-08-31
-
zeronoise.ai: Codex's Usage Reset Exposes Unbounded Agent Loops, 2026-08-31
-
OpenAI 社区:Codex Rate Limits Discussion Thread(用户侧证据,社区报告)
-
OpenAI 帮助文档:《在你的 ChatGPT 套餐中使用 Codex》