openai / openai/codex

codex exec --ephemeral --json: expose provider-reported model ID on turn.completed

Open
#39,406 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

CLI enhancement exec
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What version of Codex CLI is running?

codex-cli 0.147.0

What platform is your computer?

macOS 26.5.2 (arm64)

Authentication mode

ChatGPT authentication

Feature request

Please expose the provider-reported response model in the JSONL emitted by codex exec --json, including when the invocation is --ephemeral.

The proposed additive field is:

{
  "type": "turn.completed",
  "usage": {
    "input_tokens": 123,
    "cached_input_tokens": 45,
    "output_tokens": 67
  },
  "server_model": "provider-reported-model-id"
}

server_model should be copied from provider response metadata for that completed turn. It must not be inferred or backfilled from --model, local configuration, alias resolution, the startup banner, rollout context, a generic model field, or model-authored output.

Why this is needed

I am building a governed evaluation harness around codex exec --ephemeral --json. The requested model and configured/resolved model are useful diagnostics, but they do not independently establish which model identifier the provider returned for a turn. That prevents a pinned-model evaluation from detecting silent rerouting or failing closed when observed identity is unavailable.

The current ephemeral JSONL includes lifecycle, item, completion, and detailed usage events, but the runs I inspected did not include provider-response model identity. Dropping --ephemeral to inspect persisted rollout context would weaken the sealed-task non-persistence boundary, and rollout/banner values still describe configured or resolved state rather than the provider response.

This is the codex exec JSONL counterpart to #33880, which requests provider-reported response model data for app-server v2.

Minimal reproduction shape

No production prompt is needed:

codex exec \
  --ephemeral \
  --json \
  --model PINNED_MODEL_ID \
  --sandbox read-only \
  "Reply with exactly OK."

The terminal turn.completed event reports usage but not the provider-returned model identifier.

Requested semantics
  • Type: a non-empty string when present.
  • Provenance: provider response metadata for the completed turn.
  • Representation: the provider-returned identifier, not a client-side alias substitution.
  • Missing metadata: omit or emit null; never fall back to the requested/configured model.
  • Streaming: retain the value through aggregation and emit it on the terminal turn event.
  • Conflict: if one logical turn observes multiple distinct non-empty provider model IDs, emit an explicit conflict/error rather than choosing one silently.
  • Ephemeral parity: emit the field with --ephemeral without persisting a rollout.
  • Privacy: do not add prompts, responses, auth material, headers, account identifiers, or a telemetry requirement.

An adjacent server_provider field could be useful, but it is not a substitute for server_model.

Acceptance cases
Case Requested Provider metadata Required result
Match model-a model-a server_model: "model-a"
Reroute model-a model-b server_model: "model-b"
Missing model-a absent omitted/null, never model-a
Conflict model-a model-a, then model-b explicit conflict/error
Alias alias-a dated-model-a server_model: "dated-model-a"
Ephemeral any present field emitted; no rollout persisted

Existing turn.completed.usage values should remain unchanged, and consumers that ignore unknown fields should continue to work.

Assurance limit

A provider-reported identifier is still a provider assertion, not cryptographic weight attestation. The goal is narrower: make the served identifier observable independently of the client-side request so evaluation tooling can detect a requested-versus-served mismatch and fail closed when the value is absent.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the codex exec --json entry point and trace provider response metadata through streaming aggregation to the terminal turn.completed event, comparing ephemeral and persisted execution paths. Done means provider-reported server_model is emitted without fallback, missing metadata is handled safely, conflicts are explicit, and existing usage and ephemeral non-persistence behavior remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.