Skip to main content
MeshAI accepts standard OTLP/HTTP exports. Point any OpenTelemetry-instrumented agent at MeshAI and it will auto-discover agents, persist span activity, extract token usage when present, and populate the registry automatically.

Endpoints

All three require an API key with the telemetry:write scope. The host column is not decoration: see the note below on why logs differ.

Quick Setup

Set the standard OpenTelemetry environment variable to point at MeshAI:
Traces and metrics go to ingest.meshai.dev, a separate host from api.meshai.dev. That is deliberate, not a typo: ingest runs behind an OpenTelemetry collector that absorbs large exports and splits them into smaller batches, so a batch too big for the API in one piece is still recorded rather than rejected. Registry, cost and governance stay on api.meshai.dev.Logs are the exception. The collector is configured for traces and metrics only, so /api/v1/ingest/v1/logs is served directly by api.meshai.dev. Send logs to ingest.meshai.dev and you get a 404, which is not in OTLP’s retryable set, so the exporter drops the batch rather than holding it, with nothing to see server-side. That is why the Codex CLI connector points at api.meshai.dev.Do not infer a host from a status code here. An unauthenticated request is rejected at the edge before routing, so every path on ingest.meshai.dev answers 401 whether or not it exists.A 200 from the ingest endpoint means your batch was accepted, not yet stored, because the collector forwards it onward. A missing or malformed key returns 401 immediately, but an expired key or one lacking telemetry:write is only rejected further along. Confirm spans actually arrived in the dashboard rather than relying on the status code.
That’s it. Any OTLP-compatible SDK or agent will now export traces to MeshAI.
The ingest endpoint accepts OTLP protobuf (application/x-protobuf, the stock OTLP SDK default), OTLP JSON, and gzip-compressed bodies (Content-Encoding: gzip). Set OTEL_EXPORTER_OTLP_PROTOCOL=http/json only if you need to force JSON. OTEL_SERVICE_NAME sets the service.name attribute MeshAI uses to name your auto-discovered agent. If you use a real OpenTelemetry SDK and leave it unset, the SDK itself injects a default of unknown_service:<language> (for example unknown_service:python). If your OTLP payload omits the service.name resource attribute entirely, such as from a hand-rolled emitter that doesn’t use an OTel SDK, MeshAI falls back to naming the agent unknown-agent.

What Gets Extracted

When MeshAI receives trace data, it automatically:
  1. Discovers agents from the service.name resource attribute (set via OTEL_SERVICE_NAME or your SDK’s Resource). Each distinct service.name becomes its own agent in the registry. On the free tier only one agent is admitted: the first service.name claims the single free slot and spans from any other service.name are dropped until you upgrade, so emit under one service.name on the free tier and split into per-service agents once on a paid plan
  2. Extracts token usage from gen_ai.usage.input_tokens and gen_ai.usage.output_tokens attributes
  3. Records model info from gen_ai.request.model and gen_ai.system attributes
  4. Records non-token activity separately, so operational spans and failed calls without usage attributes still contribute activity and error evidence without appearing as billable usage
  5. Records bounded span duration samples when valid start and end timestamps are present. Missing, malformed, zero, negative, or longer-than-24-hour durations are excluded from latency statistics without rejecting the span
  6. Registers new agents in your registry if they don’t already exist

Python Example

Using the OpenTelemetry Python SDK:

Node.js Example

Framework Integration

Most agent frameworks support OpenTelemetry natively or via plugins: Set the environment variables above and these frameworks will export traces to MeshAI automatically.

Response Format

A 200 can be returned when accepted_spans is 0. Check duplicate_spans, rejected_spans, rejected_reasons, and any partial_success value rather than inferring the outcome from the status code alone. A span without gen_ai.usage.* is recorded as non-billable activity; add usage attributes when you also want cost and token accounting.

Anomaly signal coverage

Proxy and OTLP telemetry use separate reliability baselines. Both can contribute request counts and error-rate evidence. OTLP trace spans can also contribute latency when they contain a valid positive duration of no more than 24 hours. Spans without a valid duration, including synthetic spans derived from OTLP log records, remain recorded but do not become latency samples. Latency evaluation requires at least 10 samples in the baseline window, 5 in the recent window, and at least 50% duration coverage in both windows. The reported latency statistic is the mean of exact five-minute bucket p95 values. It is not a percentile recomputed across every request in the full multi-day window. Error-rate evaluation remains independent when latency is unavailable or below these gates.
The expanded anomaly pipeline is live. API PR #84 activated recurring five-minute production execution on August 11, 2026. Three consecutive UTC boundaries at 20:20, 20:25, and 20:30 each had exactly one elected runner, completed in 655 ms, 350 ms, and 490 ms, and reported no errors. The initial run created 13 continuity incidents from existing gaps; the next two created no duplicates.

Metrics (Preview)

The metrics endpoint (/api/v1/ingest/v1/metrics) accepts OTLP metric exports and acknowledges them. Metrics-based anomaly detection is coming in Phase 2.