# Connect Codex To Provon

Codex has native OpenTelemetry support. Send its traces to Provon to inspect coding-agent sessions
and run conversation diagnosis without a wrapper.

Use [Agent transcript sync](./agent-transcripts.md) to backfill existing sessions from
`~/.codex/sessions/` or when the installed Codex version does not support trace export.

## Choose Signals

Only traces are required for the Provon coding-agent workflow:

| Signal  | Recommendation | Use in Provon                                                 |
| ------- | -------------- | ------------------------------------------------------------- |
| Traces  | Required       | Trace explorer, conversations, diagnostic Rules, and Findings |
| Logs    | Optional       | Independent event search through the Telemetry Read API       |
| Metrics | Optional       | Independent aggregate usage and latency queries               |

Provon diagnostics build conversation evidence from spans. Codex logs and metrics do not enrich
that span trajectory automatically. Enabling them by default creates additional ingest and storage
without improving trace diagnosis.

The recommended configuration therefore exports traces only.

## Prerequisites

- A Provon project.
- A project API key with `telemetry:ingest`.
- A current Codex CLI release whose
  [configuration reference](https://developers.openai.com/codex/config-reference) includes
  `otel.trace_exporter`.
- Network access from Codex to the Provon OTLP endpoint.

Check the installed version:

```bash
codex --version
```

## Configure Trace Export

Codex telemetry routing belongs in the user-level `~/.codex/config.toml`. Codex ignores `otel`
settings in project-local `.codex/config.toml` files.

Merge this block into `~/.codex/config.toml`:

```toml
[otel]
environment = "development"
exporter = "none"
log_user_prompt = false

[otel.trace_exporter.otlp-http]
endpoint = "https://otel.provon.dev/v1/traces"
protocol = "binary"
headers = { Authorization = "Bearer <PROVON_API_KEY>" }
```

Replace `<PROVON_API_KEY>` with a project API key. `protocol = "binary"` selects OTLP protobuf over
HTTP. Provon does not expose OTLP/gRPC.

The endpoint is a complete signal URL. Do not append another `/v1`.

This configuration does not route Codex metrics to Provon. Codex's separate built-in analytics
setting is outside this integration and remains unchanged.

Protect the user configuration after adding the key:

```bash
chmod 600 ~/.codex/config.toml
```

### Keep The Key Out Of Codex Configuration

Codex OTel exporter headers are static configuration. Do not assume that
`Authorization = "Bearer ${PROVON_API_KEY}"` will expand: affected Codex versions send the
placeholder literally.

When the project key must not be stored in `config.toml`, send Codex traces to a local
OpenTelemetry Collector without authentication. Let the Collector read `PROVON_API_KEY` from its
secret environment, add the Bearer header, and forward traces to Provon. See
[OpenTelemetry Collector setup](./opentelemetry.md#opentelemetry-collector).

## Verify

Restart Codex, run one prompt that causes a model request and a tool call, and exit normally so the
batch exporter can flush:

```bash
codex
```

Then:

1. Open the same Provon project.
2. Open **Traces** and select the latest Codex trace.
3. Confirm that it contains model and tool child spans.
4. Confirm that conversation identity remains stable across the session.
5. Inspect model, usage, tool, error, and terminal outcome evidence.

An OTLP `200` response means Provon accepted and queued the payload. Trace summaries can appear
asynchronously.

## Optional Logs And Metrics

Enable Codex logs only when you need to query structured audit events such as API requests, tool
decisions, and tool results independently of traces. Remove `exporter = "none"` and add:

```toml
[otel.exporter.otlp-http]
endpoint = "https://otel.provon.dev/v1/logs"
protocol = "binary"
headers = { Authorization = "Bearer <PROVON_API_KEY>" }
```

Enable Codex metrics only when you need aggregate counters or histograms outside the trace views.
Add:

```toml
[otel.metrics_exporter.otlp-http]
endpoint = "https://otel.provon.dev/v1/metrics"
protocol = "binary"
headers = { Authorization = "Bearer <PROVON_API_KEY>" }
```

These signals are queried through the [Telemetry Read API](./telemetry-api.md). They are not
prerequisites for Traces, Conversations, Rules, or Findings.

## Privacy

Keep `log_user_prompt = false` unless policy explicitly permits prompt storage. Even when prompts
are redacted, paths, tool metadata, errors, and output snippets can contain sensitive information.

Use a narrowly scoped project key, apply an appropriate retention policy, and review one
representative trace before an organization-wide rollout.

Do not enable native OTel and transcript sync for the same live session without a reason. They can
project the same Codex activity as duplicate evidence.

## Local And Self-Hosted Provon

For the local Node runtime, use:

```toml
[otel]
environment = "development"
exporter = "none"
log_user_prompt = false

[otel.trace_exporter.otlp-http]
endpoint = "http://127.0.0.1:3000/v1/traces"
protocol = "binary"
headers = { Authorization = "Bearer <PROVON_API_KEY>" }
```

For another self-hosted deployment, use its public OTLP/HTTP trace URL.

## Troubleshooting

### Codex Rejects The Configuration

Update Codex and confirm that its configuration reference includes `otel.trace_exporter`. Use
transcript sync when an update is not possible.

### Provon Returns `401` Or `403`

- Replace the placeholder with the actual project key.
- Include the `Bearer ` prefix.
- Confirm that the key belongs to the intended project.
- Confirm that it has `telemetry:ingest`.

### No Trace Arrives

- Exit Codex normally and allow the exporter to flush.
- Check that the endpoint ends in exactly `/v1/traces`.
- Use `otlp-http`, not `otlp-grpc`.
- Confirm that Codex network policy permits the Provon endpoint.
- Route through an approved Collector when direct egress is restricted.

### Diagnosis Is Weak

Protocol compatibility does not guarantee complete diagnostic evidence. Inspect conversation
identity, model attributes, tool spans, errors, recovery, and terminal outcome against
[Diagnosis-ready tracing](./tracing-best-practices.md). Use transcript sync when the persisted
session contains evidence that the native exporter does not emit.

## Upstream References

- [Codex advanced configuration](https://developers.openai.com/codex/config-advanced)
- [Codex configuration reference](https://developers.openai.com/codex/config-reference)
- [Codex security, monitoring, and telemetry](https://developers.openai.com/codex/agent-approvals-security)

## Related Docs

- [OpenTelemetry setup](./opentelemetry.md)
- [OTLP/HTTP API](./otlp-api.md)
- [Agent transcript sync](./agent-transcripts.md)
- [Telemetry Read API](./telemetry-api.md)
- [Explore traces](./trace-explorer.md)
