Configure handoff destinations

Declare where a handoff can go, from a fixed assistant to a runtime webhook decision

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

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "assistant",
8 "assistantId": "03e11cfe-4528-4243-a43d-6aded66ab7ba",
9 "description": "customer wants to speak with technical support",
10 "contextEngineeringPlan": {
11 "type": "all"
12 }
13 }
14 ]
15 }
16 ]
17}

Using assistant name (for squad members)

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "assistant",
8 "assistantName": "TechnicalSupportAgent",
9 "description": "customer needs technical assistance",
10 "contextEngineeringPlan": {
11 "type": "all"
12 }
13 }
14 ]
15 }
16 ]
17}

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 for all available properties.

Multiple destinations

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

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "assistant",
8 "assistantId": "sales-assistant-123",
9 "description": "customer wants to learn about pricing or make a purchase",
10 "contextEngineeringPlan": {
11 "type": "all"
12 }
13 }
14 ]
15 },
16 {
17 "type": "handoff",
18 "destinations": [
19 {
20 "type": "assistant",
21 "assistantId": "support-assistant-456",
22 "description": "customer needs help with an existing product or service",
23 "contextEngineeringPlan": {
24 "type": "all"
25 }
26 }
27 ]
28 },
29 {
30 "type": "handoff",
31 "destinations": [
32 {
33 "type": "assistant",
34 "assistantId": "billing-assistant-789",
35 "description": "customer has questions about invoices, payments, or refunds",
36 "contextEngineeringPlan": {
37 "type": "lastNMessages",
38 "maxMessages": 5
39 }
40 }
41 ]
42 }
43 ]
44}

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

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "assistant",
8 "assistantId": "03e11cfe-4528-4243-a43d-6aded66ab7ba",
9 "description": "customer wants to learn about pricing or make a purchase"
10 },
11 {
12 "type": "assistant",
13 "assistantName": "support-assistant",
14 "description": "customer needs help with an existing product or service"
15 },
16 {
17 "type": "assistant",
18 "assistantName": "billing-assistant",
19 "description": "customer has questions about invoices, payments, or refunds"
20 }
21 ]
22 }
23 ]
24}

Dynamic handoffs

Basic dynamic handoff

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

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "dynamic",
8 "server": {
9 "url": "https://api.example.com/determine-handoff-destination",
10 "headers": {
11 "Authorization": "Bearer YOUR_API_KEY"
12 }
13 }
14 }
15 ]
16 }
17 ]
18}

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

1{
2 "destination": {
3 "type": "assistant",
4 "assistantId": "assistant-id",
5 "variableExtractionPlan": {
6 "schema": {
7 "type": "object",
8 "properties": {
9 "name": {
10 "type": "string",
11 "description": "Name of the customer"
12 }
13 },
14 "required": ["name"]
15 }
16 },
17 "contextEngineeringPlan": {
18 "type": "none"
19 }
20 }
21}

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.

1{
2 "error": "Example custom error message"
3}

Dynamic handoff with custom parameters

Pass additional context to your webhook for intelligent routing:

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "dynamic",
8 "server": {
9 "url": "https://api.example.com/intelligent-routing"
10 }
11 }
12 ],
13 "function": {
14 "name": "handoff_with_context",
15 "description": "Transfer the call to the most appropriate specialist",
16 "parameters": {
17 "type": "object",
18 "properties": {
19 "destination": {
20 "type": "string",
21 "description": "Use 'dynamic' to route to the best available agent",
22 "enum": ["dynamic"]
23 },
24 "customerAreaCode": {
25 "type": "number",
26 "description": "Customer's area code for regional routing"
27 },
28 "customerIntent": {
29 "type": "string",
30 "enum": ["new-customer", "existing-customer", "partner"],
31 "description": "Customer type for proper routing"
32 },
33 "customerSentiment": {
34 "type": "string",
35 "enum": ["positive", "negative", "neutral", "escalated"],
36 "description": "Current emotional state of the customer"
37 },
38 "issueCategory": {
39 "type": "string",
40 "enum": ["technical", "billing", "sales", "general"],
41 "description": "Primary category of the customer's issue"
42 },
43 "priority": {
44 "type": "string",
45 "enum": ["low", "medium", "high", "urgent"],
46 "description": "Urgency level of the request"
47 }
48 },
49 "required": ["destination", "customerIntent", "issueCategory"]
50 }
51 }
52 }
53 ]
54}

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:

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "squad",
8 "squadId": "your-squad-id",
9 "description": "customer needs specialized support from the enterprise team",
10 "entryAssistantName": "EnterpriseGreeter",
11 "contextEngineeringPlan": {
12 "type": "userAndAssistantMessages"
13 }
14 }
15 ]
16 }
17 ]
18}

Using a transient squad

Define the squad inline without saving it first:

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "squad",
8 "squad": {
9 "members": [
10 {
11 "assistantId": "greeter-assistant-id",
12 "assistantDestinations": [
13 {
14 "type": "assistant",
15 "assistantName": "SalesSpecialist",
16 "description": "customer is interested in purchasing"
17 }
18 ]
19 },
20 {
21 "assistantId": "sales-assistant-id"
22 }
23 ]
24 },
25 "entryAssistantName": "GreeterAssistant",
26 "description": "route customer to the sales squad"
27 }
28 ]
29 }
30 ]
31}

Squad destination properties

PropertyTypeDescription
type"squad"Required. Identifies this as a squad destination.
squadIdstringThe ID of a saved squad. Provide either squadId or squad.
squadobjectA transient squad definition. Provide either squadId or squad.
entryAssistantNamestringThe name of the assistant to start with. If not provided, the first squad member is used.
descriptionstringDescribes when the AI should choose this destination.
contextEngineeringPlanobjectControls what conversation history transfers to the squad.
variableExtractionPlanobjectExtracts structured data from the conversation before handoff.
squadOverridesobjectOverrides applied to the squad configuration (maps to squad-level membersOverrides).

For the full schema, see the API reference.

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.

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "function": {
6 "name": "handoff_to_department",
7 "description": "Transfer the customer to the appropriate department based on their needs. Only use when explicitly requested or when the current assistant cannot help.",
8 "parameters": {
9 "type": "object",
10 "properties": {
11 "destination": {
12 "type": "string",
13 "description": "Department to transfer to",
14 "enum": ["sales-team", "technical-support", "billing-department", "management"]
15 },
16 "reason": {
17 "type": "string",
18 "description": "Brief reason for the transfer"
19 },
20 "urgency": {
21 "type": "boolean",
22 "description": "Whether this is an urgent transfer"
23 }
24 },
25 "required": ["destination", "reason"]
26 }
27 },
28 "destinations": [
29 {
30 "type": "assistant",
31 "assistantId": "sales-team",
32 "description": "Sales inquiries and purchases"
33 },
34 {
35 "type": "assistant",
36 "assistantId": "technical-support",
37 "description": "Technical issues and support"
38 },
39 {
40 "type": "assistant",
41 "assistantId": "billing-department",
42 "description": "Billing and payment issues"
43 },
44 {
45 "type": "assistant",
46 "assistantId": "management",
47 "description": "Escalations and complaints"
48 }
49 ]
50 }
51 ]
52}