Skip to content

Surface reasoning_output_tokens in turn.completed.usage on the --json stream #19022

@anshulbisen

Description

@anshulbisen

Summary

codex exec --json omits reasoning-token accounting from the turn.completed event, even for reasoning models (e.g. gpt-5.4-mini). The field is already tracked internally and persisted to the session rollout file, but it never reaches the JSON stdout stream — so any tool consuming Codex programmatically (IDE extensions, gateways, SDKs) can't distinguish visible output from reasoning.

Current behavior

$ codex exec --json --skip-git-repo-check --ephemeral -m gpt-5.4-mini \
    "What is 147 times 839? Reply only with the number."

{"type":"item.completed","item":{"id":"…","type":"agent_message","text":"123333"}}
{"type":"turn.completed","usage":{"input_tokens":32161,"cached_input_tokens":1920,"output_tokens":47}}

usage carries three keys only. 47 output tokens for a six-character reply — the remainder is reasoning, but the stream doesn't say so.

Verified on a longer prompt ("prove there are infinitely many primes"): 139 output tokens, still no reasoning field in the --json output, still no agent_reasoning item events in the stream.

Where the data already lives

Codex does record reasoning_output_tokens — but only to the on-disk session rollout (~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl), inside an event_msg with payload.type == "token_count":

{
  "timestamp": "2026-04-19T11:23:41.622Z",
  "type": "event_msg",
  "payload": {
    "type": "token_count",
    "info": {
      "total_token_usage": {
        "input_tokens": 31751,
        "cached_input_tokens": 14720,
        "output_tokens": 2367,
        "reasoning_output_tokens": 413,
        "total_tokens": 34118
      },
      "last_token_usage": { "…": "same shape" },
      "model_context_window": 258400
    },
    "rate_limits": { "…": "" }
  }
}

Two reasons this isn't a workable consumer path:

  1. The rollout file is a user-facing session log, not a programmatic API. Tools running Codex non-interactively (e.g. CI, gateways, LSP features) wouldn't reliably parse it.
  2. It doesn't exist when Codex runs with --ephemeral. Tools that intentionally avoid writing per-request session state to the user's home directory cannot access it at all.

Requested change

Add reasoning_output_tokens (and ideally the other total_token_usage fields — total_tokens, model_context_window, rate-limit info) to the turn.completed.usage payload on --json, so the stream is the complete source of truth for the turn.

A minimal, backward-compatible version:

{
  "type": "turn.completed",
  "usage": {
    "input_tokens": 32161,
    "cached_input_tokens": 1920,
    "output_tokens": 47,
    "reasoning_output_tokens": 41
  }
}

Since the field is additive and optional, existing consumers are unaffected.

Why it matters

Consumers surfacing per-turn cost or context-fill to end users need the reasoning share to avoid misrepresenting output spend. A one-word reply that costs 22 output tokens with 21 reasoning is not meaningfully "22 tokens of output" to the user — it's "1 visible, 21 reasoning." The former reads as a buggy totals display.

Concrete consumer: I'm building an AI gateway that exposes ChatGPT Pro models through an OpenAI-compatible API. I want to pass the reasoning split through to clients (already present in OpenAI's native chat-completions response as usage.completion_tokens_details.reasoning_tokens). Today I have to either drop --ephemeral and parse rollout files back (stateful, race-prone, filesystem pollution) or ship a seam that never populates.

Environment

  • codex-cli 0.121.0 (installed via Homebrew on macOS)
  • Darwin 25.3
  • Observed: 2026-04-22

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestexecIssues related to the `codex exec` subcommand

    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