# Telemetry reference

> Export configuration and the fields Radiant uses for agents, messages, events and usage.

Radiant stores received span attributes and interprets the fields below for its agent, model and tool views. Use the [connection guide for your framework](/docs/platform/connect-your-agent.md) to configure export or add instrumentation.

## Configure export

Send OTLP traces over HTTP to the project’s ingestion address at **`/v1/traces`**. Both `application/x-protobuf` and `application/json` are accepted. The ingestion endpoint does not accept OTLP logs or metrics.

For exporters that read standard OpenTelemetry variables:

**Exporter configuration**

```sh
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT='https://YOUR_INGESTION_HOST/v1/traces'
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL='http/protobuf'
export OTEL_EXPORTER_OTLP_TRACES_HEADERS='Authorization=Bearer%20YOUR_INGESTION_KEY'
export OTEL_SERVICE_NAME='YOUR_SERVICE_NAME'
```

A traces-specific endpoint includes `/v1/traces`. SDKs using a base OTLP endpoint may append that path; include it exactly once. Disable request compression: the receiver accepts absent or `identity` content encoding.

The standard environment-variable header format percent-encodes the space after `Bearer`. A header supplied directly in code uses an ordinary space: `Authorization: Bearer YOUR_INGESTION_KEY`.

The ingestion key selects the destination project. Resource attributes and agent identifiers do not route activity to another project.

## Attribute scope

Span attributes describe one recorded operation. Set request or conversation identifiers on the relevant invocation or operation before its span ends. They are not automatically copied to child spans. Resource attributes describe the process producing telemetry, such as its service and deployment environment, and apply to that process’s exported spans.

