i want to override stt node in my agent. I want to...
# ask-ai
c
i want to override stt node in my agent. I want to process the transcript before sending it forward. How do i do it
✅ 1
t
Thanks for reaching out, Kushagra. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I understand you want to override the STT node to preprocess transcripts before they’re forwarded. You can do this by implementing a custom
stt_node()
in your agent and yielding modified
stt.SpeechEvent
objects. Key points: • Override
stt_node(self, audio: AsyncIterable[rtc.AudioFrame], model_settings: ModelSettings) -> Optional[AsyncIterable[stt.SpeechEvent]]
. • Call the default pipeline via
Agent.default.stt_node(self, audio, model_settings)
to get the event stream, then iterate, modify events (e.g., change
alternative.text
, filter filler words, detect keywords), and
yield
the modified events. • This is supported for STT-LLM-TTS pipeline models; it’s not available for pure realtime models. Minimal example (Python):
Copy code
async def stt_node(self, audio, model_settings):
    events = Agent.default.stt_node(self, audio, model_settings)
    async for event in events:
        if event.type in (stt.SpeechEventType.INTERIM_TRANSCRIPT, stt.SpeechEventType.FINAL_TRANSCRIPT):
            for alt in event.alternatives:
                alt.text = alt.text.replace("😊", "").strip()  # example preprocessing
            if event.type == stt.SpeechEventType.FINAL_TRANSCRIPT:
                transcript = event.alternatives[0].text.lower()
                if "urgent" in transcript:
                    await self.session.say("I detected an urgent request.")
        yield event
Would you like an example that: • Removes filler words, • Runs language detection and switches TTS language, or • Sends transcripts to an external processor before yielding? I can provide the appropriate code snippet for the option you pick. Sources: Pipeline nodes and hooks | LiveKit Documentation, with interactive elements
c
i implemented something similar and i got "no activity context found, the agent is not running" error
t
Sorry you hit that error — let's get it fixed. That message means the agent isn't in a running session when your
stt_node
is being used. To help diagnose, please share: • When exactly the error appears (startup, first transcript, after a while). • A short snippet showing how you create/start the AgentSession and where
stt_node
is invoked. • Any relevant log lines around the error (startup and shutdown lines). • Whether you're calling
await session.start()
and not using the STT node before that completes. Quick checklist to try now: • Ensure you call and await
session.start()
(or equivalent) before audio is sent or
stt_node
runs. • Don’t invoke agent methods after
session.close()
or outside the session lifecycle. • If you call
Agent.default.stt_node(...)
, call it from inside the running session context (not from module import time). Send the code snippet for session setup + your
stt_node
override and I’ll point out the exact spot to fix. Sources: Pipeline nodes and hooks | LiveKit Documentation | Build a multilingual voice agent that automatically switches languages | Li... | Build a multilingual voice agent that automatically switches languages | Li... | Agent session | LiveKit Documentation | https://docs.livekit.io/agents/logic/sessions.md|, with interactive elements
c
events = Agent.default.stt_node(self, audio, model_settings) try: agent_name = self.class.name async for event in events: ... yield event except: ...
t
Thanks — that snippet helps. The error means
stt_node
is running outside an active AgentSession. I need two small things to pinpoint the bug: 1. The code where you create/start the session (how you call
session.start()
/
AgentSession(...)
) — a short snippet is fine. 2. Where/when audio is being fed into the agent (are you sending audio before
await session.start()
completes?). Quick checks you can try now: • Make sure you call and await
session.start()
(or the equivalent start API) before any audio is sent or before
stt_node
is entered. • Ensure you are not calling
Agent.default.stt_node(...)
at import time or outside the agent instance’s running lifecycle. • Wrap your iteration in try/finally and avoid swallowing exceptions — log the exception to see if it’s raised before or after
events
iteration starts. If you paste the session-start snippet and where you attach/send audio, I’ll point out the exact fix. , with interactive elements
c
this error arises after agent transfer
t
Thanks — that helps. Since the error happens after an agent transfer, it likely means your
stt_node
is being invoked while the original session is closed or before the new session is fully running. Please share two small code snippets so I can pinpoint the fix: • The agent-transfer code plus how you create/start the new
AgentSession
(the call that does
session.start()
or equivalent). • Where you attach/send audio after the transfer (how/when audio frames are passed into the agent). Meanwhile try these checks: • Ensure you do not iterate
Agent.default.stt_node(...)
from the old session after transfer — only call it inside the new agent’s running session. • Await the new session’s
start()
before sending audio or entering
stt_node
. • After transfer, ensure any references to the old session/agent are cleared so no background task tries to use them. • Add logging around transfer: log session IDs, lifecycle state (starting, running, closed), and the exact time you call
Agent.default.stt_node(...)
. • In your
stt_node
override, wrap the call and iteration with try/finally and log exceptions with stack traces so we can see whether the failure happens immediately or after some events. Paste the two snippets and a few transfer-related logs and I’ll point out the exact change to fix this. , with interactive elements
c
Copy code
for alt in event.alternatives:
                alt.text = alt.text.replace("😊", "").strip()  # example preprocessing
            if event.type == stt.SpeechEventType.FINAL_TRANSCRIPT:
                transcript = event.alternatives[0].text.lower()
                if "urgent" in transcript:
                    await self.session.say("I detected an urgent request.")
what is the difference between looping over event.alternatives and event.alternatives[0]
t
Good question — both are valid but serve different purposes. • Looping
for alt in event.alternatives:
processes every transcription hypothesis (all alternatives). Use this when you want to clean/normalize every candidate, compare confidences, or choose a non-top alternative later. • Using
event.alternatives[0]
accesses the top (highest-confidence) hypothesis only. Use this when you just need the best guess (common for keyword checks or sending a single transcript to an LLM). In short: loop to handle every candidate; index
[0]
when you only need the primary transcription. Sources: Pipeline nodes and hooks | LiveKit Documentation | An open source stack for real-time multimodal AI | LiveKit, with interactive elements