Hero Background

Power Your Software Testing with AI Agents and Cloud

The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. Test Intelligently and Ship Faster.

AIAI TestingTesting

Voice Agent Interruption Testing: Drops and Handoffs

Barge-in is one interruption. Calls also drop, transfer and hand off mid-sentence. See how to test what survives when the session breaks rather than the turn.

Published on:

A caller gets three quarters of the way through changing an address and the line goes quiet. Your suite records a completed call with a short duration and moves on.

Nothing in that run was wrong at the turn level. Every response the agent produced was correct, and the failure sits entirely in what happened to the half-finished work.

Interruptions of this kind break the session rather than the turn, which is why a per-response suite cannot see them.

TL;DR

Voice agent interruption testing is the practice of verifying what survives when a call is cut short, moved or handed on. It exists because a suite that checks each response in isolation has no way to observe state, and state is the only thing these failures touch.

  • Is this the same as barge-in?: No. Barge-in breaks the turn and the conversation continues. These break the session, so they need different scenarios and different evidence.
  • Does a lost connection mean the call ended?: No. In the WebRTC state model a transport entering the failed state does not by itself close DTLS transports, SCTP associations or the channels running over them, so a teardown assertion can pass while resources stay open.
  • Will a drop raise an error?: Often not. Liveness on a real-time path is confirmed by periodic checks, so a path can be dead between two of them and the failure reaches your agent as silence rather than as an exception.
  • Why do correct transfers get scored as failures?: Because a transfer announcement followed by quiet while the bridge forms looks exactly like a call that ended, so anything watching for silence records an abandoned call.
  • Is a resumed call the same conversation?: That is your decision, and it has a measurement consequence. Without a correlation key across the break, one caller is counted twice and the audit trail has a hole in it.
  • Can a scenario that simply stops test this?: No. You have to remove the media path underneath the application so the stack discovers the loss itself.

Break the path deliberately, assert on what survived rather than on the last response, and make sure an action taken before the break is not repeated after it.

Interruptions That Break the Session

The caller talking over the agent is covered in barge-in testing. An interruption that ends the session changes what a test can assert, because the object an assertion refers to may stop existing partway through the case. Signaling state, media flow, and the destination on the far end can each change without the agent ever producing a wrong response.

  • A dropped call - the far end goes away without a clean hangup, so your side learns about it from something other than signaling.
  • A stalled media path - signaling still reports an active call while audio stops arriving in one or both directions.
  • A transfer - the call moves to another destination, and the agent may stay in the path or leave it, depending on the transfer type.
  • A handoff to a human - a person takes over, and whatever the agent knew has to arrive with the caller.
  • A key press during a prompt - a digit lands mid-call, and something in your stack decides whether it is acted on, queued, or lost.

Of those, the drop and the stall surface as transport conditions on a WebRTC-carried leg, where the W3C WebRTC Recommendation defines the states involved. How a full call is scored end to end is covered in testing AI calling agents. Transfer, handoff and key presses are settled in your own signaling and orchestration layer, which the Recommendation does not cover.

  • “disconnected” means connectivity is currently lost - in the RTCIceTransportState enum, the ICE Agent has determined that connectivity is currently lost for that RTCIceTransport. The spec calls this a transient state that may trigger intermittently and resolve itself without action on a flaky network, and leaves the determination implementation dependent.
  • The transient wording attaches to one enum - it belongs to RTCIceTransportState; the RTCIceConnectionState and RTCPeerConnectionState values of the same name are defined from it rather than carrying it.
  • “failed” does not close what runs over it - an RTCIceTransport entering that state does not cause DTLS transports, SCTP associations or the data channels running over them to close, and does not mute tracks. The spec preserves that because an ICE restart may cause connectivity to resume, making “failed” terminal only until ICE is restarted.
  • RTCIceConnectionState inherits that statement - the spec defines it as any RTCIceTransport being in “failed”, and does not attach the statement to RTCPeerConnectionState.

In those enums, a lost connection and a closed one are separate values. A suite that maps every interruption onto a single “call ended” outcome collapses them, and the cost lands in the expected results.

  • Recoverable loss scored as terminal - assert a hangup the moment connectivity is lost and you pass on behavior the spec describes as potentially recoverable. It sets no timeout and prescribes no hang-up policy, so how long to wait is yours to state.
  • Live resources left unchecked - after a failure state, transports and associations can still be open, so a teardown assertion that inspects one object can pass while others stay up.
  • Expected results that stop being specific - a drop, a transfer and a handoff each need their own end state, cleanup check, and record of what the caller was doing.

What survives the interruption is what a case has to check: open transports, session state, the context handed to the human, and work already committed on the caller’s account. A per-turn response check reports none of that, so it can pass while transports stay open and the account holds a half-finished change.

Note

Note: The caller speaking over the agent is a different problem with different evidence, and it is covered separately. This article deals only with interruptions that end or suspend the session, which is why endpointing and echo behaviour do not appear here.

A Call That Drops Mid-Task

In a dropped call the media path stops carrying audio and the conversation logic may never see an error, so the turn ends in silence.

On a WebRTC or ICE path, liveness holds only for as long as the next consent check confirms it. RFC 7675 defines consent freshness for WebRTC and ICE endpoints, and that mechanism explains why drops on those paths surface the way they do.

  • Checks are periodic - on these paths consent is re-confirmed on a timer, so a path that fails between two checks goes unnoticed until the next one falls due.
  • Intervals are deliberately randomized - RFC 7675 requires each interval to be randomized to between 0.8 and 1.2 times the basic period, which keeps checks from synchronizing across endpoints and makes detection timing variable.
  • Silence relaxes the requirement - RFC 7675, Section 5.1 lets an endpoint stop maintaining consent while it is not sending application data, and requires it to regain consent before it resumes sending application data. That allowance is written for WebRTC and ICE endpoints, so treat it as scoped to that transport rather than as a property of every voice path.

A path can therefore be dead for most of a check interval before anything in your stack reports it. Your application may get no exception and no hang-up event when audio stops. What it has instead is a caller who has apparently stopped talking.

The platform carrying the leg keeps its own record of why the call closed, and that record is there for the endings your own stack missed. Reading it back gives you something to assert against, since a transcript that ends in silence reads the same for a dead path and for a caller who hung up. TestMu AI’s agent testing platform surfaces that provider-reported cause per call as endedReason, so you triage from a stated cause instead of inferring one from the audio.

Remove the media path while a turn is still in progress. A path that disappears mid-turn exercises detection, cleanup and whatever resumption behavior you have built.

  • Cut underneath the application - drop the transport or block the media flow so the stack has to discover the loss on its own.
  • Cut mid-turn - remove the path while the agent is halfway through a confirmation, or while the caller is halfway through an account number.
  • Vary the moment relative to the write - before the backend call, during it, and after it but before the agent has confirmed aloud.

Then assert on the record the system wrote during and after the drop.

  • Detection - something recorded a drop at all, with a timestamp tied to the last media received rather than to the session teardown that followed.
  • Recovery versus termination - the W3C WebRTC Recommendation calls the “disconnected” ICE transport state transient, able to resolve itself without action on a flaky network. Assert that the first sight of it did not end the call by itself.
  • Partial task state - the half-finished task landed in a defined state, and you can tell abandoned from complete by reading the record alone.
  • Commitment survival - a refund, booking or callback the agent committed to before the drop either completed or rolled back, with no record left half-applied because the line died between the commitment and the confirmation.
  • Resumption identity - a caller who rings back within a short window is either stitched onto the same conversation or opened as a new one, and the system does the same thing every time.

Resumption identity is a product decision, and either answer can be correct for your business. Counting a resumed call as a new conversation turns one caller into two in every rate you report.

Transfer and the Handoff Window

