Skip to content

OpenAI#

A first-party model-provider reference for PluggableHarness Agent: OpenAI's model lineup, reasoning/caching behavior, and wire-protocol shape, as they bear on building the docs/specifications/model/ plugin adapter for this vendor. Descriptive reference, not a protocol spec — see docs/specifications/model/ for PluggableHarness Agent's own design authority.

1. Overview#

OpenAI is the default reference point most coding-agent authors build against first, given how much of the ecosystem's function-calling and streaming conventions trace back to its Chat Completions API. Its current model naming mixes a gpt-<major>.<minor> numbered lineage (gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, gpt-5.4) with suffixed variants that signal a specialization rather than a generation bump: -mini (smaller/ cheaper), -codex/-codex-max (coding-specialized), and -realtime-* (voice/speech, a separate product line entirely). The sol/terra/luna split within the 5.6 line itself is a naming pattern distinct from anything else in the lineup — nothing in the available data indicates whether these three are general-purpose siblings or differentiated by size/latency/cost tier the way -mini variants usually are.

The practical implication for a plugin author is that "the OpenAI model family" is not one uniform surface. Reasoning control is a request-level parameter rather than a separate model switch, prompt caching is fully automatic with no caller-side markup, and (per §5 below) confirmation depth drops off sharply outside the newest flagship line — a plugin adapter should not assume a -mini, -codex, or -realtime variant matches the flagship's behavior just because it shares the gpt-5 prefix.

2. Model roster & capabilities#

Model Context window Max output Tool use Vision Streaming Notes
gpt-5.6-sol 1,050,000 128,000 Yes Yes Uncertain Flagship-tier confirmation on every field except streaming, which is unconfirmed even here — unusual for a current flagship.
gpt-5.6-terra 1,050,000 128,000 Yes Yes Uncertain Same confirmation profile as gpt-5.6-sol.
gpt-5.6-luna 1,050,000 128,000 Yes Yes Uncertain Same confirmation profile as gpt-5.6-sol; naming pattern (sol/terra/luna) undocumented — treat as distinct models, not confirmed size/cost tiers.
gpt-5.5 1,000,000 Uncertain Uncertain Yes Uncertain Smaller context than the 5.6 line — plausible predecessor generation.
gpt-5.4 Uncertain Uncertain Uncertain Yes Uncertain Almost entirely unconfirmed beyond vision support.
gpt-5.4-mini Uncertain Uncertain Uncertain Uncertain Uncertain Mini tier — vision support unconfirmed; do not assume parity with gpt-5.4.
gpt-5.3-codex Uncertain Uncertain Yes Uncertain Uncertain Codex-branded, likely coding-specialized; only tool use is confirmed.
gpt-5.1-codex-max Uncertain Uncertain Yes Uncertain Uncertain Only tool use is confirmed.
gpt-realtime-2 Uncertain Uncertain Uncertain Uncertain Yes Realtime/voice family — see the wire-protocol flag below.
gpt-realtime-translate Uncertain Uncertain Uncertain Uncertain Yes Same caveat as gpt-realtime-2.
gpt-realtime-whisper Uncertain Uncertain Uncertain Uncertain Yes Likely speech-to-text-only; may not support tool use or vision at all — streaming is the only field confirmed for any of the three realtime models.

No model in this lineup is flagged as retired or deprecated in the available data. The most unusual outlier is that streaming support is uncertain for every non-realtime model, including all three current gpt-5.6-* flagships — normally the flagship line is where confidence is highest, but here confirmation gaps run "sideways" as much as "downward" by tier. The three gpt-realtime-* models are the inverse case: streaming is the one field confirmed for them (all Yes), while everything else is uncertain.

3. Reasoning & prompt caching#

