> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.vapi.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vapi.ai/_mcp/server.

# Configure handoff destinations

> Declare handoff destinations by assistant ID or name, offer the model several options, resolve one at runtime by webhook, or hand off to a whole squad.

Every handoff needs a destination. You can name a single assistant, offer the model several to choose from, resolve one at runtime from your own server, or hand the call to an entire squad.

## Basic configuration

### Single destination handoff

#### Using assistant ID

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "assistant",
          "assistantId": "03e11cfe-4528-4243-a43d-6aded66ab7ba",
          "description": "customer wants to speak with technical support",
          "contextEngineeringPlan": {
            "type": "all"
          }
        }
      ]
    }
  ]
}
```

#### Using assistant name (for squad members)

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "assistant",
          "assistantName": "TechnicalSupportAgent",
          "description": "customer needs technical assistance",
          "contextEngineeringPlan": {
            "type": "all"
          }
        }
      ]
    }
  ]
}
```

> **Note**
>
> Each assistant destination also supports **assistantOverrides** to override settings on the destination assistant, and an inline **assistant** property to create a transient assistant without saving it first. See the [API reference](/api-reference/tools/create#request.body.HandoffTool.destinations.HandoffDestinationAssistant) for all available properties.

## Multiple destinations

### Multiple tools pattern (OpenAI recommended)

Best for OpenAI models -- creates separate tool definitions for each destination:

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "assistant",
          "assistantId": "sales-assistant-123",
          "description": "customer wants to learn about pricing or make a purchase",
          "contextEngineeringPlan": {
            "type": "all"
          }
        }
      ]
    },
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "assistant",
          "assistantId": "support-assistant-456",
          "description": "customer needs help with an existing product or service",
          "contextEngineeringPlan": {
            "type": "all"
          }
        }
      ]
    },
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "assistant",
          "assistantId": "billing-assistant-789",
          "description": "customer has questions about invoices, payments, or refunds",
          "contextEngineeringPlan": {
            "type": "lastNMessages",
            "maxMessages": 5
          }
        }
      ]
    }
  ]
}
```

### Single tool pattern (Anthropic recommended)

Best for Anthropic models -- single tool with multiple destination options:

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "assistant",
          "assistantId": "03e11cfe-4528-4243-a43d-6aded66ab7ba",
          "description": "customer wants to learn about pricing or make a purchase"
        },
        {
          "type": "assistant",
          "assistantName": "support-assistant",
          "description": "customer needs help with an existing product or service"
        },
        {
          "type": "assistant",
          "assistantName": "billing-assistant",
          "description": "customer has questions about invoices, payments, or refunds"
        }
      ]
    }
  ]
}
```

## Dynamic handoffs

### Basic dynamic handoff

The destination is determined at runtime via the `handoff-destination-request` webhook:

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "dynamic",
          "server": {
            "url": "https://api.example.com/determine-handoff-destination",
            "headers": {
              "Authorization": "Bearer YOUR_API_KEY"
            }
          }
        }
      ]
    }
  ]
}
```

Your server must respond with a single destination. You can return an `assistantId`, `assistantName` (if using squads), or a transient `assistant`. For example:

```json
{
  "destination": {
    "type": "assistant",
    "assistantId": "assistant-id",
    "variableExtractionPlan": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the customer"
          }
        },
        "required": ["name"]
      }
    },
    "contextEngineeringPlan": {
      "type": "none"
    }
  }
}
```

If the handoff should not execute, either respond with an empty destination, or provide a custom error. The custom error is added to the message history.

```json
{
  "error": "Example custom error message"
}
```

### Dynamic handoff with custom parameters

Pass additional context to your webhook for intelligent routing:

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "dynamic",
          "server": {
            "url": "https://api.example.com/intelligent-routing"
          }
        }
      ],
      "function": {
        "name": "handoff_with_context",
        "description": "Transfer the call to the most appropriate specialist",
        "parameters": {
          "type": "object",
          "properties": {
            "destination": {
              "type": "string",
              "description": "Use 'dynamic' to route to the best available agent",
              "enum": ["dynamic"]
            },
            "customerAreaCode": {
              "type": "number",
              "description": "Customer's area code for regional routing"
            },
            "customerIntent": {
              "type": "string",
              "enum": ["new-customer", "existing-customer", "partner"],
              "description": "Customer type for proper routing"
            },
            "customerSentiment": {
              "type": "string",
              "enum": ["positive", "negative", "neutral", "escalated"],
              "description": "Current emotional state of the customer"
            },
            "issueCategory": {
              "type": "string",
              "enum": ["technical", "billing", "sales", "general"],
              "description": "Primary category of the customer's issue"
            },
            "priority": {
              "type": "string",
              "enum": ["low", "medium", "high", "urgent"],
              "description": "Urgency level of the request"
            }
          },
          "required": ["destination", "customerIntent", "issueCategory"]
        }
      }
    }
  ]
}
```