During a transfer the agent stops speaking while the bridge to the destination leg is negotiated, and that gap is silent by design. A detector that scores silence duration sees the same signal it sees when a caller hangs up. The stored disposition then feeds your abandonment rate and the baseline your regression runs compare against.

WebRTC’s ICE transport states draw the same line between lost connectivity and a finished session:

  • “disconnected” can clear itself - The W3C WebRTC Recommendation describes the RTCIceTransport state “disconnected” as transient, able to trigger intermittently and resolve without action on a flaky network, with the determination left implementation dependent. A detector that treats first sight of it as terminal can end a call the Recommendation describes as potentially recoverable.
  • “failed” keeps the scaffolding standing - The same enum says that an RTCIceTransport entering “failed” does not close DTLS transports, SCTP associations or the data channels running over them, and does not mute tracks, because an ICE restart may cause connectivity to resume. The spec attaches that behavior to the transport state and, derivatively, to RTCIceConnectionState; RTCPeerConnectionState is a separate aggregate.
  • Scope of the analogy - The Recommendation covers ICE transports, so it fixes no timeout for a telephony bridge or the carrier side of a transfer. What carries over is the evidentiary standard: a transport state change reports one leg’s connectivity, and an end-of-call detector reads it by default as proof the session ended.

The assertions below read the stored run record:

  • The transfer was announced - The caller heard a spoken handoff naming the destination before the quiet began, and the announcement timestamp marks the start of the permitted silence window.
  • End-of-call detection was suppressed - An explicit marker in the run switches the detector off at the announcement and clears it when the bridge completes, and the assertion checks both edges.
  • The window uses its own silence tolerance - The bridge window carries a separate allowance from mid-conversation silence, and the record shows which one was in force at each moment.
  • The disposition field reads as a transfer - Assert on the stored classification, since a transcript can read correctly while the disposition on the call record is wrong.

Context loss is what the caller feels once the bridge succeeds. Unless the platform passes context across the bridge, the human who receives the call sees nothing the caller already said, so the caller repeats the account number, the reason for the call and the detail they already gave.

  • Restated in audio - The agent summarizes the collected fields on the bridge before dropping out, so the receiving human hears them without a screen.
  • Passed as data - The same fields land in the screen pop or ticket payload at the moment of transfer, and the assertion reads those keys directly.
  • Inspectable in the record - The handoff is stored as a retrievable object on the call, so a broken handoff surfaces as a field diff in the run output.
  • Repetition flagged - Your scripted receiving party asks for one detail the caller already gave, and the run fails if the transcript shows it supplied a second time.
Detect and fix flaky tests with TestMu AI

Key Presses During a Prompt

A key press during a prompt is a routing event that lands at a known offset into the prompt while the menu is still listing its options. The behavior under test sits in the interval between that press and the end of the prompt audio. Write the assertions below against your own menu design, since none of them is a platform guarantee you get for free.

  • The digit arrived - the keypad event reaches the session carrying the same digit value the caller pressed, checked digit by digit against what was sent.
  • It was acted on at once - routing starts at the moment of the press, while the prompt audio is still playing.
  • The prompt stopped - the caller stops hearing options for a menu they have already left.
  • The destination matched the offer - the key sends the call where the menu said that key sends it, and still does after a menu revision.
  • Digits between prompts follow a stated rule - a key pressed after one prompt ends and before the next begins is either applied to the menu still in effect or discarded, and the same press behaves the same way on every run.

The harder case is several digits in quick succession, such as an extension or the front of an account number. If any single digit is also a valid menu choice, partial collection can match it and route the call before the rest of the string arrives. The remaining digits then land in the destination, where they may be dropped or may fire something of their own.

  • Longest valid entry wins where your design says it should - assert that a valid multi-digit entry is collected in full under your configured maximum length and interdigit timing, including when its first digit also matches a menu option.
  • Every digit has an owner - the record shows which collection each digit belonged to.
  • Leftovers behave as designed - assert what the destination does with trailing digits, since some platforms discard them and others let them fire an action there.
  • Cadence is varied - send the same string at human typing speed and again as fast as the keypad will emit it. The fast run is where partial collection bugs surface.

