Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions fern/calls/assistant-based-warm-transfer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ GPT-Live assistants cannot use assistant-based warm transfer. GPT-Live supports

Before you configure the transfer, prepare:

- A Vapi assistant that handles phone calls
- A Vapi assistant that handles phone calls on a Twilio number, a Vapi number, or a bring-your-own SIP trunk. On other phone providers, the call is transferred without the transfer assistant.
- A destination phone number in E.164 format, for example, `+14155550100`
- A [private Vapi API key](/security-and-privacy/api-keys) for the curl method
- A publicly accessible MP3 or WAV file if you want custom hold or completion audio
Expand All @@ -30,7 +30,7 @@ When the original assistant invokes the transfer call tool:
2. Vapi calls the destination and starts the transfer assistant.
3. The transfer assistant speaks with the operator and uses the previous conversation as context by default.
4. The transfer assistant calls `transferSuccessful` to connect the parties or `transferCancel` to return the customer to the original assistant.
5. If the destination is busy, unreachable, or not human, the fallback plan determines what the customer hears and whether the call ends.
5. With `transferAssistant` configured, a busy or unanswered destination rolls back to the configured fallback. The transfer assistant can also cancel when an operator declines or it reaches voicemail or an automated system. A transfer that doesn't finish within `transferAssistant.maxDurationSeconds` (120 seconds by default) rolls back.

The `transferSuccessful` and `transferCancel` tools are always available to the transfer assistant. You can customize them through the API, but you do not need to add them to a basic configuration.

Expand Down Expand Up @@ -159,7 +159,7 @@ Use these fields to control the transfer assistant and the two call legs. See th
| `transferAssistant.model` | Model and instructions used for the operator conversation | Required when you configure `transferAssistant` |
| `holdAudioUrl` | MP3 or WAV audio played to the customer while on hold | Default hold audio |
| `transferCompleteAudioUrl` | MP3 or WAV audio played to the destination after the introduction | No custom completion audio |
| `fallbackPlan` | Customer message and end-call behavior when the transfer fails | Default fallback behavior when omitted |
| `fallbackPlan` | Customer message and end-call behavior after a failed warm transfer | If omitted, the original assistant says "Could not transfer the call." and continues the conversation |
| `summaryPlan` | Operator summary content and generation timeout | Configure with `enabled`, `messages`, and `timeoutSeconds` |
| `contextEngineeringPlan` | Conversation context provided to the transfer assistant | All previous messages |

Expand All @@ -170,7 +170,7 @@ Use these fields to control the transfer assistant and the two call legs. See th
Keep the transfer assistant's system message focused on the operator conversation. Define when to use each built-in tool:

- Call `transferSuccessful` after a human operator confirms that they will take the call
- Call `transferCancel` for voicemail, a busy signal, no answer, an IVR or automated hold queue, or an operator who declines
- Call `transferCancel` when it hears voicemail, an interactive voice response (IVR) system, an automated hold queue, or an operator declining the call
- Answer questions about the transfer or give a brief customer summary
- Avoid unrelated conversation and complete the decision before `maxDurationSeconds`