## Squad destinations

In addition to assistant and dynamic destinations, you can hand off a call to an entire squad. This transfers the caller into a new multi-agent system where the squad's own routing logic takes over.

### Using squad ID

Reference a saved squad by its ID. To save changes to that squad or review its versions, see [squad versioning](/assistants/versioning/versioning-with-squads).

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "squad",
          "squadId": "your-squad-id",
          "description": "customer needs specialized support from the enterprise team",
          "entryAssistantName": "EnterpriseGreeter",
          "contextEngineeringPlan": {
            "type": "userAndAssistantMessages"
          }
        }
      ]
    }
  ]
}
```

### Using a transient squad

Define the squad inline without saving it first:

```json
{
  "tools": [
    {
      "type": "handoff",
      "destinations": [
        {
          "type": "squad",
          "squad": {
            "members": [
              {
                "assistantId": "greeter-assistant-id",
                "assistantDestinations": [
                  {
                    "type": "assistant",
                    "assistantName": "SalesSpecialist",
                    "description": "customer is interested in purchasing"
                  }
                ]
              },
              {
                "assistantId": "sales-assistant-id"
              }
            ]
          },
          "entryAssistantName": "GreeterAssistant",
          "description": "route customer to the sales squad"
        }
      ]
    }
  ]
}
```

### Squad destination properties

| Property                   | Type      | Description                                                                               |
| -------------------------- | --------- | ----------------------------------------------------------------------------------------- |
| **type**                   | `"squad"` | Required. Identifies this as a squad destination.                                         |
| **squadId**                | string    | The ID of a saved squad. Provide either `squadId` or `squad`.                             |
| **squad**                  | object    | A transient squad definition. Provide either `squadId` or `squad`.                        |
| **entryAssistantName**     | string    | The name of the assistant to start with. If not provided, the first squad member is used. |
| **description**            | string    | Describes when the AI should choose this destination.                                     |
| **contextEngineeringPlan** | object    | Controls what conversation history transfers to the squad.                                |
| **variableExtractionPlan** | object    | Extracts structured data from the conversation before handoff.                            |
| **squadOverrides**         | object    | Overrides applied to the squad configuration (maps to squad-level `membersOverrides`).    |

For the full schema, see the [API reference](/api-reference/tools/create#request.body.HandoffTool.destinations.HandoffDestinationSquad).

## Custom function definitions

Override the default function definition for more control. You can overwrite the function name for each tool to reference in the system prompt, or pass custom parameters in a dynamic handoff request.

```json
{
  "tools": [
    {
      "type": "handoff",
      "function": {
        "name": "handoff_to_department",
        "description": "Transfer the customer to the appropriate department based on their needs. Only use when explicitly requested or when the current assistant cannot help.",
        "parameters": {
          "type": "object",
          "properties": {
            "destination": {
              "type": "string",
              "description": "Department to transfer to",
              "enum": ["sales-team", "technical-support", "billing-department", "management"]
            },
            "reason": {
              "type": "string",
              "description": "Brief reason for the transfer"
            },
            "urgency": {
              "type": "boolean",
              "description": "Whether this is an urgent transfer"
            }
          },
          "required": ["destination", "reason"]
        }
      },
      "destinations": [
        {
          "type": "assistant",
          "assistantId": "sales-team",
          "description": "Sales inquiries and purchases"
        },
        {
          "type": "assistant",
          "assistantId": "technical-support",
          "description": "Technical issues and support"
        },
        {
          "type": "assistant",
          "assistantId": "billing-department",
          "description": "Billing and payment issues"
        },
        {
          "type": "assistant",
          "assistantId": "management",
          "description": "Escalations and complaints"
        }
      ]
    }
  ]
}
```