> ## Documentation Index
> Fetch the complete documentation index at: https://hanabiaiinc-agents-response-wait-settings.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Call Transfers

> Let the agent hand a phone call to a human: a cold carrier handoff, or a warm transfer with hold music and a private briefing

When a caller needs a person, the agent can transfer the call. Configure one or more destination numbers and the agent gains a built-in `transfer_call` tool it invokes when the caller asks for a human or the request clearly needs one. With several destinations, the agent picks the one whose name and description best match the conversation, so a single number can act as a switchboard. Transfers apply to phone calls only.

Two modes decide what the handoff feels like:

|                                | Cold                                                                                                       | Warm                                                                                                                                                                |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Handoff**                    | The agent announces the transfer and drops out; the carrier connects the caller to the destination.        | The caller waits on hold while the agent briefs the human on a private call, then the two are connected.                                                            |
| **What the human hears first** | The caller, directly.                                                                                      | The agent's briefing: who is calling and what they need.                                                                                                            |
| **Recording & analysis**       | Stop at the handoff: nothing after it appears in [post-call analysis](/agents/monitor/post-call-analysis). | Recording continues after the human joins, capturing the full call audio; the transcript (and therefore analysis) covers only the agent's segment, up to the merge. |

## Prerequisites

* A phone number bound to your agent, answering inbound calls. See [Inbound calls](/agents/telephony/inbound-calls).
* The number must support transfers. Numbers purchased from the platform inventory (`provider: "twilio"`) do; see [Phone numbers](/agents/telephony/phone-numbers). [Imported SIP numbers](/agents/telephony/byo-sip) support cold transfers when the carrier honors SIP REFER, and warm transfers when a termination is configured.

## Configure destinations

### In the console

On the agent's **Phone** page, under **Inbound calls**, turn on **Call transfer**. Give the destination a name, enter its phone number, describe when the agent should transfer there, and pick the transfer mode. Choosing **Warm** adds a handoff choice (ask the human to accept first, or connect immediately after the briefing). **Add destination** adds another card; with more than one, every destination needs a distinct name. Like every config edit, the change lands in the agent's draft and takes effect on live calls after you [publish](/agents/deploy/versions-publishing).

### Through the API

Transfer destinations live in the `conversation` section of the [agent config](/agents/build/configuration), as `transfer_destinations`. An empty list disables transfers; the list is replaced as a whole on every write.

<CodeGroup>
  ```bash Enable theme={null}
  curl --request PATCH "https://api.fish.audio/v1/agent/agents/$AGENT_ID/config" \
    --header "Authorization: Bearer $FISH_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "conversation": {
        "transfer_destinations": [
          {
            "label": "Support desk",
            "phone_number": "+14155550123",
            "mode": "warm",
            "warm_connect": "confirm"
          }
        ]
      }
    }'
  ```

  ```bash Route by context theme={null}
  curl --request PATCH "https://api.fish.audio/v1/agent/agents/$AGENT_ID/config" \
    --header "Authorization: Bearer $FISH_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "conversation": {
        "transfer_destinations": [
          {
            "label": "Billing",
            "description": "Account information, invoices, payments and refunds",
            "phone_number": "+14155550100",
            "mode": "cold"
          },
          {
            "label": "Tech support",
            "description": "Troubleshooting, outages, anything not working",
            "phone_number": "+14155550200",
            "mode": "warm",
            "warm_connect": "confirm"
          }
        ]
      }
    }'
  ```

  ```bash Disable theme={null}
  curl --request PATCH "https://api.fish.audio/v1/agent/agents/$AGENT_ID/config" \
    --header "Authorization: Bearer $FISH_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{ "conversation": { "transfer_destinations": [] } }'
  ```
</CodeGroup>

