research/codex-app-server-byo-auth/analysis.md

5.2 KiB

Analysis — Codex App Server: Embeddable Agent Protocol & BYO Auth

Part of codex-app-server-byo-auth/index

Protocol deep-dive

Transports and lifecycle

  • Default transport is stdio (newline-delimited JSON). WebSocket and unix socket are alternatives; WebSocket is explicitly experimental and unsupported for production workloads (docs: "The app-server command and WebSocket transport are experimental and aren't supported for production workloads").
  • Every connection: initialize (with clientInfo identifying your product) → initialized notification → then any method. Requests before initialization get Not initialized.
  • Core primitives: Thread (a conversation), Turn (one user request + agent work), Item (units: user message, agent message, command run, file change, tool call).
  • Lifecycle: thread/start (or resume/fork), turn/start, then read streamed notifications (item/*, turn/completed), optionally turn/steer mid-flight, turn/interrupt to cancel.
  • Capabilities opt-in: experimentalApi: true unlocks gated methods/fields (e.g. thread/backgroundTerminals/*, process/spawn). requestAttestation opt-in for desktop hosts.
  • Bindings: codex app-server generate-ts / generate-json-schema produce per-version exact schemas — no drift between your types and the protocol.

Auth modes (the core of this research)

account/login/start accepts:

  1. chatgpt (managed browser flow) — Codex owns OAuth, persists + auto-refreshes tokens. useHostedLoginSuccessPage, appBrand options.
  2. chatgptDeviceCode — same managed lifecycle, but the user approves via a device code on another device. Best for web — no account on your side needed.
  3. chatgptAuthTokens (experimental) — host app already owns the user's ChatGPT auth: supply accessToken, chatgptAccountId, optional chatgptPlanType; app-server requests fresh tokens from you on 401. You own the refresh loop.
  4. apiKey — classic BYOK.
  5. Bedrock (amazonBedrock) — AWS credential chain or Codex-managed key.
  • account/updated notification reports auth mode changes + planType; account/read reports account/plan details; account/rateLimits/read + account/usage/read let your app surface the user's plan limits.

The BYOK harness pattern

"Sign in with ChatGPT" ≠ identity provider

  • Google/GitHub sign-in → identity (email, profile). ChatGPT sign-in via app-server → model capability ("run Codex workloads billed to this user's ChatGPT plan"). No email/profile returned; chatgptAccountId is OpenAI-side only.
  • Composable pattern: gmail/github = identity layer; ChatGPT = optional model-access layer.

The no-sign-in + BYOK shape

Works for both local and hosted apps. The one design decision that matters: where does the key live?

Shape Key placement Notes
Local/desktop app Client-side (localStorage/file), never leaves machine Cleanest; BYOK-as-auth works perfectly, no server secrets
Hosted web, no sign-in User's browser (localStorage, per-session) OR your DB DB = you hold third-party secrets (security surface); browser = per-session, simpler
Hosted + device-code Token stays in Codex's own credential store, not yours Best "no-account" web option

Adapter pattern (maps to user's Effect Layer/DI)

One provider interface, multiple implementations:

  • ApiKeyProvider (OpenRouter/OpenAI key)
  • ChatGptAuthProvider (app-server device-code or external tokens) The harness (agent loop, tools, UI) is provider-agnostic — same as the user's Service + Layer adapter composition pattern from the job-aggregator/law-retrieval projects.

Architecture shapes

  • Each user runs their own codex app-server process locally (stdio or unix socket), app connects over the local transport.
  • Key/auth stored client-side. No server secrets. WebSocket not needed.
  • Best fit: local tools, CLI-adjacent products, developer apps.

B. Hosted multi-tenant (more work, experimental transport)

  • Per-user codex app-server processes on your infra, bridged over wss (WebSocket is experimental/unsupported for prod — this is the main risk).
  • Key placement decision is critical: your DB (security surface) vs user's browser vs Codex-managed device-code tokens.
  • Compliance: clientInfo.name feeds OpenAI's Compliance Logs Platform; contact OpenAI to get on a known-clients list for enterprise use.
  • Capacity: each user's ChatGPT plan rate limits apply (account/rateLimits/read to surface them).

Risks / caveats

  • Gray-area posture: Anthropic banned the Claude-equivalent BYO-subscription pattern; OpenAI currently tolerates this via the official protocol, but that posture can change.
  • Transport: WebSocket experimental — hosted production means real engineering (per-user processes + bridge), not a drop-in.
  • Capacity: user's plan bounds capacity; account/rateLimitResetCredit/consume exists but is user-side.
  • Compliance: identify your client; enterprise integrations should be on OpenAI's known-clients list.
  • Not identity: can't use chatgptAccountId as your user key.