Give a Pipecat voice agent an Indian phone number
Connect a Pipecat agent to the Indian phone network through LiveKit SIP and a RingTrunk trunk. Inbound calls land in a LiveKit room, the Pipecat pipeline joins with LiveKitTransport, and outbound calls are placed with the LiveKit API.
Updated 6 September 2026
In short: A Pipecat agent gets an Indian phone number through LiveKit SIP on a RingTrunk trunk: calls land in a LiveKit room, and the Pipecat pipeline joins it with the LiveKit transport.
Pipecat does not speak SIP itself. It joins a LiveKit room, and LiveKit's SIP service bridges the phone call into that room. So a Pipecat agent gets an Indian phone number in two layers: LiveKit connected to your RingTrunk trunk, and a Pipecat pipeline that joins the room where the caller lands.
1. Connect LiveKit to RingTrunk
Follow Connect LiveKit Cloud or Connect self-hosted LiveKit. Create the dispatch rule without room_config.agents. Pipecat is not a LiveKit Agents worker, so it is not dispatched that way.
2. Start the pipeline when a call arrives
Subscribe to LiveKit webhooks for room_started or participant_joined, and start a Pipecat pipeline for that room. The transport joins the room with an access token:
from livekit import api
from pipecat.audio.vad.silero import SileroVADAnalyzer
from pipecat.transports.services.livekit import LiveKitParams, LiveKitTransport
def agent_token(room_name: str) -> str:
return (
api.AccessToken()
.with_identity("agent")
.with_grants(api.VideoGrants(room_join=True, room=room_name))
.to_jwt()
)
transport = LiveKitTransport(
url=LIVEKIT_URL,
token=agent_token(room_name),
room_name=room_name,
params=LiveKitParams(
audio_in_enabled=True,
audio_out_enabled=True,
vad_analyzer=SileroVADAnalyzer(),
),
)
# Build the pipeline as usual:
# transport.input() -> STT -> LLM -> TTS -> transport.output()The caller's audio arrives on the transport input; the agent's speech goes back to the caller through the transport output.
3. Place a call from the agent
Create the room, start the pipeline, then add the phone leg with the LiveKit API. The caller ID must be a number attached to your RingTrunk trunk.
from livekit import api
lkapi = api.LiveKitAPI()
await lkapi.sip.create_sip_participant(
api.CreateSIPParticipantRequest(
sip_trunk_id="<YOUR_OUTBOUND_TRUNK_ID>",
sip_call_to="+91XXXXXXXXXX",
sip_number="9XXXXXXXXX",
room_name=room_name,
)
)Destinations are Indian mobile numbers only, 10 digits starting 6, 7, 8 or 9.
Audio on the phone leg
The call leg is G.711 A-law at 8 kHz. LiveKit converts between the phone leg and the room, so the pipeline does not need to know it is on a phone call. Telephony-tuned speech recognition still helps, as it does on any phone audio.
Working example
A runnable version of this page, with a webhook server that starts the bot when a call lands and a script that places calls, is at github.com/Zingaro-Ai/ringtrunk-livekit-example (MIT).
In production
Zingaro AI's phone agents are Pipecat pipelines answering Indian numbers exactly this way, through LiveKit Cloud and a RingTrunk trunk. The setup above is the one they run.