How do I make use of the speechmatics latest plugi...
# ask-ai
l
How do I make use of the speechmatics latest plugin turn detection mode TurnDetectionMode? What update do I need to input in my script?
t
Thanks for reaching out, Jeslyn. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your question about using the Speechmatics plugin’s TurnDetectionMode (the
end_of_utterance_mode
) and what change to make in your script. What to change • Add the
end_of_utterance_mode
parameter when you initialize the Speechmatics
STT
plugin. • Choose one of the enum values:
EndOfUtteranceMode.FIXED
,
EndOfUtteranceMode.ADAPTIVE
, or
EndOfUtteranceMode.NONE
. • If you pick
FIXED
or
ADAPTIVE
, you can optionally set
end_of_utterance_silence_trigger
(seconds) to control the silence threshold. If you pick
NONE
, Speechmatics’ end-of-utterance detection is disabled and you should provide a separate
turn_detection
model (for example LiveKit’s turn detector). Python examples 1) Use adaptive turn detection (adjusts silence dynamically)
Copy code
from livekit.plugins import speechmatics

stt = speechmatics.STT(
    end_of_utterance_mode=speechmatics.EndOfUtteranceMode.ADAPTIVE,
    end_of_utterance_silence_trigger=0.5,  # optional, adjusted by adaptive mode
)
2) Use a fixed silence threshold
Copy code
from livekit.plugins import speechmatics

stt = speechmatics.STT(
    end_of_utterance_mode=speechmatics.EndOfUtteranceMode.FIXED,
    end_of_utterance_silence_trigger=0.75,  # trigger after 0.75s of silence
)
3) Disable Speechmatics turn detection and use LiveKit’s turn detector instead
Copy code
from livekit.plugins import speechmatics
from livekit.agents import AgentSession
from livekit.turns import MultilingualModel
from livekit.plugins import silero

