ChatGPT Subscription
Canonical source:
docs/CHATGPT_SUBSCRIPTION_TRANSPORT.md. This page is refreshed from the Finch repository when the website builds.
Finch’s chatgpt_subscription provider is a Finch-owned HTTP transport. It does
not execute Codex, app-server, or any other provider binary, and it never reads
another application’s credential store. It is intentionally separate from the
OpenAI Platform and generic OpenAI-compatible transports.
Versioned compatibility contract
Section titled “Versioned compatibility contract”The public Responses API create method documents the message, image, function, encrypted reasoning, and streaming item shapes used here; the separate GPT-5.6 Sol model reference documents that model’s public API settings.
ChatGPT subscription routing is a compatibility contract derived from the
public OpenAI Codex source at commit 6478a751fde8884b2fdc76486fe23175a8e795d4.
Finch records that pin as
openai-codex-responses-lite@6478a751fde8884b2fdc76486fe23175a8e795d4.
The relevant source files are:
codex-rs/codex-api/src/endpoint/responses.rscodex-rs/codex-api/src/endpoint/models.rscodex-rs/codex-api/src/sse/responses.rscodex-rs/codex-api/src/rate_limits.rscodex-rs/core/src/client.rscodex-rs/protocol/src/openai_models.rs
Protocol drift fails closed; it is not silently treated as Platform behavior.
Catalog discovery sends client_version=0.160.0, and both catalog and
inference requests send version: 0.160.0. That is a released Codex
version, not Finch’s application version or a claim that Finch is Codex. It
is ahead of the audited source revision (which corresponds to 0.151.0): the
catalog served to 0.151.0 omitted GPT-6.1 Sol, so the version was moved
before the request-shape audit was redone, and that audit is still owed. Updating either
compatibility pin requires auditing the newer public Codex catalog and
Responses-Lite contracts, updating both pins together, and rerunning the
focused tests plus the explicit live acceptance test.
Identity and routing
Section titled “Identity and routing”Only a named ChatgptSubscription credential created by Finch’s device-login
flow can select this provider. Its issuer, audience, account, store reference,
revision, and generation are revalidated before reuse and after refresh.
The production origin is exactly https://chatgpt.com with these routes:
GET /backend-api/codex/models?client_version=0.160.0POST /backend-api/codex/responses
Requests use bearer authorization, ChatGPT-Account-ID, honest
originator: finch, the pinned compatibility version, and the pinned
protocol revision. Application identity remains separate: both routes use the
bounded static client identifier
finch/<version> (+https://darwin-finch.github.io/) as their
User-Agent, where <version> is Finch’s package version. It contains no
username, hostname, Brain/session, account, or credential identifier. This
provides honest client identification and project discoverability only; it
does not guarantee that OpenAI exposes telemetry or metrics to Finch. Sol
requests additionally send
x-openai-internal-codex-responses-lite: true.
Redirects, custom endpoints, userinfo, fragments, FedRAMP, Platform fallback,
and model fallback are rejected.
The account catalog is bounded and cached by account plus credential
generation. ETags may revalidate an expired cache, but an entry from another
account is never reused. A requested gpt-5.6-sol or gpt-5.6 entry must be
explicitly advertised with text, image, API, and Responses-Lite support before
inference.
Their numeric context_window values are authoritative account-catalog
metadata when they fall in the defensive range 1..=10,000,000; Finch does
not treat one exact window size as a dialect or authorization discriminator.
Missing, non-numeric, zero, and excessive values fail closed without exposing
the catalog body or account credentials. The synchronous capability descriptor
reports the context window as unknown because it cannot perform credentialed
account discovery; the validated catalog retains the exact value for each
selectable model. The service may advertise either pinned identifier without
advertising both. Finch requires the exact configured/requested identifier to
be present and compatible before inference, so an alias is never silently
substituted and an unrecognized slug is never accepted.
Request and continuation semantics
Section titled “Request and continuation semantics”Every request uses store: false, stream: true,
include: ["reasoning.encrypted_content"], and
reasoning.context: "all_turns". Reasoning effort is explicit. An omitted
profile setting emits medium, matching the
documented GPT-5.6 Sol default;
explicit low, medium, high, xhigh, and max settings are preserved.
The public API also documents none, but Finch does not send it through the
separately pinned subscription Responses-Lite route without route-specific
conformance evidence. Instructions
and tools are Responses-Lite developer items; user/assistant text, validated
PNG/JPEG inputs, function calls, and function outputs retain their history
order.
The request prefix follows the audited Codex v0.151.0 Responses-Lite shape:
ordinary function definitions are nested under the functions namespace, and
the additional_tools and developer-instructions items carry deterministic
UUID-v5 IDs with at_ and msg_ prefixes. Codex scopes those payload-derived
IDs to its thread UUID. Finch does not expose a Codex thread at this provider
boundary, so it scopes them to the pinned protocol revision instead; identical
visible prefix payloads therefore keep identity across retries without putting
a username, Brain, account, credential, or host identifier on the wire. The
pin must be re-audited if OpenAI changes the prefix identity contract.
ChatGPT reserves unprefixed collaboration names such as spawn_agent for its
own native namespace. Finch advertises its corresponding local primitives with
application-owned wire aliases (finch_spawn_agent, finch_await_agent,
finch_poll_agent, and finch_cancel_agent) and maps a validated response back
to the local name. A returned custom function may identify the advertised
functions namespace, use collaboration only with one of those aliases, or
omit the namespace as permitted by the observed Responses-Lite shape. Other
namespaces, raw native collaboration names, malformed namespace values,
unadvertised tools, and attempts to advertise a reserved Finch alias fail
closed.
The audited client also sends fields tied to Codex-owned thread and client
state, including prompt_cache_key and client_metadata. Finch does not
fabricate those values: they remain absent until Finch has an independently
defined, reviewed contract for them.
Encrypted reasoning is provider-owned opaque data. Finch bounds it, persists it as an ordered content block through the atomic conversation path, and replays it byte-for-byte. Finch never renders or interprets it. The IPC generation is 8; generation 6 peers reject the typed image and complete-content stream schema before query or stream work.
Streaming and failure policy
Section titled “Streaming and failure policy”The SSE parser bounds each line and event and the total response. It validates
standard event: names against JSON event types, requires strictly increasing
sequence numbers, accumulates completed output items by contiguous output
index, and treats validated response.output_item.done items as the
authoritative output when they are present. A terminal completion snapshot may
omit already-streamed reasoning, but its remaining items must match streamed
messages and function calls in order and one-to-one after ignoring only
validated passive item metadata. Terminal message/tool omissions, additions,
duplicates, reordering, and semantic changes fail closed.
Actual-model provenance is optional: when absent Finch reports the validated
requested catalog route; when present the bounded serving-model identity may
differ from that route but must remain unchanged throughout the response.
Unknown fields/events, malformed tool arguments, missing completion, duplicate
terminal markers, post-terminal data, partial EOF, idle timeout, receiver drop,
and payload-limit violations fail visibly before terminal chunks are published.
Unknown-field errors identify only Finch’s static containing-object or event
label; response-derived field names and values are never reflected. The pinned
Codex source tolerates response.usage.extra as an unknown passive object. A
Finch-owned PR acceptance evidence on 2026-09-05
additionally observed an object named response.usage.attribution; this is
dated live-service compatibility evidence, not a field declared by the pinned
public Codex usage struct. Finch accepts only those two named passive metadata
objects. Attribution is bounded to 256 KiB; extra remains bounded by the
enclosing stream-event limit. Neither can alter Finch’s validated input/output
token accounting, and other usage siblings remain fail-closed.
A separate Finch-owned PR acceptance record on 2026-09-05
requested one spawn_agent custom function call. The service response passed
the namespace and advertised-tool checks and rebound to exactly one local
spawn_agent call with the requested arguments. The acceptance test parses the
call but never executes it.
User dogfood on 2026-09-05 after the collaboration namespace fix
exercised the full Finch path: a fresh session advertised and executed three
local spawn_agent calls, awaited their results, and produced a final typed
Lisp response. This is evidence for that exact tested account and date, not a
general entitlement, provider-parity, or release-readiness claim.
Non-success bodies are consumed only to a small bound and discarded. A Responses-Lite rejection retains a typed HTTP status and a compatibility or entitlement hint, never the response body. Tokens, account identifiers, request bodies, image data, tool arguments, reasoning continuations, and response bodies are never placed in provider errors.
Proactive refresh is generation-bound and serialized. A 401 before the stream starts permits one shared refresh, a fresh account catalog check, and one retry. There is no retry after successful stream headers or any response event.
Opt-in live acceptance
Section titled “Opt-in live acceptance”Live auth and inference are never part of normal tests. After independent security review, a user who has explicitly completed Finch’s own device login can run:
FINCH_LIVE_CHATGPT_ACCEPTANCE=1 \FINCH_LIVE_CHATGPT_CONFIG="$HOME/.finch/config.toml" \FINCH_LIVE_CHATGPT_OAUTH_ROOT="$HOME/.finch/oauth" \CARGO_BUILD_JOBS=2 \./.agents/skills/finch-backlog/scripts/with-cargo-slot \ ./scripts/test_brains.sh cargo test --lib \ providers::chatgpt_subscription::tests::live_chatgpt_subscription_acceptance_is_explicitly_opt_in \ -- --ignored --exactThe explicit paths let the supervised test read Finch’s real configuration and use Finch’s production OAuth store while all other test state remains in the supervisor’s disposable home. The configuration file is not modified. The OAuth store retains production behavior: it creates its normal lock and may atomically refresh the credential when it is near expiry or the service returns 401. The test selects a Finch-owned named credential and requires non-empty model provenance plus the exact requested static response text. It does not print tokens or response bodies. Until that opt-in test is run, live-service acceptance—including current account entitlement and server-side compatibility with the pinned revision—remains intentionally unverified.
The same reviewed environment can verify the collaboration-tool binding without executing the returned tool:
FINCH_LIVE_CHATGPT_ACCEPTANCE=1 \FINCH_LIVE_CHATGPT_CONFIG="$HOME/.finch/config.toml" \FINCH_LIVE_CHATGPT_OAUTH_ROOT="$HOME/.finch/oauth" \CARGO_BUILD_JOBS=2 \./.agents/skills/finch-backlog/scripts/with-cargo-slot \ ./scripts/test_brains.sh cargo test --lib \ providers::chatgpt_subscription::tests::live_chatgpt_subscription_collaboration_tool_is_explicitly_opt_in \ -- --ignored --exact