Skip to main content
Traces are the OpenTelemetry view of what happened inside a call. One call or session is one trace: a tree of spans (an LLM generation, a text-to-speech step, a speech-to-text step, a tool call, your own code) plus the logs those steps emit. Zelto stores this telemetry so you can see, per call, where the time and tokens went and what failed — replacing a separate Langfuse-plus-logging stack. Open Traces in the sidebar to see the list: one row per trace, with the root span, the kinds of spans present, span count, latency, tokens, cost, and status. Click a row for a quick summary, then open the full waterfall to walk the span tree, read each span’s input/output and attributes, and see its logs.

What a trace holds

  • Spans, each tagged with a normalized kind: llm, tts, stt, vad, tool, code, telephony, livekit, session, or other. GenAI spans carry model, token, and cost fields promoted for fast filtering.
  • Logs, attached to a span or to the trace as a whole, with a severity and body.
  • A session reference (room / call / session id) that links a trace back to its conversation when the two can be matched.
Traces are retained for 90 days.

Send telemetry

If your calls come from Vapi, you get traces for free — Zelto turns each pulled call’s Vapi platform logs into a trace, with no exporter to install. See Vapi → Traces.
Traces is fed by standard OTLP/HTTP, so any agent with an OpenTelemetry exporter works — including a LiveKit agent, whose sessions LiveKit auto-instruments. There’s no Zelto-specific client code to write, but you do register an OTLP exporter pointed at Zelto — a few lines in your agent (see LiveKit for the exact snippet). Open Traces and use Connect agent to create a per-organization, write-only observability ingest key (shown once) and copy the exporter config. Creating and revoking ingest keys needs the owner or admin role. Point your exporter at Zelto’s ingest host and authenticate with that key (a bearer token):
The exporter posts spans to /v1/traces and logs to /v1/logs — the OpenTelemetry SDK appends those paths to the endpoint above for you. Both OTLP/HTTP encodings are accepted — protobuf (what most exporters send by default, including the OpenTelemetry Python SDK a LiveKit agent uses) and JSON — so you don’t have to match a specific one. gRPC (:4317) is not accepted; use the HTTP endpoint above.
The OpenTelemetry Python SDK (which LiveKit’s agents run on) sends http/protobuf and does not implement http/json, so leave OTEL_EXPORTER_OTLP_PROTOCOL at http/protobuf (its default). Zelto accepts both encodings regardless.
Ingestion is rate-limited per organization. If you export at a very high rate, some requests get a 429 with a Retry-After header — standard OpenTelemetry exporters honor it and back off automatically, so no batches are lost. If your agent legitimately exports at a high volume, ask your Zelto contact to raise the per-organization ingest rate.
If traces aren’t appearing, confirm the exporter is pointed at the ingest host above and is sending a valid Authorization: Bearer ingest key.

Native JSON

If your agent doesn’t speak OTLP, post a simpler Zelto-native JSON body of spans and logs to /webhooks/otel with the same bearer key. Use OTLP where you can — it’s the zero-code path.

Backfill from tool calls

Already recording tool calls but not yet exporting OpenTelemetry? Zelto can project your existing tool-call history into traces so the view isn’t empty while you wire up an exporter — each tool call becomes a tool span, and a call’s tool calls share one trace. Only calls from the last 90 days are kept (the trace retention window). Ask your Zelto contact to run the tool-call backfill for your organization.
  • Conversations — the transcript-and-analysis view of a call; a trace links to its conversation when the session id matches.
  • LiveKit — point a LiveKit agent’s OpenTelemetry exporter at Zelto to stream traces.