Skip to content

Refactor duplicate Codex Responses paths for agent turns and llm.complete #90193

@jalehman

Description

@jalehman

Summary

OpenClaw currently has two divergent Codex Responses paths that both reach the ChatGPT Codex Responses API but implement request/stream handling differently:

  • Normal agent turns use the provider-owned openai-chatgpt-responses implementation in src/llm/providers/openai-chatgpt-responses.ts.
  • Plugin/runtime simple completions, including llm.complete, rewrite Codex models through openclaw-openai-responses-transport via src/agents/simple-completion-transport.ts and then use the OpenAI SDK transport in src/agents/openai-transport-stream.ts.

This duplication recently caused a behavior split: normal Codex agent turns continued to work, while plugin llm.complete calls could fail on valid ChatGPT Codex HTTP 200 streams with missing content-type because the generic transport path had stricter header validation.

Why This Matters

The two paths are not merely cosmetic alternatives. They encode different assumptions about:

  • ChatGPT Codex URL normalization
  • OAuth/header construction
  • SSE parsing and error handling
  • response validation
  • WebSocket/cached-context behavior
  • usage and reasoning metadata handling

When those assumptions diverge, fixes in one path may not protect the other. The current incident is a concrete example: the provider-owned Codex path tolerated the observed upstream response shape, while the simple-completion transport path rejected it before the SDK could parse the stream.

Current Evidence

Relevant paths:

  • src/llm/providers/openai-chatgpt-responses.ts

    • direct Codex provider implementation for normal agent turns
    • builds https://chatgpt.com/backend-api/codex/responses
    • parses Codex SSE/WebSocket responses itself
  • src/agents/simple-completion-transport.ts

    • maps openai + openai-chatgpt-responses simple completions to openclaw-openai-responses-transport
    • normalizes ChatGPT base URLs to the SDK base URL form
  • src/agents/openai-transport-stream.ts

    • OpenAI SDK transport path used by the simple-completion alias
    • installs buildGuardedModelFetch(model) as the SDK fetch implementation
  • src/agents/provider-transport-fetch.ts

    • generic guarded fetch and response validation used by the OpenAI SDK transport path

Proposed Refactor Direction

Do not attempt this as part of a narrow incident fix. The immediate production fix should remain scoped to the broken validation behavior.

For follow-up refactoring, investigate one of these shapes:

  1. Route Codex simple completions through the provider-owned Codex simple stream path where possible.
  2. Extract shared Codex request/response handling so normal turns and llm.complete share URL/header/validation/SSE contracts.
  3. Keep separate entry points, but move the duplicated protocol assumptions into a small shared Codex transport contract with tests covering both call paths.

Acceptance Criteria

  • Normal agent Codex turns and plugin llm.complete Codex calls share the same documented response validation contract.
  • Tests cover missing content-type, explicit HTML, valid SSE, and valid JSON fallback behavior where applicable.
  • The refactor does not regress OAuth account-id handling, ChatGPT Codex base URL normalization, websocket/cached-context behavior, or simple completion auth injection.
  • The immediate incident fix remains independently small and does not depend on completing this refactor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.maintainerMaintainer-authored PR

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions