Skip to content

Conversation

Kaian
Copy link

@Kaian Kaian commented Aug 27, 2025

We've been exploring the idea of enabling real attended call transfers from LiveKit rooms, with the first step being support for call holding. When connecting LiveKit Trunks from a PBX, this allows music-on-hold configured in the PBX to be played to the participant.

This PR introduces the initial implementation of call hold and unhold functionality in the LiveKit SIP component. It allows the LiveKit Server to put SIP calls on hold and resume them (unhold), by adding the necessary handling of re-INVITE messages for hold/unhold.

Further PRs will be required in other LiveKit projects to fully implement this functionality across the platform (including livekit, livekit-sdks, livekit-protocol and so on).

We’d love to hear if the team is interested in this functionality and any feedback on the approach to summit additional Pull Requests.

@Kaian Kaian requested a review from a team as a code owner August 27, 2025 09:33
@CLAassistant
Copy link

CLAassistant commented Aug 27, 2025

CLA assistant check
All committers have signed the CLA.

@Kaian Kaian force-pushed the hold-resume-initial-implementation branch from 56ec5df to 29fe1b7 Compare August 27, 2025 09:35
@Kaian Kaian force-pushed the hold-resume-initial-implementation branch from 8a4cd77 to 04d94e4 Compare August 27, 2025 10:21
Copy link

codecov bot commented Aug 27, 2025

Codecov Report

❌ Patch coverage is 10.10101% with 356 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.97%. Comparing base (0460b40) to head (04d94e4).
⚠️ Report is 131 commits behind head on main.

Files with missing lines Patch % Lines
pkg/sip/inbound.go 2.56% 150 Missing and 2 partials ⚠️
pkg/sip/outbound.go 2.56% 152 Missing ⚠️
pkg/sip/service.go 0.00% 50 Missing ⚠️
pkg/service/service.go 88.88% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #443      +/-   ##
==========================================
- Coverage   65.25%   59.97%   -5.29%     
==========================================
  Files          51       32      -19     
  Lines        6588     7105     +517     
==========================================
- Hits         4299     4261      -38     
- Misses       1915     2462     +547     
- Partials      374      382       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@dennwc dennwc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you a lot for contributing the hold/resume functionality! The idea and implementation makes perfect sense. New internal API is the most straightforward way to achieve this.

What I'm wondering about is, would it make sense to hold/unhold automatically when SIP participant looses all audio track subscriptions? In this case, if a person/agent that is in the room suddenly drops, we could indicate a hold for the SIP participant instead of just relaying silence.

This way, there will be no extra API required - existing participant admin API can be used to unsubscribe SIP from existing tracks, move it to another empty room or disconnecting the other peer from the room.

What do you think about this approach?

@Kaian
Copy link
Author

Kaian commented Aug 27, 2025

Hi!

Thanks for the feedback!

We're currently testing this feature in the following scenario: An incoming call is dispatched to a room where an agent can be requested to perform a transfer, first checking whether the destination is available. The agent places the first participant on hold and creates a second participant in the same room by making an outbound call. When this second participant answers, their availability is verified, and based on the response, we remove the second participant from the room and perform a cold transfer from the first participant (or not). This approach has some advantages, such as providing a full transcription or recording of the entire process while only using a single room.

I have little to no experience with LiveKit, so I cannot say what the best approach would be. However, I’m concerned that some providers may not accept in-dialog re-INVITEs the way PBXs do, so making this behavior implicit could cause future issues in other scenarios.

Of course, your opinion is what matters the most, and if you decide to implement it differently, we’ll be more than happy to adapt how our agent works!

Best regards,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants