can an agent listens to transcription received eve...
# ask-ai
k
can an agent listens to transcription received event?
t
Thanks for reaching out, Hyeonsu. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — yes, an agent can listen for transcription events. You can subscribe to the
user_input_transcribed
event on an Agent session. That event is emitted whenever user speech is transcribed (it includes interim and final results), so your agent can react in real time. A common pattern is to wait for the final transcription (
is_final
) and then process or respond to it — for example, echoing it back or triggering downstream logic. Example (Python-style):
Copy code
@session.on("user_input_transcribed")
def on_transcript(transcript):
    if transcript.is_final:
        session.say(transcript.transcript)
If you’d like, tell me which language/SDK you’re using (Python, TypeScript, etc.) or whether you need to handle interim vs final transcripts, and I’ll provide a concrete code snippet or integration tips. Sources: Agent session | LiveKit Documentation | Repeater | LiveKit Documentation | Pi Zero Transcriber | LiveKit Documentation
k
on frontend we're using
RoomEvent.TranscriptionReceived
. is that equivalent of this?
t
Thanks — good question. Yes:
RoomEvent.TranscriptionReceived
on the frontend corresponds to the same underlying transcription data that an Agent receives via the
user_input_transcribed
event. The main differences are about where the event is delivered and how you consume it: • Scope: ◦
RoomEvent.TranscriptionReceived
is a client-side (frontend) room event you subscribe to in your app. ◦
user_input_transcribed
is the Agent-level event delivered to Agents/sessions running server-side logic. • Payload & timing: ◦ Both provide the transcription text and include interim and final results. You’ll typically see the same transcription text and
is_final
-style flag in both places. ◦ Use interim events for live UI updates and final results (
is_final
) for committing actions (e.g., triggering an intent or agent response). • Typical usage patterns: ◦ Frontend: show live transcript, captions, or highlight words as the user speaks. ◦ Agent/server: process final transcriptions to run NLP, decide actions, or speak a response (for example the Repeater pattern that echoes final transcripts). If you want, tell me which SDK/language you’re using on the frontend (web/TypeScript, React, etc.), and I can provide a short concrete code snippet showing how to subscribe to
RoomEvent.TranscriptionReceived
and how to map/use the
is_final
flag the same way an Agent would.
k
how can I get the LLM result then? i'd like to store what agent says
t
Thanks — I’m replying to your question about how to get the LLM result so you can store what the agent says. Short answer: yes — you can capture and store the agent’s LLM-generated text. Which method you choose depends on whether you want the final spoken text, real-time streaming output, or the raw LLM text before TTS. Below are the practical options and recommended approaches. 1) Capture final agent responses (recommended) • Subscribe to the
conversation_item_added
event on the Agent session. It contains completed messages with role
assistant
. This gives you the final text the agent produced (what you’d normally store as the agent’s reply). • Example (Python):
Copy code
@session.on("conversation_item_added")
def on_conversation_item_added(item):
    if item.message.role == "assistant":
        agent_text = item.message.content
        save_to_db(agent_text)
• Example (Node.js/TS):
Copy code
session.on('conversation_item_added', (item) => {
  if (item.message.role === 'assistant') {
    const agentText = item.message.content;
    saveToDb(agentText);
  }
});
2) Capture LLM streaming output (before TTS) • If you need the raw LLM output in real time (partial chunks), override
llm_node
in your Agent subclass and collect chunks as they stream. This is useful for logging, moderation, or showing typing-like progress. • You can assemble the chunks into a final string and store it when the stream completes. 3) Capture text when you explicitly call
session.say()
or generate text yourself • If your code calls
session.say(response_text)
after generating an LLM reply, simply store
response_text
at that point (no event needed). 4) Frontend / text-stream capture • Agent responses are also available as text streams on the
lk.transcription
topic (with no
lk.transcribed_track_id
when audio is disabled). You can register a text stream handler on the room to receive agent text and store it. • Example (frontend JS):
Copy code
room.registerTextStreamHandler('lk.transcription', async (reader, participantInfo) => {
  const message = await reader.readAll();
  const isAgentResponse = !reader.info.attributes['lk.transcribed_track_id'];
  if (isAgentResponse) {
    saveToDb(message);
  }
});
5) End-of-session report (full conversation export) • Generate a session report or conversation history at session end and persist any assistant messages found there (useful for audits or bulk exports). Which approach should you use? • For most cases where you want the canonical final agent reply to store: use
conversation_item_added
. • If you need partial streaming text or want to intercept text before TTS: override
llm_node
. • If you control the text directly with `session.say()`: store it where you emit it. If you tell me which SDK/language you’re using (Python, Node/TS, or frontend framework) and whether you need interim streaming or only final replies, I’ll provide a concrete example tailored to your setup and include best-practices for redaction/storage. Sources: Redacting PII from agent logs and transcripts | LiveKit
k
i also need to know when the speech started
t
Thanks — I’m replying to your follow-up about wanting both the LLM result (what the agent says) and a reliable signal for when the agent’s speech starts. Short answer: • Capture the final LLM text via the
conversation_item_added
event. • Detect speech start with
agent_state_changed
when the agent transitions to
speaking
. For an earlier signal (speech synthesized/queued) use
speech_created
. How to use them together (recommended flow) 1. Listen for
conversation_item_added
to persist the assistant message (final text). 2. Listen for
agent_state_changed
and check for
new_state == "speaking"
to mark the moment audio playback begins. 3. Optionally listen for
speech_created
if you want a notification immediately after TTS is ready (this occurs slightly before
speaking
). Concrete examples • Python (agent/server side)
Copy code
@session.on("conversation_item_added")
def on_conversation_item_added(item):
    if item.message.role == "assistant":
        agent_text = item.message.content
        save_to_db(agent_text)      # store the LLM-generated text

@session.on("agent_state_changed")
def on_agent_state_changed(ev):
    if ev.new_state == "speaking":
        # Agent audio playback has started
        mark_speech_started(timestamp_now(), ev)
• If you want the earliest signal (synthesis complete / audio queued):
Copy code
@session.on("speech_created")
def on_speech_created(speech_handle):
    # TTS has been created and queued; speaking will follow soon
    note_speech_queued(speech_handle.id)
Frontend / room-level option • If you capture agent output via room text streams (
lk.transcription
) or the frontend
RoomEvent.TranscriptionReceived
, you can still correlate the stored text with the agent speaking state by subscribing to the agent-state events (server-side) or by listening for audio-playback indicators in the client. The canonical source for “speech started” remains the agent state transition to
speaking
. Notes and best practices • Use
conversation_item_added
as your canonical place to store the final LLM reply — it contains the final assistant message content. • Use
agent_state_changed
(
speaking
) for accurate playback start timing (good for analytics, VUIs, avatar lip-sync). • Use
speech_created
if you need the earliest possible notification (it fires when audio is synthesized/queued, just before
speaking
). • If you also need to detect when speech ends, listen for playback completion /
playback_finished
on the output audio handle. Would you like examples tailored to a specific SDK/language (TypeScript, React frontend, or Node/Python backend)? If you tell me which one you’re using, I’ll give a ready-to-use snippet and show how to correlate the stored text with the speaking timestamp. Sources: Agent session | LiveKit Documentation | Turns overview | LiveKit Documentation | Agent speech and audio | LiveKit Documentation | How to detect when an agent has finished speaking