I am trying to integrate livekit inbound calls whi...
# ask-ai
p
I am trying to integrate livekit inbound calls while using a custom sip, what are the steps to take?
t
Thanks for reaching out, GODGIFT. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
To integrate LiveKit inbound calls with a custom SIP, follow these steps: 1. Set Up the SIP Service: • Ensure the SIP service is configured with a YAML file containing the required fields such as
api_key
,
api_secret
,
ws_url
, and Redis connection details. • Expose a public IP address for remote SIP peers to connect to. 2. Create an Inbound SIP Trunk: • Use the
CreateSIPTrunk
API or LiveKit CLI to create an inbound trunk. This trunk limits incoming calls to those from your SIP trunking provider. • Example CLI command: Sources: src/setup-livekit.ts | Accepting inbound calls | LiveKit Docs | README.md | SIP inbound trunk | LiveKit Docs
p
How do I connect this to my agent? Provide a sample code
t
Hey there! Let me walk you through connecting LiveKit SIP inbound calls to an agent – it's easier than you might think! 1. Create a Dispatch Rule: • First up, you'll want to set up a dispatch rule to route those incoming calls to your awesome agent. Here's a friendly example JSON to help you out:
Copy code
{
  "rule": {
    "dispatchRuleIndividual": {
      "roomPrefix": "call-"
    }
  },
  "roomConfig": {
    "agents": [
      {
        "agentName": "my-telephony-agent"
      }
    ]
  }
}
• No worries – you can create this rule super easily with the LiveKit CLI:
Copy code
lk sip dispatch create dispatch-rule.json
2. Agent Code for Answering Calls: • When the call comes in, make sure your agent gives a warm welcome! Here's a quick example in Python:
Copy code
await session.generate_reply(
    instructions="Greet the user and offer your assistance."
)
3. TypeScript Setup Code: • If you're more of a TypeScript fan, I've got you covered with a complete setup example:
Copy code
import {SipClient} from 'livekit-server-sdk';

const sipClient = new SipClient(
  LIVEKIT_URL,
  LIVEKIT_API_KEY,
  LIVEKIT_API_SECRET,
);

console.log('Setting up LiveKit SIP inbound trunk and dispatch rule');

// Create inbound trunk
const trunkName = 'inbound-trunk';
const trunks = await sipClient.listSipInboundTrunk();
let trunk = trunks.find(t => t.name === trunkName);

if (!trunk) {
  console.log('Creating LiveKit SIP inbound trunk');
  trunk = await sipClient.createSipInboundTrunk(
    trunkName,
    [TWILIO_PHONE_NUMBER],
    {
      auth_username: TWILIO_SIP_USERNAME,
      auth_password: TWILIO_SIP_PASSWORD,
    },
  );
}

// Create dispatch rule
const dispatchRuleName = 'inbound-dispatch-rule';
const dispatchRules = await sipClient.listSipDispatchRule();
let dispatchRule = dispatchRules.find(r => r.name === dispatchRuleName);

if (!dispatchRule) {
  console.log('Creating LiveKit SIP dispatch rule');
  dispatchRule = await sipClient.createSipDispatchRule(
    {
      type: 'individual',
      roomPrefix: 'call',
    },
    {
      name: dispatchRuleName,
      trunkIds: [trunk.sipTrunkId],
    },
  );
}
4. Running Your Agent: • Ready to get things rolling? Just start your agent with:
Copy code
python agent.py dev
One last pro tip: Make sure your SIP trunking provider is all set to send traffic to your LiveKit SIP instance, and those dispatch rules are ready to route calls to the right LiveKit rooms. You've got this! Sources: Agents telephony integration | LiveKit Docs | README.md | Accepting inbound calls | LiveKit Docs
p
Python please
t
Hey there! Let me walk you through setting up a super cool Python example for connecting LiveKit SIP inbound calls to an agent. It's easier than you might think! 1. Create Your Agent: • Grab the LiveKit CLI and spin up an AI voice agent with just one simple command:
Copy code
lk app create --template voice-pipeline-agent-python
2. Complete Python Agent Code:
Copy code
import asyncio
import logging
import os
from pathlib import Path
from dotenv import load_dotenv
from livekit.agents import JobContext, WorkerOptions, cli
from livekit import rtc
from livekit.agents.voice import Agent, AgentSession
from livekit.plugins import deepgram, openai, silero, elevenlabs

load_dotenv(dotenv_path=Path(__file__).parent / '.env')

