sip icon indicating copy to clipboard operation
sip copied to clipboard

Supress/Disable "SIP/2.0 180 Ringing" so client does not hear the dial tone

Open gchapellin opened this issue 4 months ago • 5 comments

I created an AI agent using LiveKit and LiveKit SIP server to make it available in Amazon Connect. I then created an external voice transfer in Amazon Connect to connect to the ai agent. It is working as expected. However, when the transfer occurs, there is a dial tone that sounds that I don't want. It looks like the Livekit SIP server is sending back a "SIP/2.0 180 Ringing". I would like to suppress or disable or bypass that directive so the dial tone is not heard by the caller but I have not been able to figure out. I would love some help. This is my docker file:

services: redis: image: redis volumes: - redis_data:/data ports: - 6379:6379 networks: - livekit-network livekit: image: livekit/livekit-server command: ['--dev', '--redis-host', 'redis:6379', '--keys', 'devkey: secret'] ports: - 7880:7880 - 7881:7881 depends_on: redis: condition: service_started networks: - livekit-network sip: image: livekit/sip ports: - "5060:5060/udp" # SIP port - "5060:5060/tcp" # SIP port (TCP) - "10000-10100:10000-10100/udp" # RTP port range environment: SIP_CONFIG_BODY: | api_key: 'devkey' api_secret: 'secret' ws_url: 'ws://livekit:7880' redis: address: 'redis:6379' sip_port: 5060 rtp_port: 10000-10100 use_external_ip: true listen_ip: '0.0.0.0' logging: level: debug depends_on: redis: condition: service_started livekit: condition: service_started networks: - livekit-network agent: build: . environment: #- ROOM_NAME=my-first-room - LIVEKIT_URL=ws://livekit:7880 - LIVEKIT_API_KEY=devkey - LIVEKIT_API_SECRET=secret depends_on: livekit: condition: service_started networks: - livekit-network

volumes: redis_data:

networks: livekit-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16

And this is my agent code:

import os import asyncio from livekit import agents from livekit.agents import AgentSession, Agent, function_tool, RunContext from livekit.plugins.aws.experimental.realtime import RealtimeModel

class SimpleAgent(Agent): def init(self) -> None: super().init( instructions=""" You are a helpful voice AI assistant. """ )

@function_tool()
async def lookup_weather(
    self,
    context: RunContext,
    location: str,
) -> dict[str, any]:
    """Look up weather information for a given location.
    
    Args:
        location: The location to look up weather information for.
    """

    # This is how we could solve for long queries/processes. However, Nova Sonic does not support this
    # Send a verbal status update to the user after a short delay
    # async def _speak_status_update(delay: float = 0.5):
    #     await asyncio.sleep(delay)
    #     await context.session.generate_reply(instructions=f"""
    #     You are searching fort he weather in \"{location}\" but it is taking a little while.
    #     Update the user on your progress, but be very brief.
    # """)

    # status_update_task = asyncio.create_task(_speak_status_update(0.5))

    # Perform search (function definition omitted for brevity)
    # await asyncio.sleep(2)
    if (location == "Minneapolis"):
        result = {"weather": "sunny", "temperature_f": 70}
    else:
        result = {"weather": "rainy", "temperature_f": 50}
    
    # Cancel status update if search completed before timeout
    # status_update_task.cancel()

    return result

async def entrypoint(ctx: agents.JobContext): session = AgentSession(llm=RealtimeModel()) agent = SimpleAgent()

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

if name == "main": agents.cli.run_app(agents.WorkerOptions(entrypoint_fnc=entrypoint, agent_name="nice-agent"))

gchapellin avatar Sep 25 '25 14:09 gchapellin

Have you found any solution for this?

Leaps-Dev-1 avatar Oct 10 '25 16:10 Leaps-Dev-1

Sort of. I forked the repo and made the following changes: In the config.go file, I added 2 new settings:

SIPSendRinging     *bool               `yaml:"sip_send_ringing"`     // whether to send 180 Ringing responses (default true)
SIPSendProcessing  *bool               `yaml:"sip_send_processing"`  // whether to send 100 Processing responses (default true)

In the inbound.go file, I made changes to the following functions to use the new settings and not send the messages: Processing(), sendRinging() and StartRinging().

It worked. However, there is still a 100 Trying message that I cannot figure out where it is coming from. Testing locally, the changes I made removed the dial tone. Testing from Amazon Connect (which is where I transfer to the livekit agent), I still get the dial tone. I think the client side of Amazon Connect still uses the 100 Trying to trigger the dial tone.

gchapellin avatar Oct 10 '25 19:10 gchapellin

What softphone are you using on amazon connect @gchapellin ? the 180 ringing leads to local ringtone unlike a 183 session progress . Does the softphone have some option to disable the local ringtone? That might be a better option than going off SIP spec

nishadmusthafa avatar Oct 12 '25 08:10 nishadmusthafa

Yes, ideally I don't have to change the SIP server and going off SIP specs. However, I have not found a way to disable that from in Amazon Connect. When the call is in Amazon Connect, I transfer that call through a voice connector (not PSTN) to LiveKit and I have very limited options on configuration.

gchapellin avatar Oct 13 '25 12:10 gchapellin

We could look at adding a config that allows sending back 100/180 right before the 200OK. I can't guarantee how quickly we can get to that though.

nishadmusthafa avatar Oct 13 '25 19:10 nishadmusthafa