> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowyte.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Warm transfer to a human

> Hand a live caller off to a person — with context, and only under the conditions you choose.

A **warm transfer** moves a live caller from the agent to a real person, after the agent
has gathered who is calling and why. Use it when a request is out of scope, the caller is
frustrated, or a rule says a human must take over. The agent stays in control right up to
the moment it connects the call. All paths are relative to
`https://builder.flowyte.com/api/v1`.

<Note>
  Authenticate with `Authorization: Bearer flowyte_sk_…`. Destination numbers are saved in E.164 (e.g. `+14155550100`); a 10-digit US number is
  normalized on save.
</Note>

There are two pieces, and most agents use both:

* **Handoff config** on the agent — a default destination plus a "transfer by context" table
  that routes described situations to specific numbers.
* **A transfer skill** — a tool the agent calls mid-conversation to move the caller to a fixed
  number, which you can gate with a spoken confirmation.

## What you'll use

| Action                           | Endpoint                    | Scope          |
| -------------------------------- | --------------------------- | -------------- |
| Set default + by-context handoff | `PATCH /agents/{id}`        | `agents:write` |
| Add a transfer skill             | `POST /agents/{id}/skills`  | `skills:write` |
| List an agent's skills           | `GET /agents/{id}/skills`   | `skills:read`  |
| Publish the change               | `POST /agents/{id}/publish` | `agents:write` |

<Steps>
  <Step title="Set the handoff config">
    The agent's `handoffConfig` holds a default `transferDestination` and a `transferRules`
    table. Each rule has a plain-language `when` the agent matches against, plus a `destination`.
    Set `warm: true` so the agent summarizes the caller and the reason before connecting, rather
    than a silent hand-off.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X PATCH https://builder.flowyte.com/api/v1/agents/$AGENT_ID \
        -H "Authorization: Bearer $FLOWYTE_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "handoffConfig": {
            "warm": true,
            "transferDestination": "+14155550100",
            "transferRules": [
              { "label": "Billing", "when": "caller asks about an invoice, charge, or refund", "destination": "+14155550111" },
              { "label": "Spanish line", "when": "caller prefers Spanish", "destination": "+14155550122" }
            ]
          }
        }'
      ```

      ```ts Node theme={null}
      await fetch(`https://builder.flowyte.com/api/v1/agents/${agentId}`, {
        method: "PATCH",
        headers: {
          Authorization: `Bearer ${process.env.FLOWYTE_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          handoffConfig: {
            warm: true,
            transferDestination: "+14155550100",
            transferRules: [
              { label: "Billing", when: "caller asks about an invoice, charge, or refund", destination: "+14155550111" },
            ],
          },
        }),
      });
      ```
    </CodeGroup>

    The default `transferDestination` is used whenever a transfer is needed and no rule matches.
  </Step>

  <Step title="Add a transfer skill for explicit handoffs">
    A `transfer` skill is a tool the agent can call on demand. Its `description` is what the
    agent reads to decide *when* to use it — write it as the condition. Set `requiresConfirmation`
    so the agent confirms before transferring, and `stakes` to tune that gate.

    ```bash theme={null}
    curl -X POST https://builder.flowyte.com/api/v1/agents/$AGENT_ID/skills \
      -H "Authorization: Bearer $FLOWYTE_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Transfer to billing",
        "description": "Transfer the caller to a billing specialist when they ask about an invoice, charge, or refund.",
        "skillType": "transfer",
        "executionConfig": { "destination": "+14155550111" },
        "requiresConfirmation": true,
        "stakes": "medium"
      }'
    ```

    <Tip>
      A data-lookup skill can pass a **dynamic** destination at call time (e.g. route to the rep
      who owns the account), instead of a fixed number — useful for franchises and large rosters.
    </Tip>
  </Step>

  <Step title="Publish">
    Edits change the **draft**. Phone and chat serve the last **published** version, so publish
    to make the transfer behavior live.

    ```bash theme={null}
    curl -X POST https://builder.flowyte.com/api/v1/agents/$AGENT_ID/publish \
      -H "Authorization: Bearer $FLOWYTE_API_KEY"
    ```
  </Step>
</Steps>

## Choosing when a transfer fires

* **By context** — the `when` text on each rule and the `description` on a transfer skill are
  how the agent decides; keep them specific.
* **On silence** — set `callControl.onNoResponseAction` to `transfer` so an unresponsive
  caller is routed to a person instead of being ended.
* **After hours** — by default the agent does *not* transfer to a live person when closed. Set
  `afterHours.allowHumanTransfer` and a `number` to allow it. See [After hours](/solutions/after-hours).

<Warning>
  The call is transferred off-net over the carrier (a blind SIP REFER), with the original caller
  ID passed through. Verify the destination number is one you control and is staffed during the
  hours the rule can fire.
</Warning>

Related: [Skills](/concepts/skills) · [Draft vs published](/get-started/draft-vs-published)
