lemon-furniture-71054
02/12/2026, 8:31 PMtall-airline-16756
02/12/2026, 8:31 PMtall-airline-16756
02/12/2026, 8:31 PMlk.transcription text stream, and sample frontend code (JS/React) to register a text-stream handler and render conversation bubbles. I’ll also show how to tell user vs agent text using the lk.transcribed_track_id attribute.
• If you’re sending audio from clients directly: I’ll outline how to enable Speechmatics STT in your agent or pipeline and how to forward transcriptions into LiveKit text streams for the UI.
• If you want speaker diarization: I’ll include the Speechmatics STT config option to enable diarization and how to parse speaker tags.
If you prefer, tell me which of these you want now (pick one): “Backend AgentSession + React UI”, “Plain JS web client”, or “Mobile app”. Once you pick, I’ll provide the exact code snippets and steps for that path.
Sources: Speechmatics STT plugin guide | LiveKit Documentation | Text and transcriptions | LiveKit Documentation | How to build an agent with speech-to-text input and text-only output | Live...lemon-furniture-71054
02/12/2026, 8:33 PMtall-airline-16756
02/12/2026, 8:34 PMAgentServer / rtc_session) and have a frontend that connects to the agent’s LiveKit room? If yes, I’ll assume the agent can accept connections and we’ll focus only on adding Speechmatics STT + frontend transcription handling. If not, say “I need the base agent running” and I’ll include the minimal server start instructions.
Below are the steps you can follow. I’ll include exact Python snippets and the frontend handler to render conversation bubbles.
1) Install the Speechmatics plugin
• Run:
uv add "livekit-agents[speechmatics]~=1.3"
This installs the Speechmatics STT plugin for your agent.
2) Add your Speechmatics API key
• Create (or update) a .env in your project root with:
SPEECHMATICS_API_KEY=your_speechmatics_api_key_here
• Load it in your Python script:
from dotenv import load_dotenv
load_dotenv()
3) Configure AgentSession to use Speechmatics STT
• Use speechmatics.STT() when creating your AgentSession. Minimal example inside an RTC session handler:
from dotenv import load_dotenv
load_dotenv()
from livekit.agents import AgentSession, Agent, JobContext, AgentServer
from livekit.plugins import speechmatics, openai
server = AgentServer()
class MyAgent(Agent):
def __init__(self):
super().__init__(instructions="You are a helpful assistant.")
@server.rtc_session()
async def on_session(ctx: JobContext):
session = AgentSession(
stt=speechmatics.STT(), # <-- Speechmatics STT enabled
llm=openai.LLM(model="gpt-4.1-mini"), # example LLM
tts=openai.TTS(model="tts-1", voice="alloy"),
)
agent = MyAgent()
await session.start(agent=agent, room=ctx.room)
# keep session open so speech is transcribed in real-time
await session.generate_reply(instructions="Say hello.")
• Start your agent server as you normally do (e.g., using your existing dev/run commands).
4) (Optional) Enable speaker diarization
• If you want speaker attribution from Speechmatics:
stt = speechmatics.STT(
enable_diarization=True,
speaker_active_format="<{speaker_id}>{text}<!--{speaker_id}-->",
)
session = AgentSession(stt=stt, llm=..., tts=...)
• The plugin will emit speaker-tagged transcripts which you can parse on the frontend.
5) How transcriptions are delivered to the frontend
• When the agent transcribes audio, LiveKit publishes the text to the lk.transcription text stream topic automatically. No extra forwarding code is required server-side.
6) Frontend: receive text-streams and show conversation bubbles
• In the browser, register a handler for lk.transcription. Example using plain JavaScript (LiveKit Room object):
// room is your connected LiveKit Room
room.registerTextStreamHandler('lk.transcription', async (reader, participantInfo) => {
const message = await reader.readAll(); // full transcription text
const attrs = reader.info.attributes || {};
const transcribedTrackId = attrs['lk.transcribed_track_id'];
if (transcribedTrackId) {
// This is a user spoken transcript
displayBubble(participantInfo.identity, message, 'user');
} else {
// Agent response / text generated by the agent
displayBubble('Agent', message, 'agent');
}
});
// Example bubble render helper:
function displayBubble(identity, text, role) {
const container = document.getElementById('bubbles');
const div = document.createElement('div');
div.className = `bubble ${role}`;
div.innerHTML = `<strong>${identity}:</strong> ${text}`;
container.appendChild(div);
container.scrollTop = container.scrollHeight;
}
• If you use React with @livekit/components-react, you can use the useTranscriptions hook to get the transcripts and render them:
import { useTranscriptions } from '@livekit/components-react';
function TranscriptionBubbles() {
const transcriptions = useTranscriptions(); // array of segments
return (
<div id="bubbles">
{transcriptions.map(segment => (
<div key={segment.id} className={`bubble ${segment.is_agent ? 'agent' : 'user'}`}>
<strong>{segment.participant?.identity ?? (segment.is_agent ? 'Agent' : 'User')}:</strong> {segment.text}
</div>
))}
</div>
);
}
7) Distinguish agent vs user transcripts
• The lk.transcription messages for user speech include the attribute lk.transcribed_track_id. Agent-produced text (like TTS text or agent text messages) will not have that attribute. Use that to classify bubbles on the frontend.
8) Test flow
• Start your Python agent server.
• Connect a browser client to the same LiveKit room and allow microphone.
• Speak — you should see live transcription bubbles for your speech and agent text bubbles when the agent replies.
9) Troubleshooting tips
• If you don’t see transcripts:
◦ Verify .env contains SPEECHMATICS_API_KEY and it’s loaded by the agent process.
◦ Confirm your AgentSession is created with speechmatics.STT().
◦ Ensure the frontend is connected to the same room and you’ve registered the lk.transcription handler.
• If speaker attribution is missing, ensure enable_diarization=True is passed to speechmatics.STT().
If you’d like, I can now:
• Provide a minimal full repo-like example (server + small frontend) you can run locally, or
• Produce the exact React component and CSS for polished conversation bubbles, or
• Help parse diarization tags into per-speaker bubbles.
Which would you prefer next?
Sources: Speechmatics STT plugin guide | LiveKit Documentation | Simple Call Answering Agent | LiveKit Documentation | Web and mobile frontends | LiveKit Documentationlemon-furniture-71054
02/12/2026, 8:38 PMtall-airline-16756
02/12/2026, 8:39 PM.env with:
◦ LIVEKIT_API_KEY=your_livekit_api_key
◦ LIVEKIT_API_SECRET=your_livekit_api_secret
◦ LIVEKIT_URL=wss://your-subdomain.livekit.cloud
◦ SPEECHMATICS_API_KEY=your_speechmatics_api_key
1. Ensure your Python process loads .env (the starter uses python-dotenv). Example:
◦ from dotenv import load_dotenv; load_dotenv()
Step 3 — add/enable the Speechmatics plugin
1. Install the plugin into the project environment:
◦ uv add "livekit-agents[speechmatics]~=1.3"
1. Update the agent code to use Speechmatics STT. In the agent session setup, replace or set stt to `speechmatics.STT()`:
Example (minimal snippet inside your agent code):
from livekit.agents import AgentSession, Agent, JobContext, AgentServer
from livekit.plugins import speechmatics, openai
server = AgentServer()
class MyAgent(Agent):
def __init__(self):
super().__init__(instructions="You are a helpful assistant.")
@server.rtc_session()
async def on_session(ctx: JobContext):
session = AgentSession(
stt=speechmatics.STT(), # Speechmatics enabled
llm=openai.LLM(model="gpt-4.1-mini"), # example LLM
tts=openai.TTS(model="tts-1", voice="alloy"),
)
agent = MyAgent()
await session.start(agent=agent, room=ctx.room)
await session.generate_reply(instructions="Say hello.")
Optional: enable diarization if you want per-speaker attribution:
stt = speechmatics.STT(
enable_diarization=True,
speaker_active_format="<{speaker_id}>{text}<!--{speaker_id}-->"
)
Step 4 — run the agent locally (test & dev modes)
• Quick terminal test (console mode that simulates a call):
uv run src/agent.py console This shows logs and transcripts in your terminal for quick verification.
• Real WebRTC testing (dev mode — accepts real connections):
uv run src/agent.py dev Then connect a client (or use the Test Agent sandbox UI described next).
Step 5 — see UI and transcripts without building a client You do not need to create your own client to see the conversation. LiveKit Cloud provides a Test Agent sandbox and Agent Insights where you can view transcriptions and logs side‑by‑side.
Option A — Test Agent sandbox (no custom client)
1. Deploy or register your agent in the LiveKit Cloud project.
2. In the LiveKit Cloud dashboard go to Agents → select your agent → click “Test Agent” (or “Regenerate test app” if it’s not present).
3. The Test Agent opens a hosted web sandbox UI (built with @livekit/components-react). Join that sandbox, allow microphone, and speak. You’ll see:
◦ Real-time transcription in the UI
◦ Agent audio responses
◦ Conversation bubbles / interaction state
Option B — Agent Insights (transcripts + logs)
1. In the dashboard go to Sessions → open a specific session → open the Agent Insights tab.
2. You’ll get a combined view:
◦ Transcript timeline and playback (user vs agent text)
◦ Trace/step view showing STT → LLM → TTS events and timing
◦ JSON logs and metadata for each turn
This gives the side‑by‑side conversation flow and logs you asked for without building a frontend.
Step 6 — what to check if you don’t see transcripts
• Confirm .env contains SPEECHMATICS_API_KEY and the agent process loads it.
• Confirm AgentSession uses speechmatics.STT() (or the diarization-enabled variant).
• Ensure the session runs (dev) or the console test shows STT output in terminal.
• Use the Test Agent sandbox to join the same room (no custom client required).
• In the transcript stream, user speech items carry lk.transcribed_track_id — the dashboard and sandbox use this to label user vs agent text.
Step 7 — next steps / optional improvements
• If you want, I can:
◦ Provide a small runnable repo layout with the exact files edited/added so you can run immediately.
◦ Give the exact commands and the single file to run using the starter repo (so you can copy-paste and run).
◦ Provide instructions for parsing diarization tags into per‑speaker bubbles in the UI (if you enable diarization).
Tell me which one: “Runnable repo example”, “Single-file start commands”, or “Diarization parsing”.
If you want, share whether you already have a LiveKit Cloud project and the starter repo cloned — I’ll tailor the next message to give exact file edits and the exact uv run command to start it.
Sources: Build a multilingual voice agent that automatically switches languages | Li... | Agents (Python) | livekit/livekit_composite | DeepWiki | Speechmatics STT plugin guide | LiveKit Documentation | Simple Call Answering Agent | LiveKit Documentation | https://livekit.io/ui/r/registry.json|lemon-furniture-71054
02/12/2026, 9:06 PMtall-airline-16756
02/12/2026, 9:06 PMuv run src/agent.py dev (or your agent start command that runs the server loop).
a. Open a client that plays audio:
• Option A (no custom client needed): Use the LiveKit Cloud “Test Agent” sandbox (see Question #3 below).
• Option B: Use Agents Playground (https://agents-playground.livekit.io/) and connect to your running agent.
• Option C: Use any LiveKit web client that subscribes to audio tracks (e.g., the provided playground or a simple @livekit/components-react page).
a. Join the same room from the browser, allow microphone and speakers — the agent’s TTS will be published as an audio track and the browser will play it.
• Quick check: if you want local audio playback without a browser, you’d need to subscribe to the room’s audio track programmatically and route it to an audio device — that’s more advanced. Using the Test Agent / browser is the easiest path.
Question #2 — Terminal “freezes” after loading the agent and typed commands show up as errors
• What’s happening: When you start the agent (console or dev modes), the agent process runs an event loop and takes over that shell session. It’s expected you won’t be able to run other commands while that process is active. That looks like the terminal is “frozen,” but it’s actually the agent running and waiting for events.
• Why extra input shows errors:
◦ When the agent is stopped or you type while the process is active, you may see strange behavior or “command not found” lines because the shell is not accepting normal interactive input.
• How to stop/exit cleanly:
a. To stop the running agent, press Ctrl+C. If it doesn’t stop immediately, press Ctrl+C again or wait a short moment for the process to shut down.
b. If Ctrl+C appears ineffective, open a new terminal tab/window and run ps aux | grep agent and kill the process with kill <pid> or kill -9 <pid> as a last resort.
• Best practice:
◦ Keep one terminal dedicated to the running agent. Use a separate terminal to run other commands. Don’t expect to type shell commands into the same session while the agent is running.
Question #3 — How to start the agent on LiveKit Cloud and use “Test Agent” / “Regenerate test app”
• Quick summary: You can deploy your agent to LiveKit Cloud and then use the Test Agent sandbox to hear audio and view transcripts without building a client.
Steps to deploy and use Test Agent:
1. Prepare your project:
◦ Ensure .env contains: LIVEKIT_API_KEY, LIVEKIT_API_SECRET, LIVEKIT_URL, SPEECHMATICS_API_KEY.
◦ Confirm dependencies and that the agent runs locally in dev mode first.
1. Use the LiveKit CLI to create/deploy the agent:
◦ If you haven’t already, run lk agent create in project root to generate required files (if needed).
◦ Deploy with: lk agent deploy (or lk agent create on first deploy). This pushes your agent to LiveKit Cloud.
1. Use the Cloud Console:
◦ In LiveKit Cloud Console → Agents, find your deployed agent.
◦ Click “Test Agent.” That opens the hosted Test Agent UI (a browser client) where you can join the room, allow mic/speaker, and interact. You will hear the agent’s TTS there.
◦ If no test UI exists, click “Regenerate test app” to create one and open it.
1. View transcripts & logs:
◦ In the Console go to Sessions → select a session → Agent Insights tab.
◦ You’ll see transcripts, audio playback, and trace logs (STT→LLM→TTS) side-by-side — useful for debugging.
Extra troubleshooting/checks you can run now
• Confirm agent is publishing audio:
◦ In logs you should see events that the session published audio tracks and TTS generated. If you see STT transcripts but no TTS logs, check your TTS configuration in AgentSession.
• Confirm browser is receiving audio:
◦ Join Test Agent sandbox and open devtools → Network/Console to see if media subscription errors appear.
• If TTS is silent:
◦ Verify you configured tts in your AgentSession (e.g., tts=openai.TTS(...) or your chosen TTS).
◦ Double-check API keys and model selection for the TTS provider.
• If speech is transcribed but no audio and logs show TTS output text only:
◦ The agent may be configured to produce agent text but not synthesize audio. Ensure your session calls TTS or session.speak() rather than only session.text_response().
Which thing would help most next?
• I can give the exact commands and a minimal single-file example you can run locally to confirm audio publishing and TTS.
• Or I can walk you through deploying your current repo to LiveKit Cloud step-by-step and then open the Test Agent for you to try.
Tell me which you prefer and whether you can run commands now (yes/no). If you want the deploy steps, tell me whether you already have the LiveKit CLI installed and your LIVEKIT_API_KEY / SECRET ready.
Sources: Google AI and LiveKit | LiveKit Documentation | Uninterruptable Agent | LiveKit Documentation | Agent Builder | LiveKit Documentation | Voice AI quickstart | LiveKit Documentationlemon-furniture-71054
02/12/2026, 9:12 PMtall-airline-16756
02/12/2026, 9:13 PMlk.transcription stream.
• Why use it: Lightweight, you control it, and it is faster than building a full app.
Option C — Use the @livekit/components-react demo (if you prefer React)
• What it is: prebuilt components including useTranscriptions which let you render conversation bubbles.
• How to use:
a. Create a simple Next.js page (I can provide a one-file component) that uses @livekit/components-react.
b. Use a server endpoint to mint a token to join the room.
c. When you connect, useTranscriptions() will surface lk.transcription segments for display.
• I can provide the minimal component and token endpoint code if you want.
Option D — Agent Insights & Session Logs (Cloud dashboard)
• If “Test Agent” is missing, Agent Insights may still show session transcripts and logs:
a. In the Cloud Console go to Sessions → select a session (if any exist).
b. Open Agent Insights / Trace / Transcript panels.
• If you have no sessions listed, you need to run the agent in dev or deploy so sessions are generated.
Option E — Quick workaround: terminal transcript streaming + simple web UI
• If you can run the agent locally and want to avoid tokens:
a. Run the agent in console mode to ensure STT is producing transcripts (you’ll see text logs).
b. Pipe those transcripts to a tiny local web server I can provide (Node or Python). The server shows a live webpage with conversation bubbles (no audio playback needed). This gives you the transcription UI immediately.
• Tell me if you prefer this and I’ll produce the exact server code (5–10 lines) that listens for stdin or a file and updates the browser via SSE or WebSocket.
Common troubleshooting checks (if you still can’t see transcripts)
• Confirm your AgentSession includes STT (speechmatics.STT()) and STT is producing output in the agent logs. If you see transcript lines in terminal, STT is working.
• Make sure your frontend subscribes to lk.transcription text stream or uses useTranscriptions() to surface transcripts.
• If user transcripts are missing attributes, check lk.transcribed_track_id in the text stream attributes to determine user vs agent fragments.
• If you run the agent in dev mode but can’t connect the playground, confirm your agent is reachable (no firewall blocking) and you have the correct LiveKit URL and token.
Which option would you like to try now?
• “Agents Playground” (I’ll help generate any token or instructions you need)
• “Minimal local web client” (I’ll paste the repo/file + token steps)
• “React demo with useTranscriptions” (I’ll give component + server token code)
• “Terminal→Web UI quick server” (I’ll give the tiny server and instructions)
Also tell me:
• Do you see transcripts printed in your agent terminal when speaking? (yes/no)
• Are you able to run uv/dev mode now and open a browser page? (yes/no)
Once you pick, I’ll give the exact commands and any code snippets needed.lemon-furniture-71054
02/12/2026, 10:19 PMtall-airline-16756
02/12/2026, 10:20 PMfrom livekit.plugins import speechmatics, silero
from livekit.agents import AgentSession
# Speechmatics STT configuration demonstrating diarization, smart_turn, and tuning
stt = speechmatics.STT(
enable_diarization=True,
# Format output with explicit tags so you can parse speaker blocks easily
speaker_active_format="<{speaker_id}>{text}<!--{speaker_id}-->",
# Make diarization a little more sensitive to speaker change
diarization_sensitivity=0.7,
# Prefer the current speaker to reduce rapid flips between similar voices
prefer_current_speaker=True,
# Use adaptive endpointing for "smart_turn" behavior
end_of_utterance_mode=speechmatics.EndOfUtteranceMode.ADAPTIVE,
# Typical silence threshold for finalizing a turn (sec) under FIXED/ADAPTIVE
end_of_utterance_silence_trigger=0.6,
# Emit interim partials for low-latency display
enable_partials=True,
# Max time to wait before finalizing the transcript (lower = lower latency)
max_delay=1.0,
# Select an operating point balancing accuracy & latency
operating_point="enhanced",
# Language code
language="en",
# Enable word timestamps & confidence if supported
enable_word_timestamps=True,
enable_word_confidence=True,
)
session = AgentSession(
stt=stt,
# Add VAD to improve turn/interrupt handling
vad=silero.VAD.load(),
# llm, tts, and other components...
)
Parsing diarization output in your UI or demo
• With the sample speaker_active_format above you’ll receive transcripts like:
◦ "<s1>Hello<!--s1-->"
◦ "<s2>Hi there<!--s2-->"
• Parse out the tags to attribute text to the correct speaker. For demos, display as:
◦ Speaker 1: Hello
◦ Speaker 2: Hi there
• If enable_partials=True, show partial lines as “(typing...)” style UI until a final transcript arrives.
Demonstrating “speaker focus” and reduced jitter
• Show two short demos back-to-back:
a. prefer_current_speaker=False, diarization_sensitivity=0.9 — highlights many switches (noisy).
b. prefer_current_speaker=True, diarization_sensitivity=0.6 — shows smoother speaker continuity.
• Explain how smart_turn (ADAPTIVE) combined with VAD reduces awkward mid-sentence endpointing.
Latency vs accuracy tradeoffs
• For low-latency demos (live captions): enable_partials=True, max_delay ~0.5–1.0, operating_point="enhanced".
• For accuracy-focused demos (post-call transcripts): enable_partials=False, operating_point="high_accuracy" (if available), higher max_delay.
Notes & pointers
• The exact parameter names and enums are defined in the plugin source you referenced; use that file as the canonical mapping if you need to pass additional flags or check available enums:
◦ https://github.com/livekit/agents/blob/main/livekit-plugins/livekit-plugins-speechmatics/livekit/plugins/speechmatics/stt.py
• If you need speaker identity mapping, confirm you have speaker enrollment/voiceprints accessible to the Speechmatics account or another speaker‑ID system — the plugin surfaces diarization IDs, but mapping to known identities requires a matching identity model.
• If you want a runnable demo for boost.ai:
◦ I can provide a small Python agent file using the above config and a minimal web UI that consumes lk.transcription and renders per-speaker bubbles (with partials). Tell me if you want a ready repo or a single-file example.
Would you like:
• A single-file runnable agent example (with this STT config) you can run locally?
• A minimal UI (HTML + JS) that connects to a running agent and shows per-speaker bubbles and partials?
Tell me which and I’ll produce the exact files and run commands.
Sources: Speechmatics STT plugin guide | LiveKit Documentation | Turns overview | LiveKit Documentationlemon-furniture-71054
02/13/2026, 12:09 AMtall-airline-16756
02/13/2026, 12:10 AM"label"=="Jeslyn" which is a boolean comparison instead of an assignment; use label="Jeslyn".
• Your long speaker identifier string contains many characters and needs to be a single string in the list; make sure it’s quoted and not split by newlines.
• The overall nesting and commas must be valid Python (each dict/constructor argument separated by commas).
• focus_speakers should be a list (or the correct type expected by the plugin), not a single untyped string unless the API expects that.
Below is a corrected, well‑formatted STT configuration block you can drop into your agent. I kept your options (diarization, adaptive endpointing, additional vocab, known speakers) and corrected the syntax. Adjust the long speaker identifier string as needed (I placed it as a single string in the list).
Corrected STT configuration (Python):
from livekit.plugins import speechmatics, silero
from livekit.agents import AgentSession
stt = speechmatics.STT(
enable_diarization=True,
speaker_active_format="<{speaker_id}>{text}<!--{speaker_id}-->",
additional_vocab=[
speechmatics.AdditionalVocabEntry(
content="LiveKit",
sounds_like=["live kit"],
),
],
# Use adaptive endpointing for "smart_turn" behavior
end_of_utterance_mode=speechmatics.EndOfUtteranceMode.ADAPTIVE,
# Typical silence threshold for finalizing a turn (sec) under FIXED/ADAPTIVE
end_of_utterance_silence_trigger=0.6,
# Max time to wait before finalizing the transcript (lower = lower latency)
max_delay=1.0,
# Select an operating point balancing accuracy & latency
operating_point="enhanced",
# Language code
language="en",
# If plugin expects a list of focus speakers, pass a list
focus_speakers=["Jeslyn"],
known_speakers=[
speechmatics.KnownSpeaker(
label="Jeslyn",
speaker_identifiers=[
"AD1NQVABAAQAAW0ACjlkYzNjNWMwOTQAAXMADC9tMG1lbUt3aVRzPQABdAAMUkppb3l6QVIzc0U9AAF2AAExADAAAAMWAAAAAHQGxM90tq_fd6GmY4I1AJAfhV1L961O0hV0QrDslSoF1kLxDHpNyCgAAAOFAAwAEBrg0CYJ9p2OCrqWZouxnyrgUnyNTyUqaN_sdvTFS2jI2bWsAZcFUfHb6OsxHSxJdHaFxvGYiBT249YpnZOXMYoJds8uE0kSvVELXcNSIgwfUmLWZPt_bPRjc-ILKEjlQh5Aq1AOj6lwczHLVfXe6xbDxsd6ojPkrTp1w25BwlI_nKPJIbhLZ-BJYtIEclJIPcCf-S9IvQ525iK4Fn8JcwJ93rM2wRjLjuC9_opQe_OQu5fTkrKxhk9JebS1NXZ4khmxFjrNCdEL9LF86YJgynTFjK5QnBn2wUeV08rHyUUjm9lwnUHB9kEbOd2KcqDy5JnBjqWwfmUTg0EbMHz-d5tbr2egcLZcxl5uPnZ_dD1wsrBhyN9xRCnJ1tOJqeBwUWKooL92JN9OK4FeA93TdjPEZNXyrnIdxqscTOOG0_naas1dL-OfvvA3i4wHJAmP_866eLBMuLAuDxoeFbkKfzD0wUqtgAbUcEiz64sQk2sLDn9CSsBRsF9gK8mPNxeRP6AP2ZimaO7WPeSj3MkO0JmuR8W4OA0Gvg_ZQA5-BKEeexqBpDRTnwotLVQiBWqt4z_Id08gDUpUhwBtrkFOaVGoM44urC7hZR51cfAo3b0H2nRJappLyzq8-qKLeJGbZs68wmGVSoZEHpIw6jnahKtQPicAMrSyUg9l3_Spd656sBSFWMZLkLM3yR8LrcWxYdGgiZluob4xdM3Ij_7z4Wu41u5wF6jeGOyUpgE3SBoIkhOgWcdYfdyVH0-AyrjYHQURH9AV9Ayhm3itDqx_Z0oTAlWmLsEY_mk8oE0ZkrbqTr8LXDGrulaUkmfBZkAN5rKy4HE0DyhrsbDnsI9rl0GcXAjC0sFFaVSQSyyyj4CfGh6GxojzuuyaGRv815f0RB5H1Ud75zj_t_3acX7k32yX3T3j3Gx5txVAWVsMTp3VRfuxnlWuJTiYw6i_BdFRfxjU_cDP5wmdHXaKjkVo-B5TTcmeqoBYfS4fhE85u7MgeuIaa8xOY8P_R3oi_1GSmgoYtFiA-LlKp4EaEH9bH3k6bhrB4eoT4l8fKdsOcyBHWW2AGeqMKAYh7fDcdl5hgtLytbQmGRDrWq-Ge9Ggoqkd8C1WwOdoAoMO-FVlB75ZKvQNh_a7q3B9qoFtTNab1v2y1GPeQhzwhOcxG-J3uZemYeVFemv0OJRiui0CUo23DmioiU1U0b-DQQzGUX6r_o_SMuayPj0Da6MewnsvWXWuPHyrehTs4roKr1uDxIUeAStAONWXS5q0sNiKbxcqPRUln7_E3LEgUGHthmmUJ8QCtBCD7NLopCKRWL4TB3FAeb82TPqJsuqwWCdOc5S-9om_zsY7wM9Zar0QhWZ2FI5AlgcGEvK-EwRc2oYxWwOmE75gsRpTaHCxjhkt"
],
),
],
)
Notes and recommendations
• Confirm that focus_speakers is the correct key and type for your plugin version. In many APIs it’s a list of labels; if your plugin expects a single name, use a string. The sample above uses a list for safety.
• Keep long speaker identifier strings as one continuous quoted string (no line breaks) or use Python triple-quoted strings if you need readability.
• If your long identifier contains characters that conflict with your file encoding, ensure the source file is UTF-8 and the string is properly escaped.
• After fixing the syntax, restart the agent process. If you still see multiprocessing spawn errors, run the agent in a simpler mode (e.g., remove concurrency or run a minimal script) to isolate whether a malformed argument is still present.
If you’d like, I can:
• Provide a minimal runnable agent example with this STT config (one Python file) so you can test quickly.
• Validate that speechmatics.KnownSpeaker constructor accepts label and speaker_identifiers fields in your plugin version (I can adapt to the exact constructor signature if you paste the relevant class definition from the plugin file).lemon-furniture-71054
02/13/2026, 12:14 AMRoomIO -> RecorderIO -> AgentSession ->
RecorderIO -> TranscriptSynchronizer -> RoomIO
{"room": "playground-IEoU-mWIe", "pid": 168502, "job_id":
"AJ_vdxaTWzszMHp", "room_id": "RM_4RB3HHnt7Jxh"}
001340.343 DEBUG… livekit.agents using transcript io: AgentSession -> TranscriptSynchronizer
-> RoomIO
{"room": "playground-IEoU-mWIe", "pid": 168502, "job_id":
"AJ_vdxaTWzszMHp", "room_id": "RM_4RB3HHnt7Jxh"}
001340.790 INFO … livekit.agents shutting down worker {"id": "AW_EoTY9sELQJma"}
001340.794 DEBUG… livekit.agents input stream detached
{"participant": null, "source": "SOURCE_UNKNOWN", "accepted_sources":
["SOURCE_MICROPHONE"], "room": "playground-IEoU-mWIe", "pid": 168502, "job_id": "AJ_vdxaTWzszMHp", "room_id":
"RM_4RB3HHnt7Jxh"}
001342.678 ERROR… livekit.agents Error in _stt_task
Traceback (most recent call last):
File "/usr/lib/python3.12/asyncio/tasks.py", line 520, in
wait_for
return await fut
^^^^^^^^^
File "/usr/lib/python3.12/asyncio/locks.py", line 212, in wait
await fut
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following
exception:
Traceback (most recent call last):
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/l…
line 17, in async_fn_logs
return await fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/l…
line 689, in _stt_task
async for ev in node:
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/l…
line 397, in stt_node
async for event in stream:
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/l…
line 442, in anext
raise exc # noqa: B904
^^^^^^^^^
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/l…
line 318, in _main_task
return await self._run()
^^^^^^^^^^^^^^^^^
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/l…
line 482, in _run
await self._client.start_session(
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/s…
line 136, in start_session
await self._start_recognition_session(
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/s…
line 199, in _start_recognition_session
await self._wait_recognition_started()
File
"/root/agent-starter-python/.venv/lib/python3.12/site-packages/s…
line 307, in _wait_recognition_started
await asyncio.wait_for(self._recognition_started_evt.wait(),
timeout)
File "/usr/lib/python3.12/asyncio/tasks.py", line 519, in
wait_for
async with timeouts.timeout(timeout):
File "/usr/lib/python3.12/asyncio/timeouts.py", line 115, in
aexit
raise TimeoutError from exc_val
TimeoutError
{"room": "playground-IEoU-mWIe", "pid": 168502, "job_id":
"AJ_vdxaTWzszMHp", "room_id": "RM_4RB3HHnt7Jxh"}
Traceback (most recent call last):
File "/usr/lib/python3.12/asyncio/tasks.py", line 520, in wait_for
return await fut
^^^^^^^^^
File "/usr/lib/python3.12/asyncio/locks.py", line 212, in wait
await fut
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/root/agent-starter-python/.venv/lib/python3.12/site-packages/livekit/agents/utils/log.py", line 17,
in async_fn_logs
https://docs.livekit.io/reference/python/livekit/plugins/speechmatics/index.html#livekit.plugins.speechmatics.DiarizationKnownSpeaker
# See all available models at https://docs.livekit.io/agents/models/stt/
stt = speechmatics.STT(
enable_diarization=True,
speaker_active_format="<{speaker_id}>{text}<!--{speaker_id}-->",
additional_vocab=[
speechmatics.AdditionalVocabEntry(
content="LiveKit",
sounds_like=["live kit"],
),
],
# Use adaptive endpointing for "smart_turn" behavior
end_of_utterance_mode=speechmatics.EndOfUtteranceMode.ADAPTIVE,
# Typical silence threshold for finalizing a turn (sec) under FIXED/ADAPTIVE
end_of_utterance_silence_trigger=0.6,
# Max time to wait before finalizing the transcript (lower = lower latency)
max_delay=1.0,
# Select an operating point balancing accuracy & latency
operating_point="enhanced",
# Language code
language="en",
# If plugin expects a list of focus speakers, pass a list
focus_speakers=["Jeslyn"],
known_speakers=[
speechmatics.DiarizationKnownSpeaker(
label="Jeslyn",
speaker_identifiers=[
"AD1NQVABAAQAAW0ACjlkYzNjNWMwOTQAAXMADC9tMG1lbUt3aVRzPQABdAAMUkppb3l6QVIzc0U9AAF2AAExADAAAAMWAAAAAHQGxM90tq_fd6GmY4I1AJAfhV1L961O0hV0QrDslSoF1kLxDHpNyCgAAAOFAAwAEBrg0CYJ9p2OCrqWZouxnyrgUnyNTyUqaN_sdvTFS2jI2bWsAZcFUfHb6OsxHSxJdHaFxvGYiBT249YpnZOXMYoJds8uE0kSvVELXcNSIgwfUmLWZPt_bPRjc-ILKEjlQh5Aq1AOj6lwczHLVfXe6xbDxsd6ojPkrTp1w25BwlI_nKPJIbhLZ-BJYtIEclJIPcCf-S9IvQ525iK4Fn8JcwJ93rM2wRjLjuC9_opQe_OQu5fTkrKxhk9JebS1NXZ4khmxFjrNCdEL9LF86YJgynTFjK5QnBn2wUeV08rHyUUjm9lwnUHB9kEbOd2KcqDy5JnBjqWwfmUTg0EbMHz-d5tbr2egcLZcxl5uPnZ_dD1wsrBhyN9xRCnJ1tOJqeBwUWKooL92JN9OK4FeA93TdjPEZNXyrnIdxqscTOOG0_naas1dL-OfvvA3i4wHJAmP_866eLBMuLAuDxoeFbkKfzD0wUqtgAbUcEiz64sQk2sLDn9CSsBRsF9gK8mPNxeRP6AP2ZimaO7WPeSj3MkO0JmuR8W4OA0Gvg_ZQA5-BKEeexqBpDRTnwotLVQiBWqt4z_Id08gDUpUhwBtrkFOaVGoM44urC7hZR51cfAo3b0H2nRJappLyzq8-qKLeJGbZs68wmGVSoZEHpIw6jnahKtQPicAMrSyUg9l3_Spd656sBSFWMZLkLM3yR8LrcWxYdGgiZluob4xdM3Ij_7z4Wu41u5wF6jeGOyUpgE3SBoIkhOgWcdYfdyVH0-AyrjYHQURH9AV9Ayhm3itDqx_Z0oTAlWmLsEY_mk8oE0ZkrbqTr8LXDGrulaUkmfBZkAN5rKy4HE0DyhrsbDnsI9rl0GcXAjC0sFFaVSQSyyyj4CfGh6GxojzuuyaGRv815f0RB5H1Ud75zj_t_3acX7k32yX3T3j3Gx5txVAWVsMTp3VRfuxnlWuJTiYw6i_BdFRfxjU_cDP5wmdHXaKjkVo-B5TTcmeqoBYfS4fhE85u7MgeuIaa8xOY8P_R3oi_1GSmgoYtFiA-LlKp4EaEH9bH3k6bhrB4eoT4l8fKdsOcyBHWW2AGeqMKAYh7fDcdl5hgtLytbQmGRDrWq-Ge9Ggoqkd8C1WwOdoAoMO-FVlB75ZKvQNh_a7q3B9qoFtTNab1v2y1GPeQhzwhOcxG-J3uZemYeVFemv0OJRiui0CUo23DmioiU1U0b-DQQzGUX6r_o_SMuayPj0Da6MewnsvWXWuPHyrehTs4roKr1uDxIUeAStAONWXS5q0sNiKbxcqPRUln7_E3LEgUGHthmmUJ8QCtBCD7NLopCKRWL4TB3FAeb82TPqJsuqwWCdOc5S-9om_zsY7wM9Zar0QhWZ2FI5AlgcGEvK-EwRc2oYxWwOmE75gsRpTaHCxjhkt"
],
),
],
),tall-airline-16756
02/13/2026, 12:15 AMfocus_speakers and speaker_identifiers).
• Use the correct constructor speechmatics.DiarizationKnownSpeaker(...) with label= and speaker_identifiers=[...].
• Keep long speaker identifier strings as a single quoted string (no unescaped newlines).
• Fix earlier syntax mistakes (no == in kwargs, commas between arguments, etc.).
Corrected STT configuration (copy‑paste into your agent):
from livekit.plugins import speechmatics, silero
from livekit.agents import AgentSession
stt = speechmatics.STT(
enable_diarization=True,
speaker_active_format="<{speaker_id}>{text}<!--{speaker_id}-->",
# custom vocabulary
additional_vocab=[
speechmatics.AdditionalVocabEntry(
content="LiveKit",
sounds_like=["live kit"],
),
],
# smart_turn/adaptive endpointing
end_of_utterance_mode=speechmatics.EndOfUtteranceMode.ADAPTIVE,
end_of_utterance_silence_trigger=0.6,
max_delay=1.0,
operating_point="enhanced",
language="en",
# focus_speakers must be a list (even if single)
focus_speakers=["Jeslyn"],
# known_speakers must be a list of DiarizationKnownSpeaker, each with
# label (string) and speaker_identifiers (list of strings)
known_speakers=[
speechmatics.DiarizationKnownSpeaker(
label="Jeslyn",
speaker_identifiers=[
"AD1NQVABAAQAAW0ACjlkYzNjNWMwOTQAAXMADC9tMG1lbUt3aVRzPQABdAAMUkppb3l6QVIzc0U9AAF2AAExADAAAAMWAAAAAHQGxM90tq_fd6GmY4I1AJAfhV1L961O0hV0QrDslSoF1kLxDHpNyCgAAAOFAAwAEBrg0CYJ9p2OCrqWZouxnyrgUnyNTyUqaN_sdvTFS2jI2bWsAZcFUfHb6OsxHSxJdHaFxvGYiBT249YpnZOXMYoJds8uE0kSvVELXcNSIgwfUmLWZPt_bPRjc-ILKEjlQh5Aq1AOj6lwczHLVfXe6xbDxsd6ojPkrTp1w25BwlI_nKPJIbhLZ-BJYtIEclJIPcCf-S9IvQ525iK4Fn8JcwJ93rM2wRjLjuC9_opQe_OQu5fTkrKxhk9JebS1NXZ4khmxFjrNCdEL9LF86YJgynTFjK5QnBn2wUeV08rHyUUjm9lwnUHB9kEbOd2KcqDy5JnBjqWwfmUTg0EbMHz-d5tbr2egcLZcxl5uPnZ_dD1wsrBhyN9xRCnJ1tOJqeBwUWKooL92JN9OK4FeA93TdjPEZNXyrnIdxqscTOOG0_naas1dL-OfvvA3i4wHJAmP_866eLBMuLAuDxoeFbkKfzD0wUqtgAbUcEiz64sQk2sLDn9CSsBRsF9gK8mPNxeRP6AP2ZimaO7WPeSj3MkO0JmuR8W4OA0Gvg_ZQA5-BKEeexqBpDRTnwotLVQiBWqt4z_Id08gDUpUhwBtrkFOaVGoM44urC7hZR51cfAo3b0H2nRJappLyzq8-qKLeJGbZs68wmGVSoZEHpIw6jnahKtQPicAMrSyUg9l3_Spd656sBSFWMZLkLM3yR8LrcWxYdGgiZluob4xdM3Ij_7z4Wu41u5wF6jeGOyUpgE3SBoIkhOgWcdYfdyVH0-AyrjYHQURH9AV9Ayhm3itDqx_Z0oTAlWmLsEY_mk8oE0ZkrbqTr8LXDGrulaUkmfBZkAN5rKy4HE0DyhrsbDnsI9rl0GcXAjC0sFFaVSQSyyyj4CfGh6GxojzuuyaGRv815f0RB5H1Ud75zj_t_3acX7k32yX3T3j3Gx5txVAWVsMTp3VRfuxnlWuJTiYw6i_BdFRfxjU_cDP5wmdHXaKjkVo-B5TTcmeqoBYfS4fhE85u7MgeuIaa8xOY8P_R3oi_1GSmgoYtFiA-LlKp4EaEH9bH3k6bhrB4eoT4l8fKdsOcyBHWW2AGeqMKAYh7fDcdl5hgtLytbQmGRDrWq-Ge9Ggoqkd8C1WwOdoAoMO-FVlB75ZKvQNh_a7q3B9qoFtTNab1v2y1GPeQhzwhOcxG-J3uZemYeVFemv0OJRiui0CUo23DmioiU1U0b-DQQzGUX6r_o_SMuayPj0Da6MewnsvWXWuPHyrehTs4roKr1uDxIUeAStAONWXS5q0sNiKbxcqPRUln7_E3LEgUGHthmmUJ8QCtBCD7NLopCKRWL4TB3FAeb82TPqJsuqwWCdOc5S-9om_zsY7wM9Zar0QhWZ2FI5AlgcGEvK-EwRc2oYxWwOmE75gsRpTaHCxjhkt"
]
)
],
)
Notes and validation steps
• The Speechmatics error you saw: "transcription_config.speaker_diarization_config.speakers: Invalid type. Expected: array, given: object" means the diarization speakers field was not an array. The corrected block uses lists everywhere required.
• Make sure the long voiceprint string is a valid identifier produced by Speechmatics voiceprint enrollment — arbitrary strings will not map to a real voice.
• If you still see a schema error:
a. Confirm your installed plugin version matches the docs: pip show livekit-plugins-speechmatics (upgrade if needed).
b. Temporarily remove known_speakers and focus_speakers and verify diarization works with only enable_diarization=True. Then add known speakers back to isolate the issue.
c. If the plugin still rejects config, paste the exact plugin class signature (from your installed package) and I’ll adapt the call to that version.
If you want, I can:
• Produce a minimal single-file agent.py with this STT config so you can run and validate quickly.
• Help you test incrementally: first enable diarization only, then add additional_vocab, then focus_speakers, then known_speakers.
Which would you like next?
Sources: Speechmatics STT plugin guide | LiveKit Documentationlemon-furniture-71054
02/13/2026, 12:28 AMlemon-furniture-71054
02/13/2026, 12:29 AMtall-airline-16756
02/13/2026, 12:29 AMlemon-furniture-71054
02/13/2026, 12:35 AMtall-airline-16756
02/13/2026, 12:35 AMlemon-furniture-71054
02/13/2026, 12:52 AM