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 conversations are extracted without re-instrumentation. 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 conversations, users, environments, and prompts. All are optional. The conversation, 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.

Conversation ID precedence

For each span, the 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 trace ID
A bare session_id attribute is deliberately ignored: it is too generic and could merge unrelated conversations. Without an explicit ID, spans group by trace — each trace becomes its own conversation — so set moda.conversation_id for anything multi-turn.

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 conversation 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 Conversations in the dashboard — conversation 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.