Overview
The session observability endpoints return the details of a single session, including its transcript, agent logs, trace spans, and metrics, and a download URL for the recording. Use them to debug a deployed agent. To find a session, see Sessions.
Every endpoint here needs the Admin role on the project.
Transcripts, recordings, and logs can contain personal information about the people who talk to your agent. Use this data only for the task at hand. Don't copy it into other tools or share it.
Observability data exists only for sessions that run while user data recording is on. Projects created in the dashboard have it on by default. Projects that you create with the API have it off unless you set enableUserDataRecording to true. To turn it on for an existing project, update the project.
When recording is off and no data exists, a request returns 400 with an ObservabilityDisabled detail that links to the project setting. Turning recording off doesn't delete data that's already recorded.
Agents export session data during the session and for a short time after it ends. A read returns the data that exists when it runs, and dataStatus.state tells you if more data can still arrive:
DATA_STATE_SESSION_ACTIVE: the session is active, and its agents can export more data.DATA_STATE_SETTLING: the session ended less than 2 minutes ago, and an agent joined it. More data can still arrive. Read again afterdataStatus.retryAfterSeconds.DATA_STATE_SETTLED: the session ended 2 minutes ago or more, or no agent joined it. LiveKit expects no more data. The data can still be incomplete, for example when an agent didn't export all of it.
While the session is active or settling, a recording URL request for a recording that doesn't exist yet returns an empty url. After that, it returns 404.
By default, LiveKit deletes the transcript, logs, traces, metrics, and recording of a session 30 days after the session ends. The session itself stays in the session list after that, without this data. To learn more, see Retention window.
A transcript item is a message, a tool call, a tool result, an agent handoff, or a change to the agent's configuration. Items come in order, with per-turn timing where the agent reported it. The text can differ from what the dashboard shows:
- An agent turn can include text-to-speech markup, such as
<expr type="expression" label="happy"/>. These endpoints return the markup as text. The dashboard shows each markup tag as a delivery cue instead. - A project with personally identifiable information (PII) redaction publishes the transcript only after it redacts the recording, so the transcript takes longer to appear. A redacted message includes
"redacted": true, with each removed value replaced by a<redaction type="..."/>marker.
To call these endpoints from the CLI, use the lk analytics session commands, for example lk analytics session transcript SESSION_ID --user-auth.
Get session transcript
/v0/projects/{projectId}/sessions/{sessionId}/transcriptReturns the conversation of a session as ordered transcript items. The items are messages, tool calls and results, agent handoffs, and agent configuration changes. It is the conversation that the transcript on the dashboard shows.
The agent exports its transcript when the session ends. There is a delay before you can read it, and the length of the delay is not fixed. On a project with PII redaction, you can read it only after LiveKit redacts the session recording. Thus, an ACTIVE session returns the items that exist, usually none, with no error. Read it again after the session ends. An unknown session returns NotFound.
Returns a list of TranscriptItem objects, with a pageInfo cursor.
Path parameters
projectIdstringThe project ID (p_...).
sessionIdstringThe session ID (RM_...).
Query parameters
page.cursorstringThe cursor of the page to return: the nextCursor of the previous page. When empty, the list starts at the first item.
page.pageSizeint32The maximum number of items to return. When 0, the list uses its default page size.
Other response fields
skippedRecordsintegerThe number of records in this page that the API cannot read as transcript items, and does not return. For example, a record of an item type that the API does not know. Zero when the page is complete.
dataStatusDataStatusThe data status of the session transcript: whether more of it can still arrive.
To learn more, see DataStatus.
Get session logs
/v0/projects/{projectId}/sessions/{sessionId}/logsReturns the log records that the agents of a session exported, in time order. These are the records that the logs panel on the dashboard shows. The chat history is not included, because GetSessionTranscript returns it. Evaluation results are included. To get the events of the session, such as participants that join, use AnalyticsService.ListSessionEvents.
An ACTIVE session returns the records that its agents exported up to now. While you page through the records, an agent can export a record with a time that your pages already passed. For example, in oldest-first order, a record with a time earlier than the cursor position. This read does not return that record. A new read returns it. An unknown session returns NotFound. A read filtered by logLevels can return no records because no record has those levels. Thus, only a read with no filter returns the ObservabilityDisabled error.
Returns a list of LogRecord objects, with a pageInfo cursor.
Path parameters
projectIdstringThe project ID (p_...).
sessionIdstringThe session ID (RM_...).
Query parameters
page.cursorstringThe cursor of the page to return: the nextCursor of the previous page. When empty, the list starts at the first item.
page.pageSizeint32The maximum number of items to return. When 0, the list uses its default page size.
logLevelsArray<LogLevel>The log levels to return, as the logs filter on the dashboard selects them. For example, only TRACE and FATAL. Returns only the records at these levels. When empty, returns all records, including records with no level, such as a passed evaluation. LOG_LEVEL_UNSPECIFIED returns InvalidArgument.
To learn more, see LogLevel.
sortOrderSortOrderThe sort direction of the timestamps. Defaults to ascending (oldest first).
To learn more, see SortOrder.
Other response fields
dataStatusDataStatusThe data status of the session logs: whether more of them can still arrive.
To learn more, see DataStatus.
Get session traces
/v0/projects/{projectId}/sessions/{sessionId}/tracesReturns the spans that the agents of a session exported, ordered by start time. These are the spans that the trace view on the dashboard shows. Each span names its parent, so you can build the span tree from the pages. The attributes of a span hold the turn and latency fields that the turn view on the dashboard uses, such as lk.generation_id and lk.response.ttft.
An ACTIVE session returns the spans that its agents exported up to now. A span exported after the first page appears only in a new read. The API reads the later pages by offset, so a span exported during your read can move them. Thus, a span can repeat, or a page can skip a span. Remove duplicates by spanId. To get a skipped span, read again from the first page. An unknown session returns NotFound.
Returns a list of Span objects, with a pageInfo cursor.
Path parameters
projectIdstringThe project ID (p_...).
sessionIdstringThe session ID (RM_...).
Query parameters
page.cursorstringThe cursor of the page to return: the nextCursor of the previous page. When empty, the list starts at the first item.
page.pageSizeint32The maximum number of items to return. When 0, the list uses its default page size.
Other response fields
dataStatusDataStatusThe data status of the session spans: whether more of them can still arrive.
To learn more, see DataStatus.
Get session metrics
/v0/projects/{projectId}/sessions/{sessionId}/metricsReturns the OpenTelemetry metric points that the agents of a session exported, ordered by time. The points include turn latencies, such as lk.agents.turn.e2e_latency and lk.agents.turn.llm_ttft, token and duration usage, such as lk.agents.usage.llm_input_tokens, and the gen_ai.* histograms. They also include the metrics that the agent's own code recorded.
These are the raw metrics that agents export. They do not exactly match the metrics panel on the dashboard, which calculates its values from the transcript and traces. Only an agent that exports OpenTelemetry metrics to LiveKit Cloud has points. An agent whose code installs its own MeterProvider exports no metrics to LiveKit Cloud, and its sessions return no points.
Some points do not have the labels that their agent exported. LiveKit Cloud groups the series of a session by their attributes only, and gives each group the name of its first point. This has these results. Several metrics can have one name. For example, the input, output, and cached token counts of an LLM all have the name lk.agents.usage.llm_input_tokens. Points of one series with the same time and the same value become one point. When a session has two agents, a point can have the resource attributes of the other agent.
An agent exports its metrics every 30 seconds, and its turn latencies when the session ends. Thus, an ACTIVE session returns the points that its agents exported up to now. An unknown session returns NotFound. A read filtered by names can return no points because no metric has those names. Thus, only a read with no filter returns the ObservabilityDisabled error.
Returns a list of MetricPoint objects, with a pageInfo cursor.
Path parameters
projectIdstringThe project ID (p_...).
sessionIdstringThe session ID (RM_...).
Query parameters
page.cursorstringThe cursor of the page to return: the nextCursor of the previous page. When empty, the list starts at the first item.
page.pageSizeint32The maximum number of items to return. When 0, the list uses its default page size.
namesArray<string>The names of the metrics to return, such as lk.agents.turn.e2e_latency. Returns only the points of these metrics. Each name must match exactly. When empty, returns all metrics. The maximum is 50 names, each 1 to 256 characters.
Other response fields
dataStatusDataStatusThe data status of the session metric points: whether more of them can still arrive.
To learn more, see DataStatus.
Get session recording URL
/v0/projects/{projectId}/sessions/{sessionId}/recording-urlReturns a short-lived signed URL for a session recording: its audio or its chat history. When the recording doesn't exist and dataStatus.state is DATA_STATE_SESSION_ACTIVE or DATA_STATE_SETTLING, the response has an empty url, because the agent can still upload the recording. In every other state, a session with no recording of that type returns NotFound.
Path parameters
projectIdstringThe project ID (p_...).
sessionIdstringThe session ID (RM_...).
Query parameters
fileTypeRecordingFileTypeThe recording to sign a URL for. RECORDING_FILE_TYPE_UNSPECIFIED returns InvalidArgument.
To learn more, see RecordingFileType.
expirySecondsintegerThe time that the URL stays valid, in seconds. Defaults to 900 (15 minutes) when unset or 0. The API clamps a larger value to 900, with no error. expiresAt gives the expiry that the API granted.
Response fields
urlstringA signed URL that downloads the recording from storage in the data region of the project. The URL needs no credentials and is valid until expiresAt. Audio is Ogg. Chat history is JSON, served with Content-Encoding: gzip. Empty when the recording doesn't exist and dataStatus.state is DATA_STATE_SESSION_ACTIVE or DATA_STATE_SETTLING.
recordingStartedAttimestampThe time that the recording started, as the agent reported it when it uploaded the recording. Use it to align the audio with the transcript.
expiresAttimestampThe time that the URL stops working: the time of the request plus the granted expiry, after the 15-minute clamp.
dataStatusDataStatusThe data status of the session recording: whether it can still arrive or change. When url is empty, expiresAt is unset: read again after retryAfterSeconds, or after the session ends.
To learn more, see DataStatus.
Types
Types used by these endpoints.
ConfigUpdate
A change to the agent's instructions or tools during the session.
instructionsstringThe new agent instructions. Empty when the instructions did not change.
toolsAddedArray<string>The tools the agent gained.
toolsRemovedArray<string>The tools the agent lost.
DataState
A state of the session data: whether more of it can still arrive.
This type has these values:
DATA_STATE_UNSPECIFIEDDATA_STATE_SESSION_ACTIVEDATA_STATE_SETTLINGDATA_STATE_SETTLED
DataStatus
The status of the session data: whether more of it can still arrive. A read returns the data that exists when it runs, so a response can hold only part of the session data in every state.
stateDataStateThe state of the session data: whether more of it can still arrive.
To learn more, see DataState.
retryAfterSecondsintegerThe number of seconds to wait before you read again. Set only when state is DATA_STATE_SETTLING, and 0 in every other state.
LogLevel
The level of a log record, as the logs panel on the dashboard shows and filters it. Python and Node.js agents use different level names, such as CRITICAL in Python and FATAL in Node.js. Thus, the level of a record comes from its OpenTelemetry severity number, or from its level name when it has no severity number. Each level has the same meaning for Python and Node.js agents.
This type has these values:
LOG_LEVEL_UNSPECIFIEDLOG_LEVEL_TRACELOG_LEVEL_DEBUGLOG_LEVEL_INFOLOG_LEVEL_WARNLOG_LEVEL_ERRORLOG_LEVEL_FATAL
LogRecord
A log record that an agent of a session exported.
idstringThe ID of the record. It is the same on every read.
timestamptimestampWhen the record was logged.
levelLogLevelThe level, mapped onto the LogLevel values.
To learn more, see LogLevel.
severityTextstringThe name of the level, as the agent logged it, such as WARN or CRITICAL.
loggerstringThe logger that wrote the record (its logger.name attribute).
messagestringThe text of the record. A structured logger puts the text in the event, message, or msg field of its body. When a structured body has none of these fields, this field holds the full body as JSON.
bodyFieldsMap<string, any>The fields of a structured log body, other than the message. Empty for a plain text body.
attributesMap<string, any>The attributes of the record, typed and nested as the agent recorded them. They include its resource and scope attributes. When an attribute has two values, the value of the record is used. An integer larger than 2^53 or smaller than -2^53 is a decimal string. Bytes are base64.
traceIdstringThe ID of the trace that the record was logged in, as lowercase hex. Empty when the record was logged outside a trace. With spanId, it links the record to its span in GetSessionTraces.
spanIdstringThe ID of the span that the record was logged in, as lowercase hex. Empty when the record was logged outside a span.
Message
A message that a participant spoke, or text added to the conversation.
roleRoleWho the message came from.
To learn more, see Role.
textstringThe text of the message. When the agent recorded the text in several parts, newlines join the parts. When redacted is true, <redaction type="..."/> markers replace the PII in the text.
interruptedbooleanWhen true, the user interrupted this agent message before it ended.
redactedbooleanWhen true, PII redaction for the project changed the text.
transcriptConfidencenumberThe speech-to-text confidence of a spoken user message, from 0 to 1.
startedSpeakingAttimestampThe time that the speaker started to speak. Unset for a message that was not spoken.
stoppedSpeakingAttimestampThe time that the speaker stopped speaking. Unset for a message that was not spoken.
e2eLatencyMsnumberThe end-to-end latency in milliseconds, from the time that the user stopped speaking to the time that the agent started to respond (the agent's e2e_latency). Set on an agent message. Unset when the agent did not record it.
llmTtftMsnumberThe LLM time to first token in milliseconds (llm_node_ttft). Set on an agent message. Unset when the agent did not record it.
ttsTtfbMsnumberThe TTS time to first byte of audio in milliseconds (tts_node_ttfb). Set on an agent message. Unset when the agent did not record it.
transcriptionDelayMsnumberThe time in milliseconds from the end of the user's speech to its final transcript (transcription_delay). Set on a user message. Unset when the agent did not record it.
endOfTurnDelayMsnumberThe time in milliseconds from the end of the user's speech to the time that the agent decided that the turn ended (end_of_turn_delay). Set on a user message. Unset when the agent did not record it.
onUserTurnCompletedDelayMsnumberThe time in milliseconds that the agent spent in its on_user_turn_completed callback (on_user_turn_completed_delay). Set on a user message. Unset when the agent did not record it.
MetricHistogram
A summary of the values that a histogram point recorded.
countint64The number of values recorded.
sumnumberThe sum of the values. Unset when the agent did not record it.
minnumberThe minimum value. Unset when the agent did not record it.
maxnumberThe maximum value. Unset when the agent did not record it.
bucketBoundsArray<number>The upper bounds of the histogram buckets. bucketCounts has one more count than bucketBounds. bucketCounts[0] counts the values up to bucketBounds[0]. bucketCounts[i] counts the values in (bucketBounds[i-1], bucketBounds[i]]. The last count counts the values above the last bound. Empty for an exponential histogram.
bucketCountsArray<int64>The number of values in each histogram bucket. See bucketBounds. Empty for an exponential histogram.
MetricKind
The OpenTelemetry data type of a metric point.
This type has these values:
METRIC_KIND_UNSPECIFIEDMETRIC_KIND_GAUGEMETRIC_KIND_SUMMETRIC_KIND_HISTOGRAMMETRIC_KIND_EXPONENTIAL_HISTOGRAM
MetricPoint
An OpenTelemetry metric data point that an agent of a session exported. It is the raw metric that the agent exports, so it does not exactly match the metrics panel on the dashboard, which calculates its values from the transcript and traces. Only an agent that exports OpenTelemetry metrics to LiveKit Cloud has points. An agent whose code installs its own MeterProvider exports no metrics to LiveKit Cloud.
namestringThe name of the metric, such as lk.agents.turn.e2e_latency or gen_ai.client.token.usage. Several metrics with the same attributes can have one name. See GetSessionMetrics.
unitstringThe unit of the metric, as the agent declared it, such as s or {token}. Empty when the agent declared no unit.
kindMetricKindWhich kind of metric the point carries, and so which field of data is set.
To learn more, see MetricKind.
startTimetimestampThe start of the interval that the point covers. An agent exports every 30 seconds, so a sum or histogram covers the time since its previous export. Unset for a gauge.
endTimetimestampThe end of the interval, and the moment a gauge was measured.
attributesMap<string, any>The attributes of the point, typed and nested as the agent recorded them. They include its resource and scope attributes, such as room_id, job_id, lk.agent_name, and the model_name of the model. When an attribute has two values, the value of the point is used. When a session has two agents, the resource attributes can be those of the other agent. An integer larger than 2^53 or smaller than -2^53 is a decimal string. Bytes are base64.
histogramMetricHistogramThe summary of a histogram or exponential histogram. Set when kind is METRIC_KIND_HISTOGRAM or METRIC_KIND_EXPONENTIAL_HISTOGRAM.
At most one of histogram and value is set.
To learn more, see MetricHistogram.
valuenumberThe value of a gauge or sum. Set when kind is METRIC_KIND_GAUGE or METRIC_KIND_SUM.
At most one of histogram and value is set.
RecordingFileType
The type of recording that GetSessionRecordingURL returns. To get the conversation of a session as typed items, use GetSessionTranscript.
This type has these values:
RECORDING_FILE_TYPE_UNSPECIFIEDRECORDING_FILE_TYPE_AUDIORECORDING_FILE_TYPE_CHAT_HISTORY
Role
The sender of a transcript message.
This type has these values:
ROLE_UNSPECIFIEDROLE_USERROLE_AGENTROLE_SYSTEMROLE_DEVELOPER
Span
A unit of work in the trace of a session, such as an agent turn or an LLM request.
spanIdstringThe ID of the span, as lowercase hex.
traceIdstringThe trace ID of the span, as lowercase hex.
parentSpanIdstringThe ID of the parent span, as lowercase hex. Empty for a root span. The dashboard also shows a span as a root when its parent is not one of the spans of the session.
namestringThe span name, as the agent recorded it.
startTimetimestampWhen the span started.
endTimetimestampWhen the span ended.
kindSpanKindWhere the span sits in the call: internal, server, client, producer, or consumer.
To learn more, see SpanKind.
statusSpanStatusWhether the span succeeded.
To learn more, see SpanStatus.
statusMessagestringWhy the span failed; set when status is error.
attributesMap<string, any>The attributes of the span, typed and nested as the agent recorded them. They include its resource and scope attributes, such as lk.agent_name. When an attribute has two values, the value of the span is used. An integer larger than 2^53 or smaller than -2^53 is a decimal string. Bytes are base64.
eventsArray<SpanEvent>The events the agent recorded on the span.
To learn more, see SpanEvent.
SpanEvent
An event with a timestamp that a span recorded, such as an exception.
timestamptimestampWhen the event happened.
namestringThe event name, as the agent recorded it.
attributesMap<string, any>The attributes of the event, typed and nested as the agent recorded them.
SpanKind
The OpenTelemetry kind of a span.
This type has these values:
SPAN_KIND_UNSPECIFIEDSPAN_KIND_INTERNALSPAN_KIND_SERVERSPAN_KIND_CLIENTSPAN_KIND_PRODUCERSPAN_KIND_CONSUMER
SpanStatus
The OpenTelemetry status code of a span.
This type has these values:
SPAN_STATUS_UNSPECIFIEDSPAN_STATUS_OKSPAN_STATUS_ERROR
ToolCall
The agent calling a tool.
namestringThe tool the agent called.
callIdstringThe ID of the call. The ToolResult of the call has the same callId.
argumentsstringThe arguments of the call, as a JSON string.
ToolResult
The output a tool returned for a ToolCall.
namestringThe tool that returned the output.
callIdstringThe callId of the ToolCall that this result answers.
outputstringWhat the tool returned.
isErrorbooleanWhen true, the tool failed, and output describes the error.
TranscriptItem
An entry in the conversation of a session. Exactly one of message, toolCall, toolResult, agentHandoff, and configUpdate is set.
idstringThe ID of the item, as the agent assigned it (item_...).
timestamptimestampThe time of the item. For a message, the time that its speaker started to speak, or else the time that the agent created it. For other items, the time that the agent recorded it. Items are ordered by the time that the agent recorded them, so the timestamp of a message can be earlier than the timestamp of the item before it.
agentHandoffTranscriptItem.AgentHandoffThe session passing from one agent to another.
At most one of agentHandoff, configUpdate, message, toolCall, and toolResult is set.
To learn more, see TranscriptItem.AgentHandoff.
configUpdateConfigUpdateA change to the agent's instructions or tools.
At most one of agentHandoff, configUpdate, message, toolCall, and toolResult is set.
To learn more, see ConfigUpdate.
messageMessageSomething said, or added to the conversation as text.
At most one of agentHandoff, configUpdate, message, toolCall, and toolResult is set.
To learn more, see Message.
toolCallToolCallThe agent calling a tool.
At most one of agentHandoff, configUpdate, message, toolCall, and toolResult is set.
To learn more, see ToolCall.
toolResultToolResultThe output a tool returned.
At most one of agentHandoff, configUpdate, message, toolCall, and toolResult is set.
To learn more, see ToolResult.
TranscriptItem.AgentHandoff
The session passing from one agent to another.
fromAgentIdstringThe ID of the agent that hands off the session. Unset for the first agent of the session.
toAgentIdstringThe agent taking over.