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

# OpenClaw Integration

> Instrument OpenClaw agents with the OpenTelemetry SDK to send AI agent traces and logs to Bronto for observability, debugging, and cost tracking.

## Overview

[OpenClaw](https://openclaw.ai) is a self-hosted personal AI assistant.
Its gateway includes a built-in [`diagnostics-otel`](https://docs.openclaw.ai/gateway/opentelemetry) plugin that exports OpenTelemetry traces and logs  over OTLP/HTTP.
Pointed at Bronto, every model call your assistant makes lands in Bronto with full token, model, provider, and (optionally) prompt/response context.

You can ship telemetry to Bronto in one of two ways:

1. **Through an OpenTelemetry Collector that forwards to Bronto** *(recommended)*. More reliable and easier to debug when something doesn't show up in Bronto.
2. **Directly from the `diagnostics-otel` plugin to Bronto's OTLP endpoints**. Fewer moving parts, but harder to troubleshoot.

This page applies wherever you run the OpenClaw gateway — Docker, a VM, or a managed host — and does not assume any particular cloud.

<Tip>
  If you've tried the direct route and don't see data in Bronto, use the OpenTelemetry Collector path.

  * The Collector batches and retries on OpenClaw's behalf
  * Its `debug` exporter prints every signal it receives. This is a reliable way to tell whether a missing signal is OpenClaw failing to emit it or Bronto-side configuration (API key, region, headers) being wrong.
  * The Collector logs failures with full details so network-level problems surface immediately.
</Tip>

## Before you start

You will need:

* A running OpenClaw gateway. The configuration is the same wherever the gateway runs - only the path to `openclaw.json` and `~/.openclaw/.env` differs.
* A Bronto API key — see [API Keys](/Account-Management/API-Keys).
* Your Bronto region (`eu` or `us`) — see [Bronto Ingestion Endpoints](/getting-started/bronto-endpoints).

The `diagnostics-otel` plugin must be installed and enabled on the gateway:

```bash theme={"dark"}
openclaw plugins install clawhub:@openclaw/diagnostics-otel
openclaw plugins enable diagnostics-otel
```

## Recommended: OpenTelemetry Collector

### 1. Run a Collector next to OpenClaw

Install the OpenTelemetry Collector on the same host as the OpenClaw gateway, or anywhere the gateway can reach over the network. The [OpenTelemetry Collector installation docs](https://opentelemetry.io/docs/collector/installation/) cover Docker, Linux packages, Homebrew, Windows, and Kubernetes; see also [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) for richer Bronto-specific configuration.

Use the config below as your starting point.

* It accepts OTLP/HTTP on port `4318`
* It prints every received signal to the Collector's standard output via the `debug` exporter
* It forwards everything to Bronto.

<Note>
  The `debug` exporter is included intentionally, as it is a useful tool for confirming that signals are reaching the Collector, and what they look like.

  **Recommended for initial setup**, but remove it from the `exporters` block and from each pipeline once telemetry is flowing reliably into Bronto.
</Note>

```yaml otel-collector-config.yaml theme={"dark"}

receivers:
  otlp:
    protocols:
      http:
        endpoint: "0.0.0.0:4318"

processors:
  batch:

exporters:
  debug:
    verbosity: detailed

  otlphttp/bronto:
    traces_endpoint: "https://ingestion.<REGION>.bronto.io/v1/traces"
    metrics_endpoint: "https://ingestion.<REGION>.bronto.io/v1/metrics"
    logs_endpoint: "https://ingestion.<REGION>.bronto.io/v1/logs"
    compression: gzip
    headers:
      x-bronto-api-key: <YOUR_API_KEY>
      x-bronto-dataset: openclaw
      x-bronto-collection: openclaw-demo

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug, otlphttp/bronto]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug, otlphttp/bronto]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug, otlphttp/bronto]
```

Replace `<REGION>` with `eu` or `us` and `<YOUR_API_KEY>` with your Bronto API key. Per-signal endpoints (`traces_endpoint`, `logs_endpoint`, `metrics_endpoint`) are required because Bronto's OTLP host does not follow the default OTLP path convention.

### 2. Point OpenClaw at the Collector

Add a `diagnostics` block at the **top level** of your `~/.openclaw/openclaw.json`, alongside the existing top-level keys (`gateway`, `agents`, `models`, `plugins`, etc..., not nested inside any of them).

```json openclaw.json theme={"dark"}
{
  // ...other top-level keys: "gateway", "agents", "models", "plugins", etc.

  "diagnostics": {
    "enabled": true,
    "otel": {
      "enabled": true,
      "endpoint": "http://localhost:4318",
      "protocol": "http/protobuf",
      "serviceName": "openclaw-gateway",
      "captureContent": true,
      "traces": true,
      "logs": true,
      "metrics": true,
      "sampleRate": 1,
      "flushIntervalMs": 10000
    }
  }

  // ...
}
```

Set `endpoint` to wherever the Collector's OTLP/HTTP receiver is reachable from the gateway.
`http://localhost:4318` is correct when both run on the same host.
If they run as separate containers on a shared Docker network, use the Collector's service or container name instead (e.g. `http://otel-collector:4318`).

Add the following to your `~/.openclaw/.env`:

```bash ~/.openclaw/.env theme={"dark"}
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
```

`OTEL_SEMCONV_STABILITY_OPT_IN` opts the gateway in to the stable GenAI semantic-convention attributes (`gen_ai.request.model`, `gen_ai.usage.input_tokens`, etc.).
It is an environment variable and cannot be set in `openclaw.json`.
Without it, spans carry only OpenClaw's own `openclaw.*` attributes.

Restart the gateway to pick up the new configuration. Use whichever of the following matches your setup:

<Tabs>
  <Tab title="OpenClaw CLI">
    ```bash theme={"dark"}
    openclaw gateway restart
    ```
  </Tab>

  <Tab title="Docker Compose">
    ```bash theme={"dark"}
    docker compose restart openclaw-gateway
    ```
  </Tab>

  <Tab title="Plain Docker">
    ```bash theme={"dark"}
    docker restart <container_name_or_id>
    ```
  </Tab>

  <Tab title="Process supervisor">
    ```bash theme={"dark"}
    # systemd
    systemctl restart openclaw

    # launchd (macOS)
    launchctl kickstart -k "gui/$(id -u)/openclaw"

    # pm2
    pm2 restart openclaw
    ```
  </Tab>
</Tabs>

### 3. Confirm signals are flowing

Send your OpenClaw assistant a message, then watch the Collector's output. The `debug` exporter writes to the Collector's standard output, so where you find that depends on how you launched it:

* **Docker** — `docker logs -f <container_name_or_id>`.
* **Foreground terminal** — if you launched the Collector binary directly in a shell, debug lines appear in that terminal.
* **systemd** — `journalctl -u otelcol -f` (or `otelcol-contrib -f` for the contrib build).
* **Other supervisors** — wherever you redirected the Collector's stdout / stderr (for example `/var/log/otelcol/otelcol.log`).

In the output, every signal type appears with its own line prefix:

| Prefix        | Signal     |
| ------------- | ---------- |
| `Span #`      | Trace span |
| `LogRecord #` | Log record |
| `Metric #`    | Metric     |

If you see all three after sending a message to the assistant, OpenClaw is emitting telemetry correctly. The next thing to verify is that it has reached Bronto:

* **Traces** — open [Traces](/tracing/explore-traces) and check that traces for the openclaw-gateway service are visible.
* **Logs** — open [Log Search](/Search-and-Visualize/Log-Search) and check for data in the `openclaw-demo/openclaw` dataset.

If signals appear in the Collector output but not in Bronto.
If they do not appear in the Collector output at all, the failure is upstream of the Collector (plugin not enabled, gateway not restarted, no model activity).
See [Troubleshooting](#troubleshooting)

## Alternative: export directly from OpenClaw to Bronto

If you cannot run a Collector alongside the gateway, the `diagnostics-otel` plugin can send to Bronto's OTLP endpoints directly. This works, but it gives limited visibility so debugging is harder.

### 1. Configure `openclaw.json`

Add a `diagnostics` block at the **top level** of your `~/.openclaw/openclaw.json`. Authenticate with the `x-bronto-api-key` header.

```json openclaw.json theme={"dark"}
{
  // ...other top-level keys: "gateway", "agents", "models", "plugins", etc.

  "diagnostics": {
    "enabled": true,
    "otel": {
      "enabled": true,
      "endpoint": "https://ingestion.eu.bronto.io",
      "tracesEndpoint": "https://ingestion.eu.bronto.io/v1/traces",
      "logsEndpoint": "https://ingestion.eu.bronto.io/v1/logs",
      "metricsEndpoint": "https://ingestion.eu.bronto.io/v1/metrics",
      "protocol": "http/protobuf",
      "serviceName": "openclaw-gateway",
      "headers": {
        "x-bronto-api-key": "${BRONTO_API_KEY}",
        "x-bronto-dataset": "openclaw",
        "x-bronto-collection": "openclaw-demo"
      },
      "captureContent": true,
      "traces": true,
      "logs": true,
      "metrics": true,
      "sampleRate": 1,
      "flushIntervalMs": 10000
    }
  }
}
```

Replace `eu` with `us` if your account is in the US region. The `${BRONTO_API_KEY}` interpolation keeps the secret out of committed config — OpenClaw resolves the variable at load time and fails fast if it is unset.

OpenClaw's `logs` toggle defaults to `false`, so set `"logs": true` to send log records alongside traces.

### 2. Configure `~/.openclaw/.env`

```bash ~/.openclaw/.env theme={"dark"}
BRONTO_API_KEY=YOUR_API_KEY
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
```

| Variable                                            | Purpose                                                                                                                                             |
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BRONTO_API_KEY`                                    | Resolved into the `x-bronto-api-key` header at gateway load.                                                                                        |
| `OTEL_SEMCONV_STABILITY_OPT_IN`                     | Opts in to stable GenAI semantic-convention attributes (`gen_ai.*`). Required for most LLM-observability tooling. Cannot be set in `openclaw.json`. |
| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Required by Bronto.                                                                                                                                 |

### 3. Restart and verify

Restart the gateway, then send the assistant a message and check Bronto:

* **Traces** — open [Traces](/tracing/explore-traces) and check that traces for the openclaw-gateway service are visible.
* **Logs** — open [Log Search](/Search-and-Visualize/Log-Search) and check for data in the `openclaw-demo/openclaw` dataset.

<Note>
  The gateway logs only emit a `logs exporter enabled` line on startup — they do **not** log a traces exporter line, and they do **not** log export failures.
</Note>

## Reference

### Endpoints by region

| Region | Traces                                     | Logs                                     |
| ------ | ------------------------------------------ | ---------------------------------------- |
| EU     | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.eu.bronto.io/v1/logs` |
| US     | `https://ingestion.us.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/logs` |

### Headers

| Header                | Description                                                     |
| --------------------- | --------------------------------------------------------------- |
| `x-bronto-api-key`    | Bronto ingestion API key (required).                            |
| `x-bronto-dataset`    | Dataset that telemetry is routed to.                            |
| `x-bronto-collection` | Groups related services within the dataset — e.g. `production`. |

### Notable `openclaw.json` diagnostics fields

| Key               | Notes                                                                                             |
| ----------------- | ------------------------------------------------------------------------------------------------- |
| `protocol`        | Must be `http/protobuf`. OpenClaw ignores gRPC.                                                   |
| `serviceName`     | Identifies the source in Bronto — appears as `service.name`.                                      |
| `traces` / `logs` | Both default to enabled-with-export, but `logs` requires explicit `true` in some plugin versions. |
| `captureContent`  | Set `true` to attach prompt and response content to spans. Off by default.                        |
| `sampleRate`      | Root-span sampling ratio, `0.0`–`1.0`. Use `1` to capture every model call.                       |
| `flushIntervalMs` | How often the exporter flushes batched signals.                                                   |

## Troubleshooting

### Step one: isolate where the failure is

Before checking individual settings, determine which side of the pipeline is failing. The Collector path makes this trivial — its `debug` exporter prints every signal it receives.

* **If using the Opentelemetry Collector:** Tail the Collector's output (see [Confirm signals are flowing](#3-confirm-signals-are-flowing)) and send the assistant a message.
  * Signals **appear** in the Collector output but **not** in Bronto → the failure is between the Collector and Bronto. Check the API key, region, and headers in `otel-collector-config.yaml`.
  * Signals **do not appear** in the Collector output → the failure is upstream of the Collector. The plugin is not enabled, the gateway has not been restarted, or no model activity is being generated.
* **If sending telemetry directly:** Test network and auth as described in the next section. If that fails switch to the OpenTelemetry Collector and run the same check. This is by far the fastest way to narrow the failure down - without it, you cannot see what OpenClaw is (or isn't) emitting.

### Network and auth test

Use this to check for networking or auth failures between the Collector and Bronto. Run both checks from the same host as the Collector (or your OpenClaw agent, if sending telemetry directly).

The examples target the EU region — swap `eu` for `us` if your account is in the US region.

**1. DNS resolution.** Empty output means DNS is broken locally (split-DNS on a corporate VPN, misconfigured `resolv.conf` inside a container, captive portal, etc.).

```bash theme={"dark"}
dig +short ingestion.eu.bronto.io
```

**2. End-to-end POST.** In the Bronto UI, go to

**My Data** (sidebar) → **Add Data** → **Test Connection** (bottom of the page).

Bronto generates a `curl` command pre-filled with a hello-world payload and your API key — copy-paste it into a shell on the Collector's host.

A `200` proves both connectivity and that the API key is valid for this region.
If it fails, re-run with `-vvv` for the full request, TLS handshake, and response, and Google the specific error.

### Common issues

**API key incorrect.** Especially common when an AI agent edited the config - agents frequently mis-substitute the key (dropped characters, wrapped in extra quotes, replaced with a placeholder like `<YOUR_API_KEY>`). Re-paste the key by hand and confirm it matches exactly.

**Logs arrive in Bronto but no traces or metrics.** This is a known intermittent issue with the `diagnostics-otel` plugin. Fully restart the gateway service — `docker compose restart openclaw-gateway`, or restart the OpenClaw container / supervised process for native installs. A simple reload is not enough.

**Traces arrive but no logs.** OpenClaw's `logs` toggle defaults to `false` in some plugin versions. Set `"logs": true` explicitly in `openclaw.json`.

**Wrong region.** The API key is region-scoped. EU keys do not work against `us` endpoints and vice versa. Confirm the key's region in Bronto and use the matching `ingestion.<region>.bronto.io` host.

**Spans arrive but `gen_ai.*` attributes are missing.** Set `OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental` in `~/.openclaw/.env` and restart the gateway. Without it, OpenClaw emits only its own `openclaw.*` attributes.

**No prompt/response content on spans.** Expected unless `captureContent` is `true` in the `diagnostics.otel` block.

**Plugin not exporting at all.** Confirm `diagnostics-otel` is in `plugins.allow`, the plugin is enabled, and both `diagnostics.enabled` and `diagnostics.otel.enabled` are `true`.

**`protocol` ignored / nothing exported.** The `protocol` field must be `http/protobuf`. OpenClaw ignores gRPC.

## Configure with AI (experimental)

If you'd rather have an OpenClaw up to Bronto for you itself, paste one of the prompts below into an agent with access to your OpenClaw host (or your local checkout of `~/.openclaw/`). Substitute occurrences of `<YOUR API KEY>` with your Bronto API key before sending.

<Warning>
  **Treat AI-generated configuration as untrusted until you've verified it.**

  **This approach is not recommended. Use at the risk of wasting your time**

  Coding agents routinely:

  * mis-substitute secrets (drop characters from the API key, wrap it in extra quotes, or leave the literal placeholder `<YOUR_API_KEY>` in place);
  * hallucinate config keys, env-var names, CLI flags, or endpoint paths that look plausible but don't exist;
  * skip steps, run them out of order, or silently overwrite parts of `openclaw.json` / `.env` that they think are irrelevant.

  After the agent finishes, **diff what changed**, open `~/.openclaw/.env` and `otel-collector-config.yaml` (if using the Collector), and confirm by hand that the API key, region, and field names match this page exactly. If telemetry doesn't show up in Bronto, start with [Troubleshooting](#troubleshooting) - and assume the agent's work is the cause until proven otherwise.
</Warning>

<AccordionGroup>
  <Accordion title="Direct path prompt">
    ````text theme={"dark"}
    **Set up OpenTelemetry collection from OpenClaw and forward it to Bronto.**

    **Bronto details:**
    - API Key: `<YOUR API KEY>`
    - Region: EU
    - Dataset: `openclaw`
    - Collection: `openclaw-demo`
    - Service name: `openclaw-gateway`

    **Steps:**

    1. Install and enable the `diagnostics-otel` plugin:
    ```
    openclaw plugins install clawhub:@openclaw/diagnostics-otel
    openclaw plugins enable diagnostics-otel
    ```

    2. Add the `diagnostics` block to `~/.openclaw/openclaw.json` (top level, merge with existing — don't nuke anything):
    ```json
    {
     "diagnostics": {
       "enabled": true,
       "otel": {
         "enabled": true,
         "endpoint": "https://ingestion.eu.bronto.io",
         "tracesEndpoint": "https://ingestion.eu.bronto.io/v1/traces",
         "logsEndpoint": "https://ingestion.eu.bronto.io/v1/logs",
         "metricsEndpoint": "https://ingestion.eu.bronto.io/v1/metrics",
         "protocol": "http/protobuf",
         "serviceName": "openclaw-gateway",
         "headers": {
           "x-bronto-api-key": "${BRONTO_API_KEY}",
           "x-bronto-dataset": "openclaw",
           "x-bronto-collection": "openclaw-demo"
         },
         "captureContent": true,
         "traces": true,
         "logs": true,
         "metrics": true,
         "sampleRate": 1,
         "flushIntervalMs": 10000
       }
     }
    }
    ```

    3. Set up `~/.openclaw/.env` — add (don't overwrite existing vars):
    ```
    BRONTO_API_KEY=<YOUR API KEY>
    OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
    OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
    ```

    4. Restart the gateway.

    **Important:** Merge configs — don't clobber existing `openclaw.json` or `.env` contents. Read first, then update.

    ````
  </Accordion>

  <Accordion title="OpenTelemetry Collector path prompt">
    ````text theme={"dark"}
    **Set up OpenTelemetry collection from OpenClaw with an OTel Collector sidecar and forward it to Bronto.**

    **Bronto details:**
    - API Key: `<YOUR API KEY>`
    - Region: EU
    - Dataset: `openclaw`
    - Collection: `openclaw-demo`
    - Service name: `openclaw-gateway`

    **Steps:**

    1. Install and enable the `diagnostics-otel` plugin:
    ```
    openclaw plugins install clawhub:@openclaw/diagnostics-otel
    openclaw plugins enable diagnostics-otel
    ```

    2. Create an OpenTelemetry Collector config file (e.g. `otel-collector-config.yaml`) with the following content. This accepts OTLP/HTTP on port `4318`, prints everything to stdout via the `debug` exporter (useful for confirming signals are flowing — remove it once telemetry is stable), and forwards everything to Bronto:

    ```yaml
    receivers:
     otlp:
       protocols:
         http:
           endpoint: "0.0.0.0:4318"

    processors:
     batch:

    exporters:
     debug:
       verbosity: detailed

     otlphttp/bronto:
       traces_endpoint: "https://ingestion.eu.bronto.io/v1/traces"
       metrics_endpoint: "https://ingestion.eu.bronto.io/v1/metrics"
       logs_endpoint: "https://ingestion.eu.bronto.io/v1/logs"
       compression: gzip
       headers:
         x-bronto-api-key: <YOUR API KEY>
         x-bronto-dataset: openclaw
         x-bronto-collection: openclaw-demo

    service:
     pipelines:
       traces:
         receivers: [otlp]
         processors: [batch]
         exporters: [debug, otlphttp/bronto]
       metrics:
         receivers: [otlp]
         processors: [batch]
         exporters: [debug, otlphttp/bronto]
       logs:
         receivers: [otlp]
         processors: [batch]
         exporters: [debug, otlphttp/bronto]
    ```

    3. Start the OTel Collector with this config. Install method varies (Docker, Homebrew, Linux package, Kubernetes — see [OTel Collector installation docs](https://opentelemetry.io/docs/collector/installation/)). Example with Docker:
    ```
    docker run --rm -p 4318:4318 -v $(pwd)/otel-collector-config.yaml:/etc/otelcol/config.yaml otel/opentelemetry-collector:latest --config=/etc/otelcol/config.yaml
    ```

    4. Add the `diagnostics` block to `~/.openclaw/openclaw.json` (top level, merge with existing — don't nuke anything):
    ```json
    {
     "diagnostics": {
       "enabled": true,
       "otel": {
         "enabled": true,
         "endpoint": "http://localhost:4318",
         "protocol": "http/protobuf",
         "serviceName": "openclaw-gateway",
         "captureContent": true,
         "traces": true,
         "logs": true,
         "metrics": true,
         "sampleRate": 1,
         "flushIntervalMs": 10000
       }
     }
    }
    ```

    If the Collector and gateway run as separate Docker containers on a shared network, change `endpoint` to the Collector's service/container name (e.g. `http://otel-collector:4318`).

    5. Add the following to `~/.openclaw/.env` (merge — don't overwrite existing vars):
    ```
    OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
    OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
    ```

    6. Restart the gateway:
    ```
    openclaw gateway restart
    ```
    ````
  </Accordion>

  <Accordion title="Troubleshooting prompt">
    Hand the agent this prompt if telemetry isn't showing up in Bronto after running one of the setup prompts above.

    ````text theme={"dark"}
    ### Step 1: Isolate where the failure is

    **If using an OTel Collector sidecar:**
    1. Tail the Collector's stdout/logs.
    2. Send the assistant a message.
    3. Check what appears:
    - Signals appear in Collector output but **not** in Bronto → failure is between Collector and Bronto (check API key, region, headers in `otel-collector-config.yaml`).
    - Signals **don't appear** in Collector output at all → failure is upstream (plugin not enabled, gateway not restarted, no model activity).

    **If sending telemetry directly (no Collector):**
    Test network and auth (step 2 below). If that fails, switch to a Collector setup — it's the fastest way to narrow down where the pipeline breaks. Without it, you can't see what OpenClaw is (or isn't) emitting.

    ### Step 2: Network and auth test

    Run these from the same host as the Collector (or the OpenClaw gateway if sending directly). Region is EU — swap to `us` if needed.

    **DNS resolution** — empty output means DNS is broken (corporate VPN, misconfigured `resolv.conf`, captive portal, etc.):
    ```bash
    dig +short ingestion.eu.bronto.io
    ```

    ### Step 3: Check common issues

    Go through these in order:

    | Symptom | Likely cause | Fix |
    |---------|-------------|-----|
    | No data at all | API key mangled (AI agents love to drop chars, add extra quotes, or replace with `<YOUR_API_KEY>`) | Re-paste the key by hand, confirm it matches exactly |
    | Logs arrive but no traces or metrics | Known intermittent issue with `diagnostics-otel` plugin | Fully restart the gateway service (not just a reload) — `docker compose restart openclaw-gateway` or restart the container/supervised process |
    | Traces arrive but no logs | `logs` toggle defaults to `false` in some plugin versions | Set `"logs": true` explicitly in `openclaw.json` |
    | Wrong region errors | API key is region-scoped — EU keys don't work against US endpoints and vice versa | Confirm key's region in Bronto, use matching `ingestion.<region>.bronto.io` |
    | Spans arrive but missing `gen_ai.*` attributes | Missing semconv opt-in | Set `OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental` in `~/.openclaw/.env` and restart gateway |
    | No prompt/response content on spans | `captureContent` not enabled | Set `"captureContent": true` in `diagnostics.otel` block |
    | Plugin not exporting at all | Plugin not properly enabled | Confirm `diagnostics-otel` is in `plugins.allow`, plugin is enabled, and both `diagnostics.enabled` and `diagnostics.otel.enabled` are `true` |
    | `protocol` ignored / nothing exported | Wrong protocol value | `protocol` must be `http/protobuf` — OpenClaw ignores gRPC |

    **Important:** Read `openclaw.json` and `.env` before making changes. Merge — don't nuke existing config.
    ````
  </Accordion>
</AccordionGroup>
