Skip to content

docs: document routing the Codex CLI through Otari - #484

Merged
njbrake merged 2 commits into
mainfrom
fix/370-codex-cli-guide
Aug 4, 2026
Merged

docs: document routing the Codex CLI through Otari#484
njbrake merged 2 commits into
mainfrom
fix/370-codex-cli-guide

Conversation

@njbrake

@njbrake njbrake commented Aug 4, 2026

Copy link
Copy Markdown
Member

Description

Note: this PR description was drafted by Claude via back-and-forth with @njbrake. The reasoning and decisions are his; the prose is Claude's.

Codex CLI can route through Otari as a custom model provider over the Responses API, but nothing documented it. docs/use-with-codex.md covered only the opposite path (importing Codex usage over OTLP), so a reader looking for the routing setup landed on the telemetry guide instead.

This PR adds the routing guide to that same page rather than creating a second one. Issue #370 asked for a new docs/use-with-codex-cli.md, but two pages for one tool, named use-with-codex.md and use-with-codex-cli.md, give a reader no way to tell which one they want, since both are the Codex CLI. The repo already settles this for the sibling tool: use-with-claude-code.md carries the routing setup and the telemetry-import path in one page. Keeping the original filename also means every existing inbound link still resolves.

docs/use-with-codex.md now leads with routing, following the OpenAI-compatible exemplar (docs/use-with-opencode.md):

  • Standalone as the primary flow: create an Otari key, export it, and a complete ~/.codex/config.toml with model_provider, base_url ending in /v1, wire_api = "responses", and env_key.
  • Connected to otari.ai as a second variant, with the two differences that actually matter: GET /v1/models is standalone-only, and hybrid mode validates Responses support on every attempt in the resolved route.
  • Choosing a model: provider:model and named-instance selectors, GET /v1/models as the source of truth, and the fact that only some providers implement the Responses API (Anthropic and Mistral return a 400).
  • model_catalog_json: why an Otari selector misses Codex's bundled model metadata, and a script that builds a catalog from codex debug models --bundled filtered against /v1/models.
  • Gotchas: the built-in OpenAI provider never reaches the gateway, a base URL missing /v1 gives 404s, provider config changes need a new session, the provider has to speak Responses, and a catalog file's schema is pinned to the Codex version that reads it.
  • Import Codex usage (without routing through Otari): the existing OTLP content, unchanged, now a section rather than the whole page. The "route or export, not both" callout moved to the top, where it governs both halves.

Also linked from docs/index.md, api-reference.md, use-with-opencode.md, and chatgpt-subscription.md.

One correction to the issue body: it says model = "openai:gpt-5.4" works because Codex ships bundled metadata for that slug. It does not. Metadata lookup is by exact slug, so any prefixed Otari selector falls back to conservative defaults. Verified on Codex CLI 0.146.0; the guide documents the catalog workaround instead.

Verified end to end

Run against a local standalone gateway with Codex CLI 0.146.0, not inferred:

  • codex exec through the documented config.toml returned a completion, and usage landed with endpoint=/v1/responses, provider openai, priced, counts_toward_budget: true.
  • A multi-turn tool-calling run round-tripped function calls correctly (the shell call itself failed on container sandbox limits, not on Otari).
  • warning: Model metadata for 'openai:gpt-5.4' not found reproduced, and the generated catalog clears it.
  • Each gotcha reproduced: no /v1 gives 404, an anthropic: model gives 400 Provider 'anthropic' does not support the Responses API, and the built-in provider dials wss://api.openai.com/v1/responses.

PR Type

  • New Feature
  • Bug Fix
  • Refactor
  • Documentation
  • Infrastructure / CI

Relevant issues

Fixes #370

Checklist

  • I understand the code I am submitting.
  • I have added or updated tests that cover my change (tests/unit, tests/integration).
  • I ran the Definition of Done checks locally (make lint, make typecheck, make test).
  • Documentation was updated where necessary.
  • If the API contract changed, I regenerated the OpenAPI spec (uv run python scripts/generate_openapi.py).

Notes on the checklist: the new test is tests/unit/test_docs_links.py, which checks that every relative link in docs/ resolves and that every use-with-*.md guide is listed in docs/index.md. It was confirmed to fail when the index link is removed. make lint, make typecheck, make test-unit (1156 passed, 1 skipped), make openapi-check, and make postman-check all pass locally; the integration suite was not run locally because this environment has no Docker for Testcontainers, so CI covers it. No API contract changed, and both generated artifacts are confirmed up to date.

AI Usage

  • No AI was used.
  • AI was used for drafting/refactoring.
  • This is fully AI-generated.