session = AgentSession(
    stt=speechmatics.STT(end_of_utterance_mode=speechmatics.EndOfUtteranceMode.NONE),
    turn_detection=MultilingualModel(),   # LiveKit turn detector
    vad=silero.VAD.load(),
)
Quick guidance on which mode to pick • Use ADAPTIVE if you want Speechmatics to adjust the silence threshold automatically for more natural turn segmentation. • Use FIXED if you need predictable, consistent behavior and know the silence duration that matches your use case. • Use NONE if you prefer LiveKit’s turn detector or another external turn-detection model to handle speaker turns. If you’d like, tell me: • Which language and runtime you’re using (Python or another SDK), and • Whether you prefer Speechmatics’ built-in detection or LiveKit’s turn detector, and I’ll give a tailored code snippet or recommendations for values to use. Sources: Speechmatics STT plugin guide | LiveKit Documentation
l
t
Thanks — I see you’re pointing to the Speechmatics STT implementation in the repo and want confirmation of the latest TurnDetectionMode (the
end_of_utterance_mode
) and the exact script change to use it. I can help—could you tell me which of these you want next so I give the most useful answer? • Do you want a short, exact code snippet that matches the current
stt.py
in the repo (Python)? • Do you want me to call out any differences you noticed between the earlier guidance and the repo implementation? If so, please paste the lines or describe the discrepancy you saw. • Are you using another SDK/language where you need the equivalent change? If you’d like the repo-aligned snippet right away, I can provide the precise instantiation of
speechmatics.STT
with the current
EndOfUtteranceMode
enum values and usage for
FIXED
,
ADAPTIVE
, and
NONE
. Which option do you prefer? Sources: Speechmatics STT plugin guide | LiveKit Documentation
l
what should I update the agent.py to make the turn detection work? https://docs.livekit.io/reference/python/livekit/plugins/speechmatics/index.html#livekit.plugins.speechmatics.TurnDetectionMode import logging from dotenv import load_dotenv from enum import Enum from livekit import rtc from livekit.agents import ( Agent, AgentServer, AgentSession, JobContext, JobProcess, cli, inference, room_io, ) from livekit.plugins import noise_cancellation, silero, speechmatics from livekit.plugins.turn_detector.multilingual import MultilingualModel logger = logging.getLogger("agent") load_dotenv(".env.local") class Assistant(Agent): def __init__(self) -> None: super().__init__( instructions="""You are a helpful voice AI assistant. The user is interacting with you via voice, even if you perceive the conversation as text. You eagerly assist users with their questions by providing information from your extensive knowledge. Your responses are concise, to the point, and without any complex formatting or punctuation including emojis, asterisks, or other symbols. You are curious, friendly, and have a sense of humor.""", ) # To add tools, use the @function_tool decorator. # Here's an example that adds a simple weather tool. # You also have to add
from livekit.agents import function_tool, RunContext
to the top of this file # @function_tool # async def lookup_weather(self, context: RunContext, location: str): # """Use this tool to look up current weather information in the given location. # # If the location is not supported by the weather service, the tool will indicate this. You must tell the user the location's weather is unavailable. # # Args: # location: The location to look up weather information for (e.g. city name) # """ # # logger.info(f"Looking up weather for {location}") # # return "sunny with a temperature of 70 degrees." server = AgentServer() def prewarm(proc: JobProcess): proc.userdata["vad"] = silero.VAD.load() server.setup_fnc = prewarm @breezy-insurance-66772.rtc_session() async def my_agent(ctx: JobContext): # Logging setup # Add any other context you want in all log entries here ctx.log_context_fields = { "room": ctx.room.name, } # Set up a voice AI pipeline using OpenAI, Cartesia, Deepgram, and the LiveKit turn detector session = AgentSession( # Speech-to-text (STT) is your agent's ears, turning the user's speech into text that the LLM can understand # See all available models at https://docs.livekit.io/agents/models/stt/ stt = speechmatics.STT( turn_detection_mode="TurnDetectionMode.EXTERNAL", #end_of_utterance_silence_trigger=0.5, #max_delay=0.7, operating_point="enhanced", language="en", # enable_diarization=True, # speaker_active_format="<{speaker_id}>:{text}", # speaker_passive_format="<{speaker_id}>[background]:{text}", # additional_vocab=[ # speechmatics.AdditionalVocabEntry( # content="Jeslyn", # sounds_like=["Jess lin"], # ), # ], # focus_speakers=["S1"], #ignore_speakers=["S2"], # known_speakers=[ # speechmatics.DiarizationKnownSpeaker( # label="Jeslyn", # speaker_identifiers=[ # "" # ], # ) # ], ), # A Large Language Model (LLM) is your agent's brain, processing user input and generating a response # See all available models at https://docs.livekit.io/agents/models/llm/ llm=inference.LLM(model="openai/gpt-4.1-mini"), # Text-to-speech (TTS) is your agent's voice, turning the LLM's text into speech that the user can hear # See all available models as well as voice selections at https://docs.livekit.io/agents/models/tts/ tts=inference.TTS( model="cartesia/sonic-3", voice="9626c31c-bec5-4cca-baa8-f8ba9e84c8bc" ), # VAD and turn detection are used to determine when the user is speaking and when the agent should respond # See more at https://docs.livekit.io/agents/build/turns turn_detection=MultilingualModel(), vad=ctx.proc.userdata["vad"], # allow the LLM to generate a response while waiting for the end of turn # See more at https://docs.livekit.io/agents/build/audio/#preemptive-generation preemptive_generation=True, ) # To use a realtime model instead of a voice pipeline, use the following session setup instead. # (Note: This is for the OpenAI Realtime API. For other providers, see https://docs.livekit.io/agents/models/realtime/)) # 1. Install livekit-agents[openai] # 2. Set OPENAI_API_KEY in .env.local # 3. Add
from livekit.plugins import openai
to the top of this file # 4. Use the following session setup instead of the version above # session = AgentSession( # llm=openai.realtime.RealtimeModel(voice="marin") # ) # # Add a virtual avatar to the session, if desired # # For other providers, see https://docs.livekit.io/agents/models/avatar/ # avatar = hedra.AvatarSession( # avatar_id="...", # See https://docs.livekit.io/agents/models/avatar/plugins/hedra # ) # # Start the avatar and wait for it to join # await avatar.start(session, room=ctx.room) # Start the session, which initializes the voice pipeline and warms up the models await session.start( agent=Assistant(), room=ctx.room, room_options=room_io.RoomOptions( audio_input=room_io.AudioInputOptions( noise_cancellation=lambda params: ( noise_cancellation.BVCTelephony() if params.participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP else noise_cancellation.BVC() ), ), ), ) # Join the room and connect to the user await ctx.connect() if name == "__main__": cli.run_app(server) scovery.cc:91 ReadFileContents Failed to open file: "/sys/class/drm/card0/device/vendor" 161554.112 DEBUG… asyncio Using selector: EpollSelector 161554.124 DEV … livekit.agents Watching /root/agent-starter-python/src 2026-02-24 161555.771469458 [WonnxruntimeDefault, device_discovery.cc:211 DiscoverDevicesForPlatform] GPU device discovery failed: device_discovery.cc:91 ReadFileContents Failed to open file: "/sys/class/drm/card0/device/vendor" 161555.811 DEBUG… asyncio Using selector: EpollSelector 161555.818 INFO … livekit.agents starting worker {"version": "1.4.1", "rtc-version": "1.0.25"} 161555.821 INFO … livekit.agents preloading plugins {"packages": ["livekit.plugins.silero", "livekit.plugins.speechmatics", "livekit.plugins.turn_detector", "av"]} 161555.827 INFO … livekit.agents starting inference executor 2026-02-24 161555.981663166 [WonnxruntimeDefault, device_discovery.cc:211 DiscoverDevicesForPlatform] GPU device discovery failed: device_discovery.cc:91 ReadFileContents Failed to open file: "/sys/class/drm/card0/device/vendor" 161557.085 INFO … livekit.agents initializing process {"pid": 20934, "inference": true} 161601.837 INFO … livekit.agents process initialized {"pid": 20934, "inference": true, "elapsed_time": 4.75} 161601.849 INFO … livekit.agents HTTP server listening on :41575 161601.987 INFO … livekit.agents registered worker {"agent_name": "", "id": "AW_DSdjwbGgaEYj", "url": "wss://testing-app-smx-842tn4s0.livekit.cloud", "region": "UK", "protocol": 16} 161604.742 INFO … livekit.agents received job request {"job_id": "AJ_auzztbpdQE7G", "dispatch_id": "AD_3u4QagbqZNqj", "room": "playground-9z4k-tQOW", "room_id": "RM_FKtNMPEVTRUV", "agent_name": "", "resuming": false, "enable_recording": true} 161604.768 DEBUG… livekit.agents received assignment {"agent_name": "", "room_id": "RM_FKtNMPEVTRUV", "room": "playground-9z4k-tQOW", "job_id": "AJ_auzztbpdQE7G", "dispatch_id": "AD_3u4QagbqZNqj", "enable_recording": true} 161604.782 INFO … livekit.agents initializing process {"pid": 20978} 161605.389 INFO … livekit.agents process initialized {"pid": 20978, "elapsed_time": 0.61} 161605.390 DEBUG… asyncio Using selector: EpollSelector {"pid": 20978, "job_id": "AJ_auzztbpdQE7G", "room_id": "RM_FKtNMPEVTRUV"} 161605.423 ERROR… livekit.agents unhandled exception while running the job task Traceback (most recent call last): File "/root/agent-starter-python/.venv/lib/python3.12/site-packages/o… line 71, in async_wrapper return await func(*args, **kwargs) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/root/agent-starter-python/.venv/lib/python3.12/site-packages/l… line 292, in _traceable_entrypoint await self._job_entrypoint_fnc(job_ctx) File "/root/agent-starter-python/src/agent.py", line 72, in my_agent stt = speechmatics.STT( ^^^^^^^^^^^^^^^^^ TypeError: STT.__init__() got an unexpected keyword argument 'turn_detection_mode' {"room": "playground-9z4k-tQOW", "pid": 20978, "job_id": "AJ_auzztbpdQE7G", "room_id": "RM_FKtNMPEVTRUV"} Traceback (most recent call last): File "/root/agent-starter-python/.venv/lib/python3.12/site-packages/opentelemetry/util/_decorator.py", line 71, in async_wrapper return await func(*args, **kwargs) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/root/agent-starter-python/.venv/lib/python3.12/site-packages/livekit/agents/ipc/job_proc_lazy_main.py", line 292, in _traceable_entrypoint await self._job_entrypoint_fnc(job_ctx) File "/root/agent-starter-python/src/agent.py", line 72, in my_agent stt = speechmatics.STT( ^^^^^^^^^^^^^^^^^ TypeError: STT.__init__() got an unexpected keyword argument 'turn_detection_mode'
t
Thanks — I see you hit the TypeError because
turn_detection_mode
is not a valid
speechmatics.STT()
constructor argument. I’ll explain what to update in your agent.py so turn detection works with the LiveKit turn detector. What to change (summary) • Remove the invalid parameter
turn_detection_mode="TurnDetectionMode.EXTERNAL"
. • Use
end_of_utterance_mode
on
speechmatics.STT()
when you want to control STT endpointing. Valid values are
EndOfUtteranceMode.FIXED
,
EndOfUtteranceMode.ADAPTIVE
, and
EndOfUtteranceMode.NONE
. • If you want LiveKit’s turn detector (e.g.,
MultilingualModel()
) to drive end-of-turn decisions, set
end_of_utterance_mode=speechmatics.EndOfUtteranceMode.NONE
and provide
turn_detection=MultilingualModel()
in the
AgentSession
. • Ensure partial results are streamed (enable partials) so the turn detector can operate on live transcripts. Minimal corrected example for your agent.py
Copy code
session = AgentSession(
    stt=speechmatics.STT(
        # Do not use `turn_detection_mode` — it's not a constructor arg
        end_of_utterance_mode=speechmatics.EndOfUtteranceMode.NONE,
        operating_point="enhanced",
        language="en",
        enable_partials=True,  # ensure partial transcripts stream to the turn detector
    ),
    llm=inference.LLM(model="openai/gpt-4.1-mini"),
    tts=inference.TTS(model="cartesia/sonic-3", voice="9626c31c-bec5-4cca-baa8-f8ba9e84c8bc"),
    turn_detection=MultilingualModel(),   # LiveKit semantic turn detector
    vad=ctx.proc.userdata["vad"],
    preemptive_generation=True,
)
Why this fixes the error • The STT constructor does not accept `turn_detection_mode`; passing it raised the TypeError you saw. • Setting
end_of_utterance_mode=EndOfUtteranceMode.NONE
disables Speechmatics’ endpointing so LiveKit’s
MultilingualModel()
can perform turn detection on streaming partials. •
enable_partials=True
(or the equivalent default behavior) ensures the turn detector receives live transcript updates rather than waiting for final utterances. Choosing modes • Use ADAPTIVE or FIXED if you want Speechmatics to perform endpointing itself. • Use NONE when you want LiveKit’s turn detector (or another external detector) to decide end-of-turn. If you want, I can: • Give a full copy of your agent.py with the changes applied, or • Show a version that keeps Speechmatics endpointing (e.g., ADAPTIVE) instead of LiveKit’s detector, or • Help tune
end_of_utterance_silence_trigger
if you prefer FIXED mode. Which would you like next? Sources: Speechmatics STT plugin guide | LiveKit Documentation | LiveKit turn detector plugin | LiveKit Documentation