<@U084APK40NS> {"message": "Task was destroyed but...
# ask-ai
c
@millions-hair-24956 {"message": "Task was destroyed but it is pending!\ntask: <Task pending name='Task-208' coro=<Event.wait() running at /usr/lib/python3.12/asyncio/locks.py:212> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[_wait.<locals>._on_completion() at /usr/lib/python3.12/asyncio/tasks.py:534]>", "level": "ERROR", "name": "asyncio", "pid": 1623068, "job_id": "AJ_Wbau73Vrxijx", "timestamp": "2025-02-25T182122.592129+00:00"} {"message": "Task was destroyed but it is pending!\ntask: <Task pending name='Task-207' coro=<VoicePipelineAgent._play_speech.<locals>._play_nested_speech() running at /home/faiq.khan/voiceai-outboundcalls/venv/lib/python3.12/site-packages/livekit/agents/pipeline/pipeline_agent.py:792> wait_for=<Future pending cb=[Task.task_wakeup()]>>", "level": "ERROR", "name": "asyncio", "pid": 1623068, "job_id": "AJ_Wbau73Vrxijx", "timestamp": "2025-02-25T182122.592259+00:00"} {"message": "Collected metrics: PipelineTTSMetrics", "level": "INFO", "name": "outbound-caller", "pid": 1623068, "job_id": "AJ_Wbau73Vrxijx", "timestamp": "2025-02-25T182122.591118+00:00"}
g
The error message "Task was destroyed but it is pending!" typically indicates that an asyncio task was cancelled or terminated before it could complete its execution. This can occur if the task is waiting on a future or an event that never gets resolved, leading to the task being left in a pending state when the program exits or when the task is explicitly cancelled. In the context of LiveKit, this issue might be related to the lifecycle management of tasks within the
VoicePipelineAgent
. Specifically, the
_play_speech
method and its nested
_play_nested_speech
coroutine seem to be involved. This could be due to improper handling of task cancellation or a failure to properly await or close tasks and resources. To address this, ensure that all tasks are properly awaited and that any resources or streams are closed when they are no longer needed. Additionally, review the task management logic to ensure that tasks are not left pending when the agent or application shuts down. If the issue persists, consider adding logging to track the state of tasks and identify where they might be getting stuck. Would you like more detailed guidance on how to manage asyncio tasks in this context? Sources: - https://livekit-users.slack.com/archives/C07FY8WHGPM/p1729242384.877639 - https://livekit-users.slack.com/archives/C07FY8WHGPM/p1727958441.050019 πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956 {"message": "_GatheringFuture exception was never retrieved\nfuture: <_GatheringFuture finished exception=CancelledError()>\nTraceback (most recent call last):\n File \"/home/faiq.khan/voiceai-outboundcalls/venv/lib/python3.12/site-packages/livekit/plugins/deepgram/stt.py\", line 500, in recv_task\n msg = await ws.receive()\n ^^^^^^^^^^^^^^^^^^\n File \"/home/faiq.khan/voiceai-outboundcalls/venv/lib/python3.12/site-packages/aiohttp/client_ws.py\", line 334, in receive\n msg = await self._reader.read()\n ^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"aiohttp/_websocket/reader_c.py\", line 112, in read\n File \"aiohttp/_websocket/reader_c.py\", line 109, in aiohttp._websocket.reader_c.WebSocketDataQueue.read\nasyncio.exceptions.CancelledError", "level": "ERROR", "name": "asyncio", "pid": 1642720, "job_id": "AJ_BTobW32Nz58k", "timestamp": "2025-02-25T205708.908945+00:00"}
g
The error message "_GatheringFuture exception was never retrieved" with a
CancelledError
indicates that an asyncio task was cancelled while it was waiting for a WebSocket message. This typically happens when the task is part of a larger operation that was cancelled, such as when shutting down a service or when a timeout occurs. In the context of LiveKit and the Deepgram STT plugin, this error is occurring in the
recv_task
function, which is responsible for receiving messages from a WebSocket connection. The cancellation could be due to several reasons, such as: 1. Timeouts: If the WebSocket connection is idle for too long, it might be closed due to a timeout, leading to task cancellation. 2. Shutdown Procedures: If the application or agent is shutting down, tasks may be cancelled as part of the cleanup process. 3. Error Handling: If an error occurs elsewhere in the application, it might trigger a cancellation of related tasks. To address this, ensure that your application handles task cancellations gracefully. This includes properly closing WebSocket connections and cleaning up resources when a cancellation is detected. Additionally, review any timeout settings to ensure they are appropriate for your use case. Would you like more detailed guidance on handling task cancellations in asyncio? Sources: - https://docs.livekit.io/python/livekit/plugins/deepgram/index.html#livekit.plugins.deepgram.SpeechStream - https://livekit-users.slack.com/archives/C07FY8WHGPM/p1729242384.877639 πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956 @llm.ai_callable() async def warm_transfer_with_fallback(self): """Initiate warm transfer to human agent with 20s timeout and fallback contact collection""" _try_: agent_number = "+1" # Announce transfer using TTS await self.agent.say("Connecting you to a specialist...") # Create SIP participant with DTMF sip_response = await self.api.sip.create_sip_participant( api.CreateSIPParticipantRequest( _room_name_=self.room.name, _sip_trunk_id_=os.getenv("SIP_OUTBOUND_TRUNK_ID"), _sip_call_to_=agent_number, _participant_identity_=f"agent_{agent_number.replace('+', '')}", _participant_name_="Human Agent", _play_dialtone_=True, dtmf="ww0#" # Send DTMF 0# after 1 second wait ) ) if not sip_response: logger.error("Failed to create SIP participant") raise Exception("SIP participant creation failed") logger.info(f"Created SIP participant for transfer: {sip_response}") # Wait for human agent to join human_joined = await asyncio.wait_for( self._wait_for_human_agent(agent_number), timeout=20 ) if human_joined: logger.info("Human agent joined successfully") # Keep AI agent connected until transfer is complete human_agent_id = f"agent_{agent_number.replace('+', '')}" # Wait for DTMF to complete and connection to establish await asyncio.sleep(2) # Verify human agent is still connected and speaking _try_: # Wait up to 10 seconds to verify human agent is active for _ in range(20): # 20 iterations * 0.5s = 10 seconds if human_agent_id not in self.room.remote_participants: raise Exception("Human agent disconnected during transfer") # If we've waited at least 5 seconds and human agent is connected if _ >= 10: # After 5 seconds (10 iterations * 0.5s) logger.info("Transfer successful, disconnecting AI agent") if self.room.local_participant: await self.room.disconnect() return "TRANSFER_COMPLETE" await asyncio.sleep(0.5) except Exception as e: logger.error(f"Error during transfer verification: {e}") raise _else_: raise asyncio.TimeoutError("Human agent did not join in time") except (asyncio.TimeoutError, Exception) as e: logger.error(f"Transfer failed: {str(e)}") await self.agent.say( "I'm sorry, we're having trouble connecting you. " "Please provide your contact details so we can reach you." ) return "TRANSFER_FAILED" async def _wait_for_human_agent(self, _agent_number_: str) -> bool: """Monitor room for human agent connection""" _try_: human_agent_id = f"agent_{agent_number.replace('+', '')}" for _ in range(30): # Check every 0.5s for 15s total if self.room.remote_participants and human_agent_id in self.room.remote_participants: return True await asyncio.sleep(0.5) return False except Exception as e: logger.error(f"Error waiting for human agent: {e}") return False error occur when transfer is done and agent is disconnected just after that
g
The error you're encountering seems to be related to the disconnection of the AI agent immediately after the transfer is completed. This could be due to the way the disconnection is handled in your code. Here are a few suggestions to address this issue: 1. Ensure Proper Disconnection: Make sure that the disconnection logic is executed only after confirming that the transfer is successful and the human agent is actively connected. You can add additional checks to ensure that the human agent is still connected before proceeding with the disconnection of the AI agent. 2. Handle Exceptions Gracefully: In the
try-except
block where you verify the human agent's connection, ensure that any exceptions are logged and handled appropriately. This will help in identifying any issues that occur during the transfer process. 3. Use Event Listeners: Consider using event listeners to monitor the connection status of participants. This can help in making more informed decisions about when to disconnect the AI agent. 4. Review Timeout Settings: Ensure that the timeout settings for waiting for the human agent to join and for verifying the connection are appropriate for your use case. Adjust these settings if necessary to allow sufficient time for the transfer to complete. If you need more detailed guidance or a code review, please let me know. Sources: - LiveKit Slack Discussion on Agent Disconnection πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
More guidance on code review .
@millions-hair-24956 Failed to create SIP participant for human agent: Protocol message CreateSIPParticipantRequest has no "metadata" field. sip_response = await self.api.sip.create_sip_participant( api.CreateSIPParticipantRequest( _room_name_=self.room.name, _sip_trunk_id_=outbound_trunk_id, _sip_call_to_=agent_number, _participant_identity_=f"human_agent_{agent_number}", metadata="Human Agent", _play_dialtone_=True, dtmf="ww0#" # Send DTMF 0# after 1 second wait )
g
The error message "Protocol message CreateSIPParticipantRequest has no 'metadata' field" indicates that the
CreateSIPParticipantRequest
object does not support a
metadata
field. This is likely because the
CreateSIPParticipantRequest
class does not define a
metadata
attribute, as per the LiveKit API specifications. To resolve this issue, you should remove the
_metadata_
field from the
CreateSIPParticipantRequest
instantiation. If you need to pass metadata to the SIP participant, consider using participant attributes or other supported fields. Here's how you can modify your code:
Copy code
sip_response = await self.api.sip.create_sip_participant(
    api.CreateSIPParticipantRequest(
        room_name=self.room.name,
        sip_trunk_id=outbound_trunk_id,
        sip_call_to=agent_number,
        participant_identity=f"human_agent_{agent_number}",
        play_dialtone=True,
        dtmf="ww0#"  # Send DTMF 0# after 1 second wait
    )
)
If you need to include additional information, you might consider using the
participant_identity
or other fields that are supported by the API. For more details, refer to the LiveKit SIP API documentation. Would you like further assistance on how to handle participant metadata or attributes? Sources: - https://livekit-users.slack.com/archives/C07FRP66XGE/p1728238862.704539 - https://livekit-users.slack.com/archives/C07FRP66XGE/p1731472908.645069 πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956 dtmf="ww0#" vs dtmf="0" ?
g
It seems likely that the difference between
dtmf="ww0#"
and
dtmf="0"
in the context of SIP calls is related to the timing and sequence of DTMF tones sent during a call. -
dtmf="ww0#"
: The
w
character is used to introduce a delay in the DTMF sequence. Each
w
typically represents a 0.5-second pause before sending the next digit. Therefore,
ww0#
would wait for 1 second (two `w`s) before sending the
0#
sequence. This can be useful when you need to ensure that the receiving system is ready to process the DTMF tones, such as when navigating automated phone menus or entering PINs. -
dtmf="0"
: This sends the
0
DTMF tone immediately without any delay. It is a straightforward way to send a single DTMF digit. The choice between these two depends on the requirements of the system you are interacting with. If the system needs time to process or if you are navigating through menus, using delays (
w
) might be necessary. Would you like more detailed information on how to implement these in a SIP call? Sources: - https://docs.livekit.io/sip/api/#CreateSIPParticipant - https://docs.livekit.io/python/livekit/rtc/room.html#livekit.rtc.room.RoomOptions Note: I wasn’t able to find highly relevant data sources, but above are a few potentially relevant links. πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956
Copy code
{
  "message": "Task was destroyed but it is pending!",
  "task": "<Task pending name='Task-173' coro=<VoicePipelineAgent._play_speech.<locals>._play_nested_speech() running at .../pipeline_agent.py:792>",
  "level": "ERROR"
}
g
The error message "Task was destroyed but it is pending!" indicates that an asyncio task was cancelled or terminated before it could complete its execution. This typically happens when a task is waiting on a future or an event that never gets resolved, leading to the task being left in a pending state when the program exits or when the task is explicitly cancelled. In the context of LiveKit and the
VoicePipelineAgent
, this issue might be related to the lifecycle management of tasks within the agent, specifically the
_play_speech
method and its nested
_play_nested_speech
coroutine. This could be due to improper handling of task cancellation or a failure to properly await or close tasks and resources. To address this issue, consider the following steps: 1. Ensure Proper Task Management: Make sure that all tasks are properly awaited and that any resources or streams are closed when they are no longer needed. This includes using
await
for asynchronous operations and ensuring that tasks are not left pending when the agent or application shuts down. 2. Handle Cancellations Gracefully: Implement proper exception handling for
CancelledError
to ensure that tasks are cancelled gracefully and resources are cleaned up appropriately. 3. Review Task Lifecycle: Check the logic around task creation and cancellation to ensure that tasks are not being prematurely cancelled or left in a pending state. If you need more detailed guidance on managing asyncio tasks in this context, please let me know. Sources: - https://livekit-users.slack.com/archives/C07FY8WHGPM/p1727958441.050019 πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956 cold transfer implementation
g
To implement a cold transfer in LiveKit, you can use the
TransferSIPParticipant
API. A cold transfer involves transferring a caller to another number or SIP endpoint without a handoff, effectively ending the original session. Here's a brief overview of how to achieve this: 1. Configure SIP Trunks: Ensure your SIP provider trunks are configured to allow call transfers. This is crucial for the transfer to be successful. 2. Use the TransferSIPParticipant API: This API allows you to transfer a SIP participant to another phone number or SIP URI. The
transferTo
parameter can be a valid telephone number or a SIP URI. 3. Example Code:
Copy code
from livekit import SipClient

   async def transfer_participant(participant):
       sip_client = SipClient(process.env.LIVEKIT_URL, process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET)
       transfer_to = "tel:+15105550100"
       await sip_client.transferSipParticipant('open-room', participant.identity, transfer_to)
4. Handle Call Transfer: Ensure that the call transfer is handled correctly by setting the appropriate caller ID and managing the session lifecycle. Would you like more detailed guidance on any specific part of the cold transfer process? Sources: - Transferring calls | LiveKit Docs - LiveKit Slack Discussion on Cold Transfer πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956
g
I'm here to help with questions related to LiveKit. Could you please provide more details or rephrase your question so I can assist you better? πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956 @llm.ai_callable() async def warm_transfer_with_fallback(self): """Initiate warm transfer to human agent with 20s timeout and fallback contact collection""" _try_: agent_number = "+16147051425" # Create speech task and ensure it completes speech_task = asyncio.create_task( self.agent.say("Connecting you to a specialist...") ) _try_: # Create SIP participant while speech is playing sip_response = await self.api.sip.create_sip_participant( api.CreateSIPParticipantRequest( _room_name_=self.room.name, _sip_trunk_id_=outbound_trunk_id, _sip_call_to_=agent_number, _participant_identity_=f"human_agent_{agent_number}", _participant_name_="Human Agent", _play_dialtone_=True, dtmf="0" ) ) if not sip_response: raise Exception("Failed to create SIP participant") logger.info(f"Created SIP participant for human agent: {sip_response.participant_identity}") # Wait for speech to complete before proceeding await speech_task # Wait for human agent with timeout human_joined = False timeout = 20 start_time = time.time() while time.time() - start_time < timeout: for participant in self.room.remote_participants.values(): if participant.identity.startswith("human_agent_"): human_joined = True logger.info(f"Human agent joined: {participant.identity}") break if human_joined: break await asyncio.sleep(1) if not human_joined: logger.info("Human agent did not join within timeout period") await self.agent.say( "I apologize, but our specialists are currently unavailable. " "We have your information and a specialist will contact you " "within the next business day." ) return "TRANSFER_TIMEOUT_COLLECTING_INFO" # Proper cleanup sequence logger.info("Transfer successful, cleaning up before disconnecting AI agent") # Cancel any pending speech tasks first if not speech_task.done(): speech_task.cancel() _try_: await speech_task except asyncio.CancelledError: pass # Close agent and STT forwarder if self.agent: await self.agent.aclose() logger.info("Closed voice pipeline agent") if self.stt_forwarder: await self.stt_forwarder.aclose() logger.info("Closed STT forwarder") # Small delay for cleanup await asyncio.sleep(0.2) # Disconnect from room if self.room.local_participant: await self.room.disconnect() logger.info("Disconnected AI agent from room") return "TRANSFER_COMPLETE" except Exception as e: logger.error(f"Failed to create/connect SIP participant: {e}") # Cancel speech task if still running if not speech_task.done(): speech_task.cancel() await self.agent.say( "I apologize, but our specialists are currently unavailable. " "We have your information and a specialist will contact you " "within the next business day." ) return "TRANSFER_FAILED_FOLLOWUP_SCHEDULED" except Exception as e: logger.error(f"Transfer failed: {str(e)}") # Ensure proper cleanup on error _try_: if self.agent: await self.agent.aclose() if self.room and self.room.local_participant: await self.room.disconnect() except Exception as cleanup_error: logger.error(f"Error during cleanup: {cleanup_error}") await self.agent.say( "I apologize, but there was an issue connecting you to a specialist. " "We have your information and someone will contact you " "within the next business day." ) return f"TRANSFER_FAILED: {str(e)}" Convert this code into cold transfer sip.
g
To convert the provided warm transfer code into a cold transfer using LiveKit's SIP capabilities, you need to use the
TransferSIPParticipant
API. A cold transfer involves transferring the call to another number or SIP endpoint without maintaining the original session. Here's how you can modify the code: 1. Remove the Speech Task: Since a cold transfer does not involve maintaining the session, you don't need to wait for any speech tasks to complete. 2. Use TransferSIPParticipant API: Replace the SIP participant creation with a call to the
TransferSIPParticipant
API. 3. Simplify Cleanup: Since the session ends with the transfer, you can simplify the cleanup process. Here's a modified version of your code for a cold transfer:
Copy code
@llm.ai_callable()
async def cold_transfer(_self_):
    """Initiate cold transfer to human agent"""
    try:
        agent_number = "<tel:+16147051425|+16147051425>"

        # Use TransferSIPParticipant API for cold transfer
        try:
            await self.api.sip.transfer_sip_participant(
                api.TransferSIPParticipantRequest(
                    participant_identity=self.room.local_participant.identity,
                    transfer_to=agent_number
                )
            )
            logger.info(f"Initiated cold transfer to: {agent_number}")

            # Disconnect AI agent from room
            if self.room.local_participant:
                await self.room.disconnect()
                logger.info("Disconnected AI agent from room")

            return "TRANSFER_COMPLETE"

        except Exception as e:
            logger.error(f"Failed to transfer SIP participant: {e}")
            await self.agent.say(
                "I apologize, but there was an issue connecting you to a specialist. "
                "We have your information and someone will contact you "
                "within the next business day."
            )
            return "TRANSFER_FAILED"

    except Exception as e:
        logger.error(f"Transfer failed: {str(e)}")

        # Ensure proper cleanup on error
        try:
            if self.agent:
                await self.agent.aclose()
            if self.room and self.room.local_participant:
                await self.room.disconnect()
        except Exception as cleanup_error:
            logger.error(f"Error during cleanup: {cleanup_error}")

        await self.agent.say(
            "I apologize, but there was an issue connecting you to a specialist. "
            "We have your information and someone will contact you "
            "within the next business day."
        )
        return f"TRANSFER_FAILED: {str(e)}"
This code initiates a cold transfer by using the
TransferSIPParticipant
API and disconnects the AI agent from the room once the transfer is initiated. The cleanup process is simplified since the session ends with the transfer. Would you like more detailed guidance on any specific part of the cold transfer process? Sources: - Transferring calls | LiveKit Docs πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956
g
I'm here to help with questions related to LiveKit. Could you please provide more details or rephrase your question so I can assist you better? πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956 So How this workflow for cold transfer works ?
g
The workflow for a cold transfer using LiveKit involves transferring a call from one participant to another endpoint without maintaining the original session. Here's a step-by-step breakdown of how this process typically works: 1. Initiate Transfer: The process begins by identifying the participant you want to transfer. This is usually done by specifying the participant's identity within the LiveKit room. 2. Use TransferSIPParticipant API: You call the
TransferSIPParticipant
API, providing the necessary details such as the participant's identity and the destination number or SIP URI to which the call should be transferred. This API handles the transfer by sending a SIP REFER request to the SIP provider. 3. Configure SIP Trunks: Ensure that your SIP provider trunks are configured to allow call transfers. This is crucial for the transfer to be successful. You may need to enable call transfer settings in your SIP provider's configuration. 4. End Original Session: Once the transfer is initiated, the original session is terminated. The participant is disconnected from the LiveKit room, and the call is handed over to the new endpoint. 5. Handle Post-Transfer Logic: After the transfer, you can implement any necessary post-transfer logic, such as logging the transfer details or notifying other participants in the room. Here's a simplified example of how you might implement a cold transfer in code:
Copy code
from livekit import SipClient

async def cold_transfer(participant_identity, transfer_to):
    sip_client = SipClient(process.env.LIVEKIT_URL, process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET)
    await sip_client.transferSipParticipant(participant_identity, transfer_to)
This code snippet demonstrates the use of the
TransferSIPParticipant
API to perform a cold transfer. The
transfer_to
parameter can be a valid telephone number or a SIP URI. Would you like more detailed guidance on any specific part of this workflow? Sources: - Transferring calls | LiveKit Docs πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956
g
I'm here to help with questions related to LiveKit. Could you please provide more details or rephrase your question so I can assist you better? πŸ‘ 0 button πŸ‘Ž 0 button πŸ’‘ Hint: Mention @runllm in the thread for followups.
c
@millions-hair-24956 is there any livekit server sdk for python or what ?
@millions-hair-24956
@millions-hair-24956
t
Thanks for reaching out, faiq. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Yes, LiveKit provides a server SDK for Python, which can be installed via pip:
Copy code
pip install livekit-api
This SDK allows you to manage various LiveKit functionalities, including rooms, participants, egress, ingress, SIP, and Agent dispatch. The primary entry point for using the SDK is the LiveKitAPI class. The Python SDK is organized into several sub-modules: β€’
livekit.agents
β€’
livekit.api
(LiveKit Server APIs for Python) β€’
livekit.plugins
β€’
livekit.protocol
β€’
livekit.rtc
(LiveKit RTC SDK) For more detailed information about the server APIs, you can refer to the LiveKit documentation at: LiveKit Server APIs Documentation The source code for the Python SDK is available on GitHub at: LiveKit Python SDKs on GitHub Let me know if you need further assistance! Sources: livekit.api API documentation | livekit API documentation | LiveKit JS Client SDK - v2.8.1
c
@millions-hair-24956 was there a livekit-server-sdk ? ecist kind of package?
t
Yes, LiveKit provides a server SDK, but it is primarily available for Go as the server-sdk-go package. This SDK is designed to help manage server-side functionalities such as room management, participant handling, and more. For Python, LiveKit offers the livekit-api package, which provides server APIs to interact with LiveKit functionalities. You can install it via pip:
Copy code
pip install livekit-api
If you are specifically looking for a Python equivalent of the Go server SDK, the livekit-api package serves a similar purpose. For more details, you can explore the LiveKit GitHub repositories: β€’ LiveKit Server SDK for Go β€’ LiveKit Python SDKs Let me know if you need further clarification!
c
@millions-hair-24956 livekit inbound and outbound trunking
t
LiveKit supports SIP trunking to enable voice communication by bridging your SIP provider and LiveKit. Here’s an overview of inbound and outbound trunking: β€’ Inbound Trunk: β—¦ Configured to accept incoming calls. β—¦ Can be limited to specific IP addresses or phone numbers. β—¦ Created using a JSON configuration file with your purchased phone numbers. β€’ Outbound Trunk: β—¦ Configured for making outgoing calls. Important Notes: β€’ The same SIP provider trunk can be associated with both inbound and outbound trunks in LiveKit. β€’ You only need to create an inbound or outbound trunk once. β€’ Dispatch Rules are associated with specific trunks and control how inbound calls are routed to LiveKit rooms. If you need further assistance with configuring SIP trunks, feel free to ask! Sources: SIP overview | LiveKit Docs | Create and configure SIP trunk | LiveKit Docs
c
@millions-hair-24956 Give me a step by step guide on doing SIP trunking on inbound and outbound on the same number , and from twilio and how would we do it.
t
I couldn't find a complete step-by-step guide for setting up SIP trunking for both inbound and outbound calls on the same number using Twilio with LiveKit. However, I can provide you with a general outline to get started: Step 1: Set Up a Twilio SIP Trunk β€’ Log in to your Twilio account and navigate to the SIP Trunking section. β€’ Create a new SIP trunk and configure the trunk name and other basic settings. β€’ Add your LiveKit server's IP address or domain to the ACL (Access Control List) to allow communication. Step 2: Configure Inbound Trunk β€’ In the Twilio SIP trunk settings, configure the Origination settings to route incoming calls to your LiveKit server. β€’ Provide the LiveKit server's SIP URI or endpoint as the destination for incoming calls. Step 3: Configure Outbound Trunk β€’ In the Twilio SIP trunk settings, configure the Termination settings to allow outgoing calls from your LiveKit server. β€’ Provide the Twilio SIP URI or endpoint as the destination for outgoing calls. Step 4: Link the Same Number β€’ Associate the same phone number with both the inbound and outbound trunks in Twilio. β€’ Ensure that the number is verified and configured correctly in your Twilio account. Step 5: Configure LiveKit β€’ In LiveKit, create a SIP trunk configuration that matches the settings in Twilio. β€’ Use the LiveKit API to manage calls and route them through the configured SIP trunk. If you need more detailed guidance or assistance with specific configurations, feel free to ask!
The error message indicates that the command is being interrupted due to spaces in the path where the Twilio CLI is being executed. Specifically, the path 'C:\Program' suggests that the command is being run from a directory with spaces in its name, such as C:\Program Files. This can cause issues when running commands in the terminal. To resolve this issue, you can try the following steps: 1. Use Quotation Marks: Wrap the entire path to the Twilio CLI executable in double quotes. For example:
Copy code
"C:\Program Files\Twilio CLI\twilio" api trunking v1 trunks origination-urls create \
   --trunk-sid TK1d603cadbad84864c8ef9ec1afb4bb1b \
   --friendly-name "LiveKit SIP URI" \
   --sip-url "sip:125sba70n67.sip.livekit.cloud;transport=tcp" \
   --weight 1 --priority 1 --enabled
2. Change to a Different Directory: Navigate to a directory without spaces in its path before running the command. For example:
Copy code
cd C:\Users\YourUsername
Then run the Twilio command from there. 3. Add Twilio CLI to PATH: Ensure that the Twilio CLI is added to your system's PATH environment variable. This allows you to run the twilio command directly without specifying the full path. 4. Use a Different Terminal: If you are using a terminal like Git Bash or PowerShell, ensure that it supports the syntax you are using. You might also try running the command in Command Prompt (cmd). Let me know if you need further assistance!
c
@millions-hair-24956 2025-03-07 100041,493 - main - ERROR - Error creating dispatch rule: module 'livekit.api' has no attribute 'AgentInfo'
@millions-hair-24956
@millions-hair-24956 { "name": "Default Dispatch Rule", "rule": { "dispatchRulePin": { "roomPrefix": "inbound-", "pinLength": 6, "maxAttempts": 3, "timeout": "30s" } }, "trunk_ids": ["YOUR_INBOUND_TRUNK_ID"] } this type of dispatch rule exists ?
@millions-hair-24956
@millions-hair-24956
@millions-hair-24956
a
@calm-optician-60209 I'm facing the same issue ERROR asyncio - Task was destroyed but it is pending! could you please guide on what you did to resolve this
c
@acoustic-guitar-10279 Hi Harshita, basically it means you forgot to close some deepgram , or any speech plugins . try using and checking if you are closing it before transfering the call or removing the participant. or maybe transcription end is opened by deepgram or any speech plugin and participant left. so it can cause this error.
a
do you have any way we can shutdown the stt connection properly . or do you have proper ways to disconnect the session or delete the session @calm-optician-60209