When I interrupt the agent while it is speaking, i...
# ask-ai
a
When I interrupt the agent while it is speaking, it does not properly reset its response. After the interruption, it continues from the previous sentence instead of starting a new one. Is there a configuration or recommended approach to ensure the agent fully stops and generates a fresh response after being interrupted?
t
Thanks for reaching out, Ruben. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I understand you’re seeing the agent continue mid-sentence after you interrupt it and you want it to fully stop and produce a fresh reply instead. That’s frustrating; let’s fix it. Short answer • The agent cancels playback and truncates the spoken output on interruption, but it does not automatically start a new reply. You need to detect the interruption and explicitly trigger a fresh generation (for example, with
session.generate_reply()
). What to do (recommended) 1. Detect the interruption using the
SpeechHandle
returned by
say()
or
generate_reply()
and check
handle.interrupted
. 2. When
handle.interrupted
is true, call
session.generate_reply()
(or
session.generateReply()
) with instructions or the latest user input to create a fresh response that starts from a clean state. Python example
Copy code
handle = session.generate_reply(instructions="Explain how our service works in detail.")
# Later, when interruption may have happened:
if handle.interrupted:
    await session.generate_reply(
        instructions="Start over: explain how our service works clearly and concisely."
    )
TypeScript example
Copy code
const handle = session.generateReply({ instructions: 'Explain how our service works in detail.' });

try {
  await handle;
} catch {
  if (handle.interrupted) {
    await session.generateReply({
      instructions: 'Start over: explain how our service works clearly and concisely.'
    });
  }
}
Alternative: always reset on user-turn complete • If you want the agent to always ignore any partial output and respond only to the latest user input, trigger generation from your
on_user_turn_completed
(or
onUserTurnCompleted
) handler. That lets you ensure every new user turn produces a fresh reply rather than continuing from a truncated interim. Notes and important points • There’s no built-in flag that automatically restarts generation after interruption — you must explicitly trigger the new generation in your code. • Don’t set
allow_interruptions=False
if you still want interruptions; that setting prevents interruptions entirely. • Use interruption detection (e.g.,
handle.interrupted
) so your app can decide whether to restart, modify the instructions, or wait for more user input. If you’d like, tell me: • Which SDK/language you’re using (Python or TypeScript), and • Whether you want the agent to always restart after any interruption or only for certain interruption types, and I’ll provide a copy-paste snippet tailored to your environment and desired behavior. Sources: Turns overview | LiveKit Documentation | Uninterruptable Agent | LiveKit Documentation | Agent speech and audio | LiveKit Documentation
a
Python
t
Thanks — great, Python it is. Below is a focused, copy-paste-ready approach you can use to ensure an agent fully stops after an interruption and then generates a fresh reply. What this does • Detects when a reply was interrupted using the
SpeechHandle
returned by
generate_reply()
(or
say()
). • On interruption, explicitly triggers a new
generate_reply()
using either the latest user input or custom instructions so the agent begins a fresh response. Python example (async)
Copy code
# Assume `session` is your active LiveKit agent session and `get_latest_user_input()` returns the user's text.
async def handle_user_turn(session, user_input: str):
    # Start generation / speech
    handle = await session.generate_reply(instructions=user_input)

    # Wait for generation/speech to finish or be interrupted
    try:
        await handle  # completes if not interrupted
    except Exception:
        # Generation was aborted/interrupted. Check the handle flag.
        pass

    # If interrupted, explicitly generate a fresh reply
    if getattr(handle, "interrupted", False):
        # Option A: Restart using the same user input
        await session.generate_reply(instructions=user_input)

        # Option B: Restart with a modified instruction (explicitly ask to "start over")
        # await session.generate_reply(instructions=f"Start over and answer clearly: {user_input}")
Notes and tips • Always check
handle.interrupted
to detect interruption reliably. • If you want the agent to always generate a fresh reply on any interruption, call
generate_reply()
unconditionally when
handle.interrupted
is true. • If you prefer to reset only for certain cases, add logic to examine the interruption reason or a timestamp, or prompt the user for clarification before regenerating. • If you want the agent to always ignore partial spoken output and respond only to the newest user input, call
generate_reply()
from your
on_user_turn_completed
handler instead of relying on automatic continuation. If you want, I can: • Provide a fuller example showing integration with an
on_user_turn_completed
lifecycle hook, or • Tailor the restart instruction text so the agent uses a different tone/length when restarting. Which would you prefer?
a
it’s not due to this false_interruption_timeout
float
Optional
Default:
2.0
The time (in seconds) to wait before signaling a false interruption. If no transcribed speech is generated during this period, an
agent_false_interruption
event is emitted and the agent resumes speaking from where it left off if
resume_false_interruption
is
True
. Set to
None
to turn off false interruption handling. When disabled, false interruptions are treated as intentional: the agent’s speech is not resumed and no `agent_false_interruption`event is emitted.
t
Thanks — that clarification helps. You’re correct: this behavior is not caused by
false_interruption_timeout
. That setting only controls detection and recovery for false interruptions; if
resume_false_interruption=True
the agent will resume speaking after a short gap when a false interruption is detected. When false-interruption handling is disabled or the interruption is intentional, the framework cancels playback and truncates the spoken output, but it does not automatically start a new response. How to ensure a truly fresh response after an interruption • Detect the interruption (use the
SpeechHandle
returned by
generate_reply()
or
say()
). • When the handle shows
interrupted
, explicitly call
session.generate_reply()
again with the user’s latest input or a restart instruction so the agent begins a new reply from a clean state. • Don’t rely on
false_interruption_timeout
to change this behavior — it only affects false interruption detection and optional resuming, not automatic regeneration. Concrete Python pattern 1. Start generation and keep the returned handle. 2. Await the handle and check
handle.interrupted
. 3. If interrupted, call
session.generate_reply()
with the desired restart instruction or user input. Copy-paste-ready example (async)
Copy code
# session is your LiveKit agent session
async def handle_user_turn(session, user_input: str):
    # Start response/speech
    handle = await session.generate_reply(instructions=user_input)

    # Wait for completion (or interruption)
    try:
        await handle
    except Exception:
        # handle may raise on abort; we'll still check the flag below
        pass

    # If the speech was interrupted, explicitly generate a fresh response
    if getattr(handle, "interrupted", False):
        # Option 1: restart with same input
        await session.generate_reply(instructions=user_input)

        # Option 2: restart with explicit "start over" instruction
        # await session.generate_reply(instructions=f"Start over and answer clearly: {user_input}")
Additional options depending on your UX • Always restart automatically: use the pattern above to unconditionally regenerate when
handle.interrupted
is true. • Ask the user before restarting: prompt the user to confirm they want a restart, then call
generate_reply()
if they confirm. • Force restart for every user turn: invoke
generate_reply()
from your
on_user_turn_completed
handler so each turn begins fresh regardless of prior partial output. If you’d like, I can: • Provide a version that logs interruption reasons and timestamps for finer control, or • Show an
on_user_turn_completed
integration example in Python that always produces a fresh reply. Which would be most helpful for your setup?