Reasoning is controlled by a discrete reasoning_effort request parameter with model-dependent value sets — typical levels are minimal, low, medium, high, xhigh, and max, though not every model supports every level. This is not a separate "thinking" model variant and not a continuous token budget; it's the same model with a configurable effort knob. The available data does not confirm a default effort level applied when a request omits reasoning_effort entirely, nor whether reasoning can be disabled outright on any given model — both should be treated as open questions per model rather than assumed.

Prompt caching is fully automatic: no explicit cache-breakpoint markers in the request, no code changes required to benefit from it. It activates for prompts over 1,024 tokens, caching the longest matching prefix in 128-token increments starting at that threshold. Cached tokens carry a 50% discount versus a fresh input token. The cache is scoped at the organization level (not shared across organizations) and expires after 5–10 minutes of inactivity, with a stated maximum retention of one hour — meaningful for a plugin considering a keepalive strategy to hold a cache warm across a tool-execution gap.

The data does not distinguish reasoning or caching behavior between individual models beyond the general pattern above — no evidence here of a gpt-5.6-* model using a different caching or reasoning mechanism than gpt-5.4 or the -codex variants, but this is also not independently confirmed per model, only assumed by extension from the general OpenAI mechanism.

4. Wire format & auth#

A tool call arrives on the wire as a tool_calls array entry on the assistant message, shaped {id, type: "function", function: {name, arguments}} — critically, arguments is a JSON-encoded string, not a parsed object, so a plugin adapter must JSON.parse() (or the Go equivalent) it before use. finish_reason: "tool_calls" signals that the turn ended on a pending tool call and the loop should continue. A tool result is submitted back as a new message with role: "tool" and a tool_call_id matching the original call's id.

Authentication is an HTTP Bearer token: Authorization: Bearer <API_KEY_OR_ACCESS_TOKEN>, with optional OpenAI-Organization and OpenAI-Project headers for org/project scoping. Rate limiting surfaces as HTTP 429 responses, with the active limits and remaining headroom exposed via response headers: x-ratelimit-limit-requests, x-ratelimit-limit-tokens, x-ratelimit-remaining-requests, x-ratelimit-remaining-tokens, x-ratelimit-reset-requests, and x-ratelimit-reset-tokens — enough for a client to implement proactive backoff without waiting for a 429 to occur.

5. Confirmed vs. uncertain#

Solidly confirmed (consistent across roster, reasoning, and wire data): context window and max output for the gpt-5.6-sol/terra/luna trio; tool use and vision for the same trio; vision support on gpt-5.5 and gpt-5.4; tool use on both -codex models; the reasoning-effort mechanism and its general value set; the automatic prompt-caching mechanism, its 1,024-token/128-token-increment thresholds, 50% discount, and organization-level scoping; the tool-calling wire shape (string-encoded arguments); the Bearer-token auth scheme; and the rate-limit header names.

Genuinely uncertain and worth an independent check before a plugin adapter relies on it:

  • Streaming support, oddly, across nearly the entire non-realtime lineup — including all three current gpt-5.6-* flagship models. This is unusual: streaming is typically one of the first-confirmed capabilities for a vendor's headline models, and its absence here should not be read as "probably yes" just because OpenAI's Chat Completions API has supported streaming for years elsewhere in the ecosystem.
  • Nearly every field (context window, max output, tool use, vision, streaming) on gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex, and gpt-5.1-codex-max. Do not assume any of these match the gpt-5.6-* flagship figures just because they share the gpt-5 prefix — gpt-5.5 is already confirmed to have a smaller context window than the 5.6 line, which is evidence against assuming parity anywhere else in the family.
  • The entire gpt-realtime-* familygpt-realtime-2, gpt-realtime-translate, gpt-realtime-whisper. Streaming is the only confirmed field for all three; context window, max output, tool use, and vision are all uncertain. More importantly, this family very likely speaks a different wire protocol (WebSocket-based) than the standard Chat/Responses shape the rest of this document describes — the tool-calling format and rate-limit header behavior above should not be assumed to carry over to realtime models at all. gpt-realtime-whisper in particular is plausibly speech-to-text-only and may not support tool use or vision in any meaningful sense.
  • Whether reasoning can be disabled on any model, and what effort level (if any) applies by default when a request omits reasoning_effort.

