Why
Operator expectation: "all subscription credentials should work" for ctx.llm. Today that's true for Anthropic (Claude Pro/Max access tokens are accepted by the Messages API with the OAuth beta header — the CLAUDE_CODE_OAUTH_TOKEN contract) but impossible for OpenAI via the platform API, probe-verified 2026-06-04 against a real codex subscription tokens.access_token:
POST api.openai.com/v1/chat/completions + subscription bearer → auth ACCEPTED, billing refused:
{"error":{"message":"You exceeded your current quota...","type":"insufficient_quota","code":"insufficient_quota"}}
POST api.openai.com/v1/responses (the sign-in-with-ChatGPT path, tried gpt-5.5-codex and gpt-5.5) → scope-blocked:
{"error":{"message":"You have insufficient permissions for this operation. Missing scopes: api.responses.write...","type":"invalid_request_error"}}
So cloud's resolver correctly refuses to inject these tokens as OPENAI_API_KEY (cloud#1890) — injecting one produces configured-then-insufficient_quota on every call, strictly worse than the explicit stub. The current mitigations are workarounds: anthropic cross-stamp for openai-family personas (workforce#197), house relay-managed key, or platform BYOK.
What
A third provider leg in packages/runtime/src/cloud-llm.ts that speaks the codex/ChatGPT backend protocol (what the codex CLI itself uses for subscription inference) instead of the platform API:
- New credential source recognized by
selectCredential (e.g. CODEX_OAUTH_TOKEN / a structured env the cloud resolver can emit for provider_oauth + openai once this leg exists).
- The leg implements the codex backend session/completion exchange (endpoint, headers, account_id from the auth blob, streaming shape) and adapts it to the
LlmContext interface.
- Token refresh: subscription access tokens expire in hours — compose with the existing refresh seam (cloud's
refreshHarnessCliCredentialIfStale already refreshes openai blobs via auth.openai.com/oauth/token).
- Cloud follow-up (separate PR): lift the
provider_oauth+openai rejection in resolveCredentialValue to emit the new env contract instead of throwing, and stamp openai-family selections in the deploy clients.
Open questions
- Protocol stability/ToS: the ChatGPT backend API is not a published platform contract; assess maintenance risk before committing (the codex CLI's own implementation is the reference).
- Model mapping: subscription backend serves codex-tuned models;
resolveModel needs a mapping table rather than pass-through.
Context
cloud#1890 (rejection + rationale), workforce#196/#197 (selections stamping + cross-stamp fallback), probe transcript in the team channel 2026-06-04.
🤖 Generated with Claude Code
Why
Operator expectation: "all subscription credentials should work" for
ctx.llm. Today that's true for Anthropic (Claude Pro/Max access tokens are accepted by the Messages API with the OAuth beta header — the CLAUDE_CODE_OAUTH_TOKEN contract) but impossible for OpenAI via the platform API, probe-verified 2026-06-04 against a real codex subscriptiontokens.access_token:POST api.openai.com/v1/chat/completions+ subscription bearer → auth ACCEPTED, billing refused:{"error":{"message":"You exceeded your current quota...","type":"insufficient_quota","code":"insufficient_quota"}}POST api.openai.com/v1/responses(the sign-in-with-ChatGPT path, triedgpt-5.5-codexandgpt-5.5) → scope-blocked:{"error":{"message":"You have insufficient permissions for this operation. Missing scopes: api.responses.write...","type":"invalid_request_error"}}So cloud's resolver correctly refuses to inject these tokens as
OPENAI_API_KEY(cloud#1890) — injecting one produces configured-then-insufficient_quotaon every call, strictly worse than the explicit stub. The current mitigations are workarounds: anthropic cross-stamp for openai-family personas (workforce#197), house relay-managed key, or platform BYOK.What
A third provider leg in
packages/runtime/src/cloud-llm.tsthat speaks the codex/ChatGPT backend protocol (what the codex CLI itself uses for subscription inference) instead of the platform API:selectCredential(e.g.CODEX_OAUTH_TOKEN/ a structured env the cloud resolver can emit forprovider_oauth+ openai once this leg exists).LlmContextinterface.refreshHarnessCliCredentialIfStalealready refreshes openai blobs viaauth.openai.com/oauth/token).provider_oauth+openai rejection inresolveCredentialValueto emit the new env contract instead of throwing, and stamp openai-family selections in the deploy clients.Open questions
resolveModelneeds a mapping table rather than pass-through.Context
cloud#1890 (rejection + rationale), workforce#196/#197 (selections stamping + cross-stamp fallback), probe transcript in the team channel 2026-06-04.
🤖 Generated with Claude Code