OpenAI Codex Observability with OpenTelemetry: Trace Every Session (2026)

Codex exports OpenTelemetry natively. One config block turns every session into a trace with tool calls, tokens and failed API requests.

On this page
  1. What Codex exports
  2. Option 1: send it to your own collector
  3. Option 2: send it to Voight
  4. What a session looks like
  5. Privacy
  6. Troubleshooting

OpenAI Codex runs long, autonomous coding sessions: it reads the repo, runs commands, asks for permissions and calls the model many times per task. When a session burns more tokens than expected or a command fails halfway, the terminal scrollback is all you have, unless the session was recorded.

Codex has a built-in way to record itself: it can export OpenTelemetry. This guide shows what Codex exports, how to point it somewhere useful, and what you can read from a session once it lands.

What Codex exports

Codex (the CLI, the TUI and the desktop app) ships native, opt-in OpenTelemetry export. With it enabled, each session produces records for:

Codex telemetryWhat it tells you
codex.conversation_startsA session began: model, sandbox mode and approval policy
codex.user_promptThe prompt that started it (the text only if you allow it)
codex.sse_event token summariesOne model call per turn: input, output, cached and reasoning tokens
codex.tool_resultEach tool call: name, duration, outcome and a snippet of output
codex.tool_decisionPermission decisions, including the ones you denied
codex.api_request failuresFailed calls to the API, with their HTTP status

Every record carries the conversation id, which is what lets a backend group a whole session together.

Option 1: send it to your own collector

If you already run an OpenTelemetry collector, add an exporter to ~/.codex/config.toml that points at it. You get the raw records; turning them into a readable timeline per session (pairing tool calls, summing tokens per turn, pricing them) is up to you and your backend.

Option 2: send it to Voight

Voight runs an OTLP receiver that understands Codex records, so one config block is enough. The wizard writes it for you:

Terminal
npx -y @voightxyz/sdk setup --target=codex

It asks for your privacy level and your Voight key, writes an [otel] section into ~/.codex/config.toml and keeps a one-time backup of the previous file as config.toml.voight-backup. If your config already exports OpenTelemetry somewhere else, the wizard refuses to overwrite it and lets you choose, because Codex supports one exporter per signal.

To do it by hand, append:

TOML
[otel]
log_user_prompt = true

[otel.exporter.otlp-http]
endpoint = "https://api.voight.xyz/v1/otel/logs"
protocol = "json"
headers = { Authorization = "Bearer vk_YOUR_KEY" }

Two settings matter:

  • protocol = "json" is required. The receiver answers binary protobuf with a 415 that says exactly this.
  • log_user_prompt = true exports the text of your prompts, so each trace shows what the session was about. With false, Codex sends a redacted placeholder, which Voight does not store.

Restart Codex (quit the desktop app or open a new CLI session) and run any task.

What a session looks like

Each Codex conversation becomes one trace:

  • The prompt that started it, at the top.
  • One row per model call, with input, output, cached and reasoning tokens, so you can see which turns were expensive and how much the cache saved.
  • Every tool call with its duration and outcome, and a snippet of what it returned.
  • Permission decisions, with denied ones marked, which is useful when a session "did nothing" because it was waiting or blocked.
  • API failures as error events with their status code.

Streaming deltas, websocket traffic and startup phases are dropped on purpose: they would bury the timeline without adding anything a token summary does not already say.

On top of the timeline, Smart Traces apply to Codex sessions out of the box: the waterfall, the automatic diagnosis (first failure, latency and cost hotspots, retry loops) and Explain with AI.

Privacy

Codex attaches your OpenAI account id and email to every telemetry record. Voight's receiver strips user.email, user.account_id and every auth.* attribute before anything is stored, so they are never persisted.

Troubleshooting

  • Nothing shows up. Restart Codex after editing the config, and check that the block says protocol = "json".
  • You already export elsewhere. Codex allows one exporter per signal; decide which backend keeps the logs signal.
  • codex exec sessions. Non-interactive runs export logs too. Codex does not emit metrics there, and Voight does not need them.

See what your agents do. In one command.

Connect Claude Code, Codex or Cursor, or wrap your OpenAI and Anthropic clients. Traces show up in seconds.

npx -y @voightxyz/sdk setup