Expand All @@ -180,7 +180,13 @@ For example:
Call transferCancel if the destination plays an IVR message, automated queue announcement, or hold message. Call transferSuccessful only after a live operator responds and accepts the call.
```

The transfer assistant receives the previous conversation by default. Set `contextEngineeringPlan.type` to `none` when the operator must not receive that context, or use `lastNMessages` to limit it.
Busy and no-answer call statuses can trigger rollback before the transfer assistant speaks. The transfer assistant receives the previous conversation by default. Set `contextEngineeringPlan.type` to `none` when the operator must not receive that context, or use `lastNMessages` to limit it.

When you configure the transfer through the API, set `fallbackPlan.endCallEnabled`. With `false`, the original assistant says the fallback message and continues the conversation. With `true`, it says the message and ends the call. If omitted, the caller stays on the call with the original assistant.

<Warning>
Keep `transferPlan.transferAssistant` configured when you depend on no-answer fallback or a transfer timeout. In the Dashboard, turning off **Summary generation** can remove that configuration and prevent a no-answer event from starting the fallback. Keep **Summary generation** on or configure `transferAssistant` through the API, then verify the result with a controlled call.
</Warning>

## Verify the warm transfer

Expand All @@ -191,7 +197,7 @@ Place a test call and trigger the transfer. Confirm that:
3. Accepting the call connects the customer and operator.
4. Declining the call or reaching voicemail returns the customer to the original assistant or ends the call according to `fallbackPlan`.

In [**Logs → Calls**](/observability/logs/call-logs), inspect the original call, destination call leg, transcript, and ended reason. To retrieve these details through the API, see the [Get Call API reference](/api-reference/calls/get). An `assistant-forwarded-call` ended reason confirms that the transfer was initiated; it does not confirm that the destination answered.
In [**Logs → Calls**](/observability/logs/call-logs), inspect the original call, any available destination-leg record, transcript, and ended reason. To retrieve call details through the API, see the [Get Call API reference](/api-reference/calls/get). An `assistant-forwarded-call` ended reason alone does not confirm that the destination answered.

<Note>
Assistant-based warm transfers to phone or SIP destinations do not send `transfer-update`, including when the call switches to the transfer assistant and back. A `status-update` event with `status: "forwarding"` signals that the transfer started, not that it succeeded. See [transfer event behavior](/server-url/events#transfer-update) for payloads and subscription requirements.
Expand All @@ -201,16 +207,16 @@ In [**Logs → Calls**](/observability/logs/call-logs), inspect the original cal

| Symptom | Likely cause | Resolution |
| --- | --- | --- |
| The customer is transferred without an operator conversation | The destination uses a blind or non-assistant warm-transfer mode | Set `transferPlan.mode` to `warm-transfer-experimental`. |
| The customer is transferred without an operator conversation | The destination uses a blind or non-assistant warm-transfer mode, the call uses an unsupported phone provider, or a Twilio call is transferring to a SIP address | Set `transferPlan.mode` to `warm-transfer-experimental`, and use a Twilio number, Vapi number, or bring-your-own SIP trunk. On Twilio, use a phone-number destination. |
| The transfer assistant never speaks | `firstMessage` is omitted or `firstMessageMode` waits for the operator | Set `firstMessage` and use `assistant-speaks-first`, or let the operator speak first. |
| The transfer assistant talks but never connects the parties | The prompt does not require `transferSuccessful` | Tell the transfer assistant to call `transferSuccessful` immediately after the operator accepts. |
| Voicemail, an IVR, a hold queue, or a declined transfer connects anyway | The prompt does not define cancellation conditions | Require `transferCancel` for non-human destinations, busy signals, no answer, and declined transfers. |
| Voicemail, an IVR, a hold queue, or a declined transfer connects anyway | The prompt does not define cancellation conditions | Require `transferCancel` for non-human destinations and declined transfers. Busy and no-answer call statuses can trigger rollback before the transfer assistant speaks. |
| The customer hears summary text instead of the fallback message | The transfer produced unexpected `warm-transfer-experimental` behavior | Record the affected call ID, the message the customer heard, whether `summaryPlan` was enabled, and the `endedReason`, then contact support. |
| The customer hears the wrong audio | Hold audio was configured as a tool message | Put customer hold audio in `transferPlan.holdAudioUrl`. Use `transferCompleteAudioUrl` for audio played to the destination after the introduction. |
| The customer cannot continue after a failed transfer | `fallbackPlan.endCallEnabled` is `true` | Set it to `false` so the original assistant remains on the call. |
| The transfer ends during a long operator interaction | A duration or silence timeout is too short | Increase `maxDurationSeconds` or `silenceTimeoutSeconds` within the supported ranges. |

Check the affected call's **Logs** tab in [**Logs → Calls**](/observability/logs/call-logs) for validation and transfer errors. If Vapi initiated the transfer but the destination never rings, inspect the telephony provider's call detail records and follow [Troubleshoot call forwarding drops](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops).
Check the affected call's **Logs** tab in [**Logs → Calls**](/observability/logs/call-logs) for validation and transfer errors. If Vapi initiated the transfer but the destination never rings, inspect the telephony provider's call detail records and follow [Troubleshoot call transfers](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops).

## API reference

Expand All @@ -228,7 +234,7 @@ The [Create Tool API reference](/api-reference/tools/create) documents transfer
<Card title="Dynamic call transfers" icon="fa-light fa-route" href="/calls/call-dynamic-transfers">
Choose a transfer destination at runtime.
</Card>
<Card title="Troubleshoot forwarding drops" icon="fa-light fa-screwdriver-wrench" href="/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops">
<Card title="Troubleshoot call transfers" icon="fa-light fa-screwdriver-wrench" href="/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops">
Diagnose failed or incomplete transfers.
</Card>
</CardGroup>
7 changes: 4 additions & 3 deletions fern/calls/call-ended-reason.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ These indicate the assistant intentionally ended the call — not errors.
- `assistant-ended-call-after-message-spoken` — The assistant ended the call after speaking its final message.
- `assistant-ended-call-with-hangup-task` — The assistant ended the call using a hangup task.
- `assistant-said-end-call-phrase` — The assistant said a phrase configured to trigger call termination.
- `assistant-forwarded-call` — The assistant transferred the call to another number or service.
- `assistant-forwarded-call` — The assistant started a transfer to another number or service. This reason doesn't confirm that the destination answered.
- `assistant-join-timed-out` — The assistant failed to join the call within the expected timeframe.

## Customer actions
Expand Down Expand Up @@ -160,7 +160,7 @@ Common transcriber error patterns:
- `call.in-progress.error-warm-transfer-silence-timeout` — Silence timeout during a warm transfer.
- `call.in-progress.error-warm-transfer-microphone-timeout` — Microphone timeout during a warm transfer.

For step-by-step transfer debugging, see [Debug forwarding drops](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops).
For step-by-step transfer debugging, see [Troubleshoot call transfers](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops).

## Transport and connectivity

Expand Down Expand Up @@ -208,7 +208,8 @@ For SIP trunk setup issues, see [Troubleshoot SIP trunk credential errors](/adva
- `call.ringing.hook-executed-transfer` — A transfer hook executed during ringing ended the call.
- `call.ending.hook-executed-say` — A say hook executed during the ending phase.
- `call.ending.hook-executed-transfer` — A transfer hook executed during the ending phase.
- `call.forwarding.operator-busy` — The operator was busy during call forwarding.
- `call.forwarding.operator-busy` — The destination of a blind transfer was busy, or an assistant-based warm transfer failed and the fallback ended the call. For blind transfers, this reason appears only when transfer outcome detection is enabled.
- `call.forwarding.no-answer` — The destination of a blind transfer didn't answer. This reason appears only when transfer outcome detection is enabled.

## Other reasons

Expand Down
4 changes: 2 additions & 2 deletions fern/calls/troubleshoot-call-errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ If a voice error ends the call, follow [Troubleshoot voice fallback](/voice-fall

For response-class guidance and checks across Vapi, your SIP provider, and your SIP infrastructure, see [Troubleshoot SIP response codes](/advanced/sip/troubleshoot-sip-response-codes).

For a detailed transfer debugging walkthrough, see [Debug forwarding drops](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops).
For a detailed transfer debugging walkthrough, see [Troubleshoot call transfers](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops).

## Call ended normally

Expand All @@ -271,7 +271,7 @@ These are not errors — they indicate the call ended as expected.

- **[Call end reasons](/calls/call-ended-reason):** Complete reference of every `endedReason` code.
- **[Debugging voice agents](/debugging):** General debugging workflow using dashboard tools, logs, Simulations, and Evals.
- **[Debug forwarding drops](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops):** Deep dive into transfer failures.
- **[Troubleshoot call transfers](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops):** Deep dive into transfer failures.
- **[Troubleshoot SIP trunk errors](/advanced/sip/troubleshoot-sip-trunk-credential-errors):** Resolve SIP credential validation failures.
- **[Troubleshoot SIP response codes](/advanced/sip/troubleshoot-sip-response-codes):** Identify where a SIP request failed and what to check next.
- **[How to report issues](/issue-reporting):** Include your `call_id` and account email when contacting support.
Loading
Loading