Hi I run a livekit agent that a user can talk to e...
# ask-ai
t
Hi I run a livekit agent that a user can talk to either via voice or text chat. Since updating to livekit-agents 1.5 text messages seem to be getting ignored with log message: "text stream with topic 'lk.chat', no callback attached". Did something change in the API here?
➕ 1
✅ 1
t
Thanks for reaching out, Tom. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I hear you: text messages are being ignored after upgrading to livekit-agents 1.5 and you see the log "text stream with topic 'lk.chat', no callback attached". Let’s troubleshoot that together. What this message means • The agent process is receiving text on the
lk.chat
stream but no handler/callback is registered to process it. The log indicates a missing callback for that topic, so incoming text is observed but not acted on. Likely causes and quick checks • If you relied on a default built-in text handler in previous versions, it’s possible the way text callbacks are registered changed in 1.5 and a callback now must be explicitly provided. • Check how you initialize the agent/room options: do you pass a text input callback (or any custom text handler) when creating the agent or joining the room? • Verify your agent code that previously handled text wasn’t removed or overwritten during the upgrade (for example, if you replaced defaults with custom options that omit text handlers). What I recommend you try next 1. Confirm how you create the agent/room: ◦ Share the snippet where you construct room/agent options (the part that could register input callbacks). If you can paste that, I can point out what to change. 1. Explicitly register a text callback for
lk.chat
and see if the log goes away. The agents system supports providing a text input callback in the room options — adding one will ensure incoming
lk.chat
messages are delivered to your logic. 2. If you use default behavior (no custom callback) and expect built-in handling, tell me whether that worked before the upgrade and include the previous version number. That helps confirm whether default registration changed between versions. If you want, paste: • The code that creates/initializes the agent or joins the room (especially the options object), and • The exact upgrade steps (what you changed from the previous version) I’ll look at your snippet and give precise code changes to register the text callback so your
lk.chat
messages are processed again. Sources: Text and transcriptions | LiveKit Documentation, with interactive elements
t
here's from my python backend. I didn't used to need to explicitly have a callback for it. This hasn't changed at all: await session.start( room=ctx.room, agent=Assistant( student_data=student_data, is_demo=is_demo, memory_context=memory_context, tutor_instructions=tutor_instructions, conversation_history=conversation_history, target_session_minutes=target_session_minutes, ), room_input_options=RoomInputOptions( # For telephony applications, use
BVCTelephony
instead for best results noise_cancellation=noise_cancellation.BVC(), ), room_output_options=RoomOutputOptions(audio_enabled=not text_only_mode), )
t
Thanks — that’s very helpful. You’ve shown the Python startup call you use and confirmed you didn’t previously need an explicit text callback. I’ll focus on why you’re seeing the log "text stream with topic 'lk.chat', no callback attached" and what to check next. What that log means • The system is seeing incoming text on the
lk.chat
topic but reports there is no custom callback registered for that topic. This log is informational; default text handling is still present and should process
lk.chat
messages automatically for standard chat use. What to verify next (quick checks) 1. Confirm the incoming messages are actually using topic
lk.chat
(not a variant or typo). 2. Ensure the participant sending text is connected to the same room referenced by
ctx.room
. 3. Check whether text input is enabled for the session — by default it is, and your shown code (with no explicit text callback) is normally sufficient for default processing. 4. Confirm there is no custom agent logic elsewhere that explicitly unregisters or blocks text callbacks before the default handler runs. If the agent is receiving but ignoring messages, please tell me: • Are there any other logs (errors or warnings) around the same time as the "no callback attached" message? • Do you observe the agent responding at all (text or TTS) when you send a chat message, or is nothing produced? • The exact livekit-agents version you upgraded from and the full version string you upgraded to (1.5.x) — that helps confirm whether logging behavior changed versus actual behavior. If everything above looks normal, next diagnostic step • Paste the code where you construct the
Assistant
class (or any custom hooks you add to the session/agent) and any place you might override room/agent defaults. I’ll scan those for anything that could suppress the default text handler. Optional immediate workaround • You can attach an explicit simple text callback to confirm delivery and processing. If you want, I can show the minimal Python snippet to register a
lk.chat
handler that forwards incoming text into the agent pipeline — this will both silence the log and ensure messages are processed if something in your environment is preventing the default from running. Which would you like me to do next? • I can provide the explicit callback snippet now, or • You can paste the additional logs and the
Assistant
/ session initialization code and I’ll look for what’s suppressing the default handler. Sources: Text and transcriptions | LiveKit Documentation, with interactive elements
t
it's definitely receiving to the right room, as whenever I send text message I see a new "ignored text stream with topic 'lk.chat', no callback attached" message. I even tried setting up the explicit RoomOptions callback handler from https://docs.livekit.io/agents/multimodality/text/#text-input but it does not get hit, I still just see that log message
t
Thanks — I appreciate the details and your patience. You’ve confirmed: • Messages arrive in the correct room (you see the "ignored text stream..." log), • You tried the documented RoomOptions callback but it never fires, • This started after upgrading to livekit-agents 1.5. Quick summary of what the logs mean • The log "ignored text stream with topic 'lk.chat', no callback attached" indicates the runtime sees an lk.chat text stream but has no custom callback registered to consume it. That log is normally informational — the system can still use the built-in text handling — but in your case the explicit callback also isn’t being invoked, which points to a registration or lifecycle issue rather than a simple mismatch of topic names. Checks and diagnostics to narrow this down 1. Confirm text input is enabled at runtime ◦ Even though default is enabled, verify it explicitly at session start or after start: ▪︎ Call
session.input.set_text_enabled(True)
(or the equivalent) to ensure text input is on. 1. Confirm you’re passing the callback in the right place ◦ The callback must be provided in the RoomOptions/TextInputOptions that the session actually uses. If you construct a different options object (or pass
room_input_options
vs
room_options
) the callback could be attached to the wrong object. 1. Ensure session has fully started before messages arrive ◦ If messages are sent before the session/agent finishes initialization, the callback might not yet be registered and the stream will be ignored. Check logs for session start/connected events and try sending a message after those events. 1. Verify callback function signature and import path ◦ Use the minimal signature the docs show (e.g.,
def custom_text_handler(session, event): ...
) and avoid using methods with bound-self vs standalone functions until it’s working. 1. Check for code that may unregister or disable callbacks ◦ Search your codebase for any calls that set
text_input=False
, call
session.input.set_text_enabled(False)
, or otherwise modify RoomOptions after start. Minimal diagnostic callback you can add right now • Add a tiny callback that only logs receipt and calls a simple reply. This confirms whether the callback registration path is being used:
Copy code
def debug_text_handler(session, event):
    # quick log to stdout so we can see it immediately
    print("DEBUG: received text event:", event.text)
    # interrupt any current activity, then generate a simple reply
    session.interrupt()
    session.generate_reply(user_input=event.text)

