I recently updated my livekit python packages, Now...
# ask-ai
i
I recently updated my livekit python packages, Now getting this error while the agent speaking. I can hear the agent sound, but it is not taking my input, and showing this error.
Copy code
"room_id": "RM_CbYM2j5d97k8"}
    12:13:14.628 INFO … session.llm        [51dc80f0-f111-4a6f-85f9-f02358fc3fa4]     
                                           LLM genearted Response                     
                                      {"pid": 4082658, "job_id": "AJ_rFaETRqyguby", 
"room_id": "RM_CbYM2j5d97k8"}
                 WARNI… livekit.agents     failed to stream event to clients          
                                           Traceback (most recent call last):         
                                             File                                     
                                           "/home/rashi-aidetic/Documents/Fabrichq/…  
                                           line 507, in _send_client_event            
                                               event_data = event.model_dump_json()   
                                                            ^^^^^^^^^^^^^^^^^^^^^^^   
                                             File                                     
                                           "/home/rashi-aidetic/Documents/Fabrichq/…  
                                           line 352, in model_dump_json               
                                               return                                 
                                           self.__pydantic_serializer__.to_json(      
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^…  
                                           pydantic_core._pydantic_core.PydanticSer…  
                                           Error serializing to JSON:                 
                                           PydanticSerializationError: Error calling  
                                           function `serialize`: AttributeError:      
                                           'str' object has no attribute 'audio'      
                                         {"pid": 4082658, "job_id": "AJ_rFaETRqyguby",
"room_id": "RM_CbYM2j5d97k8"}
Traceback (most recent call last):
  File 
"/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3.
12/site-packages/livekit/agents/voice/client_events.py", line 507, in 
_send_client_event
    event_data = event.model_dump_json()
                 ^^^^^^^^^^^^^^^^^^^^^^^
  File 
"/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3.
12/site-packages/pydantic/main.py", line 352, in model_dump_json
    return self.__pydantic_serializer__.to_json(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.PydanticSerializationError: Error serializing to JSON: 
PydanticSerializationError: Error calling function `serialize`: AttributeError: 'str' 
object has no attribute 'audio'
    12:13:14.629 INFO … session.agent      [51dc80f0-f111-4a6f-85f9-f02358fc3fa4]     
                                           Assistant left the room.                   
                                        {"pid": 4082658, "job_id": "AJ_rFaETRqyguby", 
"room_id": "RM_CbYM2j5d97k8"}
                 DEBUG… livekit.agents     input stream detached
✅ 1
t
Thanks for reaching out, Abdul. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I see you're getting a Pydantic serialization error right after updating your LiveKit Python packages: the agent's audio plays, but user input is not accepted and the server log shows "'str' object has no attribute 'audio'" when calling event.model_dump_json(). I'll help you narrow this down and get it working again. To diagnose quickly, I need a few small pieces of information and I’ll also give targeted next steps you can try right away. What I need from you • The exact LiveKit-related packages and versions you upgraded to (output of
pip freeze | grep livekit
or similar). • A minimal code snippet showing where you create/send the client event or call
session.say()
(or any custom event emission) — especially the lines around the error site in your logs. • Whether you changed any custom event handling, TTS, or overrides to
session.say()
recently. • The full stack trace around the call to
client_events._send_client_event
(you included most — the few surrounding lines where the event is constructed are helpful). Quick checks and things to try now 1. Inspect event payloads before serialization • Add a debug log right before the call that sends the event (the code that leads to
event.model_dump_json()
), and print the event's type and keys/attributes. • Confirm that the field that should contain audio is not a plain string. The error means the code expected an object with an
.audio
attribute but got a
str
. 1. Verify how you call
session.say()
or emit audio events • If you call
session.say()
with just a string (or pass a raw string into a lower-level event), newer package versions may expect a structured audio object instead of a bare string. Ensure you use the API that attaches audio correctly, for example passing text and an audio generator/object as separate parameters rather than putting raw audio data into a string field. 1. Reproduce with the previous working version • If you still have the older version, test by downgrading to the version that was working to confirm this is a regression: pip install livekit-agents==previous-version • If the error disappears after downgrade, that confirms a breaking change in the newer release. 1. Trace pipeline outputs • If you use pipeline nodes (STT / LLM / TTS), log the output types at each node (stt_node -> llm_node -> tts_node). One node may be returning a raw string where the following step expects a structured audio model. How I can help next • Once you paste the version list and the small code snippet around where events are created/sent, I will: ◦ Point out exactly which field is mismatched and show how to construct the correct payload. ◦ Provide a minimal patch/example that converts your current string output into the expected audio object. ◦ Suggest the exact package version to test if you want to confirm a regression. If you'd like, paste the version output and the small snippet now and I’ll walk through the exact fix step‑by‑step. Sources: How to detect when an agent has finished speaking | Job lifecycle | LiveKit Documentation | Agent speech and audio | LiveKit Documentation | Pipeline nodes and hooks | LiveKit Documentation | Client SDKs | livekit/livekit_composite | DeepWiki, with interactive elements
i
async def on_enter(self): if self._session_logger: self._session_logger.log_info( LogComponent.AGENT, "Assistant entered room, saying greeting." ) # Say greeting message await self.session.say(f"Hello, Am I talking to {self._prompt_variable_values.get('candidate_name')}?", allow_interruptions=False) pip freeze | grep livekit livekit==1.1.2 livekit-agents==1.4.6 livekit-api==1.1.0 livekit-blingfire==1.1.0 livekit-plugins-assemblyai==1.4.6 livekit-plugins-cartesia==1.4.6 livekit-plugins-deepgram==1.4.6 livekit-plugins-elevenlabs==1.4.6 livekit-plugins-groq==1.4.6 livekit-plugins-noise-cancellation==0.2.5 livekit-plugins-openai==1.4.6 livekit-plugins-silero==1.4.6 livekit-plugins-turn-detector==1.4.6 livekit-protocol==1.1.3 I did not make any changes after updating the packages. it was working fine before update
t
Thanks — this is very helpful. You’ve confirmed the exact call (
await self.session.say(f"Hello, ...")
) and the LiveKit package versions, and that nothing else changed. I’ll focus on the serialization error ("'str' object has no attribute 'audio'") and give concrete troubleshooting steps and a short workaround to get you back to a working state. What’s happening (brief) • The code that serializes the client event expects an object with an
audio
attribute, but it received a plain string. That means
session.say(...)
(or lower-level event code it calls) is producing/receiving a string where the library now expects a structured audio model/field. • This appeared right after the package update, so it’s most likely a change in the library’s expected event payload shape (regression or breaking change). Immediate steps to test and narrow root cause 1. Confirm behavior with a very small change ◦ Replace your call briefly to see if non-audio text-only flow triggers the same failure:
Copy code
await self.session.say(text="Hello, Am I talking to ...?", allow_interruptions=False)
• If
session.say
accepts a
text=
keyword and that avoids the error, it indicates positional string usage is now treated differently by the new version. 1. Log the event payload just before send ◦ Add a debug log right before
session.say()
or in any wrapper you have, printing the exact argument types:
Copy code
self._session_logger.log_info(type(greeting), repr(greeting))
• If you can, intercept or patch the library call site (where
event.model_dump_json()
is called) to print
event
and
event.__dict__
to confirm which attribute is a string. 1. Try a quick downgrade to verify regression ◦ Downgrade
livekit-agents
to the prior working version (or try a close previous patch) to confirm the update caused the regression: pip install livekit-agents==1.4.5 • If the error disappears when downgraded, we know the update introduced a breaking change. Workaround you can try now • Construct an explicit payload that separates text and audio rather than passing a bare string (if the API supports it). For example:
Copy code
# pseudo-example — adapt to your API surface
  await self.session.say(text=f"Hello, Am I talking to {name}?", audio=None, allow_interruptions=False)
• If the library now expects an
audio
field (object), explicitly passing
audio=None
or the proper audio object could avoid the implicit conversion that produced a string in the wrong spot. What I can do next for you • If the quick
text=
test or downgrade confirms the regression, paste the output of the downgrade test (did it fix the issue?) and the debug print of the event payload you see right before serialization. • With that I’ll: ◦ Show the exact change needed in your code to match the new expected shape (if the API changed). ◦ Create a minimal reproducible snippet you can run locally to confirm the fix. ◦ Suggest the exact package version to pin to if you need a stable rollback. If you want to continue now, please: • Try the small
text=
change and tell me whether the error still appears. • If possible, add the quick debug print of the greeting variable type/value and paste that output here. • If you already remember the prior working versions, tell me which
livekit-agents
version worked for you and I’ll recommend the downgrade command. I’ll stay with you through the steps — paste the quick test results and I’ll point to the exact fix. , with interactive elements
i
added this line async def on_enter(self): if self._session_logger: self._session_logger.log_info( LogComponent.AGENT, "Assistant entered room, saying greeting." ) self._session_logger.log_info( LogComponent.AGENT, f"Hello, Am I talking to {self._prompt_variable_values.get('candidate_name')}?" ) # Say greeting message await self.session.say(text=f"Hello, Am I talking to {self._prompt_variable_values.get('candidate_name')}?", allow_interruptions=False) getting this error
Copy code
"room_id": "RM_6oqESasCiC4d"}
                 INFO … session.agent      [7a7e14e7-7476-40ac-8499-57f634592c7a]     
                                           Assistant entered room, saying greeting.   
                                        {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9", 
"room_id": "RM_6oqESasCiC4d"}
                 INFO … session.agent      [7a7e14e7-7476-40ac-8499-57f634592c7a]     
                                           Hello, Am I talking to John Doe?           
                                        {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9", 
"room_id": "RM_6oqESasCiC4d"}
    13:57:57.098 DEBUG… livekit.agents     using audio io: `RoomIO` ->                
                                           `AgentSession` ->                          
                                           `TranscriptSynchronizer` -> `RoomIO`       
                                         {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9",
"room_id": "RM_6oqESasCiC4d"}
                 DEBUG… livekit.agents     using transcript io: `AgentSession` ->     
                                           `TranscriptSynchronizer` -> `RoomIO`       
                                         {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9",
"room_id": "RM_6oqESasCiC4d"}
                 INFO … session.agent      [7a7e14e7-7476-40ac-8499-57f634592c7a]     
                                           Agent session started successfully         
                                        {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9", 
"room_id": "RM_6oqESasCiC4d"}
    13:57:57.504 DEBUG… livekit.agents     aec warmup active, disabling               
                                           interruptions for 3.00s                    
                                         {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9",
"room_id": "RM_6oqESasCiC4d"}
    13:57:57.543 INFO … session.agent      [7a7e14e7-7476-40ac-8499-57f634592c7a]     
                                           tts_metrics metrics collected              
                                        {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9", 
"room_id": "RM_6oqESasCiC4d"}
    13:57:57.897 DEBUG… livekit.….deepgram Established new Deepgram STT WebSocket     
                                           connection:                                
                                           {"headers": {"dg-project-id": 
"c976f576-354b-4460-a92f-db310453ce77", "dg-request-id": 
"99cda67d-f0b2-4679-9603-dd314cfad6cb", "Date": "Wed, 18 Mar 2026 08:27:57 GMT"}, 
"pid": 4113781, "job_id": "AJ_krLD44MaaAN9", "room_id": "RM_6oqESasCiC4d"}
    13:57:58.948 INFO … session.llm        [7a7e14e7-7476-40ac-8499-57f634592c7a]     
                                           LLM genearted Response                     
                                      {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9", 
"room_id": "RM_6oqESasCiC4d"}
    13:57:58.950 WARNI… livekit.agents     failed to stream event to clients          
                                           Traceback (most recent call last):         
                                             File                                     
                                           "/home/rashi-aidetic/Documents/Fabrichq/…  
                                           line 507, in _send_client_event            
                                               event_data = event.model_dump_json()   
                                                            ^^^^^^^^^^^^^^^^^^^^^^^   
                                             File                                     
                                           "/home/rashi-aidetic/Documents/Fabrichq/…  
                                           line 352, in model_dump_json               
                                               return                                 
                                           self.__pydantic_serializer__.to_json(      
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^…  
                                           pydantic_core._pydantic_core.PydanticSer…  
                                           Error serializing to JSON:                 
                                           PydanticSerializationError: Error calling  
                                           function `serialize`: AttributeError:      
                                           'str' object has no attribute 'audio'      
                                         {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9",
"room_id": "RM_6oqESasCiC4d"}
Traceback (most recent call last):
  File 
"/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3.
12/site-packages/livekit/agents/voice/client_events.py", line 507, in 
_send_client_event
    event_data = event.model_dump_json()
                 ^^^^^^^^^^^^^^^^^^^^^^^
  File 
"/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3.
12/site-packages/pydantic/main.py", line 352, in model_dump_json
    return self.__pydantic_serializer__.to_json(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.PydanticSerializationError: Error serializing to JSON: 
PydanticSerializationError: Error calling function `serialize`: AttributeError: 'str' 
object has no attribute 'audio'
    13:57:59.415 INFO … session.egress     [7a7e14e7-7476-40ac-8499-57f634592c7a]     
                                           Room composite egress EG_WB8dDPhwiphQ      
                                           started for                                
                                           ROOM-candidate-7306600306-20260318135734   
                                           (audio)                                    
                                         {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9",
"room_id": "RM_6oqESasCiC4d"}
    13:58:00.504 DEBUG… livekit.agents     aec warmup expired, re-enabling            
                                           interruptions                              
                                         {"pid": 4113781, "job_id": "AJ_krLD44MaaAN9",
"room_id": "RM_6oqESasCiC4d"}
    13:58:04.332 DEBUG… livekit.agents     received user transcript  
                                         {"user_transcript": "You are talking to John.
So", "language": "en", "transcript_delay": 0.3642466068267822, "pid": 4113781, 
"job_id": "AJ_krLD44MaaAN9", "room_id": "RM_6oqESasCiC4d"}
    13:58:04.526 DEBUG… livekit.…_detector eou prediction
older version of agent livekit-agents==1.2.13 current version = 1.4.6
t
Thanks — this is very helpful. I can see you reproduced the issue, and that it works on 1.2.13 but fails on 1.4.6 with the Pydantic serialization error: "'str' object has no attribute 'audio'". That confirms this is a change in the newer agent package where an audio-containing field is now expected to be a structured object rather than a raw string. What’s happening (short) • The event serializer expects an object with an
audio
attribute but is receiving a plain string. Your call
await self.session.say(...)
is still valid syntactically, but the library’s internals now appear to treat the positional string or certain fields differently and produce an event that fails to serialize. Concrete next steps you can try now 1) Quick test — explicitly use the
text=
parameter (you already tried this, which still hit the error). That confirms the issue is deeper in the pipeline (not just positional vs keyword argument). 2) Immediate workaround — force the session to produce a structured reply instead of a raw string. Try calling
session.say
with a dict-like or object-shaped payload that matches the newer expected event shape. If the public API supports
text
and
audio
fields, explicitly pass
audio=None
to ensure the serializer sees an audio attribute, for example:
Copy code
# Try explicitly supplying text and an audio field (audio=None) to avoid implicit conversion
await self.session.say(text=f"Hello, Am I talking to {name}?", audio=None, allow_interruptions=False)
If that API signature is not accepted at runtime, another approach is to construct the event yourself using the agent event model (pseudo-code — adapt to your codebase):
Copy code
from livekit.agents.voice import ClientEvent  # adjust import path if different