AI Model/Tool used:

Claude Opus 5 via Claude Code.

Any additional AI details you'd like to share:

The guide was written from a live test rather than from the model's priors: a standalone gateway was started locally, a virtual key created, and Codex CLI 0.146.0 pointed at it. Every command, config block, warning, and error message in the page came out of that session, including the correction to the issue's claim about bundled metadata.

NOTE:
When responding to reviewer questions, please respond yourself rather than copy/pasting reviewer comments into an AI and pasting back its answer. We want to discuss with you, not your AI :)

  • I am an AI Agent filling out this form (check box if true)

🤖 Generated with Claude Code

Summary

  • Added Codex CLI routing guidance for Otari through the OpenAI Responses API.
  • Documented standalone and hosted configurations, API keys, model selection, and troubleshooting.
  • Clarified Codex usage import without API routing.
  • Added links from related documentation pages.
  • Added tests for valid documentation links and indexed integration guides.

These changes make Codex setup clearer and help prevent broken or unlisted documentation links.

Codex CLI can route through Otari as a custom model provider over the
Responses API, but nothing documented it: the existing "Use with Codex"
page covers the opposite path (importing Codex usage over OTLP), so
readers looking for the routing setup found the telemetry guide instead.

Add docs/use-with-codex-cli.md with the standalone flow as the primary
path and the otari.ai-connected variant alongside it, verified end to end
against a local gateway with Codex CLI 0.146.0: key creation, the
config.toml provider entry, a completion, and a tool-calling turn. The
gotchas are the ones that actually bite, each reproduced: the built-in
OpenAI provider never reaches the gateway, a base URL missing /v1 404s,
a provider without Responses support returns 400, and an Otari selector
misses Codex's bundled model metadata unless a model_catalog_json maps
it back (with that file's schema pinned to the Codex version reading it).

Link it from the docs index and from the neighbouring pages, and rename
the index entry for the telemetry guide so the two are told apart. The
new test keeps relative doc links resolvable and every use-with guide
listed in the index.

Fixes #370
@njbrake
njbrake temporarily deployed to integration-tests August 4, 2026 10:27 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9a9d35b0-9ca3-49f6-b22c-f367fe9d5f41

📥 Commits

Reviewing files that changed from the base of the PR and between 86bf391 and b5f6ecd.

📒 Files selected for processing (6)
  • docs/api-reference.md
  • docs/chatgpt-subscription.md
  • docs/index.md
  • docs/use-with-codex.md
  • docs/use-with-opencode.md
  • tests/unit/test_docs_links.py

Walkthrough

The PR expands Codex integration documentation for Responses API routing and telemetry import, adds cross-references across related guides, and introduces tests for relative documentation links and index coverage.

Changes

Codex documentation

Layer / File(s) Summary
Codex integration guide
docs/use-with-codex.md
Documents standalone and hosted configuration, API keys, model selection, Responses API requirements, telemetry import, configuration constraints, and related resources.
Documentation cross-references
docs/api-reference.md, docs/index.md, docs/chatgpt-subscription.md, docs/use-with-opencode.md
Adds Codex links and describes Responses API routing and telemetry import coverage.
Documentation link validation
tests/unit/test_docs_links.py
Checks relative Markdown links and verifies that every use-with-*.md guide appears in docs/index.md.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

  • mozilla-ai/otari#371: Directly expands the Codex integration documentation requested by this change.
  • mozilla-ai/otari#439: Modifies related ChatGPT subscription and Codex documentation cross-references.

Suggested reviewers: angpt, khaledosman

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/370-codex-cli-guide
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/370-codex-cli-guide

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Use with Codex CLI” routing guide so users can configure Codex CLI to talk to Otari via the OpenAI Responses API (distinct from the existing Codex telemetry-import doc), and strengthens docs navigation integrity by adding a unit test that validates intra-doc relative links and index coverage.

Changes:

  • Add docs/use-with-codex-cli.md documenting standalone and otari.ai-connected Codex CLI setup via /v1/responses, plus model-selection, metadata-catalog, and gotchas sections.
  • Update related docs to link to the new guide and clarify the distinction between “routing” vs “telemetry import” Codex flows.
  • Add a unit test to ensure relative links in docs/ resolve and that all use-with-*.md guides are listed in docs/index.md.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/unit/test_docs_links.py Adds unit tests to validate relative doc links and ensure use-with-* guides are indexed.
docs/use-with-opencode.md Adds a “See also” link to the new Codex CLI routing guide.
docs/use-with-codex.md Clarifies routing-vs-telemetry guidance and links to the Codex CLI routing page.
docs/use-with-codex-cli.md New end-to-end guide for routing Codex CLI through Otari via the Responses API.
docs/index.md Adds/adjusts index entries to include the new Codex CLI routing guide and disambiguate the telemetry-import page.
docs/chatgpt-subscription.md Links to the Codex CLI routing guide from related “see also” content.
docs/api-reference.md Adds a note about provider Responses API support and links to the Codex CLI guide as an example.

Comment thread docs/use-with-codex-cli.md Outdated
Comment on lines +24 to +25
Codex sends the key as `Authorization: Bearer <token>`, which is the scheme Otari
accepts. In the dashboard: Keys -> create a key for a user. Or over the API with

@khaledosman khaledosman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spot-checked the code-backed claims and they hold: hybrid validates every resolved attempt (responses.py:374-377), GET /v1/models is standalone-only (api/main.py:41-42), the 400 string matches responses.py:183, and the two models.md#… anchors in the new page resolve (the new test doesn't check anchors). No relative link in docs/ breaks, and no OpenAPI or dashboard-bundle impact. Inline notes are non-blocking.

🤖 Generated with Claude Code

Comment thread docs/use-with-codex-cli.md Outdated
### The provider has to speak the Responses API

Otari serves `/v1/responses` only for providers that implement it, such as
OpenAI, Azure OpenAI, Groq, Fireworks, and HuggingFace, plus any

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Responses support is read at runtime from any-llm's SUPPORTS_RESPONSES (src/gateway/api/routes/responses.py:179-181), so this list drifts on every dependency bump — the currently installed any-llm also flags gmi and neosantara, so it's already incomplete. Describing the mechanism (and the 400 you get) ages better than enumerating providers.

def test_relative_links_resolve(doc: Path) -> None:
broken: list[str] = []
for lineno, line in enumerate(doc.read_text(encoding="utf-8").splitlines(), 1):
for target in _LINK.findall(line):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scan doesn't strip fenced code blocks, so the first doc that shows an example markdown link fails the check for a link that was never meant to resolve. Dropping lines inside ``` fences before matching is a two-line fix. Also silently unchecked: reference-style ([a]: url), autolinks (`https://…`), and anchor fragments.

Comment thread docs/use-with-codex-cli.md Outdated
served = {m["id"] for m in json.load(open("served.json"))["data"]}
bundled = json.load(open("bundled.json"))["models"]
models = [dict(m, slug=PREFIX + m["slug"]) for m in bundled if PREFIX + m["slug"] in served]
json.dump({"models": models}, open("otari-models.json", "w"), indent=2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A prefix typo here writes a valid-but-empty catalog and the user just gets an emptier model picker with no error. Worth a with block plus a check that models is non-empty, since this is a snippet people copy-paste.

Comment thread docs/index.md Outdated
- [Use with Claude Code](use-with-claude-code.md): point the Claude Code CLI at Otari.
- [Use with Codex](use-with-codex.md): point the Codex CLI at Otari.
- [Use with Codex CLI](use-with-codex-cli.md): route the Codex CLI through Otari over the Responses API.
- [Use with Codex](use-with-codex.md): import Codex usage into Otari without routing through it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Use with Codex CLI" (routing) directly above "Use with Codex" (telemetry) is a coin flip for anyone scanning the nav, and the telemetry page is the misnamed one. Renaming it (import-codex-usage.md) and letting the routing guide own use-with-codex.md reads better, at the cost of breaking inbound external links. Your call; the reworded descriptions do most of the work.

Two pages for one tool, named use-with-codex.md and use-with-codex-cli.md,
gave a reader no way to tell which one they wanted: both are the Codex CLI.
The repo already answers this for the sibling tool, since
use-with-claude-code.md carries the routing setup and the telemetry-import
path in a single page.

Follow that shape here. The routing content moves into use-with-codex.md
ahead of the existing OTLP material, which becomes "Import Codex usage
(without routing through Otari)", and the "route or export, not both"
callout moves up top where it now governs both halves. Keeping the
original filename means every existing inbound link still resolves.

Refs #370
@njbrake
njbrake temporarily deployed to integration-tests August 4, 2026 15:18 — with GitHub Actions Inactive
@njbrake njbrake changed the title docs: add a use-with guide for the Codex CLI docs: document routing the Codex CLI through Otari Aug 4, 2026
@coderabbitai
coderabbitai Bot requested review from angpt and khaledosman August 4, 2026 15:19
@njbrake
njbrake merged commit a1c1bdb into main Aug 4, 2026
8 checks passed
@njbrake
njbrake deleted the fix/370-codex-cli-guide branch August 4, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: add use-with guide for Codex CLI

3 participants