await session.start(
    room=ctx.room,
    agent=Assistant(...),
    room_input_options=RoomInputOptions(
        noise_cancellation=noise_cancellation.BVC(),
        text_input=RoomInputOptions.TextInputOptions(
            text_input_cb=debug_text_handler
        ),
    ),
    room_output_options=RoomOutputOptions(audio_enabled=not text_only_mode),
)
Notes about the snippet above: • I used
room_input_options.text_input.text_input_cb
as the nested option location because some SDK variants nest TextInputOptions under room input options. If your SDK variant uses
room_options=RoomOptions(text_input=TextInputOptions(...))
use that shape instead — the key is to attach to the exact options object that
session.start
consumes. • If your current attempt followed the docs exactly and still didn’t run, try placing the callback function in module scope (not as a bound method) as a test — just to rule out serialization/closure issues. If that still doesn’t hit • Paste the exact code you tried when registering the callback (the RoomOptions/TextInputOptions object you passed). I’ll review it for placement/signature mistakes. • Also paste the immediate logs around session start (connected/ready) and the "ignored text stream..." entry — timestamps and a few lines before/after are useful. Why this likely isn’t an LLM/processing bug • The log specifically reports an unhandled text stream. That points to the callback registration/enablement path or timing, rather than the downstream LLM/TTS pipeline. So we should focus on where/when the callback is attached and whether text input is enabled for the active session. Next step • If you want, paste the exact RoomInputOptions/TextInputOptions code you used and a short snippet showing session start logs. I’ll point out exactly where to change it (or provide a tailored minimal example that will definitely be invoked in your environment). Sources: Text and transcriptions | LiveKit Documentation, with interactive elements
t
This is what i have now, still doesn't work, the print is not hit __ def custom_text_input_handler( session: AgentSession, event: room_io.TextInputEvent ) -> None: print(f"🔥 Custom text input handler: {event}") # Access the incoming text message message = event.text # Default behavior: interrupt and generate reply session.interrupt() session.generate_reply(user_input=message) await session.start( room=ctx.room, agent=Assistant( student_data=student_data, is_demo=is_demo, memory_context=memory_context, tutor_instructions=tutor_instructions, conversation_history=conversation_history, target_session_minutes=target_session_minutes, ), room_options=room_io.RoomOptions( text_input=room_io.TextInputOptions( text_input_cb=custom_text_input_handler ), audio_input=room_io.AudioInputOptions( # For telephony applications, use
BVCTelephony
instead for best results noise_cancellation=noise_cancellation.BVC(), ), audio_output=not text_only_mode, ), ) session.input.set_text_enabled(True)
t
Thanks — I can see why this is frustrating. You’ve shown a clear callback and the correct-looking RoomOptions shape, and yet the handler never fires while the runtime logs “ignored text stream with topic 'lk.chat', no callback attached.” Let’s narrow this down and get you a working diagnostic. What I’m responding to • Your custom function
custom_text_input_handler(...)
and the
room_options=room_io.RoomOptions(text_input=room_io.TextInputOptions(...))
snippet, plus the fact you still see "ignored text stream..." and the print never runs. Immediate observations • The runtime log indicates the session isn’t recognizing any callback attached for the
lk.chat
stream. That usually means either (A) the options object with the callback isn’t the one used by the active session, (B) text input is disabled at the time messages arrive, or (C) the callback registration happens too late (timing/lifecycle issue). • Your callback signature looks correct and your handler code is fine as a diagnostic (simple print + interrupt + generate_reply). Concrete checks & quick fixes to try now 1. Ensure the options object you pass is actually used by session.start ◦ You used
room_options=room_io.RoomOptions(...)
in your snippet. Confirm the
session.start
you call accepts
room_options=
(not
room_input_options=
or
room_io.RoomOptions
vs
RoomInputOptions
mismatch). Some SDK variants use
room_input_options
/
room_output_options
names. Use the exact parameter name the version of the SDK expects. 1. Move callback registration earlier (before start) and enable text explicitly ◦ Call
session.input.set_text_enabled(True)
before or immediately after
session.start
, but preferably before any clients send messages. 1. Use a module-level (not bound method) function for the callback ◦ For debugging, keep
custom_text_input_handler
as a top-level function (not a method on a class instance) to avoid issues with serialization/closure or bound-self mismatch. 1. Add logs around session lifecycle ◦ Print/log immediately after
session.start
and in any session connected/ready event handlers. Make sure messages are sent only after you see connected/ready. 1. Try the minimal diagnostic example below — copy-paste this and run it to rule out config shape/timing issues. Minimal diagnostic example (guarantees callback placement)
Copy code
# module-level handler
def debug_text_handler(session, event):
    print("🔥 DEBUG: text handler invoked, event:", event.text)
    session.interrupt()
    session.generate_reply(user_input=event.text)

