Surface server-declined service tiers (Fast mode silently falls back to standard in codex exec)
What variant of Codex are you using?
CLI (codex-cli 0.144.0, macOS, ChatGPT auth)
What feature would you like to see?
Two related asks around Fast mode in non-interactive use:
1. Warn when the serviced tier differs from the requested tier. #31284 added a client-side warning when the configured service tier isn't advertised by the model catalog. The silent case remains: the request goes out with the tier and the server declines it. response.completed already reports the tier that actually serviced the request, so the client has what it needs to surface "Fast mode was requested but this turn ran on standard."
2. Clarify (and ideally support) Fast mode for codex exec. Related: #22622. Verified on 0.144.0 and an instrumented build of main (6138909d6e): with service_tier = "priority" in config.toml (what /fast on persists) and the fast_mode feature enabled, codex exec turns DO transmit "service_tier":"priority" in the websocket response.create payload — but the backend echoes service_tier:"auto" and response.completed reports "default". Same result on gpt-5.6-sol and gpt-5.5, so it is not model-specific. If Fast mode is intentionally unavailable for headless traffic, documenting that (plus the warning from ask 1) would save users the investigation; if it's meant to work, honoring the transmitted tier would be even better.
Additional information
Repro:
# config.toml: service_tier = "priority"; features fast_mode enabled
RUST_LOG=trace codex exec -m gpt-5.6-sol -c 'service_tier="priority"' "Reply with exactly one word: ok"
# trace shows the outbound response.create payload carrying "service_tier":"priority",
# response.created echoes "auto", response.completed reports "default"
Why headless matters: the Codex plugin for Claude Code (https://github.com/openai/codex-plugin-cc) delegates review/rescue work through the local Codex CLI and app server, so codex exec-style non-interactive runs are becoming a primary surface. Plugin users who configure Fast mode currently get the standard tier with no signal anywhere that their setting isn't taking effect.
2 Comments
Thanks for the existing report. I reproduced and extended this on macOS with the latest standalone CLI available during the investigation (
codex-cli 0.144.5, ChatGPT auth,fast_modeenabled, Responses WebSocket handshake HTTP 101).This appears closely related to #30413 and #32191, so I am adding evidence here rather than opening a duplicate issue.
Additional environment
0.144.5(updated withcodex updatefrom0.144.1)transport="responses_websocket",wire_api=responses)gpt-5.6-terragpt-5.5,gpt-5.6-luna,gpt-5.6-terra, explicitgpt-5.3-codex-sparkcodex doctor --jsonreportedoverallStatus: "ok",fast_modeenabled, ChatGPT auth configured, and a successful Responses WebSocket handshake.Catalog result
I queried the live app-server
model/listresponse on0.144.5:The four returned models were:
This differs from #30413, which reports a local model cache advertising
priority/Fast forgpt-5.5. That cache-vs-app-server discrepancy may itself be relevant.Effective-tier probe
I drove app-server JSON-RPC directly with fresh ephemeral threads.
GPT-5.5 without a tier:
GPT-5.5 with an explicit priority tier:
Both
thread/startresponses returned:The same normalization to
nulloccurred for Spark with bothserviceTier: "priority"andserviceTier: "fast". Spark is not present inmodel/list, but explicit model selection is accepted.This indicates that this app-server/model-resolution path removes the tier before the model request. It also means a timing comparison using these requests cannot establish backend priority behavior.
Streaming measurements
I timestamped live agent-message delta notifications over app-server stdio JSON-RPC and captured
thread/tokenUsage/updatedoutput-token counts. The prompt was the same approximate-10,000-word Unix process architecture prompt for each run.GPT-5.5 result:
The output lengths differed, and the priority request was not confirmed as effective (
thread/startresolved it tonull). The useful observation is that observed generation cadence was the same: approximately 55 output tokens/second and 18 ms per streamed delta. These runs should not be interpreted as proof that the backend ignored a valid priority request.Relevant source behavior
In
codex-rs, the lower-level request format supports the field:The WebSocket conversion copies it into
response.create, and there is a serialization test usingservice_tier: Some("priority").Separately, the TUI service-tier resolver only retains a configured tier when the selected model advertises it in
service_tiers; otherwise it returnsNone. The livemodel/listresult above advertises no tiers.Requested clarification/fix
Could the team clarify which of these is expected?
/fastas active.model/listis stale/incomplete. If so, please publish the supported tiers and effective defaults in the app-server catalog.response.created/response.completedservice-tier metadata and surface a warning when the requested tier differs from the serviced tier.For a definitive client/backend diagnostic, it would help if app-server exposed:
The key issue is that a user-visible Fast setting can currently collapse to
nullbefore the request, or potentially be downgraded by the backend, without an observable reason. That makes it impossible to tell whether Fast is active or to evaluate its performance impact.Related: #30413, #32191.
I reproduced this on the current CLI with a controlled output-length benchmark. This adds one important data point beyond the earlier reports: the request includes the newer
x-codex-routing-hinttier signal, but Fast still has no measurable effect on generation speed.Environment
0.149.0Darwin 25.5.0 arm64 armgpt-5.6-solxhighThe live model catalog advertised Fast for
gpt-5.6-solwithservice_tiers=[{id: "priority", name: "Fast"}]andadditional_speed_tiers=["fast"].Wire-level verification
For every Fast run, CLI
0.149.0sent all of the expected signals:All requests returned HTTP 200.
response.completed.response.service_tierwasdefaultfor both Standard and Fast.Controlled A/B result
I ran three Standard requests and three Fast requests in a balanced order, using the same account, model, effort, machine, prompt, and transport. The prompt was:
Every response produced exactly 3,005 non-reasoning output tokens, so the durations are directly comparable.
| Mode | Durations | Mean | Aggregate visible output rate |
|---|---:|---:|---:|
| Standard | 57.232s, 56.915s, 58.142s | 57.430s | 52.32 tok/s |
| Fast (
priorityon wire) | 56.797s, 57.864s, 57.861s | 57.507s | 52.25 tok/s |Fast was 0.14% slower on the mean, which is effectively identical. This is far from the documented 1.5x speed increase. At the observed Standard rate, a 1.5x Fast run would be expected to finish in roughly 38 seconds rather than 57.5 seconds.
This conclusion does not rely on
response.service_tier=defaultalone: the measured output cadence itself is the same across both modes.Why this seems actionable
Earlier reports predated the model/tier routing hint added in #37345. On
0.149.0, the catalog advertises Fast and the client sends bothservice_tier=priorityand thetier=priorityrouting hint, yet the backend behavior is still indistinguishable from Standard.Could the CLI/backend expose whether Fast was accepted, rejected, or downgraded, and why? If Fast cannot be applied for a turn,
/fast statusshould not present it as effectively active without a warning.Related: #30413. Official documentation: https://learn.chatgpt.com/docs/agent-configuration/speed#fast-mode