πŸ”₯ DeepEval for TypeScript is now in beta. Read the announcement.

Interruptions

Beta

By default voice mode is half-duplex: the simulated user finishes speaking, then waits for the agent via exchange_turn. Give the caller's persona an interruption_behavior to exercise barge-in β€” the same connector session, driven with concurrent uplink and downlink instead.

How It Works

With interruptions enabled, the simulator no longer uses exchange_turn(). It drives the same connector with concurrent uplink and downlink:

  1. Speak the user turn. TTS synthesizes the simulated user's message; the connector pushes it with stream_uplink (cancelable) without waiting for the agent to finish.
  2. Listen on the downlink. iter_agent_events() streams agent audio and partial transcripts as they arrive.
  3. Judge mid-speech. As the partial transcript grows, the simulator model decides whether a real caller at this frequency would barge in now β€” and with what utterance.
  4. Barge (optional). If the judge says yes, TTS speaks that utterance and stream_uplink starts overlapping the agent.
  5. Recover from double-talk. If both sides overlap, the agent gets a grace window to stop; if it doesn't, the user yields, waits through an awkward pause, and may retry. A successful barge marks the assistant Turn with interrupted=True.
  6. Continue. Once the floor settles, the simulator records the turns and generates the next user message as usual.

Setup Interruptions

Interrupting is a trait of the caller, not of the run β€” an impatient customer talks over your agent no matter which scenario they are calling about. So interruptions are enabled whenever a non-None InterruptionBehavior is supplied to a Persona:

from deepeval.dataset import InterruptionBehavior, Persona

persona = Persona(
    characteristics="You are impatient and finish other people's sentences.",
    interruption_behavior=InterruptionBehavior(
        frequency="normal",
        overlap="adaptive",
    ),
)

There are TWO optional parameters when creating an InterruptionBehavior:

  • [Optional] frequency: how often the simulated caller considers barging in β€” "rare", "normal", or "frequent". Defaulted to "normal".
  • [Optional] overlap: how the caller behaves when the agent keeps talking over an interruption β€” "yield", "adaptive", or "insist". Defaulted to "adaptive".

Barging in only happens once that persona is driving a conversation, so attach it to the ConversationalGolden you simulate:

from deepeval.dataset import ConversationalGolden

golden = ConversationalGolden(
    scenario="Andy Byron wants to purchase a VIP ticket to a Coldplay concert.",
    persona=persona,
)

When Does It Interrupt?

Interruptions are not random. While the agent is speaking, the simulator model acts as a judge: it reads the partial transcript so far (plus the scenario, the caller's persona, and prior turns) and decides whether a real caller at this frequency would cut in now, and with what utterance.

That decision is content-based β€” e.g. the agent contradicted itself, asked something already answered, or is rambling β€” not a coin flip. frequency only changes how eager the judge is and how often it is asked:

  • "rare" β€” interrupt only on clear errors / contradictions; prefer waiting out the full reply. At most 1 barge per conversation and 1 per agent utterance. The judge is polled less often (needs ~80 more transcript characters and at least 2s between polls).
  • "normal" β€” interrupt when a real caller would clarify, redirect, answer early, or cut an obvious digression β€” not on routine helpful speech. Up to 4 barges per conversation and 2 per agent utterance (~40 chars / 1s between polls).
  • "frequent" β€” interrupt aggressively on verbosity, slow pacing, digressions, or chances to cut ahead β€” still skip nonsense mid-word cuts. Up to 8 per conversation and 3 per agent utterance (~20 chars / 0.5s between polls).

Leave Persona.interruption_behavior unset (or set it to None) for half-duplex β€” the simulator uses exchange_turn, never barges in, and Turn.interrupted stays unset.

The only randomness in the loop is a small delay before retrying after double-talk. That varies when a retry may fire, not whether the judge chose to interrupt in the first place.

When Both Sides Talk at Once

A barge-in is not instant success. For a moment both sides may be talking over each other β€” the agent still finishing a sentence while the simulated user cuts in. Real phone calls do the same thing: one person starts speaking, the other keeps going for a beat, then someone yields (or both pause awkwardly and try again).

deepeval models that recovery path explicitly. After the simulated user starts overlapping the agent:

  1. Brief overlap is allowed. The user keeps talking for a short window while the agent is still on the downlink. That overlap is the interruption β€” without it, the user could never talk over the agent.
  2. The agent gets a chance to stop. If the agent goes quiet, the barge worked: the assistant reply is cut short (interrupted=True) and the conversation continues from the user's cut-in.
  3. If the agent keeps talking, overlap decides what happens.
    • "yield" backs off quickly and does not retry that interruption.
    • "adaptive" allows a brief overlap, then yields and may retry after a natural pause.
    • "insist" holds the floor longer and retries sooner if the agent ignores the interruption.
  4. The conversation recovers. When the caller yields, the simulator leaves a short β€œno, you go” pause before listening or retrying. The timing is selected automatically by the overlap behavior.

One important detail: the connector only cuts the user's uplink when the agent talks after a barge has started. If that rule were always on, the user could never begin an interruption in the first place.

Use frequency to control how readily the caller interrupts and overlap to control how they recover from double-talk. The simulator chooses the underlying timing values as a coordinated preset, so users do not need to tune interdependent millisecond values.

What Gets Recorded

  • Assistant turns cut short by a successful barge get interrupted=True.
  • Frustrated barges (grace miss) surface on user turns via metadata: barge_in, frustrated, and grace_missed_ms.

The rest of the conversation is still a normal ConversationalTestCase β€” see What a voice simulation produces.

On this page