# Start session with explicit room_options shape that attaches the text callback
await session.start(
    room=ctx.room,
    agent=Assistant(...),
    room_options=room_io.RoomOptions(
        text_input=room_io.TextInputOptions(
            text_input_cb=debug_text_handler
        ),
        audio_input=room_io.AudioInputOptions(
            noise_cancellation=noise_cancellation.BVC(),
        ),
        audio_output=not text_only_mode,
    ),
)

# Ensure text input is explicitly enabled once the session has started
session.input.set_text_enabled(True)

print("Session started and text input explicitly enabled")
If your SDK variant instead expects
room_input_options
replace
room_options=
with
room_input_options=
and attach the same nested
text_input
there — the key is to attach to the exact options parameter that
session.start
reads. If that still doesn’t hit, please paste two small things • The exact signature of
session.start
in your installed package (e.g., quick print of
help(session.start)
or the import path/version) — this confirms which parameter name to use. • The session startup logs (a few lines before and after
session.start
and the "ignored text stream..." message) so I can check ordering/timing. Why I suspect a mismatch • You’re seeing the ignored-text log which means the runtime observes the incoming
lk.chat
stream but didn’t find a callback on the active session. That’s most often caused by passing the callback in the wrong options object / parameter or registering it after the session is already connected and messages arrive. Next step I’ll take with you • Once you paste the small items above (or confirm whether your SDK uses
room_options
vs
room_input_options
), I’ll give the exact corrected snippet that matches your SDK and a small test you can run to prove the handler is invoked. If needed, I’ll also show how to subscribe to
conversation_item_added
as an alternate way to observe incoming text events while we debug callback registration., with interactive elements
t
I've also tried this and doesn't work: _ await session.start( room=ctx.room, agent=Assistant( student_data=student_data, is_demo=is_demo, memory_context=memory_context, tutor_instructions=tutor_instructions, conversation_history=conversation_history, target_session_minutes=target_session_minutes, ), room_input_options=RoomInputOptions(text_input_cb=custom_text_input_handler), room_output_options=RoomOutputOptions(audio_enabled=not text_only_mode), ) livekit.agents - WARNING agent-1 | [convo=77be3574] - RoomInputOptions agent-1 | and RoomOutputOptions are agent-1 | deprecated, use RoomOptions instead
t
Thanks — I see what you tried and why you’re still stuck. You’re using a
room_input_options
parameter that the runtime warns is deprecated, and your explicit callback never fires while the runtime logs “ignored text stream with topic 'lk.chat', no callback attached.” Let’s solve this step-by-step. What I’m responding to • Your last snippet that uses
room_input_options=RoomInputOptions(text_input_cb=...)
and the runtime warning to use
RoomOptions
instead. You also confirmed the callback print is never hit and the ignored-text log continues. Why this likely isn’t your handler code • Your handler signature and body look fine for diagnosing (simple print then interrupt + generate). • The runtime message strongly suggests the session never saw a registered callback for the active RoomOptions that the session is actually using. The deprecation warning points to a parameter/shape mismatch as the most likely root cause. Concrete next steps — try this exact flow 1) Use RoomOptions (not RoomInputOptions/RoomOutputOptions) and attach TextInputOptions there • Copy this minimal, module-level example exactly and run it. Make sure the function is defined at module scope (not as a bound method).
Copy code
# module-level handler
def custom_text_input_handler(session, event):
    print("🔥 Custom text input handler invoked:", event.text)
    session.interrupt()
    session.generate_reply(user_input=event.text)