6. Implications for PluggableHarness Agent#

Two adapters, not one. The strongest signal in this data is that the gpt-realtime-* family likely requires a fundamentally different transport than the rest of the OpenAI lineup. The protocol's StreamCompletion RPC is specified as server-streaming-with-cancellation over the standard canonical-message request/response shape; if the realtime models genuinely speak WebSocket rather than that shape, an OpenAI plugin targeting them cannot simply route through the same StreamCompletion handler as gpt-5.6-*/-codex — it either needs an internal protocol bridge (WebSocket in, StreamEvents out) inside the plugin process, or the realtime family should be excluded from an initial OpenAI plugin's supported roster until that translation is designed and verified. Given the confirmation gaps above, verifying transport shape before writing any realtime-model handling is a prerequisite, not an implementation detail.

ModelSpec.supports_streaming as an honesty check, not a formality. Because streaming is uncertain for every non-realtime model in this slice, including the current flagships, a plugin author should treat this field as requiring direct verification against the live API rather than defaulting it to true by assumption. Per data-types.md#modelspec, this field is a UX hint (whether the frontend renders a live-typing cursor), not a transport-shape switch — protocol.md#streamcompletion requires every plugin to implement the StreamCompletion RPC shape regardless, emitting a single terminal burst if the backend itself is batch-only. That still means an OpenAI adapter must get the boolean itself right per model, since getting it wrong misleads the frontend regardless of which RPC shape is actually used underneath.

ThinkingSpec mapping. OpenAI's reasoning_effort parameter is a textbook fit for ThinkingSpec's effort control, with levels populated per model from the confirmed value set (minimal/low/medium/high/xhigh/max, where supported). Because the default applied on an omitted reasoning_effort isn't confirmed by this data, the adapter author needs to determine it directly against the live API per model before publishing an effort.default — shipping a guessed default would violate the field's stated purpose of making real default behavior auditable, and the conformance suite rejects a default that is not one of the declared levels. disable and adaptive_by_default likewise need real per-model answers rather than assumed ones.

CachingSpec mapping. OpenAI's automatic caching maps directly onto CachingSpec's implicit_automatic: true, with explicit_markers: false — so the adapter never needs to place cache breakpoints on content blocks the way an Anthropic or Mistral adapter would, and MUST ignore any it is sent. The 5–10 minute inactivity TTL (max one hour) is short enough that an OpenAI plugin wanting to exploit the keepalive mechanism should seriously consider implementing it — keepalive_supported: true — given the 50% cached-token discount is meaningful savings for any multi-turn coding session with gaps between turns for tool execution. Pricing.cache_write_per_mtok is not meaningful for an automatic-caching vendor in the way it is for an explicit-marker one; only cache_read_per_mtok needs a real non-null value.

Tool-call argument translation. OpenAI's arguments field arrives as a JSON-encoded string, not a parsed object — the adapter sits on the string-encoding side of the split called out in data-types.md's tool schema section. Per that section, the kernel's internal ToolCall/ToolResult representation stores arguments as already-parsed JSON, so the OpenAI adapter owns both directions of translation: parsing the string on the way in, and re-serializing to a string on the way out for any tool-result resubmission that echoes arguments back.

Roster completeness before GetCapabilities ships. Given how many fields are uncertain outside the gpt-5.6-* trio, an initial OpenAI GetCapabilities implementation has a real choice to make: ship ModelSpec entries only for the models with confirmed field sets (risking an incomplete roster) or ship every model with honestly uncertain fields resolved to real values pulled from a live API check before publishing (the safer choice, since GetCapabilities is a MUST-implement, cheaply-repeatable call the kernel may query before every routing decision — a wrong ModelSpec value here propagates into every routing decision made against it, not just an initial guess that gets corrected later).