| Field                        | Description                                                                                                                                                                                                                                                                                                                                             |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`                       | Destination type; `phone` is the only value today and the default.                                                                                                                                                                                                                                                                                      |
| `label`                      | Name for the destination, shown in the Builder and used by the agent to pick one. At most 64 characters. Required, and unique (case-insensitive), once there is more than one entry.                                                                                                                                                                    |
| `description`                | When to transfer here, in plain language ("Invoices, payments, account balance"). The agent reads it when choosing between destinations. At most 500 characters.                                                                                                                                                                                        |
| `phone_number`               | The destination in E.164 format, for example `+14155550123`.                                                                                                                                                                                                                                                                                            |
| `mode`                       | `cold` (default) or `warm`; see the comparison above.                                                                                                                                                                                                                                                                                                   |
| `warm_connect`               | Warm only: `confirm` (default) waits for the human's go-ahead before connecting; `direct` connects right after the briefing.                                                                                                                                                                                                                            |
| `warm_briefing_instructions` | Warm only: what the agent says to your team member before asking them to take the call, replacing the default introduction. Notes from the conversation are always added after it, and [dynamic variables](/agents/build/dynamic-variables) are filled in per call. At most 1000 characters. See [Customizing the briefing](#customizing-the-briefing). |

Destination numbers must be E.164 and are limited to a set of supported countries. A number outside the list is rejected with `422 Unprocessable Entity` and an error naming the allowed country codes. The transfer card in the console shows the current list. A missing label, or two labels that differ only in case, is rejected the same way. There is no cap on the number of destinations, but every description is part of the agent's tool instructions on every turn, so keep the list to what a receptionist could hold in their head.

## How the agent decides to transfer

Configuring a destination is what enables the built-in `transfer_call` tool: an empty destination list removes it. Unlike the toggled [system tools](/agents/build/system-tools), you won't find it in the `tools` config section; it ships automatically on phone sessions whenever a valid destination exists.

Your system prompt decides when the agent transfers. Only when it says nothing about transfers does the built-in default apply, which is conservative: the agent transfers when the caller asks for a person, or when the request clearly needs one and the agent cannot help further. A switchboard agent should say so plainly, for example "Route the caller to the right team as soon as you know what they need; do not try to answer billing or technical questions yourself."

With several destinations, the tool gains a `destination` argument listing every label, and its instructions carry each destination's description. The agent picks the destination whose description matches what the caller needs based on the conversation so far, asks one short question when the need is unclear, and otherwise takes the closest match. Write descriptions the way you would brief a receptionist: what the team handles, in the caller's words.

<Tip>
  The prompt can loosen the policy as well as tighten it: "Transfer to a human
  whenever the caller mentions a refund" or "Never transfer before collecting
  the caller's name and account number." See [Tools](/agents/build/tools) for
  how the agent chooses between its tools.
</Tip>

## What happens on a cold transfer

The agent says its handoff line and, once that finishes playing, the call is handed to the carrier. By default the line is one short sentence telling the caller they are being transferred; the system prompt can script it ("Say: One moment, connecting you to billing.") or drop it ("Transfer silently, without announcing it."). The caller hears a dial tone while the destination rings; the agent drops out and its session ends at the handoff.

If the handoff is refused (the destination is unreachable, or the number doesn't support transfers), the agent stays on the line, apologizes, and keeps helping. It can attempt the transfer again later.

## What happens on a warm transfer

<Steps>
  <Step title="The caller goes on hold">
    The agent asks the caller to hold for a moment, in the session's language,
    and hold music starts. As with a cold transfer, the system prompt can
    script this line or ask for silence; hold music starts either way.
  </Step>

  <Step title="The platform dials your human agent">
    A separate, private consult call rings the destination for up to 30 seconds.
    It presents the number the caller originally dialed as caller ID, so your
    team sees a number they recognize.
  </Step>

  <Step title="The agent briefs the human">
    The agent greets the human, reads out the caller's number digit by digit
    with a pause between groups when the caller ID is known, and relays short
    third-person notes on who is calling and what they need, generated from
    the conversation so far. The
    caller hears none of this. `warm_briefing_instructions` scripts the
    introduction; see [Customizing the briefing](#customizing-the-briefing).
  </Step>

  <Step title="The calls merge">
    With `warm_connect: "confirm"` the merge waits for the human to agree; with
    `direct` it happens right after the briefing. The hold music stops, the
    human joins the caller, and the agent leaves without another word.
  </Step>
</Steps>

If the human cannot be reached, declines, or the consult call hits voicemail, the caller comes off hold and the agent apologizes and continues helping. It can retry if the caller asks. If the caller hangs up while on hold, the agent briefly tells the human what happened and ends the consult call.

### Customizing the briefing

By default the agent introduces itself, reads out the caller's number, relays the notes, and asks whether the person can take the call. A warm destination's briefing instructions replace that introduction. The notes generated from the conversation and the handoff itself stay as they are: the agent still waits for a yes (or connects right away with `direct`), so the text only has to say what you want relayed and how.

The text is rendered with [dynamic variables](/agents/build/dynamic-variables) when the session starts, so it can carry facts the conversation may not mention. A custom text is spoken as written, so if it should include the caller's number, put it in yourself with `{{system.caller_number_spoken}}`, which arrives pre-grouped for speech (`+1; 4 1 5; 5 5 5; 0 1 2 3`) so the voice reads it digit by digit in any language; see [Reading a number out loud](/agents/build/dynamic-variables#reading-a-number-out-loud).

Two things to keep in mind. The variables are filled in once, when the session is created, so an order number the caller mentions later reaches the colleague only through the notes. And a withheld caller ID renders as an empty string, so write the text to read well without it.

#### In the console

On the destination card, choosing **Warm** shows a **Briefing instructions** field beneath the handoff choice. Leave it empty to keep the default introduction.

#### Through the API

Set `warm_briefing_instructions` on the destination; it is ignored on cold destinations.

<CodeGroup>
  ```bash Custom briefing theme={null}
  curl --request PATCH "https://api.fish.audio/v1/agent/agents/$AGENT_ID/config" \
    --header "Authorization: Bearer $FISH_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "conversation": {
        "transfer_destinations": [
          {
            "label": "Support desk",
            "phone_number": "+14155550123",
            "mode": "warm",
            "warm_connect": "confirm",
            "warm_briefing_instructions": "Say the caller number, {{system.caller_number_spoken}}, then explain in one sentence why they are calling and ask if the colleague can take the call. Skip the number if it is empty."
          }
        ]
      }
    }'
  ```
</CodeGroup>

## Limitations

* **Phone calls only**: web and SDK sessions have no phone leg to hand off, so the `transfer_call` tool never ships for them.
* **Transfer-capable numbers**: the number the caller dialed must be a `twilio`-provider number.
* **Supported countries**: destination numbers are limited to an allowlist of country codes.

## Billing

Time after a transfer is billed separately from agent time, at a cold or warm transfer rate per minute. The agent rate stops when the call is handed over (cold) or when the caller and the person are joined (warm); from that point the call is billed as transfer minutes. Current rates are on the [Pricing](/agents/pricing) page.

## Going further

<CardGroup cols={2}>
  <Card title="Inbound calls" icon="phone-arrow-down-left" href="/agents/telephony/inbound-calls">
    Bind a number and put your agent on the phone.
  </Card>

  <Card title="Phone numbers" icon="hashtag" href="/agents/telephony/phone-numbers">
    Number management, providers, and agent bindings.
  </Card>

  <Card title="System tools" icon="gears" href="/agents/build/system-tools">
    The other built-in capabilities, like hanging up.
  </Card>

  <Card title="Conversation history" icon="clock-rotate-left" href="/agents/monitor/conversation-history">
    Review transcripts and recordings of transferred calls.
  </Card>
</CardGroup>