Presence of the digit in the call record settles little, since a system that queues the press until the prompt finishes still logs it. The assertion is about ordering, so the record has to carry timestamps you can line up against the prompt timeline.

  • Digit value and arrival time - whatever timestamp your platform exposes closest to the network edge, ahead of the point where the application handled the press.
  • Prompt start and stop - when playout began and when it actually ended.
  • Routing decision and target - when the branch was taken and which destination it named.
  • Gap between arrival and prompt stop - trend it per build, because a queued implementation tends to show up as that gap growing toward the full remaining length of the prompt.

Context That Survives the Break

Whatever caused the break, the second leg has to recover the state the first leg wrote and the identifier that finds it. On an ICE-negotiated media path, RFC 8445 Section 9 says an ICE restart causes “all previous states of the data streams, excluding the roles of the agents, to be flushed”, though data can still flow over the existing data sessions while that path holds. A cold transfer or a handoff to a human need not involve ICE at all, so conversation state belongs above the media path.

The second leg resumes only if it can recover each of these.

  • What the caller already provided - the account number, the date of birth, the order ID they read out digit by digit. A second leg that asks for all of it again tells the caller that nothing survived.
  • What the agent already committed to - a quoted price, a promised callback window, a refund the agent said it would process. The caller will hold you to it whether or not it was written anywhere durable.
  • Where in the flow the caller was - partway through verification, past the disclosure, waiting on a confirmation. A second leg that cannot read the position restarts verification from the first field.
  • The correlation key - one identifier written into both legs and into every downstream record either leg touches.

Two legs with no shared key count as two calls wherever call records are read. One caller who dropped and redialed counts as two callers in any outcome measurement, and the audit trail ends at the first leg with no pointer to where the work finished.

Write each one as an assertion, so a broken recovery fails a test.

A context assertion that runs only inside one unbroken conversation confirms the agent can hold an account number for as long as the session stays open. A session-history evaluation tracks whether an agent retains and correctly uses information from earlier in the conversation, and the harder version of that check is the one where the history has to cross a break in the session. Check whether any context assertion you have today is exercised across a break at all, and write the ones below so they run on the second leg.

  • State written before the interruption is readable after it - assert on the actual values the second leg reads back, since a session record can exist and still come back empty.
  • A partially completed action is completed or rolled back - there is no third outcome where the record sits half written and the agent has no way to tell which half landed.
  • The same caller is identifiable across the break - the second leg resolves to the same caller identity as the first through the correlation key, because a phone number can be withheld or shared across a household.

An action issued just before a drop may have succeeded in the backend and never been confirmed to the agent. The retry has to resolve to the same result, or the dropped call becomes a duplicate payment or ticket.

  • Every write carries an idempotency key - derived from the correlation key and the action itself, so a retry after the break reuses the same key.
  • Test the ambiguous window - kill the leg after the request reaches the backend and before the response reaches the agent, then reconnect and let the agent retry on its own.
  • Replay the retry twice - a second reconnection after the same ambiguous window should still leave one record, because callers redial more than once when a line is bad.
  • Assert on the record count - one refund, one ticket, one shipment, counted in the system of record, since the agent transcript shows only what the agent believed happened.
Note

Note: TestMu AI keeps a per-scenario transfer window so end-of-call detection is suppressed during a handoff announcement and the silence tolerance widens for that window. Create a free account to run interruption scenarios against your own agent.

Scenarios Worth Writing

Each interruption fails on a different surface: transport state, call record, slot value. The fixture has to supply a break trigger, records from both sides, and readable transport state.

  • A break you can trigger - the harness cuts the media path on command at a chosen point in the turn, so the cut repeats to the millisecond on every run.
  • Records from both sides - call detail from the agent and platform sides, joined on a shared identifier, so a drop separates from a hang-up.
  • Transport state you can read - ICE state, STUN traffic and the candidate exchange captured per call, since a lost path shows as an ICE state change before the transcript goes quiet.

