Pass context and variables

Control which conversation history and extracted variables reach the next assistant

When a call moves to another assistant, you control what travels with it. Context engineering decides how much conversation history the receiving assistant can see, and variable extraction captures specific values and forwards them explicitly.

Context engineering

Control what conversation history transfers to the next assistant or squad. Set contextEngineeringPlan on any destination.

All messages (default)

Transfers the entire conversation history:

1{
2 "contextEngineeringPlan": {
3 "type": "all"
4 }
5}

Last N messages

Transfers only the most recent N messages. Use this to limit context size for performance:

1{
2 "contextEngineeringPlan": {
3 "type": "lastNMessages",
4 "maxMessages": 10
5 }
6}

User and assistant messages only

Transfers only user and assistant messages, filtering out system messages, tool calls, and tool results. This gives the next assistant a clean view of the conversation without internal implementation details:

1{
2 "contextEngineeringPlan": {
3 "type": "userAndAssistantMessages"
4 }
5}

Use userAndAssistantMessages when the destination assistant does not need to see tool call history or system prompts from the previous assistant. This produces a cleaner context and reduces token usage.

Previous assistant messages

Transfers only the conversation history from before the current assistant’s session. This excludes the current assistant’s own messages, tool calls, and tool results entirely, forwarding only the context that existed when the current assistant first received the call.

1{
2 "contextEngineeringPlan": {
3 "type": "previousAssistantMessages"
4 }
5}

This mode is particularly useful when the current assistant handles sensitive data (such as payment card numbers in a PCI-compliant flow). By excluding the current assistant’s session from the forwarded context, you prevent sensitive tool call results from reaching the next assistant.

Use previousAssistantMessages when handing off from a sensitive assistant (e.g., one collecting payment data) to a non-sensitive assistant. It preserves useful conversation context from earlier in the call while ensuring the sensitive assistant’s tool call data is not forwarded. See the PCI Compliance - Handoff Context Configuration guide for a complete walkthrough.

No context

Starts the next assistant with a blank conversation:

1{
2 "contextEngineeringPlan": {
3 "type": "none"
4 }
5}

Variable extraction

Extract and pass structured data during handoff. Variables extracted by the Handoff tool are available to all subsequent assistants in the conversation chain. When a handoff extracts a variable with the same name as an existing one, the new value replaces the previous value.

Extraction via variableExtractionPlan in destinations

This extraction method makes an OpenAI structured output request to extract variables. Use this when you have multiple destinations, each with different variables that need to be extracted.

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "assistant",
8 "assistantName": "order-processing-assistant",
9 "description": "customer is ready to place an order",
10 "variableExtractionPlan": {
11 "schema": {
12 "type": "object",
13 "properties": {
14 "customerName": {
15 "type": "string",
16 "description": "Full name of the customer"
17 },
18 "email": {
19 "type": "string",
20 "format": "email",
21 "description": "Customer's email address"
22 },
23 "productIds": {
24 "type": "array",
25 "items": {
26 "type": "string"
27 },
28 "description": "List of product IDs customer wants to order"
29 },
30 "shippingAddress": {
31 "type": "object",
32 "properties": {
33 "street": { "type": "string" },
34 "city": { "type": "string" },
35 "state": { "type": "string" },
36 "zipCode": { "type": "string" }
37 }
38 }
39 },
40 "required": ["customerName", "productIds"]
41 }
42 }
43 }
44 ]
45 }
46 ]
47}

Variable access patterns

Once extracted, variables are accessible using Liquid template syntax ({{variableName}}). The access pattern depends on the schema structure:

Schema typeAccess patternExample
Simple property{{propertyName}}{{customerName}}
Nested object{{object.property}}{{name.first}}, {{name.last}}
Array item{{array[index]}}{{zipCodes[0]}}, {{zipCodes[1]}}
Array of objects{{array[index].property}}{{people[0].name}}, {{people[0].age}}
Nested array{{array[index].nestedArray[index]}}{{people[0].zipCodes[1]}}

Top-level object properties are extracted as direct global variables. For example, a schema with properties name and age produces {{name}} and {{age}} — not {{root.name}}.

Variable aliases

Use aliases to create additional variables derived from extracted values. Aliases support Liquid template syntax for transformations and compositions.

1{
2 "variableExtractionPlan": {
3 "schema": {
4 "type": "object",
5 "properties": {
6 "firstName": {
7 "type": "string",
8 "description": "Customer's first name"
9 },
10 "lastName": {
11 "type": "string",
12 "description": "Customer's last name"
13 },
14 "company": {
15 "type": "string",
16 "description": "Customer's company name"
17 }
18 }
19 },
20 "aliases": [
21 {
22 "key": "fullName",
23 "value": "{{firstName}} {{lastName}}"
24 },
25 {
26 "key": "greeting",
27 "value": "Hello {{firstName}}, welcome to {{company}}!"
28 },
29 {
30 "key": "customerCity",
31 "value": "{{addresses[0].city}}"
32 }
33 ]
34 }
35}

Each alias creates a new variable accessible as {{key}} during the call and stored in call.artifact.variableValues after the call. Alias keys must start with a letter and contain only letters, numbers, or underscores (max 40 characters).

Extraction via tool.function

You can also extract variables through the LLM tool call parameters (in addition to sending these parameters to your server in a handoff-destination-request for dynamic handoffs). Include the destination parameter with the assistant names or IDs in enum — Vapi uses this to determine where to hand off the call. The destination parameter itself is not extracted as a variable. Add destination and all other required variables to the schema’s required array.

1{
2 "tools": [
3 {
4 "type": "handoff",
5 "destinations": [
6 {
7 "type": "assistant",
8 "assistantName": "order-processing-assistant",
9 "description": "customer is ready to place an order"
10 }
11 ],
12 "function": {
13 "name": "handoff_to_order_processing_assistant",
14 "parameters": {
15 "type": "object",
16 "properties": {
17 "destination": {
18 "type": "string",
19 "description": "The destination to handoff the call to.",
20 "enum": ["order-processing-assistant"]
21 },
22 "customerName": {
23 "type": "string",
24 "description": "Full name of the customer"
25 },
26 "email": {
27 "type": "string",
28 "format": "email",
29 "description": "Customer's email address"
30 },
31 "productIds": {
32 "type": "array",
33 "items": {
34 "type": "string"
35 },
36 "description": "List of product IDs customer wants to order"
37 },
38 "shippingAddress": {
39 "type": "object",
40 "properties": {
41 "street": { "type": "string" },
42 "city": { "type": "string" },
43 "state": { "type": "string" },
44 "zipCode": { "type": "string" }
45 }
46 }
47 },
48 "required": ["destination", "customerName", "email"]
49 }
50 }
51 }
52 ]
53}