llm span in the last day) without opening each
trace one at a time. Both views share the same filter bar, scope, and date
window.
With no date filter the list shows the last 48 hours. The date control
offers quick ranges (last 48 hours, 7 days, 30 days) or a custom from / to,
up to 30 days at a time — a wider range is limited to 30 days, and the
chip says so. Older traces are still there: pick a range to reach them, back to
the 90-day retention window. Opening a trace, or a call’s Trace tab, has no
window at all. If a range is too heavy for your volume, the page says traces are
temporarily unavailable — retry, or narrow the range.
Explore a trace
On the full trace page, use the copy icon beside the trace ID in the header to copy the complete ID. Open conversation opens the linked call. If the header says No linked conversation, the info icon opens the connection guide. The viewer has two panes: span navigation on the left and details on the right. It starts in Timeline and remembers your chosen view and panel width. Drag the divider, or focus it and use the arrow keys, to resize the panes. The view tabs, search, and collapse button share the left toolbar. Collapse span navigation to give details more room, then expand it to restore your selection, zoom, and width. Audio keeps playing while navigation is collapsed. Search works across all three views; filtering Tracks keeps the full time scale. The left pane offers three views with a shared selection:- Tree shows the parent/child hierarchy, span types, duration, and tokens.
- Timeline adds timing bars on a shared axis beside the hierarchy. Search and collapse are shared with Tree.
- Tracks groups spans into STT, LLM, tool, TTS, and other recorded lanes. Concurrent spans occupy separate rows. For names that are too short to read on a bar, use Tree or select the bar to inspect its details.
messages array. Use Raw to see the original input and output, or switch
back to Formatted. Tool calls and other message metadata are available under
Additional fields. Text content blocks are readable as text; other blocks
remain visible as JSON. Plain text and unrecognized or incomplete JSON keep
their original display.
Select Trace overview at the top of the left pane to open Overview,
Attributes, and Logs tabs. Overview shows trace statistics and
Duration by step; on the full page, it also holds Call, Transcript,
and Monitors for a linked call. Attributes groups recorded values by span,
so repeated keys keep their original context. Logs shows all trace logs in time
order, including logs without a matching span. Select a span name beneath a log
to inspect that span.
Select Call, Transcript, or Monitors to load that linked-call panel;
select it again to collapse it.
When the trace links to a conversation with audio, a player stays below the
left pane. Play, pause, seek, change speed, or download the recording while
inspecting spans. Playback continues when switching spans or navigation views.
On narrow screens, selecting a span or Trace overview opens the detail view.
Use Back to spans or Escape to return. Trace and span logs show
millisecond timestamps; hover a timestamp for the full date and timezone.
Link traces to conversations
Linking connects a trace’s timing, errors, and token usage to what happened in the actual call. You can open the conversation from the trace header, read its transcript and monitor results, and listen to its recording while inspecting spans. Audio, transcripts, and monitor results appear when they are available on the conversation; linking does not generate missing call data.-
Send the conversation to the same organization. Use your provider
integration or the call ingestion API.
For API-ingested calls, set
call.externalIdto the provider’s call, room, or session ID. Exporting traces alone does not create a conversation. -
Send that same ID with the trace. Set
session.idon your spans or OpenTelemetry resource to the exact external ID stored with the conversation. For example, inside an active Python span:Zelto also recognizescall.id,gen_ai.conversation.id,conversation.id,zelto.reference_id,livekit.room,livekit.room_name,room.name, andlk.room_name. These attributes are external call references, not the trace ID. With native JSON, use the span’ssessionReffield. For LiveKit, use the same room name incall.externalIdand the trace’s room/session attribute. - Reopen the trace after both arrive. The header shows Open conversation when Zelto finds one matching conversation. You can send the trace before or after the conversation.
Identify agents with your own IDs
Send your stable agent ID aszelto.agent_external_id on each span/log, or as
an OpenTelemetry resource attribute when the resource represents one agent:
agent.externalId in your call uploads. Keep it stable
across calls and releases. session.id changes for each call; it should match
that call’s call.externalId.
Zelto reuses the matching agent in your organization, or creates one named after
your external ID. A trace can arrive before its call. Include
zelto.agent_provider with the same provider used by call ingestion (livekit
in the example) so both paths create the same agent. If omitted, an existing
unambiguous match is reused; new agents use the zelto provider. IDs are
case-sensitive strings of up to 255 characters; provider names support up to
50 characters. An ambiguous ID across providers stays unassigned until you
specify its provider. Merged IDs resolve to their surviving agent.
For multiple agents in one exporter, put the external ID on each span/log
instead of a shared resource. Span/log attributes override resource defaults.
An explicit zelto.agent_id remains a Zelto UUID and takes precedence;
do not put your external ID in that field, even if it is also a UUID.
Native JSON exports use the same keys inside each span or log’s attributes
object. Their existing agentId field still means a Zelto UUID.
What a trace holds
- Spans, each tagged with a normalized kind:
llm,tts,stt,vad,tool,code,telephony,livekit,session, orother. 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.
Send telemetry
Start with Send traces to Zelto for a runnable first trace, agent identity, call linking, logs, and troubleshooting.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.
owner or
admin role. Point your exporter at Zelto’s
ingest host and authenticate with that key (a bearer token):
/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.
Telemetry requests to /v1/traces, /v1/logs, and /webhooks/otel accept up to
10 MB (10,000,000 bytes) per request, measured after decompression. Larger
requests return HTTP 413; reduce the export batch size before retrying them.
The Python HTTP exporter used in these examples sends protobuf. Leave
OTEL_EXPORTER_OTLP_PROTOCOL at http/protobuf; Zelto also accepts OTLP JSON
from exporters that support it.429 with a Retry-After header — honor it and retry with
backoff. Exporter retry budgets and queues are finite, so monitor export errors
and dropped batches. If your agent legitimately exports at a high volume, ask your Zelto contact to raise the
per-organization ingest rate.
If no traces match your filters, use Clear filters or adjust the date range.
If your organization has no traces yet, confirm the exporter is pointed at the
ingest host above and is sending a valid
Authorization: Bearer ingest key.200 acknowledges acceptance. With buffered ingestion, query visibility
follows asynchronously; the target is 30 seconds under normal load, not a
guaranteed maximum. Exporter batching and outages can add delay. OTLP returns
{} and native JSON returns {"received":true}.
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. See the
complete example.
Use OTLP when your stack already supports it.
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 atool 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.
Related
- Tool calls: compare tool usage, outcomes, and duration across calls and agents.
- 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.

