Skip to content

Event-Driven Core

At the heart of the Orchestrator is the EventBus. This internal mechanism allows for decoupled communication between "Sources" (which produce events) and "Managers" (which consume and act on events).

The Event Bus

The EventBus is an asynchronous implementation that supports: - Subscribe: Register an async callback for a specific EventType. - Publish: Broadcast an Event to all registered subscribers. - Concurrency: Callbacks are executed as independent tasks, ensuring that a slow subscriber (like a logger) doesn't block the main interaction flow.

Common Event Types

The system defines a standard set of events in orchestrator/events.py:

Event Category Type Description
Input input.speech_start User started speaking (useful for interruption).
input.transcript.final Finalized sentence from STT.
input.transcript.interim Real-time partial transcript from STT.
LLM llm.request Prompt sent to the LLM.
llm.token A single token generated by the LLM.
llm.response_done LLM generation is complete.
llm.cancelled LLM generation was aborted.
TTS tts.request Text sent to the TTS service for synthesis.
tts.audio_chunk Raw PCM audio received from TTS.
System system.state_changed Updates to listening, responding, or playing states.

Why Event-Driven?

  1. Low Latency: As soon as a "Source" gets data (like a finalized transcript), it fires an event. The InteractionManager starts the LLM request immediately while other components (like the UI) update simultaneously.
  2. Extensibility: Want to add OBS subtitles? Simply create a SubtitleManager that subscribes to tts.request or llm.token. You don't need to modify the core interaction logic.
  3. Robustness: If one subscriber fails, the EventBus catches the exception and continues notifying others.