Event subscription interrupt modes

Interrupt modes control how an AI Employee's flow handles incoming events when it is already processing a previous event. By configuring interrupt modes on event subscriptions, you determine whether new events wait in line, take priority, or get dropped.

Flow execution and the event queue

In the Newo.ai platform, each flow maintains an execution queue for a specific user persona. When an AI Employee receives events (such as a user message, speech start, or a system signal), the flow processes them sequentially. By default, every incoming event is appended to the end of the queue and executed in order.

However, sequential processing is not always desirable. Consider a voice call where the user begins speaking while the agent is mid-response. The agent should stop talking immediately and listen, not finish its current response first. Interrupt modes give you this level of control.

The three interrupt modes

Each event subscription in a flow YAML file includes an interrupt_mode property. The three available values are queue, interrupt, and cancel.

ModeQueue behaviorCurrent executionUse case
queueAppends the event to the end of the queueContinues uninterruptedStandard sequential processing where every event must be handled
interruptClears the entire queue and inserts this eventStops immediatelyUrgent events like user speech that must take priority
cancelIf the queue is busy, the event is dropped entirely; if idle, the event executes normallyContinues uninterrupted (if busy)Low-priority or redundant events that only matter when the agent is idle

Queue mode

Queue mode is the default. Events arrive and wait their turn. No data is lost, and execution order is preserved.

When to use it: Any event where order matters and every occurrence must be processed, such as conversation_ended, analyze_conversation, or API-based user messages.

events:
  - idn: conversation_ended
    skill_idn: ConversationEndedSkill
    state_idn: null
    integration_idn: null
    connector_idn: null
    interrupt_mode: queue

Interrupt mode

Interrupt mode gives the incoming event immediate priority. When an interrupt-mode event arrives:

  1. The currently executing action receives an interrupt signal.
  2. All pending events in the queue are cleared.
  3. The new event begins executing immediately.

When to use it: Real-time voice interactions where the user's speech must override the agent's current activity, or any scenario where the latest input renders all queued work obsolete.

events:
  - idn: user_message
    skill_idn: UserPhoneReplySkill
    state_idn: null
    integration_idn: newo_voice
    connector_idn: newo_voice_connector
    interrupt_mode: interrupt

In the standard ConvoAgent configuration, voice-based user_message events (from newo_voice, vapi, twilio_messenger, and telegram) use interrupt mode, while chat-based user_message events (from newo_chat, sandbox, and api) use queue mode. This reflects the difference in conversational dynamics: voice calls require immediate responsiveness, while chat conversations benefit from processing every message in order.

Cancel mode

Cancel mode implements a "skip if busy" strategy. The event only executes if the flow is idle (no event is currently executing and the queue is empty). Otherwise, the event is silently discarded.

When to use it: Background checks, status polling, or any event that loses relevance when the agent is already engaged. For example, a voice reply event that should not execute if the agent is already handling another message:

events:
  - idn: user_message
    skill_idn: NewoVoiceReply
    state_idn: null
    integration_idn: newo_voice
    connector_idn: null
    interrupt_mode: cancel

Handling interrupts within actions

The event subscription interrupt_mode controls when the flow receives an interrupt signal. Individual actions within the flow control how they respond to that signal. Some actions can be configured to ignore, delay, or respond immediately to interrupts.

Non-interruptible blocks

To guarantee that a sequence of actions completes atomically regardless of any interrupt signals, wrap them in a non-interruptible block using StartNotInterruptibleBlock and StopNotInterruptibleBlock.

When an interrupt signal arrives during a non-interruptible block, the system holds the signal and waits until StopNotInterruptibleBlock is reached before processing the interruption.

::: 🗒️ NOTE Non-interruptible blocks are available in the guidance (.nslg) runner type. The NSL runner type does not currently support these blocks. :::

Example: protecting state updates during conversation end

{{StartNotInterruptibleBlock()}}

{{Set(name="user_id", value=GetUser(field="id"))}}
{{SetState(name="user_reply_buffer", value=" ")}}
{{SetState(name="fast_prompt", value=" ")}}
{{SetPersonaAttribute(id=user_id, field="current_integration_idn", value=" ")}}

{{StopNotInterruptibleBlock()}}

This pattern is common when resetting session state on conversation end. Without the non-interruptible block, an incoming event could interrupt the cleanup midway, leaving the state partially reset.

Example: buffering the user reply

{{StartNotInterruptibleBlock()}}
{{SetState(name="user_reply_buffer", value=Stringify(Concat(GetState(name="user_reply_buffer"), " ", GetTriggeredAct(fields="text"))))}}
{{StopNotInterruptibleBlock()}}

Here the non-interruptible block ensures the reply buffer is updated atomically before any interrupt-mode event can clear the queue.

GenStream interrupt modes

The GenStream action, used for streaming generated AI responses, has its own interruptMode parameter. This parameter controls how GenStream responds to an interrupt signal that arrives during text generation and streaming.