Framework metadata can use different exported keys. [Mastra](/docs/platform/connect-your-agent/mastra.md#add-attributes) exports custom metadata with a `mastra.metadata.` prefix, while [Pydantic AI](/docs/platform/connect-your-agent/pydantic-ai.md#optional-add-conversation-context) records additional run metadata inside a JSON `metadata` attribute. Both can record a conversation identifier as `gen_ai.conversation.id`. Use the exported field, not the framework option’s name, when filtering or grouping in Logs.

For custom instrumentation, [add attributes to the existing OpenTelemetry span](/docs/platform/connect-your-agent/opentelemetry.md#add-attributes). Keep a per-conversation identifier on the invocation rather than setting one process-wide value for every request.

## Agent runs

An agent invocation is recognized when its `gen_ai.operation.name` attribute equals `invoke_agent`. The span’s display name does not need a particular prefix.

Radiant also recognizes native Codex turns: a `session_task.turn` span from `service.name = codex_exec` with `target` or `code.module.name` set to `codex_core::tasks`. This mapping treats each turn as one invocation, rather than treating every internal operation or the whole CLI session as a run.

| Attribute                                       | Interpretation                                               |
| ----------------------------------------------- | ------------------------------------------------------------ |
| `gen_ai.agent.id`                               | Preferred stable identity discriminator.                     |
| `gen_ai.agent.name`                             | Display name; identity discriminator when no ID is supplied. |
| `gen_ai.agent.description`                      | Description shown in the agent catalog.                      |
| `gen_ai.agent.version`                          | Version used for filtering and comparison within the agent.  |
| Resource `service.namespace` and `service.name` | Service scope for the derived agent identity.                |

The discriminator’s kind, its value and both service fields form the identity. Changing from a name-based identity to an explicit ID creates a different agent, even if their text matches. Version, replica and deployment-environment attributes do not create a new agent.

When no agent ID or name is supplied, recognized `claude_code.interaction` invocations use **Claude Code** as their agent name, and recognized Codex turns use **Codex**. Their CLI version comes from resource `service.version` unless `gen_ai.agent.version` is present. Other recognized invocations without an ID or name remain runs without a catalog association.

A run’s outcome is based on its invocation span: it remains in progress until that span ends, then is an error if the span has OpenTelemetry status `ERROR` or a non-empty `error.type`; otherwise it is successful. Child-span errors do not independently change that outcome.

## Model requests

The execution view recognizes `chat` operations by the span name or `gen_ai.operation.name`.

| Attribute                                     | Interpretation                                                |
| --------------------------------------------- | ------------------------------------------------------------- |
| `gen_ai.provider.name`                        | Provider; `gen_ai.system` is accepted as a fallback.          |
| `gen_ai.request.model`                        | Requested model.                                              |
| `gen_ai.response.model`                       | Model reported in the response.                               |
| `gen_ai.response.finish_reasons`              | Recorded completion reasons.                                  |
| `gen_ai.prompt.name`, `gen_ai.prompt.version` | Prompt identification attributes retained with the operation. |

Message content uses the [message attributes](#messages); usage uses the [token and cost fields](#tokens-and-costs).

## Tool calls

The agent’s tool-call catalog recognizes a span when `gen_ai.operation.name` is `execute_tool` or `gen_ai.tool.name` is present.

| Attribute                    | Interpretation                                   |
| ---------------------------- | ------------------------------------------------ |
| `gen_ai.tool.name`           | Tool name.                                       |
| `gen_ai.tool.description`    | Tool description.                                |
| `gen_ai.tool.type`           | Recorded tool type.                              |
| `gen_ai.tool.call.id`        | Call identifier.                                 |
| `gen_ai.tool.call.arguments` | Input; falls back to `gen_ai.tool.call.input`.   |
| `gen_ai.tool.call.result`    | Output; falls back to `gen_ai.tool.call.output`. |

For each payload, the first present field wins. In the agent’s tool-call detail, those payloads become dedicated input/output fields and are omitted from its generic attribute map. The trace record’s **Attributes** tab retains the received span attributes.

## Messages

[Thread](/docs/platform/logs/threads.md) reads these attributes on the selected operation. Values can be structured values or JSON-encoded strings.

| Attribute                    | Format                               |
| ---------------------------- | ------------------------------------ |
| `gen_ai.system_instructions` | Array of message parts.              |
| `gen_ai.input.messages`      | Input message or array of messages.  |
| `gen_ai.output.messages`     | Output message or array of messages. |

A message has a `role` and a `parts` array. For example, these are the values of two message attributes:

**Message attribute values**

```json
{
  "gen_ai.input.messages": [
    { "role": "user", "parts": [{ "type": "text", "content": "What changed?" }] }
  ],
  "gen_ai.output.messages": [
    { "role": "assistant", "parts": [{ "type": "text", "content": "The configuration changed." }] }
  ]
}
```

Supported part types are `text` and `reasoning` with `content`; `tool_call` with `name`, `arguments` and an optional `id`; and `tool_call_response` with `id` and `response`. Matching tool-call IDs associate results with calls. Other parts are displayed as their recorded data.

## Tokens and costs

| Attribute                                  | Interpretation                                        |
| ------------------------------------------ | ----------------------------------------------------- |
| `gen_ai.usage.input_tokens`                | Input token count.                                    |
| `gen_ai.usage.output_tokens`               | Output token count.                                   |
| `gen_ai.usage.cache_creation.input_tokens` | Cache-creation input tokens shown in model details.   |
| `gen_ai.usage.cache_read.input_tokens`     | Cache-read input tokens shown in model details.       |
| `gen_ai.usage.reasoning.output_tokens`     | Reasoning output tokens shown in model details.       |
| `gen_ai.usage.cost`                        | Exported cost in USD; falls back to `llm.cost.total`. |

Base token counts and costs accept finite, non-negative numbers or numeric strings. Token counts are converted to whole numbers. The additional cache and reasoning counters are displayed when recorded as numbers. `gen_ai.usage.cost_usd` is not a recognized cost field. Radiant does not calculate provider prices from a model name.

**Inclusive usage** covers an invocation and its descendants. When a span reports a value, it is used as that subtree’s aggregate instead of adding its children again. Otherwise, descendant values are summed.

**Direct usage** applies the same rule but stops at nested agent invocations. Run lists show inclusive usage; agent metrics use direct usage. The trace view shows both when they differ. Model cost remains separate from [Radiant credits](/docs/platform/administration/usage-and-billing.md).

For recognized Codex turns, Radiant reads `codex.turn.token_usage.input_tokens` and `codex.turn.token_usage.output_tokens` when standard usage attributes are absent. These turn totals take precedence over descendant usage. For Claude Code model requests, native `input_tokens`, `cache_read_tokens` and `cache_creation_tokens` contribute to input usage, and `output_tokens` supplies output usage. Standard usage attributes take precedence when present.

## Events

An OTLP span event has a name, timestamp and attributes. The [Events tab](/docs/platform/logs/events-and-inspection.md) takes its level from the string attribute `level` and its message from the string attribute `message`. The event’s name and all attributes remain available when it is expanded.

An event named `exception` can provide `exception.type`, `exception.message` and `exception.stacktrace` for the operation’s error details. A non-empty span attribute `error.type` or OpenTelemetry status `ERROR` marks the span as failed. Use low-cardinality error types; the agent failure breakdown groups missing types as `unknown`.

## Inspection events

The [Inspection tab](/docs/platform/logs/events-and-inspection.md#inspect-captured-inputs-and-outputs) projects Polaris inspection events into inputs and outputs. An event needs `polaris.inspection.system`, `polaris.inspection.param` and a supported phase to be included.

| Event attribute                | Interpretation                                              |
| ------------------------------ | ----------------------------------------------------------- |
| `polaris.inspection.system`    | System that produced the capture.                           |
| `polaris.inspection.param`     | Parameter name used to group captures.                      |
| `polaris.inspection.phase`     | `Before` for inputs or `After` for outputs.                 |
| `polaris.inspection.value`     | Captured value.                                             |
| `polaris.inspection.type_name` | Optional type metadata.                                     |
| `polaris.inspection.kind`      | Optional parameter or return kind.                          |
| `polaris.inspection.rendering` | Rendering format; `text` values are decoded where possible. |
| `polaris.inspection.truncated` | Whether the capture was truncated.                          |

Repeated captures for one parameter are retained together. The presentation can unwrap supported successful-result and agent-input envelopes; the original event is retained unchanged.

## Correlation and grouping

Trace and span identity is scoped to the project. A trace ID is 16 bytes and a span ID is 8 bytes. Propagate trace context across service boundaries to preserve parent-child relationships.

### Conversations

Export a non-empty string `gen_ai.conversation.id` on agent invocations to associate related runs across requests. The [Conversations view](/docs/platform/logs/search-and-filters.md#conversations) groups agent runs by this identifier within the selected project and time range. The identifier can also be inherited from an ancestor operation. Runs without it remain available in **All agent runs**.

For positively identified Codex telemetry, Radiant also resolves `conversation.id` from an ancestor `codex.turn_input` span. The original attributes are retained. Generic `session.id`, `thread.id` and `conversation.id` attributes are not automatic conversation identifiers for other telemetry.

Other application attributes remain available for [custom grouping](/docs/platform/logs/search-and-filters.md#grouping). Grouping does not create parent-child span relationships or a combined message transcript.

`vapi.call.id` must be a string on the selected span for [Vapi recordings](/docs/platform/integrations/vapi.md).

### Group membership and filters

A group contains operations with the selected grouping value, together with their descendants. A child operation without the grouping attribute remains in its parent’s group. A child with a different value is excluded from that group.

Filters determine which groups appear, rather than removing individual operations from a group. Different operations can satisfy different filter conditions: one may match the error status and another the selected model. Opening the result shows the complete group, including operations that did not match those filters. See [Grouping in Logs](/docs/platform/logs/search-and-filters.md#grouping) for the controls.

## Simulation correlation

Simulation participants and the application under test produce separate records. Application traces appear in a run’s **Evidence** when they carry its run identifier in the same project:

| Span attribute                | Meaning                                                                                                                                   |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `hubble.simulation.batch_id`  | String containing the Radiant simulation run ID. Associates the operation with that run.                                                  |
| `hubble.simulation.simulated` | `true` identifies the simulator’s own activity, which is excluded from application Evidence. Application spans leave this unset or false. |

When application instrumentation already receives the run ID, set the batch attribute on the relevant operation before its span ends. Opening the run’s Logs group includes matching operations and their descendants. The association does not establish a parent-child relationship between separate traces.

The hosted browser and phone network do not automatically pass that identifier or OpenTelemetry trace context into the application. An exporter alone cannot establish the association. Application activity without the run identifier remains available in Logs using its own request or conversation identifiers and time range. See [Application evidence](/docs/platform/simulations/runs-and-results.md#application-evidence).

## Control captured content

Configure content capture in the [framework guide](/docs/platform/connect-your-agent.md). Apply redaction before export, including custom attributes and event fields. Project [retention and deletion settings](/docs/platform/administration/organizations-and-projects.md#retention-and-deletion) govern stored telemetry.

## Troubleshoot tracing

### No traces appear in Logs

Check the selected project, time range and query. Inspect exporter errors, then verify the ingestion URL, bearer header and protocol against [Configure export](#configure-export). For a short-lived process, flush or shut down its exporter before exit.

### The exporter returns 401

Use an active ingestion key for the intended project, not an MCP credential. Check key status in **Settings → Project settings → API keys** and the header encoding above.

### The trace appears, but the agent does not

Check the invocation’s `gen_ai.operation.name` against [Agent runs](#agent-runs), or the native Codex detection fields for that integration. A catalog entry also needs an agent ID or name, except where a supported coding-agent mapping supplies one. Exporting a model request alone does not create an agent invocation.
