Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Note
Features in this article are powered by the standard harness, which uses the billing options described in Licensing for agents powered by the standard harness. Learn how to access standard features in Access standard agents and agent flows.
By integrating Application Insights with your real-time voice agent, you can monitor, troubleshoot, and analyze conversations in near real-time.
By using this integration, you can:
- Track end-to-end voice conversations from ring to hang-up.
- Measure caller-perceived response latency.
- Diagnose tool execution and failures.
- Understand how your agent behaves across different scenarios.
Prerequisites
Before using diagnostics for real-time voice agents, make sure that you:
- Have an Azure Application Insights resource.
- Enable real-time voice on your agent.
Set up Application Insights integration
To enable diagnostics, configure Application Insights for your environment.
How the data is organized
All real-time voice telemetry lands in the traces table in Application Insights. Before you query, keep in mind the following points:
- The meaningful content is in the
customDimensionscolumn. The top-level message field is a placeholder (log record), so don't rely on it. - Every row represents one event from a call, identified by
customDimensions.Subject. - Every event a call produces shares a single
correlationId. That's how you pull one call's rows out of the table. - Always filter by
Subject; rows without one belong to other telemetry pipelines, not the voice agent.
Event types
Each row's customDimensions.Subject tells you what kind of event it is:
| Subject | What it captures | Key fields |
|---|---|---|
CallLifecycle |
Base context on every event; also emitted standalone when the call ends | EventType |
DialogLifecycle |
Conversation started or ended duration and end reason | DialogDuration_Ms, EndReason |
SpeechPipeline |
Voice pipeline setup at call start | AudioLatency_Ms |
LlmInvocation |
One row per model reply; latency and token usage | Duration_Ms (TTFAB), Model, InputTokens, OutputTokens |
ToolExecution |
One row per tool the model called | ToolName, ToolResult, TotalDuration_Ms |
Field reference
Every event carries the base CallLifecycle context in addition to its own fields in the following sections.
CallLifecycle (base context on every event)
CallLifecycle is the base event that every other event carries. Every row in the traces table—DialogLifecycle, SpeechPipeline, LlmInvocation, ToolExecution—includes the CallLifecycle context. CallLifecycle is also emitted as a standalone event when the call ends.
correlationId: The single ID that ties all of a call's rows together. Use this in every query to isolate a call.OrganizationId: The identifier of the organization to which the call belongs. This value also serves as the Application Insights routing key.Timestamp: When the event happened.EventType: The specific moment or event this row marks. The value depends on whetherCallLifecycleis composed with another event or standalone:- When composed with another event,
EventTypetakes the value of that event:DialogStarted,DialogCompleted,SpeechPipeline,LlmInvocation, orToolExecution. - When
CallLifecycleis emitted standalone, the only value isCallDisconnected(the call ended).
- When composed with another event,
ChannelType: Voice. Currently populated only onSpeechPipelinerows.
DialogLifecycle
DialogId: ID of this dialog (agent session).BotId: Which AI agent handled the dialog. Filter on this to isolate a specific agent's calls.DialogStatus: Started or Completed (emitted as a numeric enum: 0 = Started, 1 = Completed).DialogDuration_Ms: How long the dialog ran, in milliseconds. Populated only onDialogCompletedrows.EndReason: Why the dialog ended. Populated only onDialogCompletedrows.CallDisconnected: The call ended (caller hangup or graceful agent end; the two aren't distinguished).StopDialog: The dialog ended without the call ending (for example, a transfer to another dialog).
Emitted as a numeric enum (1 = CallDisconnected). Convert with iff(toint(customDimensions.EndReason) == 1, "CallDisconnected", "StopDialog").
SpeechPipeline
PipelineType: The voice pipeline used, such asGenAI_Realtimefor real-time speech-to-speech. The value is emitted as a numeric enum.AudioLatency_Ms: A setup marker for how long the call's audio session took to start, typically a few milliseconds. This value isn't an audio delay or a network round-trip. It's an internal readiness signal at call start.
Note
The system doesn't yet emit per-utterance speech timing, including Speech-to-Text duration, Text-to-Speech duration, and per-turn audio timestamps.
LlmInvocation (one row per model reply)
Duration_Ms: Caller-perceived reply latency, also called Time to First Audio Back (TTFAB). Measured from when the user stops speaking to when the first audio byte reaches the caller from any source. This source can be the model's spoken reply, a tool's TTS prompt, or a system-generated message. Smaller values are snappier, and sub-second is typical.Model: The model deployment that produced the reply, such asgpt-realtime-2025-08-28.InputTokens: Tokens the model reads for this reply, including the system prompt, conversation history, and latest user input. This number usually grows over a call as history accumulates.OutputTokens: Tokens the model produces for this reply.
For more information about how Duration_Ms behaves on multistep turns, see How latency is measured (voice-specific).
ToolExecution (one row per tool the model calls)
ToolName: The tool or function invoked.ToolResult: Success or Failed, indicating whether the tool call threw an error.TotalDuration_Ms: Total time the tool took from the agent runtime's perspective.McsProcessingTime_Ms: Processing time on the platform side.ExternalCallTime_Ms: The external-service portion of a tool call. This value is populated only when the tool makes an external call. It might be empty for internal tools.
Note
In the current version, the external-service portion of a tool call isn't always fully separated from platform processing time.
Sample queries
Use the following Kusto queries in Application Insights to analyze real-time voice agent telemetry.
Find a specific conversation
When you know the correlationId of the call you're investigating, use this query to return every row from that call in order:
let corr = "<paste-correlationId>";
traces
| extend cl = parse_json(tostring(customDimensions.CallLifecycle))
| where tostring(cl.TrackingContext.CorrelationId) == corr
| project
timestamp,
subject = tostring(customDimensions.Subject),
eventType = tostring(cl.EventType)
| order by timestamp asc
Conversation timing
traces
| where customDimensions.Subject == "DialogLifecycle"
| extend cl = parse_json(tostring(customDimensions.CallLifecycle))
| project
ts = timestamp,
eventType = tostring(cl.EventType), // DialogStarted | DialogCompleted
status = tostring(customDimensions.DialogStatus),
dialogId = tostring(customDimensions.DialogId),
botId = tostring(customDimensions.BotId),
corrId = tostring(cl.TrackingContext.CorrelationId),
duration = toint(customDimensions.DialogDuration_Ms), // DialogCompleted only
endReason = tostring(customDimensions.EndReason) // DialogCompleted only
LLM response latency per invocation
traces
| where customDimensions.Subject == "LlmInvocation"
| extend cl = parse_json(tostring(customDimensions.CallLifecycle))
| project
ts = timestamp,
corrId = tostring(cl.TrackingContext.CorrelationId),
model = tostring(customDimensions.Model),
ttfabMs = toint(customDimensions.Duration_Ms),
inTok = toint(customDimensions.InputTokens),
outTok = toint(customDimensions.OutputTokens)
Tool call time and outcome
traces
| where customDimensions.Subject == "ToolExecution"
| extend cl = parse_json(tostring(customDimensions.CallLifecycle))
| project
ts = timestamp,
corrId = tostring(cl.TrackingContext.CorrelationId),
tool = tostring(customDimensions.ToolName),
totalMs = toint(customDimensions.TotalDuration_Ms),
mcsMs = toint(customDimensions.McsProcessingTime_Ms),
extMs = toint(customDimensions.ExternalCallTime_Ms),
ok = tostring(customDimensions.ToolResult) == "Success"
How latency is measured (voice-specific)
For real-time voice agents, Duration_Ms on LlmInvocation rows measures caller-perceived response latency, which is Time to First Audio Back (TTFAB):
- Start: The moment the user stops speaking.
- End: The moment the first audio byte reaches the caller regardless of source. This moment includes the real-time model speaking, a tool playing a TTS prompt, or a platform-provided message. All three count because they're what the caller actually hears.
Multi-step turns
A single user turn can produce multiple LlmInvocation rows. For example, when the agent says "Let me check that for you," calls a tool, and then delivers the answer. Each step gets its own row, but every row's timer anchors back to the same user-stop-speaking moment.
This means:
- Several rows in the same turn can share the same
Duration_Msvalue. They all point back to the first sound the caller heard. - A step that completed before any sound played can show a smaller, less meaningful value.
- Don't read each row as its own wait time.
To get a single "how long until the caller heard something" value per turn, group by correlationId (and turn boundary) and take the maximum Duration_Ms. Tool duration itself is reported separately on the corresponding ToolExecution row.
Note
For multi-step turns, Duration_Ms doesn't capture per-step latency. It represents perceived latency to the first sound the caller hears, shared across that turn's related rows. A finer-grained per-step breakdown is planned for a future update.
What one call looks like
Every following row shares the same correlationId; that's one call end-to-end:
SpeechPipeline pipeline ready
DialogLifecycle DialogStarted
LlmInvocation TTFAB 603 ms in 13,034 / out 204
LlmInvocation TTFAB 254 ms in 13,275 / out 387
ToolExecution Rewards-Program-FAQ Success 4,101 ms
LlmInvocation TTFAB 280 ms in 13,956 / out 996
DialogLifecycle DialogCompleted duration 134,831 ms
CallLifecycle CallDisconnected
Key scenarios
- Analyze conversation lifecycle: How long was the call? Did it end early? Was it a caller hangup or a dialog transfer?
- Measure AI response latency: Identify slow turns, compare TTFAB across models, and analyze end-to-end caller wait time. For multi-step turns, use the maximum
Duration_Msper turn. - Diagnose tool execution problems: Which tools are being called, how long they take, and whether they succeed or fail. Compare
McsProcessingTime_MsandExternalCallTime_Msto see where time is spent. - Analyze multi-step interactions: Correlate the sequence of
LlmInvocationandToolExecutionrows within a singlecorrelationIdto understand full turn behavior.
Best practices
- Enable diagnostics for all production voice agents.
- Monitor latency and failures on an ongoing basis, not just during incidents.
- Always filter by
correlationIdwhen investigating a specific conversation. - Filter by
customDimensions.Subjectto exclude unrelated telemetry.
Limitations
- Some fields defined in the schema aren't populated yet, including per-utterance speech timing (STT/TTS durations), per-invocation sequence numbers, and dedicated error diagnostics events. These fields are planned for future updates.
- Cancelled responses aren't included.
- Voice and text latency semantics differ. For real-time voice,
Duration_Msis caller-perceived TTFAB, not full-response duration.