# start the session using RoomOptions (replace ... with your existing args)
await session.start(
    room=ctx.room,
    agent=Assistant(
        student_data=student_data,
        is_demo=is_demo,
        memory_context=memory_context,
        tutor_instructions=tutor_instructions,
        conversation_history=conversation_history,
        target_session_minutes=target_session_minutes,
    ),
    room_options=room_io.RoomOptions(
        text_input=room_io.TextInputOptions(
            text_input_cb=custom_text_input_handler
        ),
        audio_input=room_io.AudioInputOptions(
            noise_cancellation=noise_cancellation.BVC(),
        ),
        audio_output=not text_only_mode,
    ),
)

# explicitly enable text input after start to be safe
session.input.set_text_enabled(True)
print("Session started; text input explicitly enabled")
2) Ensure messages arrive after the session is ready • Wait for the session start logs / connected-ready messages before sending a test message. If you send messages before the session finishes initializing, the stream may be ignored. 3) Confirm the frontend sends to the
lk.chat
topic • Send text using the client
sendText(..., topic='lk.chat')
. The runtime ignores other topics by default. 4) If the handler still does not run, capture these items and paste them here: • The exact livekit-agents package version (the full version string for 1.5.x you installed). • The console logs for session start: show a few lines before and after
await session.start(...)
and the exact "ignored text stream..." log lines (timestamps help). • A copy of the import names you use (e.g.,
from livekit.agents import room_io
vs other import paths) so I can confirm the correct option class names. Why I asked for these items • The runtime warning about deprecation suggests your session may be reading a different options shape. If
room_input_options
is being ignored by the new session API, the callback will never attach and the runtime will log ignored streams even though your handler exists in code. • Logs + version let me confirm whether this is a migration issue introduced in 1.5 or a timing/usage mismatch. Optional alternate diagnostic • If you want a quick alternative while testing, subscribe to
conversation_item_added
events (those trigger when text is committed to history). That will at least let you observe incoming messages server-side while we get the direct callback path fixed. Let me know which you prefer: • I can review the exact logs + version you paste and point to the precise fix, or • If you want, I can provide a second minimal example that uses
conversation_item_added
to confirm messages reach the session while we debug the direct callback registration. Sources: Agent session | LiveKit Documentation | Text and transcriptions | LiveKit Documentation, with interactive elements
t
even
conversation_item_added
isn't getting hit. should i try scubscribing to lk.chat directly?
t
Thanks — I understand how frustrating this is. You’ve tried the documented callbacks, the deprecated and new options shapes, and even
conversation_item_added
, and none of them fire. That strongly narrows the problem to one of a few places: text input is disabled for the active session, messages are not being sent to the
lk.chat
topic the server expects, or the session/options object the agent actually uses doesn’t have the callback attached. Short answer to your question: yes — subscribing directly to the
lk.chat
text stream is a good diagnostic step. It will tell you whether the server is receiving those text frames at all, independent of the agent callback machinery. Concrete troubleshooting steps (in order) 1) Confirm text input is enabled for the active session • Explicitly enable text input before sending messages: ◦ Call
session.input.set_text_enabled(True)
right after you start the session (or before sending test messages). ◦ If your SDK offers a
text_input
flag in
RoomOptions
, set it explicitly to true. 2) Verify the client is sending to topic 'lk.chat' • On the client, ensure sendText (or equivalent) is called with
topic='lk.chat'
. • If you have control of the client, send a test message after you see the session print “Session started; text input explicitly enabled”. 3) Subscribe directly to the lk.chat stream as a diagnostic • Add a low-level subscription to see raw incoming text frames. This bypasses the agent callback layer so you can confirm delivery. How you do this will depend on your environment, but conceptually: ◦ Add a handler that listens for incoming text streams/messages and logs them immediately. ◦ If you see the messages here, the problem is in how RoomOptions/callbacks are attached or in agent lifecycle timing. ◦ If you do not see them, the messages are not arriving to the server (client/topic mismatch or transport problem). 4) Re-run with a minimal end-to-end test • Use the minimal module-level callback + RoomOptions example I gave earlier. • Start the session, explicitly enable text, wait for the "started/ready" log, then send a single test message from the client to
lk.chat
. What to capture and paste if this still fails • The livekit-agents package version (exact string for 1.5.x). • The exact session start logs (a few lines before and after
await session.start(...)
) including the deprecation warning you saw. • The log lines when you send a test message (timestamped) showing "ignored text stream..." or not. • The client call used to send text (the sendText invocation or equivalent), showing the topic parameter. Quick example: subscribe to lk.chat (conceptual — adapt to your stack) • If your SDK exposes a lower-level event bus, add a handler that logs every incoming text frame on any topic, and filter for
lk.chat
. • If you can’t do a low-level subscription, use
conversation_item_added
as a fallback — but you already said that didn’t fire, which makes the direct subscription even more useful. Why this approach • If direct subscription shows messages arriving, we’ll know callbacks are not being attached correctly (timing/options mismatch) and can focus on exactly where to pass RoomOptions. • If direct subscription shows nothing, the client is likely sending to the wrong topic or text input is disabled upstream. If you want, I can: • Provide a minimal direct-subscribe example tailored to the exact import names you use (e.g.,
from livekit.agents import room_io
) — paste your imports and I’ll tailor it. • Review the logs and version you paste and give an exact correction to the session.start call that will attach the callback correctly. Which would you like to do next — try the direct subscription now, or paste the logs + version and I’ll analyze them? , with interactive elements
t
To fix it i've had to manually add this subscription to the lk.chat: __ def _register_lk_chat_text_handler(room: rtc.Room, session: AgentSession) -> None: """useChat (components-react) sends text streams on TOPIC_CHAT, not lk.agent.session run_input.""" local = room.local_participant.identity def on_text_stream(reader: rtc.TextStreamReader, participant_identity: str) -> None: async def consume() -> None: if participant_identity == local: return try: text = (await reader.read_all()).strip() except Exception: logger.exception("Failed to read lk.chat text stream") return if not text: return try: await session.interrupt() except RuntimeError: pass session.generate_reply(user_input=text) asyncio.create_task(consume()) room.register_text_stream_handler(TOPIC_CHAT, on_text_stream) _ But why the hell did upgrading to python livekit-agents 1.5.0 cause me to need to do this? Isn't this a major bug?
t
I hear your frustration — this was a painful regression for you and I appreciate the clear debugging you did. I’ll summarize what’s happening, why you had to add the manual subscription, and the practical options to fix it so your agent behaves reliably going forward. What happened (short) • After upgrading to livekit-agents 1.5, the agent no longer invoked your previous high-level text callbacks; the runtime logged that the
lk.chat
stream had no callback attached. • You confirmed the documented RoomOptions/TextInputOptions callbacks and
conversation_item_added
didn’t fire. • Manually registering a low-level text-stream handler for the chat topic (what you posted) fixed it — messages are now seen and processed. Why this explains the behavior you saw • The runtime is reporting that no handler was attached for the
lk.chat
stream on the active session. The deprecation warning you saw about
RoomInputOptions
/
RoomOutputOptions
means the SDK’s session options shape and callback-registration surface changed; if callbacks are passed to the wrong options object or if the client is sending on a different topic, the SDK won’t wire up a handler for those incoming frames. • In addition, some UI libraries (you mentioned useChat / components-react) send text on a different topic constant (your TOPIC_CHAT), not necessarily
lk.chat
. If the frontend is sending on a non-
lk.chat
topic, the agent’s high-level text callback (which listens for
lk.chat
) won’t be invoked. Your manual subscription listens to that topic directly and therefore bypasses the higher-level callback wiring — that’s why it worked. Is this a bug? • I can’t declare internal intent or promises about releases, but from the symptoms: ◦ This looks like a behavior change in how text streams are routed/registered (and/or a migration requirement caused by the options deprecation). ◦ If you were previously relying on an implicit handler accepting any chat-like topic, and now the SDK requires callbacks be attached to
lk.chat
(or requires RoomOptions in the new shape), that is a breaking change in behavior even if intentional. • Whether it’s a bug or an intentional breaking change depends on release notes / maintainers’ decision. The important part now is reliable fix paths you can use immediately. Practical options to fix and avoid fragility You have three clear choices — pick the one that fits your setup best: 1) Make the frontend send text on the expected topic (
lk.chat
) • If you can change the client, send messages with topic='lk.chat' so the agent’s high-level text path (RoomOptions/TextInputOptions) will see them automatically. • This is the cleanest fix if you control both client and server. 2) Attach the high-level callback correctly using the new RoomOptions shape • Ensure you pass the callback in the
room_options=RoomOptions(text_input=TextInputOptions(text_input_cb=...))
parameter that the active SDK expects (not deprecated
room_input_options
/
room_output_options
). • Keep the callback a module-level function during testing to avoid binding/serialization issues and make sure text is enabled (
session.input.set_text_enabled(True)
) before sending test messages. 3) Keep your low-level subscription (what you implemented) as a deliberate compatibility shim • Your
_register_lk_chat_text_handler
approach is valid and reliable: it bypasses the agent callback registration and consumes text frames directly, so it works even if frontends use different topics or the high-level callback path is not wired. • This is the right choice when you don’t control the client topic or want to be tolerant of different client libraries. Recommended next steps I can help with • If you prefer to convert the client to
lk.chat
, I can show the exact client-side change needed. • If you prefer to use the high-level RoomOptions callback, paste the exact
session.start
call and imports you use; I’ll give the exact minimal snippet matching your package so it attaches correctly. • If you keep the low-level handler (which is fine), I can suggest a couple of small hardening changes (filtering out local participant reliably, adding metrics/logging, and safe exception handling). If you want, I can also: • Draft a concise issue/feedback text you can raise against the livekit-agents release notes or repo describing this break (so maintainers can clarify if it’s intended), or • Provide a minimal end-to-end example (client + server) that uses the new RoomOptions
text_input
callback and shows the full flow working. Which path would you like to take — fix the client to send
lk.chat
, make the RoomOptions callback work, or harden your low-level subscription? , with interactive elements
r
t
Thanks — I see the PR you linked. I appreciate you sharing it; that helps explain the change you hit. Quick summary based on what you’ve found • That PR is the likely root cause: the agents package behavior around text streams / option shapes changed. The SDK now prefers the unified
RoomOptions
shape and stricter wiring of text callbacks, and older/deprecated paths or implicit handling you relied on no longer get automatically attached. • Because your frontend was (or may have been) sending text on a topic that the new high-level callbacks weren’t wired to, the agent runtime logged the ignored
lk.chat
stream and none of the high-level callbacks fired — which forced you to add the low-level
lk.chat
subscription as a pragmatic fix. Why your manual subscription made it work • Your handler listens directly to the room text stream and consumes frames regardless of the higher-level callback registration. That bypasses the changed callback registration path and restores message delivery to your agent logic. Is this a bug or intended? • From your symptom set and the PR link, this behaves like a breaking change (intentional or accidental) in how text streams are registered/handled. Whether it’s classified as a bug depends on the maintainers’ intent and the release notes for that PR. Practically speaking, it is a breaking change in behavior relative to older versions and understandably disruptive. Recommended production paths (pick one) • If you control the client: make the client send messages explicitly to
lk.chat
and use the new
RoomOptions(text_input=TextInputOptions(...))
callback shape. This is the clean, forward-compatible solution. • If you don’t control the client or want robustness: keep the low-level
room.register_text_stream_handler(TOPIC_CHAT, ...)
shim (your current fix). It’s reliable and tolerant of differing client topics. • If you want the high-level API: migrate all server-side startup to use
room_options=RoomOptions(...)
with
text_input=TextInputOptions(text_input_cb=...)
and ensure
session.input.set_text_enabled(True)
happens before messages arrive. Use a module-level callback function for testing. I can help with any of these: • Give the exact minimal server snippet that uses the new
RoomOptions
shape matching your imports. • Provide the exact client-side change to send with
topic='lk.chat'
. • Draft a concise issue/PR comment you can paste into the linked GitHub PR describing your regression and environment (version, logs, and the workaround you used) so maintainers can prioritize a fix or clarify intended behavior. Which would you like next — a migration snippet for your server, the client-change snippet, or help drafting a clear issue comment for the PR? , with interactive elements
r
t
Thanks — I see you found the related issue and workaround. I appreciate you digging into the PR and filing/reading the issue links — that confirms this is a regression/migration pain introduced around the 1.5 changes. Summary and confirmation • The behavior you saw (no high-level callback invoked, "ignored text stream with topic 'lk.chat', no callback attached") is tied to the 1.5 changes: the SDK now expects the unified RoomOptions/TextInputOptions shape and tighter routing of text streams. • Your manual low-level subscription to the chat text stream is a correct and practical workaround when high-level callbacks aren’t firing (or when frontends use a different topic). • The issue link you posted documents the regression and the workaround others are using. Treat your shim (registering a text stream handler on TOPIC_CHAT /
lk.chat
) as an acceptable compatibility fix until the SDK behavior is clarified or fixed. Recommended next steps (pick one) • If you control the client: change the client to send text on
topic='lk.chat'
and attach your callback via
room_options=RoomOptions(text_input=TextInputOptions(text_input_cb=...))
. That’s the clean, forward-compatible approach. • If you don’t control the client or prefer resilience: keep your low-level subscription as a deliberate compatibility shim (your current code). I can help harden it (logging, dedup, error handling). • If you want the SDK-level fix: I can help you draft a concise comment/issue summary for the PR/issue that explains the regression with your version, logs, and the minimal repro you used (that helps maintainers prioritize a fix or document the breaking change). Optional help I can provide now • A minimal server-side snippet using the new RoomOptions shape that you can drop into your app to test. • A minimal client example to send to
lk.chat
. • A short issue comment you can paste into the linked PR/issue describing your environment, logs, and the workaround you used. Which would you like me to do next — provide the migration snippet, client change, hardening suggestions for your shim, or help draft an issue comment for the PR? , with interactive elements