GenStream modeBehavior
noneIgnores interrupt signals entirely. The full response is generated and streamed before the flow processes any interruption.
interruptStops generation and streaming immediately when an interrupt signal is received.
interruptWindowCreates a time-based buffer (set by the interruptWindow parameter in seconds). If the interrupt signal arrives within the window, generation stops and nothing is sent to the user. If the window has already passed, the full response is streamed to completion.

The interruptWindow mode is particularly useful for voice interactions. It prevents the agent from sending a partial or irrelevant sentence fragment when the user begins speaking shortly after generation starts, while still allowing a fully generated response to be delivered if the user waits longer.

Example: GenStream with interrupt window

{% set agent_answer = GenStream(
    interruptMode="interruptWindow",
    interruptWindow=0.7,
    temperature=0.2,
    topP=0.5,
    maxTokens=4000,
    skipFilter=True,
    sendTo="actors",
    actorIds=[actor_id],
    thinkingBudget=thinking_budget
) %}

In this example, if the user interrupts within 0.7 seconds of generation starting, the response is discarded entirely. If the user waits longer than 0.7 seconds, the response streams to completion.

Sleep interruptibility

The Sleep action pauses flow execution for a specified duration. Its interruptible parameter determines whether an interrupt signal can cut the sleep short.

  • interruptible="y" or interruptible="True": The sleep ends immediately when an interrupt signal is received, and the flow processes the interrupt.
  • interruptible="n" or interruptible="False": The sleep runs for its full duration regardless of interrupt signals. Any pending interrupts are processed only after the sleep completes.

Example: interruptible sleep while waiting for a callback

{{Sleep(duration=stop_call_timeout, interruptible="y")}}

Example: non-interruptible sleep in an outbound call dispatcher

{{Sleep(duration="10", interruptible="n")}}

Use non-interruptible sleep for timed delays that must complete (such as waiting for a call to connect), and interruptible sleep for optional waits that should yield to user activity.

Voice-specific interrupt configuration

Voice interactions introduce additional interrupt-related settings beyond flow-level event subscriptions.

Turn-off interrupt mode

The voice connector includes a turn_off_interrupt_mode setting with a configurable timeout (turn_off_interrupt_mode_timeout_seconds). When enabled, this temporarily disables the interrupt mechanism for a set period after the agent begins speaking. This prevents false interrupts caused by audio echo or background noise in the first moments of agent speech.

V2V turn detection

For voice-to-voice (V2V) mode, the V2VUpdateSessionTurnDetection configuration controls how the voice provider detects when the user has finished or started speaking. These settings directly affect when interrupt signals are generated:

ParameterDescription
typeDetection algorithm: server_vad (voice activity detection) or semantic_vad (language-aware detection)
thresholdSensitivity threshold for voice activity detection (float, 0 to 1)
prefix_padding_msMilliseconds of audio to include before detected speech onset
silence_duration_msMilliseconds of silence required before the system considers a turn complete
eagernessHow eagerly the model responds: low, medium, high, or auto
interrupt_responseBoolean that controls whether user speech can interrupt the agent's response
create_responseBoolean that controls whether the system automatically generates a response when a turn is detected

Setting interrupt_response to false effectively makes the agent non-interruptible at the voice provider level, regardless of the flow-level interrupt mode configuration.

How interrupt modes interact with the event queue

The following sequence illustrates how interrupt modes affect event processing within a single flow:

  1. Event A arrives with interrupt_mode: queue. The queue is empty, so it begins executing immediately.
  2. Event B arrives with interrupt_mode: queue. The queue is busy, so Event B is appended to the queue behind Event A.
  3. Event C arrives with interrupt_mode: interrupt. The system sends an interrupt signal to Event A's currently executing action. If the action is interruptible, it stops. All queued events (Event B) are discarded. Event C begins executing.
  4. Event D arrives with interrupt_mode: cancel. The queue is busy (Event C is executing), so Event D is dropped silently.
  5. Event C finishes. The queue is now empty.
  6. Event E arrives with interrupt_mode: cancel. The queue is empty, so Event E executes normally.

::: ❗❗ IMPORTANT When an interrupt signal clears the queue, all pending events are permanently discarded. Those events are not re-queued or retried. Design your interrupt mode assignments carefully to avoid losing critical events. Use non-interruptible blocks around state-critical operations that must not be partially executed. :::

Choosing the right interrupt mode

  • Use queue as the default for most events. It guarantees every event is processed.
  • Use interrupt for real-time voice input and any event that makes all previous queued work obsolete.
  • Use cancel for background or low-priority events that are only relevant when the agent has nothing else to do.
  • Combine interrupt mode with StartNotInterruptibleBlock / StopNotInterruptibleBlock and GenStream's interruptWindow to fine-tune exactly how the agent responds at the action level.

See Events and the event system for details on event subscription configuration. See Integrations and connectors for details on voice connector settings.