Could we play background music while our agent is ...
# ask-ai
n
Could we play background music while our agent is on hold?
t
Thanks for reaching out, Mubbashir. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
I'm happy to share that LiveKit does support playing background music while an agent is on hold using the
BackgroundAudioPlayer
class in the LiveKit Agents SDK for Python. This feature lets you play custom audio files, like hold music, whenever you need. Here’s a simple way to set this up: • First, disable the customer's audio input and output. • Then, use the
BackgroundAudioPlayer
to play your chosen background audio file on a loop. For example:
Copy code
def start_hold(self):
    self.customer_session.input.set_audio_enabled(False)
    self.customer_session.output.set_audio_enabled(False)
    self.hold_audio_handle = self.background_audio.play(
        AudioConfig("hold_music.mp3", volume=0.8),
        loop=True,
    )
Once the hold is over, you can easily stop the music using the
PlayHandle
that the
play
method gives you. Just a quick note: this handy feature is currently available only in the Python SDK. If you have any questions or need help with this, please don’t hesitate to reach out—I’m here to help! Sources: examples/drive-thru/drivethru_agent.py | Agent speech and audio | LiveKit Docs
n
import logging import asyncio import random import string from datetime import datetime from livekit.agents import Agent, function_tool, get_job_context from livekit import api, rtc from lib.db import get_collection from bson import ObjectId logger = logging.getLogger("helpful_assistant") logger.setLevel(logging.INFO) class HelpfulAssistant(Agent): def __init__(self, instructions: str = "You are a helpful assistant.") -> None: super().__init__(instructions=instructions) self._state = { "record_id": None, "info_saved": False, "promotion_done": False, "auth_generated": False } self.collection = get_collection("crm") # ---------- Utility Methods ---------- async def _get_record(self, record_id: str): return self.collection.find_one({"_id": ObjectId(record_id)}) async def _update_record(self, record_id: str, data: dict): return self.collection.update_one({"_id": ObjectId(record_id)}, {"$set": data}) def _clean_phone(self, phone: str) -> str: return ''.join(filter(str.isdigit, phone)) # ---------- Agent Functions ---------- @function_tool() async def end_call(self): """Gracefully end the call and close the room.""" logger.info("Ending call...") try: job_ctx = get_job_context() await job_ctx.api.room.delete_room(api.DeleteRoomRequest(room=job_ctx.room.name)) except Exception as e: logger.error(f"Error ending call: {e}") @function_tool() async def save_initial_customer_info(self, name: str, zip_code: str = "") -> str: """Store basic customer info when the conversation starts.""" caller_phone = await self._extract_caller_phone() if not caller_phone: logger.warning("Could not extract caller phone from SIP metadata, using dummy phone") caller_phone = "0000000000" # Generate serial number serial_number = self.collection.count_documents({}) + 1 crm_data = { "name": name, "phone": caller_phone, "email": "test@gmail.com", "serial_number": serial_number, "zip_code": zip_code, "created_at": datetime.utcnow(), "partial_record": True, "actual_bill": None } try: result = self.collection.insert_one(crm_data) self._state.update({"record_id": str(result.inserted_id), "info_saved": True}) return str(result.inserted_id) except Exception as e: logger.error(f"Error saving info: {e}") return f"Error: {str(e)}" async def _extract_caller_phone(self): """Try to extract phone from participants or room name.""" try: job_ctx = get_job_context() for p in job_ctx.room.remote_participants.values(): if hasattr(p, 'kind') and p.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP: # Use the correct attribute for phone number if hasattr(p, 'attributes') and 'sip.phoneNumber' in p.attributes: return p.attributes['sip.phoneNumber'] # Fallback to identity if it looks like a phone number if p.identity.startswith("+"): return p.identity # Existing room name fallback if "_" in job_ctx.room.name: parts = job_ctx.room.name.split("_", 1) if len(parts) > 1 and parts[1].startswith("+"): return parts[1] except Exception as e: logger.warning(f"Phone extraction failed: {e}") return None @function_tool() async def complete_promotion_record(self, record_id: str, bill_amount: float, billing_department_phone: str, months: int = 6) -> str: """Finalize promotion data for the customer record.""" record = await self._get_record(record_id) if not record: return "Error: Customer record not found" update = { "bill_amount": bill_amount, "months": months, "billing_department_phone": billing_department_phone, "card_numbers": [], "paid_flag": False, "sales_flag": True, "partial_record": False, "updated_at": datetime.utcnow(), } result = await self._update_record(record_id, update) if result.modified_count: self._state["promotion_done"] = True return "Promotion record completed successfully" return "Error: Failed to update promotion record" @function_tool() async def generate_auth_code(self, record_id: str) -> str: """Generate and save a random 5-digit authorization code.""" if not self._state["info_saved"]: return "Please provide your name and phone number first." auth_code = ''.join(random.choices(string.digits, k=5)) try: result = await self._update_record(record_id, { "auth_code": auth_code, "auth_code_generated_at": datetime.utcnow() }) if result.modified_count: self._state["auth_generated"] = True except Exception as e: logger.error(f"Auth code save failed: {e}") return auth_code @function_tool() async def save_payment_time(self, record_id: str, payment_time: str) -> str: """Save customer payment time to CRM record.""" record = await self._get_record(record_id) if not record: return "Error: Customer record not found" result = await self._update_record(record_id, { "payment_time": payment_time, "payment_time_saved_at": datetime.utcnow() }) return f"Payment time '{payment_time}' saved." if result.modified_count else "Error: Could not save payment time" @function_tool() async def wait_for_actual_bill(self, record_id: str) -> str: """ Wait until the actual bill amount is added in MongoDB, then return it. If the bill is missing, the agent will keep retrying silently until it exists. """ while True: try: record = await self._get_record(record_id) if record and record.get("actual_bill") is not None: bill = record["actual_bill"] return str(bill) except Exception as e: logger.error(f"Error checking actual bill: {e}") return "Error while checking bill" # Sleep to avoid hammering DB / sockets await asyncio.sleep(5) My helpful assistant code it is i want baground audio while my agent is fetching wait_for_actual_bill()
t
To help make the waiting time more pleasant while your agent fetches the actual bill in the
wait_for_actual_bill
method, you can easily add background audio using the
BackgroundAudioPlayer
class from the LiveKit Agents SDK for Python. Let me walk you through how to update your code: 1. First, initialize the
BackgroundAudioPlayer
inside your
HelpfulAssistant
class like this:
Copy code
from livekit.agents import BackgroundAudioPlayer, AudioConfig

class HelpfulAssistant(Agent):
    def __init__(self, instructions: str = "You are a helpful assistant.") -> None:
        super().__init__(instructions=instructions)
        self.background_audio = BackgroundAudioPlayer()
2. Then, update the
wait_for_actual_bill
method so it plays some background audio while waiting:
Copy code
@function_tool()
    async def wait_for_actual_bill(self, record_id: str) -> str:
        """
        Wait until the actual bill amount is added in MongoDB, then return it.
        If the bill is missing, the agent will keep retrying silently until it exists.
        """
        # Start playing background audio
        audio_handle = self.background_audio.play(
            AudioConfig("hold_music.mp3", volume=0.8),
            loop=True
        )

        try:
            while True:
                record = await self._get_record(record_id)
                if record and record.get("actual_bill") is not None:
                    bill = record["actual_bill"]
                    return str(bill)

                # Sleep to avoid hammering DB / sockets
                await asyncio.sleep(5)
        finally:
            # Stop the background audio when done
            audio_handle.stop()
This way, your agent will play some soothing background music on a loop while it waits for the bill to be ready, and it will stop automatically once everything is done. If you have any questions or need more help with this, just let me know—I’m here to assist!
n
Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\cli\_run.py", line 79, in _worker_run await worker.run() File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\worker.py", line 403, in run await self._inference_executor.initialize() File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\ipc\supervised_proc.py", line 169, in initialize init_res = await asyncio.wait_for( ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\asyncio\tasks.py", line 502, in wait_for raise exceptions.TimeoutError() from exc TimeoutError
t
I'm sorry to hear you're encountering a
TimeoutError
during LiveKit agent initialization. This can happen for a few reasons, like timeout settings being a bit too short, resource limitations, or network hiccups. Let's walk through some steps that might help resolve this together: 1. Increase Timeout Settings: Try adjusting the
initialize_process_timeout
parameter in the
WorkerOptions
class. For example:
worker_options = WorkerOptions(\n    entrypoint_fnc=your_entrypoint,\n    initialize_process_timeout=30.0  # Increase timeout to 30 seconds\n)
2. Pre-load Assets: It can really help to download models and assets during the image build process using the
download-files
command. This reduces the time needed during initialization. 3. Use Adequate Compute Resources: For smoother performance, try to avoid burstable instance types like t3 or t4 in production. Instead, opting for consistent performance instances such as m5, c5, or c6i can make a difference. 4. Check Network and Configuration: Double-check that your network connection is stable and that all necessary environment variables, like API keys, are properly set. I hope these suggestions help you move forward! Please feel free to reach out if you have any more questions or need additional support—I’m here to help. Sources: Builds and Dockerfiles | LiveKit Docs | Builds and Dockerfiles | LiveKit Docs | Troubleshooting Latency and Timeout Errors with Turn Detection on AWS | Voice Assistants | livekit/livekit_composite | DeepWiki | Infrastructure & Deployment | livekit/livekit_composite | DeepWiki
n
File "C:\Users\HP\AiCallAgentBackend\classes\helpful_assistant.py", line 159, in wait_for_actual_bill audio_handle = self.background_audio.play( ^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'HelpfulAssistant' object has no attribute 'background_audio' 2025-09-12 174338,093 - DEBUG livekit.agents - tools execution completed {"speech_id": "speech_17d361195825"}
t
It looks like the error is happening because the
HelpfulAssistant
class doesn’t have the
background_audio
attribute set up yet. No worries—we can fix this together by making sure the
BackgroundAudioPlayer
is properly initialized inside the constructor of your
HelpfulAssistant
class. Here’s a simple way to do that:
Copy code
from livekit.agents import BackgroundAudioPlayer\n\nclass HelpfulAssistant(Agent):\n    def __init__(self, instructions: str = \"You are a helpful assistant.\") -> None:\n        super().__init__(instructions=instructions)\n        self.background_audio = BackgroundAudioPlayer()  # Initialize BackgroundAudioPlayer
Just add this initialization to your class constructor, and you’ll have
self.background_audio
ready to use in your methods. If you run into any more questions or need a hand with anything else, feel free to reach out—I’m here to help!
n
audio_handle = self.background_audio.play( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\voice\background_audio.py", line 197, in play raise RuntimeError("BackgroundAudio is not started") RuntimeError: BackgroundAudio is not started 2025-09-12 175203,315 - DEBUG livekit.agents - tools execution completed {"speech_id": "speech_9af92b7093a2"}
t
Hi there! The error "BackgroundAudio is not started" happens because the
BackgroundAudioPlayer
needs to be started before you call the
play
method. To fix this, just make sure you call
await self.background_audio.start()
before using
play
. It’s a simple step that makes everything run smoothly! Here’s a little guide to help you out:
Copy code
from livekit.agents import BackgroundAudioPlayer\n\nclass HelpfulAssistant(Agent):\n    def __init__(self, instructions: str = \"You are a helpful assistant.\") -> None:\n        super().__init__(instructions=instructions)\n        self.background_audio = BackgroundAudioPlayer()\n\n    async def start_audio(self, room, session):\n        # Start the BackgroundAudioPlayer\n        await self.background_audio.start(room=room, agent_session=session)
Before you call
play
, just follow these steps: 1. Connect to the room. 2. Start the agent session (if you have one). 3. Call
await self.background_audio.start(room=ctx.room, agent_session=session)
. Once that’s done, you’re all set to use
play
to emit audio without any worries. If anything’s still unclear or you want to chat more about it, just let me know—I’m here to help! Sources: examples/voice_agents/background_audio.py | Agent speech and audio | LiveKit Docs | Agent speech and audio | LiveKit Docs
n
@function_tool() async def wait_for_actual_bill(self, record_id: str) -> str: """ Wait until the actual bill amount is added in MongoDB, then return it. If the bill is missing, the agent will keep retrying silently until it exists. """ audio_handle = self.background_audio.play( AudioConfig("hold_music.mp3", volume=0.8), loop=True ) while True: try: record = await self._get_record(record_id) if record and record.get("actual_bill") is not None: bill = record["actual_bill"] return str(bill) except Exception as e: logger.error(f"Error checking actual bill: {e}") return "Error while checking bill" # Sleep to avoid hammering DB / sockets await asyncio.sleep(5) checkthis and make corrections
t
Thank you for sharing your implementation! I noticed a couple of important points that can help your
wait_for_actual_bill
method work more smoothly. First, it’s essential to start the
BackgroundAudioPlayer
before calling
play
. Also, to make sure the background audio stops properly when the method finishes or exits, we should call
audio_handle.stop()
. Here’s an updated version that takes care of these details:
Copy code
@function_tool()\nasync def wait_for_actual_bill(self, record_id: str) -> str:\n    \"\"\"\n    Wait until the actual bill amount is added in MongoDB, then return it.\n    If the bill is missing, the agent will keep retrying silently until it exists.\n    \"\"\"\n    # Ensure BackgroundAudioPlayer is started\n    await self.background_audio.start(room=ctx.room, agent_session=session)\n\n    # Start playing background audio\n    audio_handle = self.background_audio.play(\n        AudioConfig(\"hold_music.mp3\", volume=0.8),\n        loop=True\n    )\n\n    try:\n        while True:\n            record = await self._get_record(record_id)\n            if record and record.get(\"actual_bill\") is not None:\n                bill = record[\"actual_bill\"]\n                return str(bill)\n\n            # Sleep to avoid hammering DB / sockets\n            await asyncio.sleep(5)\n    finally:\n        # Stop the background audio when done\n        audio_handle.stop()
Here are the key changes I made: • Added
await self.background_audio.start(room=ctx.room, agent_session=session)
to make sure the audio player is properly started. • Used a
try...finally
block around the loop so that
audio_handle.stop()
is always called when the method exits, keeping things tidy. If anything is unclear or you’d like me to walk through any part in more detail, please don’t hesitate to ask. I’m here to help!
n
2025-09-12 180654,966 - ERROR livekit.agents - exception occurred while executing tool {"function": "wait_for_actual_bill", "speech_id": "speech_a0ca77620cb4"} Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\voice\generation.py", line 517, in _traceable_fnc_tool val = await function_callable() ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AiCallAgentBackend\classes\helpful_assistant.py", line 161, in wait_for_actual_bill if ctx and session: ^^^ NameError: name 'ctx' is not defined 2025-09-12 180654,976 - DEBUG livekit.agents - tools execution completed {"speech_id": "speech_a0ca77620cb4"}
t
It looks like the error is happening because the variables
ctx
and
session
aren’t defined in your
wait_for_actual_bill
method. These are important because they’re needed to start the
BackgroundAudioPlayer
. To fix this, you can pass them as arguments to the method or get them from the job context. Here’s an updated version of your method that should help:
Copy code
@function_tool()\nasync def wait_for_actual_bill(self, record_id: str, ctx, session) -> str:\n    \"\"\"\n    Wait until the actual bill amount is added in MongoDB, then return it.\n    If the bill is missing, the agent will keep retrying silently until it exists.\n    \"\"\"\n    # Ensure BackgroundAudioPlayer is started\n    await self.background_audio.start(room=ctx.room, agent_session=session)\n\n    # Start playing background audio\n    audio_handle = self.background_audio.play(\n        AudioConfig(\"hold_music.mp3\", volume=0.8),\n        loop=True\n    )\n\n    try:\n        while True:\n            record = await self._get_record(record_id)\n            if record and record.get(\"actual_bill\") is not None:\n                bill = record[\"actual_bill\"]\n                return str(bill)\n\n            # Sleep to avoid hammering DB / sockets\n            await asyncio.sleep(5)\n    finally:\n        # Stop the background audio when done\n        audio_handle.stop()
Here are the key updates: • Added
ctx
and
session
as parameters to the method. • Make sure to pass these variables when you call the method. If anything is unclear or you’d like me to walk you through it step-by-step, just let me know—I’m here to help!
n
@function_tool() async def wait_for_actual_bill(self, record_id: str) -> str: """ Wait until the actual bill amount is added in MongoDB, then return it. If the bill is missing, the agent will keep retrying silently until it exists. """ while True: try: record = await self._get_record(record_id) if record and record.get("actual_bill") is not None: return str(record["actual_bill"]) except Exception as e: logger.error(f"Error checking actual bill: {e}") return "Error while checking bill" # Sleep to avoid hammering DB / sockets await asyncio.sleep(5) I want when my agent is running this tool user mic should be disabled. What happend when agent is waiting for actual payment and user say hello hello hello Agent will say the bill amount 4 times so i want that user input should not be there during thid period
t
To help make sure the user's microphone is disabled while the agent is running the
wait_for_actual_bill
tool, you can simply disable the user's audio input right at the start of the method and then re-enable it once everything is done. This way, the user won’t accidentally send any input during this waiting period. Here’s the updated method for you to try out:
Copy code
@function_tool()\nasync def wait_for_actual_bill(self, record_id: str) -> str:\n    \"\"\"\n    Wait until the actual bill amount is added in MongoDB, then return it.\n    If the bill is missing, the agent will keep retrying silently until it exists.\n    \"\"\"\n    # Disable user microphone\n    self.customer_session.input.set_audio_enabled(False)\n\n    try:\n        while True:\n            try:\n                record = await self._get_record(record_id)\n                if record and record.get("actual_bill") is not None:\n                    return str(record["actual_bill"])\n            except Exception as e:\n                logger.error(f"Error checking actual bill: {e}")\n                return "Error while checking bill"\n\n            # Sleep to avoid hammering DB / sockets\n            await asyncio.sleep(5)\n    finally:\n        # Re-enable user microphone\n        self.customer_session.input.set_audio_enabled(True)
Here’s what’s new: • We disable the user's microphone right at the start with
self.customer_session.input.set_audio_enabled(False)
. • Then, in the
finally
block, we make sure to turn it back on, so the user’s microphone is restored even if something unexpected happens. This approach helps keep things smooth by preventing any input while the agent waits for the actual bill. If you have any questions or need a hand with anything else, just let me know—I’m here to help!
n
2025-09-12 190745,762 - ERROR livekit.agents - exception occurred while executing tool {"function": "wait_for_actual_bill", "speech_id": "speech_768a745a12de"} Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\voice\generation.py", line 517, in _traceable_fnc_tool val = await function_callable() ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AiCallAgentBackend\classes\helpful_assistant.py", line 167, in wait_for_actual_bill self.customer_session.input.set_audio_enabled(False) ^^^^^^^^^^^^^^^^^^^^^
t
It looks like the error is happening because
self.customer_session.input.set_audio_enabled(False)
might not be properly initialized or accessible in your method. To help fix this, let's make sure the
AgentSession
instance is correctly passed and used within your function. Here’s an updated version that should work better for you:
Copy code
@function_tool()\nasync def wait_for_actual_bill(self, record_id: str, session) -> str:\n    \"\"\"\n    Wait until the actual bill amount is added in MongoDB, then return it.\n    If the bill is missing, the agent will keep retrying silently until it exists.\n    \"\"\"\n    # Disable user microphone\n    session.input.set_audio_enabled(False)\n\n    try:\n        while True:\n            try:\n                record = await self._get_record(record_id)\n                if record and record.get("actual_bill") is not None:\n                    return str(record["actual_bill"])\n            except Exception as e:\n                logger.error(f"Error checking actual bill: {e}")\n                return "Error while checking bill"\n\n            # Sleep to avoid hammering DB / sockets\n            await asyncio.sleep(5)\n    finally:\n        # Re-enable user microphone\n        session.input.set_audio_enabled(True)
Here are the key updates: • We added
session
as a parameter to your method so the
AgentSession
instance is accessible. • Used
session.input.set_audio_enabled(False)
to properly disable the microphone. If anything is unclear or you want me to walk you through this further, just let me know—I’m here to help! Sources: Text and transcriptions | LiveKit Docs | examples/voice_agents/push_to_talk.py
n
text: Eric, can I get your billing department phone number, 2025-09-12 191435,506 - INFO conversation_persistor - Started new conversation with ID: 68c42acb0fd15c67eddd051c 2025-09-12 191435,766 - WARNING livekit.plugins.silero - inference is slower than realtime {"delay": 0.46738310000288763} 2025-09-12 191435,776 - WARNING livekit.agents - failed to generate LLM completion, retrying in 2.0s {"llm": "livekit.plugins.openai.llm.LLM", "attempt": 2} Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\llm.py", line 767, in _run to_fnc_ctx(self._tools, strict=self._strict_tool_schema) File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\utils.py", line 39, in to_fnc_ctx llm.utils.build_strict_openai_schema(fnc) File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\utils.py", line 218, in build_strict_openai_schema model = function_arguments_to_pydantic_model(function_tool) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\utils.py", line 310, in function_arguments_to_pydantic_model type_hint = type_hints[param_name] ~~~~~~~~~~^^^^^^^^^^^^ KeyError: 'session' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\llm.py", line 177, in _main_task return await self._run() ^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\llm.py", line 830, in _run raise APIConnectionError(retryable=retryable) from e livekit.agents._exceptions.APIConnectionError: Connection error. (body=None, retryable=True) 2025-09-12 191437,791 - WARNING livekit.agents - failed to generate LLM completion, retrying in 2.0s {"llm": "livekit.plugins.openai.llm.LLM", "attempt": 3} Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\llm.py", line 767, in _run to_fnc_ctx(self._tools, strict=self._strict_tool_schema) File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\utils.py", line 39, in to_fnc_ctx llm.utils.build_strict_openai_schema(fnc) File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\utils.py", line 218, in build_strict_openai_schema model = function_arguments_to_pydantic_model(function_tool) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\utils.py", line 310, in function_arguments_to_pydantic_model type_hint = type_hints[param_name] ~~~~~~~~~~^^^^^^^^^^^^ KeyError: 'session' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\llm.py", line 177, in _main_task return await self._run() ^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\llm.py", line 830, in _run raise APIConnectionError(retryable=retryable) from e livekit.agents._exceptions.APIConnectionError: Connection error. (body=None, retryable=True) 2025-09-12 191439,799 - ERROR livekit.agents - Error in _llm_inference_task Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\llm.py", line 767, in _run to_fnc_ctx(self._tools, strict=self._strict_tool_schema) File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\utils.py", line 39, in to_fnc_ctx llm.utils.build_strict_openai_schema(fnc) File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\utils.py", line 218, in build_strict_openai_schema model = function_arguments_to_pydantic_model(function_tool) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\utils.py", line 310, in function_arguments_to_pydantic_model type_hint = type_hints[param_name] ~~~~~~~~~~^^^^^^^^^^^^ KeyError: 'session' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\llm.py", line 177, in _main_task return await self._run() ^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\plugins\openai\llm.py", line 830, in _run raise APIConnectionError(retryable=retryable) from e livekit.agents._exceptions.APIConnectionError: Connection error. (body=None, retryable=True) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\utils\log.py", line 16, in async_fn_logs return await fn(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\opentelemetry\util\_decorator.py", line 71, in async_wrapper return await func(*args, **kwargs) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\voice\generation.py", line 124, in _llm_inference_task async for chunk in llm_node: File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\voice\agent.py", line 378, in llm_node async for chunk in stream: File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\llm.py", line 326, in anext raise exc # noqa: B904 ^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\opentelemetry\util\_decorator.py", line 71, in async_wrapper return await func(*args, **kwargs) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\HP\AppData\Local\Programs\Python\Python311\Lib\site-packages\livekit\agents\llm\llm.py", line 189, in _main_task raise APIConnectionError( livekit.agents._exceptions.APIConnectionError: failed to generate LLM completion after 4 attempts (body=None, retryable=True)
t
I don't have the answer you're looking for. You could also try asking your question: • in one of the other Slack channels or • to https://deepwiki.com/livekit/livekit_composite which is trained on all LiveKit source code If you find the answer, please post it here to help others!
n
@function_tool() async def wait_for_actual_bill(self, record_id: str) -> str: """ Wait until the actual bill amount is added in MongoDB, then return it. If the bill is missing, the agent will keep retrying silently until it exists. """ while True: try: record = await self._get_record(record_id) if record and record.get("actual_bill") is not None: bill = record["actual_bill"] return str(bill) except Exception as e: logger.error(f"Error checking actual bill: {e}") return "Error while checking bill" # Sleep to avoid hammering DB / sockets await asyncio.sleep(5) I want during this tool call user audio input should be disabled?