I'm having an issue transferring a call from the m...
# ask-ai
a
I'm having an issue transferring a call from the main pbx number to an internal extension in yeastar PBX a bridge transfer is there a document or reference I can go through, what happens now I invite ext xyz to the same room and I want the AI agent to leave the room as soon as the ext participant has joined but what happens is the call starting all over again as if the the newly joined participant is another ai agent like if it's redialing the main pbx number and not an extension . The exact samme setup works in Grandstream UCM PBX
t
Thanks for reaching out, Basil. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I hear you: you want the AI agent to hand off a call to an internal Yeastar extension (bridge transfer) and leave as soon as that extension joins, but instead the call restarts and the new participant looks like another AI call (similar setup works on Grandstream UCM). I don’t have Yeastar-specific docs here, so I need a few details to diagnose and give actionable steps: 1. How are you adding/inviting the extension into the LiveKit room? ◦ Using the LiveKit SDK in a client? Server-side REST API? SIP gateway that dials the extension? 1. How is the AI agent implemented and removed now? ◦ Do you explicitly call a leave/disconnect API for the AI participant? Or rely on PBX signaling to remove it? 1. What exactly does “bridge transfer” mean in your Yeastar flow? ◦ Blind transfer, attended transfer, or SIP REFER/transfer? Does Yeastar send a SIP REFER to your system or create a new call leg? 1. Do you see any SIP signaling differences between Grandstream and Yeastar? ◦ If you can share SIP messages (INVITE/REFER/200/ACK) or call flow logs (redacted okay) that would help. 1. Versions/config: ◦ Yeastar PBX model and firmware version ◦ LiveKit server version or deployment details 1. Any logs or observable behaviors: ◦ Does LiveKit receive a new incoming call (new SID) when the extension joins, or does it look like a re-INVITE? Any error messages? Common causes and preliminary guidance you can try now • If Yeastar performs the transfer by creating a new call leg (new INVITE) rather than REFER/transfer of the existing leg, LiveKit may treat the new INVITE as a fresh caller — that explains the “call starting all over again.” Grandstream may be doing a REFER/transfer that preserves the call leg. • Ensure your transfer flow uses SIP REFER (or an attended transfer that results in REFER) so the PBX moves the existing call leg to the extension rather than originating a new outbound call to the extension. • If you control the AI participant in LiveKit, call the AI participant’s leave/disconnect immediately when you detect the extension has joined the room (for example, on the server side when you see the extension's participant SID). But first confirm whether the extension's join is actually the same call leg or a new one; if it’s new, removing the AI may drop media unexpectedly. • Compare SIP headers/Call-IDs between the two PBXs. If the Call-ID changes, Yeastar is creating a new leg. If you can share any of the items above (answers to 1–6, SIP call flow or logs, and how you currently remove the AI participant), I’ll give exact next steps and example flows to ensure the AI leaves only after a successful handoff.
a
exactly grandstream works because it supports REFER but yeastar doesn't support REFER so in the rest SDK I do create a new participant which is an INVITE for Yeastart PBX tenants
t
Thanks — that clarifies things: Yeastar doesn’t support REFER so you create a new participant via INVITE and that new INVITE is being treated as a fresh caller, causing the AI to behave like it’s starting a new call. What you CAN do now (options and next steps): • Use server-side participant-handling logic to detect the extension’s successful join and then remove the AI participant. ◦ Wait until the extension participant’s state is fully connected (joined) before calling the API to disconnect the AI. This avoids removing the AI too early and dropping the bridge. ◦ If your REST SDK returns participant SIDs or events, listen for the extension’s joined event and then call the remove/disconnect endpoint for the AI participant. • Correlate call legs at the SIP layer to avoid duplicate behavior. ◦ Compare SIP headers (Call-ID, From/To tags) in the INVITE that creates the extension participant. If Yeastar creates a new Call-ID, treat this as a separate leg and follow the server-side sequence above. ◦ If you can add a custom SIP header or tag on the INVITE you send for the extension (for example
X-Transfer-From: <original-id>
), use that header to identify the handoff and ensure your app only removes the AI after seeing that header or the extension’s connected event. • Implement a short overlap window to ensure media continuity. ◦ When extension joins, keep AI in the room for 1–2 seconds (or until you detect stable RTP flow) and then disconnect the AI. This avoids perceptible interruptions when Yeastar issues a new INVITE. • Use a SIP Re-INVITE or update flow if possible from your side. ◦ If you can modify the INVITE you create to reuse the original identifiers (not always possible), that can simulate a transfer. If not, follow the join-then-remove flow above. If you want, share one of the following and I’ll give a concrete code/sequence example: • The REST SDK call you use to create the extension participant (request body, headers you set). • How you currently detect participants joining (events/logs). • Any SIP headers you can set on the INVITE. Which of those can you share?