> ## Documentation Index
> Fetch the complete documentation index at: https://langwatch.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAI Codex CLI Integration Guide

> Send OpenAI Codex CLI sessions, cost and traces to LangWatch with the LangWatch command line tool.

The OpenAI Codex command line tool reports every session over OpenTelemetry. The LangWatch command line tool connects that report to your workspace, so you can read the cost of each session, the trace of each turn, and the conversation behind both.

There are two ways to set it up:

* `langwatch codex` starts Codex and sets up the connection on the first run. Use it on a machine you work on.
* `langwatch instrument codex` writes the same setup and exits. Use it on a server, or when the telemetry must go to a team project.

After either one, a plain `codex` run also reports to LangWatch. The connection lives in `~/.codex/config.toml`, so it stays after you close the terminal.

## Before you start

* Install the Codex command line tool.
* Install the LangWatch command line tool: `npm install -g langwatch`
* Create an account at [app.langwatch.ai](https://app.langwatch.ai), or run your own instance with `npx @langwatch/server`.

## Run Codex through the wrapper

```bash theme={null}
langwatch login --device
langwatch codex
```

The first run asks one question:

| Answer                           | What it does                                                                                                                                 |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Using a ChatGPT subscription** | Codex keeps your own plan and your own login. LangWatch receives telemetry only.                                                             |
| **Using an API key**             | Codex calls travel through the LangWatch gateway with a virtual key. LangWatch receives telemetry and applies your budget and your policies. |

LangWatch remembers the answer, so later runs do not ask again. Everything else is unchanged: `langwatch codex` accepts the same flags and the same subcommands as `codex`, and it returns the same exit code.

<Note>
  A virtual key is created the first time you choose the gateway, not at login. If you always keep your own subscription, LangWatch never creates one for you.
</Note>

To route the model calls themselves through the gateway with a service key, and to read the routing, budget and model alias options, see [Codex CLI on the AI Gateway](/docs/ai-gateway/cli/codex).

## Set up a machine without starting Codex

`langwatch instrument codex` writes the connection into `~/.codex/config.toml` and exits. A plain `codex` run on that machine then sends its telemetry to LangWatch. This is the setup for a server that holds many agents, for a machine image, or for a configuration management run.

```bash theme={null}
langwatch instrument codex
```

### Choose where the telemetry goes

Pass one scope flag, and one only.

| Command                                             | Destination                     | Needs a login |
| --------------------------------------------------- | ------------------------------- | ------------- |
| `langwatch instrument codex`                        | Your personal workspace         | Yes           |
| `langwatch instrument codex --project <id-or-slug>` | A team project                  | Yes           |
| `langwatch instrument codex --key <ingest-key>`     | The project that owns the key   | No            |
| `langwatch instrument codex --personal`             | Back to your personal workspace | Yes           |

### Send the telemetry to a team project

```bash theme={null}
langwatch instrument codex --project acme-app
```

This creates an ingest key for this device and holds Codex to that project. LangWatch creates one key per device and never replaces the key of another device, so many machines can report to one project at the same time. You need a login and the `traces:create` permission on the project. See [Roles and permissions](/docs/ai-governance/roles-and-permissions).

The wrapper accepts the same flags. This pins the project and then starts Codex:

```bash theme={null}
langwatch codex --project acme-app
```

`--project` and `--personal` are LangWatch flags. LangWatch removes them from the command line before Codex reads it, so they never reach the agent.

### Set up a machine that never logs in

`--key` takes an ingest key (`ik-lw-…`). It needs no login and contacts no server, which makes it the option for a shared machine, a build agent, or a base image.

```bash theme={null}
langwatch instrument codex --key ik-lw-...
```

The command reads the same value from the `LANGWATCH_INGEST_KEY` environment variable:

```bash theme={null}
export LANGWATCH_INGEST_KEY=ik-lw-...
langwatch instrument codex
```

For a self-hosted instance, add its address:

```bash theme={null}
langwatch instrument codex --key ik-lw-... --endpoint https://langwatch.your-company.internal
```

To get an ingest key without the command line tool, install an ingestion template for the tool in the dashboard: the setup drawer mints one for you. See [Ingestion templates](/docs/ai-governance/ingestion-templates).

### Move a tool back to your personal workspace

```bash theme={null}
langwatch instrument codex --personal
```

This removes the project pin and writes the personal connection again.

### Remove the setup

```bash theme={null}
langwatch logout
```

This deletes every connection the command line tool wrote, for every tool.

## What you get in LangWatch

Open your personal page at `/me`, or open the project you pinned Codex to.

* **Sessions**: one row per Codex session, with the context it carried, how long it worked, and the pull requests it drove.
* **Traces**: one trace per turn, with the model, the tokens and the timing of each step.
* **Cost**: the amount per session and per turn.
* **Content**: the prompt of each turn, each tool call with its result, and the answer of the model.

Your agent can read all of this back. See [Explore your usage with your own agent](/docs/ai-governance/explore-your-usage-with-your-own-agent).

## Content and privacy

Content reaches LangWatch on one path only, and you can turn that path off. Codex's own OpenTelemetry export carries no conversation content; the `notify` program LangWatch installs does send it. Read both parts below before you decide.

The OpenTelemetry export carries two signals. The trace exporter reports each turn with the model, the tokens and the timing. The event exporter reports the facts of the session: each tool run with its name, duration and result, each prompt as a length without its text, tool approvals and denials, and the time to the first token. LangWatch enables both, and the session view is built from them. The prompt text, the tool output and the answer never ride either signal, and no Codex setting turns that content on. So the `[otel]` block alone gives you usage numbers and nothing that was said.

Codex does write the whole conversation to a transcript on your machine, and each turn there records the trace that Codex reported it under. `langwatch codex` and `langwatch instrument codex` register a small program on the Codex `notify` setting, which Codex runs after each completed turn. That program reads the turn from the transcript and records it against the same trace, so a session you started with a plain `codex` still shows what was said. This is the path that carries content, and LangWatch installs it unless you say otherwise. A `notify` program of your own keeps running: LangWatch calls it after its own.

To collect the usage numbers and no content, remove the `notify` setting from `~/.codex/config.toml` and keep the `[otel]` block. Tokens, cost, model, timing, tool counts and prompt lengths continue.

<Warning>
  The `[otel]` block holds an ingest key on the `Authorization` header, because Codex reads that header on every run and that is what makes a plain `codex` report. LangWatch writes the file with owner-only permissions (`0600`). Keep those permissions if you edit the file by hand, and never commit it.
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Nothing arrives in LangWatch">
    Run `langwatch instrument codex` again and read what it prints. It names the file it wrote and the destination the telemetry goes to.

    Then check that `~/.codex/config.toml` holds a `[otel]` block between the two LangWatch marker lines.
  </Accordion>

  <Accordion title="Traces arrive but every turn is empty">
    The turn program is missing. It is the part that recovers the conversation, because Codex itself exports no content. Run `langwatch instrument codex` again and read the result.

    If it reports that your Codex configuration already runs a program of its own after every turn and cannot be moved safely, remove the `notify` setting from `~/.codex/config.toml` and run the command again.
  </Accordion>

  <Accordion title="Traces arrive but the session shows no tools or prompts">
    Codex separates the exporters by signal: `[otel.trace_exporter.otlp-http]` sends the spans and `[otel.exporter.otlp-http]` sends the events that carry the tool runs and the prompt lengths. A configuration written before the event exporter was part of the block only has the first one. Run `langwatch instrument codex` again to write both.
  </Accordion>

  <Accordion title="The endpoint returns 404">
    Codex does not append the signal path to the endpoint, unlike most OpenTelemetry libraries. Write the full path per exporter: `https://app.langwatch.ai/api/otel/v1/traces` on the trace exporter and `https://app.langwatch.ai/api/otel/v1/logs` on the event exporter.
  </Accordion>

  <Accordion title="The telemetry goes to the wrong workspace">
    Run `langwatch instrument codex --project <id-or-slug>` to move it to a team project, or `langwatch instrument codex --personal` to move it back to your own.
  </Accordion>

  <Accordion title="Authentication errors">
    Check that the key is live and that the header reads `Authorization = "Bearer <key>"`. An ingest key can write traces and nothing else, so a key that works for ingestion still fails on other endpoints.

    On a machine with a login, run `langwatch login --device` again to refresh the session.
  </Accordion>
</AccordionGroup>

For more failure modes see [CLI debug](/docs/ai-governance/cli-debug).

## Manual OpenTelemetry setup

Use this when you cannot install the LangWatch command line tool. The block below is the one `langwatch instrument codex` writes for you.

Add it to `~/.codex/config.toml`:

```toml theme={null}
[otel]
environment = "your-organization"

[otel.trace_exporter.otlp-http]
endpoint = "https://app.langwatch.ai/api/otel/v1/traces"
protocol = "json"
headers = { "Authorization" = "Bearer ik-lw-your-ingest-key" }

[otel.exporter.otlp-http]
endpoint = "https://app.langwatch.ai/api/otel/v1/logs"
protocol = "json"
headers = { "Authorization" = "Bearer ik-lw-your-ingest-key" }
```

The header takes an ingest key (`ik-lw-…`), which can create traces and nothing else. Keep a full project API key (`sk-lw-…`) out of the configuration of a coding agent: it can read and change your project data, and a coding agent has no use for that.

Then set the file to owner-only permissions, because it holds a key:

```bash theme={null}
chmod 600 ~/.codex/config.toml
```

For a self-hosted instance, replace the host with the address of your instance and keep the `/api/otel/v1/traces` and `/api/otel/v1/logs` paths.

<Note>
  The `environment` value is a free label. It arrives on every trace, so a name such as your organization or your team makes the traces easier to filter.
</Note>

A manual block reports the tokens, the model and the timing of each turn, and with the event exporter also the tool runs, the prompt lengths and the time to first token. It does not report the conversation, because Codex exports no content. The conversation needs the turn program that `langwatch instrument codex` installs.