event = ClientEvent(type="assistant_speech", text=f"Hello, Am I talking to {name}?", audio=None)
await self._send_client_event(event)  # call whatever internal send helper your session uses
The goal is to ensure the object given to serialization contains an
audio
attribute (even if None) rather than being a raw string. 3) Confirm regression via downgrade • Downgrade to the previously-working version you mentioned: pip install livekit-agents==1.2.13 • If that removes the error, it confirms a breaking change in 1.4.6 and gives you a working baseline while we identify the exact code change. 4) Add a narrow debug at the serialization point • If you can, add logging inside the library call site
client_events._send_client_event
(where
event.model_dump_json()
is called) to print: ◦ type(event) ◦ event.dict or model_dump() ◦ the specific field(s) that should be audio This will show which attribute is a plain string and let us craft a precise patch. How I can help next • If you want, try the quick workaround (explicit
audio=None
or constructing a ClientEvent) and tell me whether it prevents the serializer error. • If the downgrade fixes things, tell me and I’ll: ◦ Recommend pinning to 1.2.13 for now, and ◦ Prepare a minimal reproducible example and suggested patch you can use to open a bug with the maintainers. • If you can paste the debug output from the serializer (type(event) and event.model_dump() or event.dict), I will point exactly which field to change and provide the exact code snippet to fix it. If you’d like to proceed, tell me which option you prefer now: try the explicit
audio=None
call, downgrade to 1.2.13, or add the small debug to capture the event shape — and I’ll guide you step‑by‑step. , with interactive elements
i
Are you sure this is happening with session.say? Because I am able to hear the agnet asking "hello am I taking to ..."
t
Thanks — good question. You're right to point out that audio plays; that detail helps narrow the problem. Here's a clear explanation and the next diagnostic step. Why audio can play even though serialization fails • The TTS/audio playback path and the client-event serialization path are related but distinct. • Your agent's TTS ran and audio was sent to the room (so you heard "Hello…"). That means the TTS and audio output pipeline worked end-to-end for playback. • The error comes from the code that serializes a client event for streaming to clients (the call to
event.model_dump_json()
in
client_events._send_client_event
). That serializer expects a structured event object (with an
audio
attribute) but encountered a plain string somewhere, causing the Pydantic serialization error. • In short: session.say (or something invoked by it) produced audio for playback, but it also triggers creation/emission of a client event object that failed to serialize. The playback can succeed while the secondary client-event serialization fails. How to confirm whether session.say (or a downstream step) is the source 1. Add a focused debug right before the library serializes events (or in your own wrapper before calling
session.say()
), printing the event shape and types: ◦ If you can, patch or temporarily log inside
client_events._send_client_event
at the line calling `event.model_dump_json()`: ▪︎ Log
type(event)
and
event.model_dump()
(or
event.__dict__
) so you can see which attribute is a string. ◦ If you can't modify the library, add logging right before your
session.say(...)
call showing the argument types and values:
Copy code
greeting = f"Hello, Am I talking to {name}?"
     self._session_logger.log_info(type(greeting), repr(greeting))
     await self.session.say(text=greeting, allow_interruptions=False)
