Agent speaks the transfer announcement but never executes the transfer tool

Hi Retell team,

We run agents (gpt-4.1) that transfer callers via a custom webhook tool getTransferPhone followed by the native transfer tool transferToLiveAgent.

In roughly 1 in 100 transfer attempts, the agent gets the getTransferPhone result and speaks the transfer announcement (“Please hold while I transfer your call…”) but the transfer_call tool never executes. The agent then acts as if the transfer were in progress — keeps telling the caller to stay on the line, asks “are you still there?”, and eventually ends the call without ever transferring.

Example call IDs:

  • call_39cea54de6abd6c798f8f15d564
  • call_3d23201114b154950bbb6e90b37
  • call_c125980616bde10d5a2b4313a1e
  • call_be6109f9140bff06334fa6f78f8

We replayed these exact turns (same prompt, history, and tools as far as we know) directly against gpt-4.1 as tests, and the model calls the transfer tool every single time — so we can’t reproduce this outside Retell. It seems we are not getting the correct llm interaction in order to reproduce the scenario. Since this is 1 in 100 occurance we run the tests many times.

Any guidance on reproducing this deterministically? We’d like to build a regression test we can run before/after any mitigation we do on the prompts.

Thanks!

Hello @pkostadinov

I have escalated your issue to the relevant team. As soon as I receive any updates from them, I will make sure to keep you informed.

Best Regards.

Hello @pkostadinov

It looks like you’re using a two-step transfer flow: first to retrieve the phone number and then to transfer the call. The issue is that the agent cannot call both functions consecutively without a user turn in between.

You can resolve this by prompting the user to confirm the transfer after the first function completes, then proceeding with the transfer function. Alternatively, you can simplify the flow to a single step by retrieving the phone number through the inbound webhook before the call starts.

Best Regards.

Hi, thanks for looking at this — but the diagnosis doesn’t match what we see in the call logs.

The two-step flow works in the overwhelming majority of calls. Over the last 90 days roughly 220,000 calls completed both functions back-to-back, and the failure rate is about 1 in 100. If the agent couldn’t call both functions consecutively without a user turn in between, none of these would have worked. Here are a few successful examples on the same agent as the failing calls, where getTransferPhone is followed directly by transferToLiveAgent with no user turn between them: call_658a7ed1ccd9931e8d1e07051e5, call_4757ff971f4c629604a2b1a873e, call_13022c6a1f9552ae73658995acc.

We also replay the failing turns in our test harness directly against gpt-4.1 — same prompt, same conversation history including the getTransferPhone result, same tools — including the variant where a customer turn lands between the phone retrieval and the transfer. Across thousands of runs the model calls the transfer function every single time with and without customer turn in between. So the model reliably produces the transfer call given this flow; in the rare failing calls something between the model output and the tool execution appears to drop it.

The inbound-webhook suggestion unfortunately doesn’t fit our case: the transfer destination depends on the transfer reason (which department or intent the call resolved to), and that’s only known mid-conversation at the moment of transfer — that’s exactly why the number is retrieved with a function at that point rather than up front.

What would really help: could you check the interaction logs for the failing calls (call_39cea54de6abd6c798f8f15d564, call_3d23201114b154950bbb6e90b37, call_c125980616bde10d5a2b4313a1e, call_be6109f9140bff06334fa6f78f8) at the turn right after the getTransferPhone result? Specifically whether the LLM emitted a transfer_call invocation that was discarded — for example because the caller spoke during the transfer announcement — or never emitted one at all. We’ve noticed the failures correlate with the caller backchanneling (“Okay”, “Yes”) while the agent speaks the announcement. That’s the piece we can’t observe from outside, and it’s what we need to build a reproducible test and then experiment with fixes.

Best Regards.

Hello @pkostadinov

I have escalated your issue to the relevant team.

Best Regard.

Hello @pkostadinov

This hiccup occurs because the LLM sometimes attempts to call the second function but fails internally to generate the response after it. I recommend splitting it into two separate steps: first, inform the user you are checking if someone is available to take the call; then, notify them that you are transferring. For a better solution, use conversation flow to control the steps and call the function deterministically every time.

Best Regards.

Hi, thanks — this is actually the most useful piece of information so far, and I’d like to confirm we’re reading it correctly.

You’re saying the LLM does attempt the transferToLiveAgent call in these cases, and the failure happens internally when generating the response after it. Two questions on that:

First, that attempted invocation is not visible anywhere we can see — not in the transcript, not in transcript_with_tool_calls, and our webhook never receives anything for the turn. If the invocation is attempted and then dropped, could you confirm that’s what your internal logs show for the calls we referenced (e.g. call_3d23201114b154950bbb6e90b37)? And is there any place this failure mode is surfaced to us — call analysis, webhook event, anything — so we can at least detect it when it happens?

Second, and more importantly: why does executing the transfer depend on a response being generated after the function call? From our side, once the model has emitted the transfer_call invocation, we’d expect the transfer to execute regardless of whether a follow-up utterance gets generated — the tool itself already has speak_during_execution with an execution message for exactly that purpose. If a post-invocation generation failure cancels the tool execution, that seems like the actual bug here: the caller ends up announced-but-never-transferred and the agent continues as if the transfer were in progress. Is committing the tool execution before (or independently of) the follow-up generation something you can fix or that we can configure?

On the workarounds: splitting the announcement into two spoken steps doesn’t change anything about the invocation being dropped, so we don’t expect it to help. Regarding conversation flow — does the transition node execute the transfer through a different mechanism than retell-llm function calling, i.e. is it actually immune to this internal failure? If yes, that’s a meaningful argument for migrating; if it rides on the same mechanism, it isn’t.

We’re happy to provide more failing call IDs if it helps — we have around 40 confirmed examples over the last 90 days.

Thanks!

Hello @pkostadinov

Can you share 2-5 call ids to check.

Best Regards.

Sure — here are ten failed-transfer calls across different call scenarios. In every one of them getTransferPhone returns a number, the agent speaks the transfer announcement, and transferToLiveAgent never executes:

  • call_d6b957b2965090a7aafca56f603 — reschedule not possible in system, transfer announced (Aug 10)
  • call_bed051a0a8b9d5f33a7d59661c6 — cancellation requires transfer (Aug 10)
  • call_818d407c61553a0d249ea5b9129 — customer needs same-day/sooner service (Aug 11)
  • call_7a47e118614f3a9e3818ea1cdfc — existing-job question, not a new service request (Aug 10)
  • call_066d1ac41b035fbb03ad29f8992 — appointment not found, transfer to a human (Aug 8)
  • call_1aa2ddf38d371dd95233e6efdd6 — customer explicitly asked for a human (Aug 3)
  • call_0f2e63702cc4f2439620c8c64df — no acceptable appointment slot available (Aug 3)
  • call_e16d69509658e5bd634120aebcb — scheduling cutoff triggered a transfer (Jul 24)
  • call_af098ae9c7d3830ea18c85815bd — transfer after a tool error (Jul 21)
  • call_64bdcd1a6b749711bdcfa2731b7 — caller outside service area (Jun 30)

These span several different agents (including multi-prompt agents after an agent_swap and single/entry agents with no swap) and both customer-requested and system-triggered transfers.

Thanks again for taking the time to help us with this.

Hello @pkostadinov

I have escalated your request to the relevant team. As soon as I receive any updates, I’ll let you know.

Best Regards.