Skip to main content
Moda accepts standard OpenTelemetry traces over OTLP/HTTP. If your application is already instrumented — with the OpenTelemetry GenAI semantic conventions, OpenLLMetry, or the Vercel AI SDK’s telemetry — point that exporter at Moda’s trace endpoint and Moda traces are extracted without re-instrumentation. A Moda trace is one full agent run, keyed by the moda.conversation_id attribute (the trace ID); it can span many OpenTelemetry traces, and the OTLP traceId is only a fallback for grouping. The Moda SDKs use this same endpoint; you only need this page when integrating an existing OpenTelemetry pipeline directly.

Endpoint and authentication

Both OTLP/HTTP encodings are accepted; OTLP/gRPC is not supported.

Point an exporter at Moda

Standard OTLP exporters read these variables:
Use the _TRACES_-scoped variables (rather than OTEL_EXPORTER_OTLP_ENDPOINT) so the exporter posts to the exact /v1/traces path and other signals in your pipeline are unaffected.
Already running OpenTelemetry inside a Node.js app? The Moda SDK for Node.js attaches its span processor to your existing TracerProvider instead of replacing it — see Node.js SDK.

Supported attribute conventions

Moda recognizes GenAI spans in each of these conventions automatically, per span — mixed batches are fine: When a span carries both llm.* and numbered gen_ai.* message attributes, the llm.* set is used — messages are never extracted twice from one span.

Model, provider, usage, and finish reason

For each field, the first attribute found wins:

Moda attribution attributes

Set these span attributes to control how spans map onto Moda traces, users, environments, and prompts. All are optional. The trace ID, user, and prompt keys are also read from the Vercel AI SDK metadata form ai.telemetry.metadata.moda.*, which is how getVercelAITelemetry() sets them. On the resource, user.id / enduser.id and deployment.environment are read as defaults for every span under that resource.

Trace ID precedence

For each span, the trace ID (conversation_id) is resolved in this order:
  1. moda.conversation_id (including the ai.telemetry.metadata.moda.conversation_id form)
  2. gen_ai.conversation.id — the legacy underscore form gen_ai.conversation_id and the Traceloop key traceloop.association.properties.session_id are also honored
  3. The span’s OpenTelemetry traceId
A bare session_id attribute is deliberately ignored: it is too generic and could merge unrelated traces. Without an explicit conversation_id, spans group by OpenTelemetry trace — each OTLP trace becomes its own Moda trace — so set moda.conversation_id for anything multi-step.

Environment normalization

Environments are normalized to development, staging, or production. Common aliases map to their canonical forms (dev / developdevelopment, stg / stagestaging, prodproduction); unrecognized values fall back to production. A span-level moda.environment overrides the resource-level deployment.environment.

Example request

A minimal OTLP/JSON request with one GenAI chat span:
JSON requests receive a JSON acknowledgment, where count is the number of trace messages extracted (the example yields two — one user message and one assistant message):
Protobuf requests receive a standard OTLP ExportTraceServiceResponse (Content-Type: application/x-protobuf), so unmodified OTLP exporters work without changes. After sending, open Traces in the dashboard — trace conv-123 appears with the extracted user and assistant messages within minutes.

Limits and errors

  • Request bodies are limited to 5 MB (413 Request too large). There is no per-request span-count limit below that.
  • An optional X-Request-ID header (UUID) is echoed back as requestId for correlating requests with responses.

Next steps

  • Ingestion overview — all ingestion endpoints, authentication, and shared limits.
  • Vercel AI SDK — the AI SDK integration that emits ai.* telemetry to this endpoint.
  • HTTP API — the simple JSON alternative when you don’t run OpenTelemetry.
  • Reliability — retries, limits, and error envelopes.