logger = logging.getLogger("inbound-agent")
logger.setLevel(<http://logging.INFO|logging.INFO>)

class InboundAgent(Agent):
    def __init__(self, job_context=None) -> None:
        self.job_context = job_context
        super().__init__(
            instructions="""
                You are a helpful AI assistant answering incoming phone calls.
                Greet callers warmly and offer your assistance.
            """,
            stt=deepgram.STT(),
            llm=openai.LLM(model="gpt-4o"),
            tts=elevenlabs.TTS(model="eleven_multilingual_v2"),
            vad=silero.VAD.load()
        )

async def entrypoint(ctx: JobContext):
    session = AgentSession()
    agent = InboundAgent(job_context=ctx)

    await session.start(
        agent=agent,
        room=ctx.room
    )

    # Greet the caller after picking up
    await session.generate_reply(
        instructions="Greet the user and offer your assistance."
    )

    def on_participant_connected_handler(participant: rtc.RemoteParticipant):
        asyncio.create_task(async_on_participant_connected(participant))

    async def async_on_participant_connected(participant: rtc.RemoteParticipant):
        <http://logger.info|logger.info>(f"New participant connected: {participant.identity}")

        # Check if this is a SIP participant
        if participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP:
            <http://logger.info|logger.info>(f"SIP participant connected: {participant.identity}")

            # Log SIP call information
            if participant.attributes:
                call_id = participant.attributes.get('sip.callID', 'Unknown')
                call_status = participant.attributes.get('sip.callStatus', 'Unknown')
                phone_number = participant.attributes.get('sip.phoneNumber', 'Unknown')
                
                <http://logger.info|logger.info>(f"SIP Call ID: {call_id}")
                <http://logger.info|logger.info>(f"SIP Call Status: {call_status}")
                <http://logger.info|logger.info>(f"SIP Phone Number: {phone_number}")

        await agent.session.say(f"Welcome, {participant.name or participant.identity}!")

    ctx.room.on("participant_connected", on_participant_connected_handler)

if __name__ == "__main__":
    cli.run_app(
        WorkerOptions(
            entrypoint_fnc=entrypoint,
            # Give this agent a name for dispatch
            agent_name="inbound-agent",
        ),
    )
3. Environment Setup: • Let's get your environment variables sorted – it's super quick!
Copy code
export LIVEKIT_URL=<your livekit server url>
export LIVEKIT_API_KEY=<your api key>
export LIVEKIT_API_SECRET=<your api secret>
4. SIP Trunk Configuration: • Create a friendly inbound trunk configuration file `inbound-trunk.json`:
Copy code
{
  "trunk": {
    "name": "My inbound trunk",
    "numbers": [
      "+15105550100"
    ]
  }
}
• And create that trunk with just one command:
Copy code
lk sip inbound create inbound-trunk.json
5. Dispatch Rule Setup: • Whip up a dispatch rule file `dispatch-rule.json`:
Copy code
{
  "dispatch_rule": {
    "rule": {
      "dispatchRuleIndividual": {
        "roomPrefix": "call-"
      }
    },
    "roomConfig": {
      "agents": [
        {
          "agentName": "inbound-agent"
        }
      ]
    }
  }
}
• Create the dispatch rule – you're almost there!
Copy code
lk sip dispatch create dispatch-rule.json
6. Running the Agent: • Time to bring your agent to life:
Copy code
python agent.py dev
And just like that, you're all set! Once your agent is up and running, you can dial the configured phone number and start chatting with your awesome AI-powered assistant. How cool is that? 😊 Sources: Integrating with Telephony | LiveKit Docs | Accepting incoming calls | LiveKit Docs | README.md | Agents telephony integration | LiveKit Docs
p
If using twilio, how can I set it to send traffic to livekit SIP
t
Hey there! Let me walk you through setting up Twilio to send traffic to LiveKit SIP. I've got two approaches for you, and I'll break them down in a super friendly way. Approach 1: Elastic SIP Trunking (Our Top Pick!) Step 1: Create a SIP Trunk • Let's kick things off by creating a SIP trunk - it's easier than you might think:
Copy code
twilio api trunking v1 trunks create \
--friendly-name "My test trunk" \
--domain-name "<http://my-test-trunk.pstn.twilio.com|my-test-trunk.pstn.twilio.com>"
Step 2: Configure Origination URL • Now, we'll point your trunk to your LiveKit SIP host:
Copy code
twilio api trunking v1 trunks origination-urls create \
--trunk-sid <twilio_trunk_sid> \
--friendly-name "LiveKit SIP URI" \
--sip-url "sip:<your_sip_host>" \
--weight 1 --priority 1 --enabled
Step 3: Associate Phone Number with Trunk • Time to link your Twilio phone number to the SIP trunk:
Copy code
twilio api trunking v1 trunks phone-numbers create \
--trunk-sid <twilio_trunk_sid> \
--phone-number-sid <twilio_phone_number_sid>
Approach 2: Twilio Programmable Voice Step 1: Set up a TwiML Bin • We'll create a quick TwiML Bin with this handy snippet:
Copy code
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial>
    <Sip username="<sip_trunk_username>" password="<sip_trunk_password>">
      sip:<your_phone_number>@<your_sip_host>
    </Sip>
  </Dial>
</Response>
Step 2: Configure Phone Number • Head over to your Twilio Manage Numbers page, find your phone number, and set the "A call comes in" field to use the TwiML Bin we just created. Required Environment Variables • Don't forget to set these environment variables - they're super important:
Copy code
LIVEKIT_SIP_URI=<your_livekit_sip_uri>
TWILIO_ACCOUNT_SID=<your_twilio_account_sid>
TWILIO_AUTH_TOKEN=<your_twilio_auth_token>
TWILIO_PHONE_NUMBER=<your_twilio_phone_number>
TWILIO_SIP_USERNAME=<your_twilio_sip_username>
TWILIO_SIP_PASSWORD=<your_twilio_sip_password>
Quick pro tip: The Elastic SIP Trunking approach is our recommended route for full SIP functionality. The Programmable Voice method is simpler but has a few more limitations. Got questions? I'm right here to help you out! Sources: Create and configure a Twilio SIP trunk | LiveKit Docs | .env.example | Inbound calls with Twilio Voice | LiveKit Docs
p
Why do I get this error? Call was not authorized by trunk configuration
t
Hey there! 👋 Looks like you're running into a tricky SIP trunk authorization error. No worries – I've got your back and we'll troubleshoot this together! 1. Authentication Failure: • Double-check that your
auth_username
and
auth_password
are matching up perfectly between LiveKit and your SIP provider. It's like making sure your keys fit the right lock! • Take a quick peek at your
allowed_addresses
to make sure all your SIP provider's IP addresses are included. • Watch out for flood protection – if too many calls are coming from the same spot, it might trigger a block. 2. Missing Dispatch Rule: • Make sure you've got a dispatch rule set up for incoming calls. • Confirm that the rule is linked to the right
trunk_ids
. • Do a quick check that the rule covers all the phone numbers you're expecting to receive calls on. 3. SIP Provider Setup: • Verify that your SIP trunk credentials are matching up on both sides – LiveKit and your provider. • Ensure your LiveKit SIP service IP is on your provider's approved list. • Double-check that calls are actually being routed to your LiveKit SIP instance. I know this might seem a bit technical, but we'll get through it together! If you're stuck on any of these steps or need a bit more guidance, just give me a shout. We've got this! 💪 Sources: Accepting inbound calls | LiveKit Docs | test/lktest-sip-outbound/README.md | livekit/livekit_sip.pb.go
p
Where will I set the auth username and password?
t
Hey there! Let's walk through setting up the authentication for your LiveKit SIP trunk configuration together. I'll break it down step by step to make it super easy. For Inbound SIP Trunks: • You'll want to set the
auth_username
and
auth_password
fields in the trunk configuration. Here's a quick example to help you out:
Copy code
{
  "trunk": {
    "name": "My inbound trunk",
    "auth_username": "<sip_trunk_username>",
    "auth_password": "<sip_trunk_password>"
  }
}
• No worries if that looks complicated - you can also use the LiveKit CLI, which is super straightforward:
Copy code
lk sip inbound create --auth-user "username" --auth-pass "password"
• Or if you're more of a code person, here's how you can do it programmatically with the SDK (Node.js example):
Copy code
await sipClient.createSipInboundTrunk(name, numbers, {
  authUsername: "username",
  authPassword: "password"
});
For Outbound SIP Trunks: • Same deal here - just set those
auth_username
and
auth_password
fields. Here's a handy CLI command:
Copy code
lk sip outbound create --auth-user "username" --auth-pass "password"
The key is making sure your credentials match exactly what your SIP provider is expecting. Don't worry if something doesn't look right - I'm here to help! Feel free to reach out if you need any extra guidance or run into any hiccups. Sources: SIP APIs | LiveKit Docs | Inbound calls with Twilio Voice | LiveKit Docs | cmd/lk/sip.go | packages/livekit-server-sdk/src/SipClient.ts | protobufs/livekit_sip.proto