1. Try the explicit
audio=None
experiment ◦ Call
session.say(text=..., audio=None, allow_interruptions=False)
to see if supplying an explicit
audio
attribute avoids creating a malformed event. If this prevents the serializer error, it confirms the serializer expects an
audio
attribute that is missing or mis-typed. 1. Short alternative test: downgrade to the working version ◦ You noted 1.2.13 worked. Temporarily installing that version (pip install livekit-agents==1.2.13) and verifying the error disappears will confirm the change is due to the library update. What I can do next • If you paste the output of one of these: ◦ The event dump from inside
_send_client_event
(type and model_dump), or ◦ The logs after trying
audio=None
, or ◦ Whether downgrading to 1.2.13 removes the error— I will pinpoint the exact field that is the wrong type and give a concrete patch you can use (either a change in your code or a small shim to normalize the event before serialization). Would you like me to walk you through adding the small log inside
_send_client_event
, or do you prefer to try
audio=None
first? , with interactive elements
i
i see this agent is throwing this error when I am trying to speak with the agent. Agent is able to deliver the message well. Also I have another agent there i am able to chat with it
t
Thanks — that extra detail helps. You're hearing the agent speak and another agent in the same room accepts input fine, so this is likely a problem in how the failing agent constructs or emits client events (not in the audio playback stack). I’ll help you narrow it down quickly. Quick summary of what’s likely happening • The TTS/audio playback succeeds (so the audio path is fine). • Separately, the code creates a client event to stream to clients; when that event is serialized, a field that should be an object with an
.audio
attribute is a plain string, causing the Pydantic serialization error and preventing downstream input handling. • Because another agent works, this is probably specific to the failing agent’s event construction, plugin, or pipeline output. To narrow root cause — please provide two quick pieces of info 1) Details about the working agent • Which LiveKit packages/version does the working agent use? (Run
pip freeze | grep livekit
in that agent’s environment.) • Does it use different TTS/STT or plugin(s) (e.g., ElevenLabs vs. Silero, Deepgram vs. AssemblyAI)? Name any plugins configured for that agent. 2) A short event dump or log from the failing agent right before serialization • If you can, add a very small log in your environment at/near the serialization call inside
client_events._send_client_event
(line around
event.model_dump_json()
), or log from your wrapper prior to calling
session.say()
. Paste the output here. Specifically, we want: ◦ type(event) ◦ event.model_dump() or event.dict If you can’t edit library code, logging the greeting variable type/value right before
session.say()
is still useful:
Copy code
greeting = f"Hello, Am I talking to {name}?"
self._session_logger.log_info("greeting_type", type(greeting), repr(greeting))
await self.session.say(text=greeting, allow_interruptions=False)
Tests to run now (pick one to try) • Compare plugins/config: If the working agent uses a different TTS/STT plugin, that could produce a different event shape. Tell me which plugin differs. • Try explicit audio field: Call
session.say(text=greeting, audio=None, allow_interruptions=False)
to see if explicitly providing an
audio
attribute avoids the serializer error. • Swap agents’ configs: If possible, run the failing agent with the working agent’s plugin list (or vice versa) to see if the problem follows a plugin. What I’ll do once you share the above • If you provide the event dump (type + model_dump/*dict*), I will point exactly which attribute is the wrong type and give the exact code to normalize it (a small shim or change to your call). • If you provide the working agent’s package/plugin differences, I’ll highlight which component likely changes the event shape and show how to adapt. • If the explicit
audio=None
test changes behavior, I’ll show a safe short-term patch you can apply. Would you like to: • Paste the event dump (best), or • Tell me the working agent’s plugin list and versions, or • Try
audio=None
and paste that log result? I’ll stay with you and provide the exact fix once you paste whichever output you can get. , with interactive elements
i
Untitled
t
Thanks — you’ve given a lot of useful detail. I’ll summarize where we are, what’s most likely happening, and the smallest focused steps to get this fixed or isolated quickly. Short summary • Audio playback works (you hear the agent), but a Pydantic serialization error fires when the agent creates a client event: "'str' object has no attribute 'audio'". • The same room has another agent that accepts input fine, and the failing agent worked on livekit-agents==1.2.13 but fails on 1.4.6. That strongly points to a change in the agent package that altered the expected event shape (some field that previously could be a string now must be an object with an .audio attribute). What I want to confirm next (one of these will pinpoint the problem) • The most useful single thing: a dump of the event object right before it is serialized (inside or before the call to
event.model_dump_json()
in
client_events._send_client_event
). We want: ◦ type(event) ◦ event.model_dump() or event.dict If you cannot modify the library, paste the log output from adding a debug just before your
session.say()
call showing the greeting type/value (you already logged the greeting text — now include type): self._session_logger.log_info("greeting_type", type(greeting), repr(greeting)) Three very small tests you can try now (pick one and tell me the result) 1) Explicit audio attribute (quickest to try) • Change the call to: await self.session.say(text=greeting, audio=None, allow_interruptions=False) • Tell me whether the serialization error still appears. 2) Downgrade to confirm regression • Temporarily reinstall the working agent version: pip install livekit-agents==1.2.13 • If the error disappears, we confirm a breaking change in newer releases. 3) Add narrow debug at serializer • If you can edit site-packages temporarily, add these logs at the top of
client_events._send_client_event
(right before
event.model_dump_json()
): ◦ print(type(event)) ◦ print(event.model_dump()) # or event.dict • Paste that output here. Why each test helps • (1) If
audio=None
fixes it, the serializer expects an
audio
attribute and the library no longer auto-wraps strings. We can add a small shim in your code to always provide an
audio
attribute. • (2) If rollback fixes it, we have a stable workaround (pin to 1.2.13) while we craft a small patch. • (3) Seeing the event shape gives me the exact field that is the wrong type and I can provide the exact code to normalize it. Short-term workaround option • If you need an immediate restore of functionality, pin to the older working version: pip install livekit-agents==1.2.13 This is safe while we identify the exact change and produce a minimal code fix. What I’ll do for you next • If you try (1) or (2), tell me the result and I’ll give the exact code change or the pin command. • If you can paste the event dump (from (3)), I will point to the specific attribute and provide the exact code to convert it into the required structure (a tiny shim you can add to your agent). Would you like to try the
audio=None
call first, or paste the event dump from inside
_send_client_event
? I’ll guide you step‑by‑step. , with interactive elements
i
BUT HERE IT IS CLEAR THAT IT IS HAPPENING FROM FROM chat_context.py right? Traceback (most recent call last): File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/llm/chat_context.py", line 137, in serialize d: dict[str, Any] = {"type": "instructions", "audio": v.audio} ^^^^^^^ AttributeError: 'str' object has no attribute 'audio' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/utils/log.py", line 17, in async_fn_logs return await fn(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/voice/agent_session.py", line 891, in _aclose_impl await activity.aclose() File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/voice/agent_activity.py", line 785, in aclose await self._close_session() File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/voice/agent_activity.py", line 759, in _close_session await self._audio_recognition.aclose() File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/voice/audio_recognition.py", line 210, in aclose await self._end_of_turn_task File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/utils/log.py", line 17, in async_fn_logs return await fn(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/voice/audio_recognition.py", line 599, in _bounce_eou_task .to_dict( ^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/llm/chat_context.py", line 588, in to_dict item.model_dump( File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/pydantic/main.py", line 308, in model_dump return self.__pydantic_serializer__.to_python( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pydantic_core._pydantic_core.PydanticSerializationError: Error calling function `serialize`: AttributeError: 'str' object has no attribute 'audio' 170726.310 ERROR… livekit.agents Error in _run_job_task Traceback (most recent call last): File "/home/rashi-aidetic/Documents/Fabrichq/… line 137, in serialize d: dict[str, Any] = {"type": "instructions", "audio": v.audio} … AttributeError: 'str' object has no attribute 'audio' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/rashi-aidetic/Documents/Fabrichq/… line 17, in async_fn_logs return await fn(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/… line 353, in _run_job_task await session.aclose() File "/home/rashi-aidetic/Documents/Fabrichq/… line 939, in aclose await self._aclose_impl(reason=CloseReason.USE… File "/home/rashi-aidetic/Documents/Fabrichq/… line 17, in async_fn_logs return await fn(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/… line 891, in _aclose_impl await activity.aclose() File "/home/rashi-aidetic/Documents/Fabrichq/… line 785, in aclose await self._close_session() File "/home/rashi-aidetic/Documents/Fabrichq/… line 759, in _close_session await self._audio_recognition.aclose() File "/home/rashi-aidetic/Documents/Fabrichq/… line 210, in aclose await self._end_of_turn_task File "/home/rashi-aidetic/Documents/Fabrichq/… line 17, in async_fn_logs return await fn(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/… line 599, in _bounce_eou_task .to_dict( ^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/… line 588, in to_dict item.model_dump( File "/home/rashi-aidetic/Documents/Fabrichq/… line 308, in model_dump return self.__pydantic_serializer__.to_python( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^… pydantic_core._pydantic_core.PydanticSer… Error calling function `serialize`: AttributeError: 'str' object has no attribute 'audio' {"pid": 130465, "job_id": "AJ_J7m3LGgCtHbW", "room_id": "RM_phUepG6eA5Gr"} Traceback (most recent call last): File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/llm/chat_context.py", line 137, in serialize d: dict[str, Any] = {"type": "instructions", "audio": v.audio} ^^^^^^^ AttributeError: 'str' object has no attribute 'audio' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/utils/log.py", line 17, in async_fn_logs return await fn(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rashi-aidetic/Documents/Fabrichq/automated_call_notifications/venv/lib/python3. 12/site-packages/livekit/agents/ipc/job_proc_lazy_main.py", line 353, in _run_job_task
t
Thanks — this is exactly the kind of trace I needed. You’re right: the error originates in livekit.agents.llm.chat_context.serialize where the code does: {"type": "instructions", "audio": v.audio} and v is a plain string, so v.audio raises AttributeError. That confirms a type-mismatch: the chat context code now expects an Instruction-like object (with an .audio attribute) but your chat context contains a raw string. What this means • The serializer expects entries in the chat context to be message objects (e.g., InstructionMessage or a similar model with
.audio
) but one or more items are plain strings. • That explains why audio plays (TTS worked) but serialization fails when building a structured representation of the chat context for clients/LLM: playback and event serialization are different code paths. • This mismatch surfaced after the package upgrade because newer code enforces that shape when serializing. What I need to confirm • Do you (or any code path you use) append raw strings into the chat context or instructions? Common places to check: ◦ Any call like
session.context.set_instructions(...)
,
session.chat_context.append(...)
, or direct manipulations of chat context where you pass plain strings. ◦ Custom tool outputs or pipeline nodes that return strings and are then added into the chat context without wrapping. Small, targeted fixes you can try now 1) Convert strings to an Instruction-like object before adding them • Wherever you add instructions/messages to the chat context, wrap them in the proper model rather than adding a bare string. Example (adapt to your codebase / imports):
Copy code
from livekit.agents.llm.chat_context import InstructionMessage  # adjust import if different

instr = InstructionMessage(text="Your instruction here", audio=None)
session.chat_context.append(instr)
If
InstructionMessage
has a different constructor in your version, use the fields required (ensure an
audio
attribute exists — can be
None
if no audio). 2) Normalize existing context when serializing (short shim) • If you cannot find the insertion point quickly, add a small normalization before serialization (or before you call the API that triggers serialization). Example pseudo-shim:
Copy code
def normalize_item(v):
    if isinstance(v, str):
        # build minimal object with an audio attr
        return InstructionMessage(text=v, audio=None)
    return v

# before serialization / before session close
session.chat_context = [normalize_item(v) for v in session.chat_context]
3) Quick debugging to find where the string is introduced • Add logging at places you modify the chat context, or temporarily log the chat_context contents just before the error path (e.g., right before AgentSession aclose or where audio recognition bounces EOU). Print types and reprs to find which entry is a str:
Copy code
for i, item in enumerate(session.chat_context):
    logger.info("ctx_item", i=i, type=type(item), repr=repr(item))
Immediate workaround options • If you need fast recovery, roll back to the working package version you mentioned: pip install livekit-agents==1.2.13 That will restore behavior until you convert the string entries to the expected object shape. • Alternatively, apply the small normalization shim above to convert any string entries to Instruction-like objects before serialization. What I can do next • If you paste any code that modifies the chat context (calls to set_instructions, append, or any custom tool output that gets added), I’ll point out exactly where to change it and give the exact code snippet for your version. • If you’d prefer, paste a small dump of session.chat_context (types and reprs) and I’ll mark which items are wrong and show the exact conversion to the expected model. Would you like me to: • Provide the exact import/constructor for
InstructionMessage
for your installed version (I can look it up if you confirm you want that), or • Give the minimal shim to normalize current chat context items into the correct model so you can patch quickly? Tell me which you prefer and paste any small snippet that adds to chat context and I’ll give the exact patch. , with interactive elements