You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use Codex Fast mode against any provider whose API offers an accelerated processing tier — with the catalog only advertising Fast where the route can actually honor it, the wire request using each provider's own dialect, and usage/cost reporting reflecting what each attempt actually did.
This is the umbrella tracking issue for FastWire, the design that generalizes Fast mode across providers. It sequences the refactor phases and links the per-provider delivery units (starting with #1875 for xAI). The design went through a five-round adversarial review against the current code and was accepted as the implementation basis.
What prevents this today?
Fast mode is currently a single-dialect feature, with three hardwired assumptions:
The only wire shape OpenCodex can emit is service_tier: "priority", and only on the two OpenAI adapters (openai-chat, openai-responses). Anthropic's speed: "fast" + beta header, Groq's service_tier: "performance", and Azure's deployment-scoped priority cannot be expressed at all.
The catalog Fast blurb is the OpenAI one ("1.5x speed, increased usage") for every provider, even where the provider's actual terms differ (xAI Priority Processing bills at 2× the standard token price).
chatServiceTier couples chat serialization into capability resolution (serviceTierSupportForModel() inlines canSerializeServiceTierForChatModel()), so one flag simultaneously influences catalog publication, routing-profile require.serviceTier eligibility, compatibility fingerprints, injection, and the gate.
Additionally, cost attribution reads top-level request fields rather than per-attempt outcomes, which mis-prices combo/fallback attempts, and there is no way to express "this provider's fast tier exists but is entitlement-gated" without either lying in the catalog or blocking the capability entirely.
What should OpenCodex do?
Separate three concerns that are currently entangled (existing config field names unchanged):
FastCapability — may this provider/model/auth route offer Fast at all? Existing tri-state fields: supportsServiceTier (provider-level, false is fail-closed), modelSupportsServiceTier (exact-match), auth-mode overlay.
CallerTierForward — may caller-supplied foreign tiers (flex, unknown strings) be forwarded? This becomes chatServiceTier's sole duty after migration.
FastWire — how does canonical Fast serialize on this route? A new registry descriptor: kind: "service-tier" | "anthropic-speed", a canonicalToWire map, foreignCallerTiers: "verbatim" | "drop", optional betas.
Key behaviors:
The Codex-side contract never changes. The catalog always publishes service_tiers: [{id: "priority", name: "Fast"}]; the internal canonical tier stays "priority"; translation to the provider dialect happens only at the final serialization step.
FastPolicyAuthority + one pure resolver. Catalog flights capture an immutable authority before takeoff (declaration tri-state fastWire: FastWire | null | undefined, precomputed modelWireOverrideAllowed covering the canonical-OpenAI-forward wire-override guard, auth transport, capability maps, model adapters, hard pins, route pins). resolveFastPolicy(authority, modelId, inbound) is shared by catalog and runtime. capability (pure tri-state) stays separate from eligibility (eligible | capability-unsupported | unclassified | wire-unavailable | pin-unavailable); catalog, routing, and injection consume only eligibility === "eligible".
The outbound decision honors the existing three-state contract.support === false: fail-closed strip. support === undefined: full passthrough — fastMode does not intervene, no translation, no injection (today's behavior, preserved). Only support === true ∧ fastWire ≠ null enters the force-fast / force-default / inherit state machine.
Billing truth moves per attempt. Each attempt records an AttemptTierOutcome (canonical tier, wire kind/value, fastOutcome: not-requested | applied | downgraded | unknown, confirmation, response echo). Pricing becomes an explicit (provider, model, tierBand) matrix; a missing cell with no per-entry priceRelation: "gte-standard" evidence yields cost unavailable ("unpriced-tier") rather than a guessed multiplier.
Fast is a routing preference, not a requirement. A route that cannot express Fast strips it and records fastOutcome: "downgraded"; it never filters candidates.
Provider defaults (registry):
Provider
fastWire
capability default
OpenAI / ChatGPT
derived default (service-tier / priority)
true (status quo)
xAI (API key)
service-tier / priority
key-auth overlay true — #1875, held until pricing verified
provider undefined; verified slugs exact-true, each with an atomic route pin (final only ⊆ pin ∧ allow_fallbacks: false; conflict downgrades Fast instead of overriding user routing)
Groq
service-tier / performance
false; enterprise users opt in explicitly
Cerebras
service-tier / priority
false; dedicated-endpoint users opt in
Anthropic
anthropic-speed / fast + betas
undefined; verified in Phase C
Google
explicit null
deferred — no Interactions wire path yet
Kimi / MiniMax -highspeed
excluded
separate model IDs, not a request tier; the Fast toggle must never silently swap models
Delivery phases:
A0 — characterization only (zero production changes): lock the current three-state fastMode contract, the support undefined × fastMode × caller {priority, fast, flex} matrix, exact-model foreign-tier forwarding, requestedServiceTier recording timing, routing-profile require.serviceTier evidence, fingerprint projection, raw-body observation points, catalog byte goldens, and the two known bugs below as current behavior.
A1 — pure refactor (zero outbound-wire bytes, zero catalog bytes): FastWire / FastPolicyAuthority / ResolvedFastPolicy / tier-decision state machine land; kind→adapter table contains only the existing two adapters; inbound normalization produces internal markers only.
while the Codex catalog row advertises the same priority/Fast tier it does everywhere else, and the usage log records wireValue: "performance" with canonical "priority". On an Anthropic route (Phase C), the same Fast selection would instead produce "speed": "fast" plus the documented beta header, and never a service_tier field.
Alternatives or workarounds
Keep adding per-provider booleans to the current supportsServiceTier/chatServiceTier machinery. Rejected: it cannot express non-OpenAI dialects (Anthropic, Groq values), keeps the capability/serialization coupling, and forces every entitlement-gated provider into "lie in the catalog or block entirely".
Users can already hand-declare modelSupportsServiceTier/chatServiceTier on custom providers, but that only works for OpenAI-dialect upstreams and silently mis-prices attempts because cost reads top-level request fields.
Treating "fast" model variants (Kimi/MiniMax -highspeed) as the Fast toggle. Rejected: that silently swaps model IDs and billing; those stay separate catalog models.
History: Phase 90 deliberately stripped inherited Fast metadata from every routed provider pending per-transport verification; FastWire restores it only where the final transport is verified, and makes the verification unit (shape vs. capability vs. pricing) explicit.
Design provenance: five review rounds against the live code preceded this issue; the review-driven corrections (three-state passthrough preservation, per-attempt billing, atomic OpenRouter pins, modelWireOverrideAllowed) are folded into the text above.
Checks
I searched existing issues and documentation.
This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
Area
Multiple areas
What are you trying to accomplish?
Use Codex Fast mode against any provider whose API offers an accelerated processing tier — with the catalog only advertising Fast where the route can actually honor it, the wire request using each provider's own dialect, and usage/cost reporting reflecting what each attempt actually did.
This is the umbrella tracking issue for FastWire, the design that generalizes Fast mode across providers. It sequences the refactor phases and links the per-provider delivery units (starting with #1875 for xAI). The design went through a five-round adversarial review against the current code and was accepted as the implementation basis.
What prevents this today?
Fast mode is currently a single-dialect feature, with three hardwired assumptions:
service_tier: "priority", and only on the two OpenAI adapters (openai-chat,openai-responses). Anthropic'sspeed: "fast"+ beta header, Groq'sservice_tier: "performance", and Azure's deployment-scoped priority cannot be expressed at all.chatServiceTiercouples chat serialization into capability resolution (serviceTierSupportForModel()inlinescanSerializeServiceTierForChatModel()), so one flag simultaneously influences catalog publication, routing-profilerequire.serviceTiereligibility, compatibility fingerprints, injection, and the gate.Additionally, cost attribution reads top-level request fields rather than per-attempt outcomes, which mis-prices combo/fallback attempts, and there is no way to express "this provider's fast tier exists but is entitlement-gated" without either lying in the catalog or blocking the capability entirely.
What should OpenCodex do?
Separate three concerns that are currently entangled (existing config field names unchanged):
supportsServiceTier(provider-level,falseis fail-closed),modelSupportsServiceTier(exact-match), auth-mode overlay.flex, unknown strings) be forwarded? This becomeschatServiceTier's sole duty after migration.kind: "service-tier" | "anthropic-speed", acanonicalToWiremap,foreignCallerTiers: "verbatim" | "drop", optionalbetas.Key behaviors:
service_tiers: [{id: "priority", name: "Fast"}]; the internal canonical tier stays"priority"; translation to the provider dialect happens only at the final serialization step.FastPolicyAuthority+ one pure resolver. Catalog flights capture an immutable authority before takeoff (declaration tri-statefastWire: FastWire | null | undefined, precomputedmodelWireOverrideAllowedcovering the canonical-OpenAI-forward wire-override guard, auth transport, capability maps, model adapters, hard pins, route pins).resolveFastPolicy(authority, modelId, inbound)is shared by catalog and runtime.capability(pure tri-state) stays separate fromeligibility(eligible | capability-unsupported | unclassified | wire-unavailable | pin-unavailable); catalog, routing, and injection consume onlyeligibility === "eligible".support === false: fail-closed strip.support === undefined: full passthrough —fastModedoes not intervene, no translation, no injection (today's behavior, preserved). Onlysupport === true ∧ fastWire ≠ nullenters theforce-fast / force-default / inheritstate machine.AttemptTierOutcome(canonical tier, wire kind/value,fastOutcome: not-requested | applied | downgraded | unknown, confirmation, response echo). Pricing becomes an explicit(provider, model, tierBand)matrix; a missing cell with no per-entrypriceRelation: "gte-standard"evidence yieldscost unavailable ("unpriced-tier")rather than a guessed multiplier.fastOutcome: "downgraded"; it never filters candidates.Provider defaults (registry):
service-tier/priority)true(status quo)service-tier/prioritytrue— #1875, held until pricing verifiedservice-tier/priorityundefined(neverfalse); per-deployment exact-model opt-inservice-tier/priorityundefined; verified slugs exact-true, each with an atomic route pin (finalonly ⊆ pin ∧ allow_fallbacks: false; conflict downgrades Fast instead of overriding user routing)service-tier/performancefalse; enterprise users opt in explicitlyservice-tier/priorityfalse; dedicated-endpoint users opt inanthropic-speed/fast+ betasundefined; verified in Phase Cnull-highspeedDelivery phases:
fastModecontract, thesupport undefined × fastMode × caller {priority, fast, flex}matrix, exact-model foreign-tier forwarding,requestedServiceTierrecording timing, routing-profilerequire.serviceTierevidence, fingerprint projection, raw-body observation points, catalog byte goldens, and the two known bugs below as current behavior.FastWire/FastPolicyAuthority/ResolvedFastPolicy/ tier-decision state machine land; kind→adapter table contains only the existing two adapters; inbound normalization produces internal markers only.callerServiceTierraw evidence, value-aware gate, fingerprint projection, dashboard per-attempt display.fastCapabilityForModel()replaces the resolver's inline chat-serializer coupling. Three precisely-scoped behavior changes: (a) provider-true∧ chat adapter ∧chatServiceTier ≠ true∧ no exact-true→ injection starts working; (b) caller"fast"on supported routes → serialized as the canonical translation; (c) exact-true∧chatServiceTier ≠ true∧ caller foreign tier → dropped instead of forwarded.false; chat→responses converter dropsservice_tier.anthropic-speedwire kind, after live verification on both auth entries.Out of scope: Google Interactions API, requirement-mode routing, multi-tier UI beyond Fast, model-swap "highspeed" variants.
Example usage or interface
A Groq enterprise user with Performance-tier entitlement opts in with one line:
{ "providers": { "groq": { "supportsServiceTier": true } }, "fastMode": true }Because the registry already declares Groq's wire shape (
canonicalToWire: { priority: "performance" }), the effective Chat Completions body becomes:{ "model": "llama-3.3-70b-versatile", "service_tier": "performance" }while the Codex catalog row advertises the same
priority/Fast tier it does everywhere else, and the usage log recordswireValue: "performance"with canonical"priority". On an Anthropic route (Phase C), the same Fast selection would instead produce"speed": "fast"plus the documented beta header, and never aservice_tierfield.Alternatives or workarounds
supportsServiceTier/chatServiceTiermachinery. Rejected: it cannot express non-OpenAI dialects (Anthropic, Groq values), keeps the capability/serialization coupling, and forces every entitlement-gated provider into "lie in the catalog or block entirely".modelSupportsServiceTier/chatServiceTieron custom providers, but that only works for OpenAI-dialect upstreams and silently mis-prices attempts because cost reads top-level request fields.-highspeed) as the Fast toggle. Rejected: that silently swaps model IDs and billing; those stay separate catalog models.Additional context
modelWireOverrideAllowed) are folded into the text above.Checks