The evidence column assumes a media path that uses ICE and STUN. A transport built on neither meets the same interruptions, settled by its own signalling log and media counters.

InterruptionWhat it exercisesEvidence that settles it
Media path lost mid-turnWhether a state the spec calls transient triggers recovery or ends the callTransport trace showing “disconnected” and what followed, with the recording
Media path moved mid-session by ICE restartRenegotiation while the existing path, if still usable, keeps carrying audioA changed username fragment in the USERNAME attribute of STUN connectivity checks
Transfer to a humanContext carried across the handoff, and what the caller hearsBoth legs joined on the shared identifier, with collected fields at the desktop
Transfer that nobody answersThe fallback when the target rings outThe unanswered leg, plus the recovery the caller got
Key press during a promptDigit capture while the agent is still speakingDigit events logged against the prompt they landed in, plus the slot value
Caller hangs up mid-taskWhether partial work commits, rolls back, or sits half writtenBackend state after the call, against the disconnect reason
  • Restart credentials - RFC 8445 requires changing both the password and the username fragment for the streams being restarted. Only the username fragment reaches the media path; the restart is signalled out of band, so the candidate exchange carries the other half.
  • Consent freshness - RFC 7675 expires consent after 30 seconds without a valid STUN binding response and recommends a 5-second check interval, randomized to a period between checks of 4 to 6 seconds. A longer period is conformant, and only the 4-second floor is a hard requirement.
  • What “failed” leaves standing - in a WebRTC stack, an RTCIceTransport entering “failed” does not close DTLS transports, SCTP associations or the data channels over them, and does not mute tracks, because an ICE restart may cause connectivity to resume.

Every case here measures recovery behavior at a cut the harness chose. Frequency comes from production call records, where disconnect reasons carry the real rate.

  • Count before you rank - pull a month or so of call records and tally how calls ended, by disconnect reason and by transfer leg, and the largest buckets are your first cases.
  • Split by direction - inbound support and outbound campaigns can end up with very different distributions, so rank each on its own.
  • Re-rank after routing changes - a new transfer target or a changed queue can shift the distribution, so re-run the tally after each change.

Conclusion

Add a correlation key before adding scenarios. Without one, every assertion about what survived an interruption is unprovable, because you cannot tie the two halves of the call together.

Then write the transfer case first, since it is the interruption your callers meet most often and the one most likely to be recorded as something it was not.

Treat idempotency as the last assertion rather than the first. An action taken before a drop and repeated after it turns one caller into two records, and that damage outlives the call.

Author

...

Samyak Goyal

Blogs: 21

  • Linkedin

Samyak Goyal is a Senior Member of Technical Staff at TestMu AI engineering Kane CLI, the command-line tool that runs browser automation from the terminal, where a flow described in natural language executes in a real Chrome browser and returns pass or fail with shareable proof. He is a backend engineer with 4+ years of experience, previously an SDE at Innovaccer, where he built APIs, introduced Kafka, and cut deployment from weeks to hours. Samyak also builds multi-agent systems, skill-orchestration frameworks, and a personal copilot that indexes 200+ microservice repositories.

Reviewer

...

Shubham Soni

Reviewer

  • Linkedin

Shubham Soni is a Senior Member of Technical Staff at TestMu AI (formerly LambdaTest), building the Real Device Cloud and real-time testing infrastructure. He optimized the WebRTC services that power live testing to sub-100ms latency with adaptive bitrate streaming, led a frontend migration from Angular to React that cut page load time from 5-6 seconds to 1-1.5 seconds, and contributes to the official Device SDK. He led a team of four to build an accessibility testing product covering manual and automated testing and mentored a team of six on a real-time testing product. He brings over eight years of experience and earlier scaled a cloud code platform to 200K+ monthly users. Shubham holds a B.Tech in Computer Science.

Add to Google preferred sources

Summarise with AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free

Interruption Testing FAQs

Did you find this page helpful?

More Related Blogs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests