This example shows how to place an outbound call via LiveKit Telephony. The script creates an agent dispatch, then dials a number through a SIP trunk to connect the caller into the agent's room. This is not an agent itself, but a utility script that triggers an agent and connects a phone call to it.
Prerequisites
- Add a
.envin this directory with your LiveKit credentials:LIVEKIT_URL=your_livekit_urlLIVEKIT_API_KEY=your_api_keyLIVEKIT_API_SECRET=your_api_secretSIP_OUTBOUND_TRUNK_ID=your_sip_trunk_id - Provision a SIP outbound trunk in LiveKit and set
SIP_OUTBOUND_TRUNK_ID - Install dependencies:pip install livekit-api dotenv
Load configuration and logging
Load environment variables and set up logging for call status tracking.
import asyncioimport osimport loggingfrom dotenv import load_dotenvfrom livekit import apiload_dotenv()logger = logging.getLogger("make-call")logger.setLevel(logging.INFO)
Configure room, agent, and trunk
Set the room name, agent dispatch target, and outbound trunk ID pulled from the environment.
room_name = "my-room"agent_name = "test-agent"outbound_trunk_id = os.getenv("SIP_OUTBOUND_TRUNK_ID")
Create the agent dispatch and dial
Use the LiveKit API client to create a dispatch (which starts your agent in the room) and then create a SIP participant to dial the phone number into that room.
async def make_call(phone_number):lkapi = api.LiveKitAPI()dispatch = await lkapi.agent_dispatch.create_dispatch(api.CreateAgentDispatchRequest(agent_name=agent_name, room=room_name, metadata=phone_number))if not outbound_trunk_id or not outbound_trunk_id.startswith("ST_"):logger.error("SIP_OUTBOUND_TRUNK_ID is not set or invalid")returnawait lkapi.sip.create_sip_participant(api.CreateSIPParticipantRequest(room_name=room_name,sip_trunk_id=outbound_trunk_id,sip_call_to=phone_number,participant_identity="phone_user",))await lkapi.aclose()
Run the script with a number
Provide a phone number (with country code) and run the async entrypoint.
async def main():phone_number = "+1231231231"await make_call(phone_number)if __name__ == "__main__":asyncio.run(main())
Run it
python make_call.py
How it works
- An agent dispatch starts the target agent in the specified room.
- A SIP participant is created via the outbound trunk to dial the user's phone number.
- Once connected, the caller and agent are in the same LiveKit room.
- Close the API client after the call is set up.
Full example
import asyncioimport osimport loggingfrom dotenv import load_dotenvfrom livekit import apiload_dotenv()logger = logging.getLogger("make-call")logger.setLevel(logging.INFO)room_name = "my-room"agent_name = "test-agent"outbound_trunk_id = os.getenv("SIP_OUTBOUND_TRUNK_ID")async def make_call(phone_number):"""Create a dispatch and add a SIP participant to call the phone number"""lkapi = api.LiveKitAPI()logger.info(f"Creating dispatch for agent {agent_name} in room {room_name}")dispatch = await lkapi.agent_dispatch.create_dispatch(api.CreateAgentDispatchRequest(agent_name=agent_name, room=room_name, metadata=phone_number))logger.info(f"Created dispatch: {dispatch}")if not outbound_trunk_id or not outbound_trunk_id.startswith("ST_"):logger.error("SIP_OUTBOUND_TRUNK_ID is not set or invalid")returnlogger.info(f"Dialing {phone_number} to room {room_name}")try:sip_participant = await lkapi.sip.create_sip_participant(api.CreateSIPParticipantRequest(room_name=room_name,sip_trunk_id=outbound_trunk_id,sip_call_to=phone_number,participant_identity="phone_user",))logger.info(f"Created SIP participant: {sip_participant}")except Exception as e:logger.error(f"Error creating SIP participant: {e}")await lkapi.aclose()async def main():phone_number = "+1231231231"await make_call(phone_number)if __name__ == "__main__":asyncio.run(main())