> 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 full documentation content, see https://docs.vapi.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vapi.ai/_mcp/server.

# Workflows quickstart

> Build a simple agent that greets users and gathers basic information using Vapi workflows.

We no longer recommend Workflows for new builds. Use **Assistants** for most cases or **Squads** for multi-assistant setups. See [Assistants](/assistants/dynamic-variables) and [Squads](/squads). Existing workflow content remains for reference.

## Overview

Build a simple voice agent using Vapi's visual workflow builder that greets users, collects their information, and demonstrates core workflow concepts like variable extraction, conditional routing, and global nodes.

<img src="https://files.buildwithfern.com/https://vapi.docs.buildwithfern.com/3f01cd9fc4cf766167cadc33cc7fc0a7ea9e8930963a2facb6aa585e216662db/static/images/workflows/workflows-quickstart-flow.png" alt="Vapi Workflows" />

**Agent Capabilities:**

* Greet users and ask about their voice agent needs
* Extract and store user information (name and city)
* Use variables in dynamic responses
* Handle escalation to human agents at any point

**What You'll Build:**

* Multi-node conversation flow with branching logic
* Variable extraction and liquid template usage
* Global escalation nodes for human transfer
* End-call automation with natural conversation termination

## Prerequisites

* A [Vapi account](https://dashboard.vapi.ai)
* For SDK usage: API key from the Dashboard

**Developing with the Vapi CLI?** You can manage workflows and test webhook integrations from your terminal:

```bash
# List all workflows
vapi workflow list

# Test workflow webhooks locally
vapi listen --forward-to localhost:3000/webhook
```

[Learn more about the Vapi CLI →](/cli)

## Scenario

We will create a simple information-gathering workflow that demonstrates the core features of Vapi's workflow builder. This workflow will showcase conversation flow, variable extraction, and escalation patterns that form the foundation of more complex workflows.

**Workflows vs Assistants**: Workflows are visual conversation flows with branching logic and variable extraction. Assistants are single AI agents with tools and continuous conversation. This guide covers workflows specifically.

***

## 1. Create a Workflow

Go to [dashboard.vapi.ai](https://dashboard.vapi.ai) and log in to your account.

Click `Workflows` in the left sidebar.

* Click `Create Workflow`.
* Enter workflow name: `Information Gathering Demo`.
* Select the blank template.
* Click **Create Workflow**.

```bash title="npm"
npm install @vapi-ai/server-sdk
```

```bash title="yarn"
yarn add @vapi-ai/server-sdk
```

```bash title="pnpm"
pnpm add @vapi-ai/server-sdk
```

```bash title="bun"
bun add @vapi-ai/server-sdk
```

```typescript
import { VapiClient } from '@vapi-ai/server-sdk';

// Initialize the Vapi client
const vapi = new VapiClient({
  token: 'YOUR_API_KEY'
});

async function createWorkflow() {
  try {
    const workflow = await vapi.workflows.create({
      name: 'Information Gathering Demo',
      // Start with a basic conversation node
      nodes: [
        {
          id: 'start',
          type: 'conversation',
          firstMessage: 'Hey there!',
          systemPrompt: 'Ask users what kind of voice agent they want to build. Be friendly and conversational.',
        }
      ],
      edges: []
    });

    console.log('Workflow created:', workflow.id);
    return workflow;
  } catch (error) {
    console.error('Error creating workflow:', error);
    throw error;
  }
}

// Create the workflow
createWorkflow();
```

```bash
pip install vapi_server_sdk
```

```python
from vapi import Vapi

# Initialize the Vapi client
client = Vapi(token="YOUR_API_KEY")  # Replace with your actual API key

def create_workflow():
    try:
        workflow = client.workflows.create(
            name="Information Gathering Demo",
            // Start with a basic conversation node
            nodes=[
                {
                    "id": "start",
                    "type": "conversation",
                    "firstMessage": "Hey there!",
                    "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational.",
                }
            ],
            edges=[]
        )

        print(f"Workflow created: {workflow.id}")
        return workflow
    except Exception as error:
        print(f"Error creating workflow: {error}")
        raise error

// Create the workflow
create_workflow()
```

```bash
curl -X POST "https://api.vapi.ai/workflow" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Information Gathering Demo",
    "nodes": [
      {
        "id": "start",
        "type": "conversation",
        "firstMessage": "Hey there!",
        "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational."
      }
    ],
    "edges": []
  }'
```

***

## 2. Configure the Start Node

The blank template includes a conversation node. Click on it and configure:

**First Message**:

```txt
Hey there!
```

**Prompt**:

```txt
Ask users what kind of voice agent they want to build. Be friendly and conversational.
```

Click **Call** in the top right to test your initial setup. The agent should greet you and ask about voice agents.

```typescript
async function updateStartNode(workflowId: string) {
  try {
    const updatedWorkflow = await vapi.workflows.update(workflowId, {
      nodes: [
        {
          id: 'start',
          type: 'conversation',
          firstMessage: 'Hey there!',
          systemPrompt: 'Ask users what kind of voice agent they want to build. Be friendly and conversational.',
        }
      ]
    });

    console.log('Start node configured successfully');
    return updatedWorkflow;
  } catch (error) {
    console.error('Error updating start node:', error);
    throw error;
  }
}

// Update the start node
updateStartNode('your-workflow-id');
```

```python
def update_start_node(workflow_id: str):
    try:
        updated_workflow = client.workflows.update(
            workflow_id,
            nodes=[
                {
                    "id": "start",
                    "type": "conversation",
                    "firstMessage": "Hey there!",
                    "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational.",
                }
            ]
        )

        print("Start node configured successfully")
        return updated_workflow
    except Exception as error:
        print(f"Error updating start node: {error}")
        raise error

// Update the start node
update_start_node("your-workflow-id")
```

```bash
curl -X PATCH "https://api.vapi.ai/workflow/your-workflow-id" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nodes": [
      {
        "id": "start",
        "type": "conversation",
        "firstMessage": "Hey there!",
        "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational."
      }
    ]
  }'
```

You can change the node type by selecting a different type from the dropdown at the top of the node configuration panel. For example, you can change the start node type to API Request to trigger an HTTP request as soon as the call is connected.

***

## 3. Add Information Collection Flow

* Click the **+** button below the first node
* Select **Conversation Node**
* Configure the new node:

**Prompt**:

```txt
Acknowledge the user's voice agent use case, then ask for information about the user. Ask for their first name and what city they're in.
```

**Extract Variables** (expand this section):

* Variable 1:
  * Name: `first_name`
  * Type: `string`
  * Description: `the user's first name`
* Variable 2:
  * Name: `city`
  * Type: `string`
  * Description: `the user's city`

Click on the edge between the two nodes and configure:

* **Condition**: `User describes their voice agent`
* Click **Save**

```typescript
async function addInformationCollectionNode(workflowId: string) {
  try {
    // Get current workflow to preserve existing nodes
    const currentWorkflow = await vapi.workflows.get(workflowId);
    
    // Add information collection node
    const updatedNodes = [
      ...currentWorkflow.nodes,
      {
        id: 'collect_info',
        type: 'conversation',
        systemPrompt: 'Acknowledge the user\'s voice agent use case, then ask for information about the user. Ask for their first name and what city they\'re in.',
        extractVariables: [
          {
            name: 'first_name',
            type: 'string',
            description: 'the user\'s first name'
          },
          {
            name: 'city',
            type: 'string',
            description: 'the user\'s city'
          }
        ]
      }
    ];

    // Add connecting edge
    const updatedEdges = [
      ...currentWorkflow.edges,
      {
        from: 'start',
        to: 'collect_info',
        condition: 'User describes their voice agent'
      }
    ];

    const updatedWorkflow = await vapi.workflows.update(workflowId, {
      nodes: updatedNodes,
      edges: updatedEdges
    });

    console.log('Information collection node added successfully');
    return updatedWorkflow;
  } catch (error) {
    console.error('Error adding information collection node:', error);
    throw error;
  }
}

// Add information collection flow
addInformationCollectionNode('your-workflow-id');
```

```python
def add_information_collection_node(workflow_id: str):
    try:
        # Get current workflow to preserve existing nodes
        current_workflow = client.workflows.get(workflow_id)
        
        # Add information collection node
        updated_nodes = current_workflow.nodes + [
            {
                "id": "collect_info",
                "type": "conversation",
                "systemPrompt": "Acknowledge the user's voice agent use case, then ask for information about the user. Ask for their first name and what city they're in.",
                "extractVariables": [
                    {
                        "name": "first_name",
                        "type": "string",
                        "description": "the user's first name"
                    },
                    {
                        "name": "city",
                        "type": "string",
                        "description": "the user's city"
                    }
                ]
            }
        ]
        
        # Add connecting edge
        updated_edges = current_workflow.edges + [
            {
                "from": "start",
                "to": "collect_info",
                "condition": "User describes their voice agent"
            }
        ]
        
        updated_workflow = client.workflows.update(
            workflow_id,
            nodes=updated_nodes,
            edges=updated_edges
        )

        print("Information collection node added successfully")
        return updated_workflow
    except Exception as error:
        print(f"Error adding information collection node: {error}")
        raise error

# Add information collection flow
add_information_collection_node("your-workflow-id")
```

```bash
# Get current workflow structure first
WORKFLOW_ID="your-workflow-id"

# Update workflow with information collection node
curl -X PATCH "https://api.vapi.ai/workflow/$WORKFLOW_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nodes": [
      {
        "id": "start",
        "type": "conversation",
        "firstMessage": "Hey there!",
        "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational."
      },
      {
        "id": "collect_info",
        "type": "conversation",
        "systemPrompt": "Acknowledge the user'\''s voice agent use case, then ask for information about the user. Ask for their first name and what city they'\''re in.",
        "extractVariables": [
          {
            "name": "first_name",
            "type": "string",
            "description": "the user'\''s first name"
          },
          {
            "name": "city",
            "type": "string",
            "description": "the user'\''s city"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "start",
        "to": "collect_info",
        "condition": "User describes their voice agent"
      }
    ]
  }'
```

***

## 4. Add Dynamic Response Node

Add another **Conversation Node** with this prompt:

```txt
Say "Thanks {{first_name}}, {{city}} is great!"

Then say a few nice words about the {{city}}. Keep it brief. After that, ask the user if there's anything you can help with and help them, unless they no longer need help.
```

Click on the edge leading to this node and:

* Remove any condition text (leave it blank)
* Click **Save**

This allows automatic flow after the variables are extracted.

```typescript
async function addDynamicResponseNode(workflowId: string) {
  try {
    // Get current workflow
    const currentWorkflow = await vapi.workflows.get(workflowId);
    
    // Add dynamic response node
    const updatedNodes = [
      ...currentWorkflow.nodes,
      {
        id: 'dynamic_response',
        type: 'conversation',
        systemPrompt: 'Say "Thanks {{first_name}}, {{city}} is great!" Then say a few nice words about the {{city}}. Keep it brief. After that, ask the user if there\'s anything you can help with and help them, unless they no longer need help.'
      }
    ];

    // Add edge without condition for automatic flow
    const updatedEdges = [
      ...currentWorkflow.edges,
      {
        from: 'collect_info',
        to: 'dynamic_response'
      }
    ];

    const updatedWorkflow = await vapi.workflows.update(workflowId, {
      nodes: updatedNodes,
      edges: updatedEdges
    });

    console.log('Dynamic response node added successfully');
    return updatedWorkflow;
  } catch (error) {
    console.error('Error adding dynamic response node:', error);
    throw error;
  }
}

// Add dynamic response node
addDynamicResponseNode('your-workflow-id');
```

```python
def add_dynamic_response_node(workflow_id: str):
    try:
        # Get current workflow
        current_workflow = client.workflows.get(workflow_id)
        
        # Add dynamic response node
        updated_nodes = current_workflow.nodes + [
            {
                "id": "dynamic_response",
                "type": "conversation",
                "systemPrompt": "Say \"Thanks {{first_name}}, {{city}} is great!\" Then say a few nice words about the {{city}}. Keep it brief. After that, ask the user if there's anything you can help with and help them, unless they no longer need help."
            }
        ]

        # Add edge without condition for automatic flow
        updated_edges = current_workflow.edges + [
            {
                "from": "collect_info",
                "to": "dynamic_response"
            }
        ]

        updated_workflow = client.workflows.update(
            workflow_id,
            nodes=updated_nodes,
            edges=updated_edges
        )

        print("Dynamic response node added successfully")
        return updated_workflow
    except Exception as error:
        print(f"Error adding dynamic response node: {error}")
        raise error

# Add dynamic response node
add_dynamic_response_node("your-workflow-id")
```

```bash
curl -X PATCH "https://api.vapi.ai/workflow/your-workflow-id" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nodes": [
      {
        "id": "start",
        "type": "conversation",
        "firstMessage": "Hey there!",
        "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational."
      },
      {
        "id": "collect_info",
        "type": "conversation",
        "systemPrompt": "Acknowledge the user'\''s voice agent use case, then ask for information about the user. Ask for their first name and what city they'\''re in.",
        "extractVariables": [
          {
            "name": "first_name",
            "type": "string",
            "description": "the user'\''s first name"
          },
          {
            "name": "city",
            "type": "string", 
            "description": "the user'\''s city"
          }
        ]
      },
      {
        "id": "dynamic_response",
        "type": "conversation",
        "systemPrompt": "Say \"Thanks {{first_name}}, {{city}} is great!\" Then say a few nice words about the {{city}}. Keep it brief. After that, ask the user if there'\''s anything you can help with and help them, unless they no longer need help."
      }
    ],
    "edges": [
      {
        "from": "start", 
        "to": "collect_info",
        "condition": "User describes their voice agent"
      },
      {
        "from": "collect_info",
        "to": "dynamic_response"
      }
    ]
  }'
```

***

## 5. Add Global Escalation Node

Add a new **Conversation Node** and configure:

**Global Node**: Toggle this **ON**

**Conversation Prompt**:

```txt
Confirm that the user wants to speak to a human and ask them what would they like to talk to the human about.
```

**Condition Prompt**:

```txt
User wants to speak to a human
```

Add a **Transfer Call Node** below the global node:

* **Destination**: Enter your phone number or `+1-555-DEMO-123`
* Configure **Transfer Plan** with a brief summary message

```typescript
async function addEscalationNodes(workflowId: string) {
  try {
    // Get current workflow
    const currentWorkflow = await vapi.workflows.get(workflowId);
    
    // Add escalation and transfer nodes
    const updatedNodes = [
      ...currentWorkflow.nodes,
      {
        id: 'escalation',
        type: 'conversation',
        isGlobal: true,
        systemPrompt: 'Confirm that the user wants to speak to a human and ask them what would they like to talk to the human about.',
        condition: 'User wants to speak to a human'
      },
      {
        id: 'transfer',
        type: 'transferCall',
        destination: '+1-555-DEMO-123', // Replace with your number
        transferPlan: {
          message: 'The user wants to speak with a human agent.'
        }
      }
    ];

    // Add edge from escalation to transfer
    const updatedEdges = [
      ...currentWorkflow.edges,
      {
        from: 'escalation',
        to: 'transfer'
      }
    ];

    const updatedWorkflow = await vapi.workflows.update(workflowId, {
      nodes: updatedNodes,
      edges: updatedEdges
    });

    console.log('Escalation nodes added successfully');
    return updatedWorkflow;
  } catch (error) {
    console.error('Error adding escalation nodes:', error);
    throw error;
  }
}

// Add escalation functionality
addEscalationNodes('your-workflow-id');
```

```python
def add_escalation_nodes(workflow_id: str):
    try:
        # Get current workflow
        current_workflow = client.workflows.get(workflow_id)
        
        # Add escalation and transfer nodes
        updated_nodes = current_workflow.nodes + [
            {
                "id": "escalation",
                "type": "conversation",
                "isGlobal": True,
                "systemPrompt": "Confirm that the user wants to speak to a human and ask them what would they like to talk to the human about.",
                "condition": "User wants to speak to a human"
            },
            {
                "id": "transfer",
                "type": "transferCall",
                "destination": "+1-555-DEMO-123",  # Replace with your number
                "transferPlan": {
                    "message": "The user wants to speak with a human agent."
                }
            }
        ]

        # Add edge from escalation to transfer
        updated_edges = current_workflow.edges + [
            {
                "from": "escalation",
                "to": "transfer"
            }
        ]

        updated_workflow = client.workflows.update(
            workflow_id,
            nodes=updated_nodes,
            edges=updated_edges
        )

        print("Escalation nodes added successfully")
        return updated_workflow
    except Exception as error:
        print(f"Error adding escalation nodes: {error}")
        raise error

# Add escalation functionality
add_escalation_nodes("your-workflow-id")
```

```bash
curl -X PATCH "https://api.vapi.ai/workflow/your-workflow-id" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nodes": [
      {
        "id": "start",
        "type": "conversation",
        "firstMessage": "Hey there!",
        "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational."
      },
      {
        "id": "collect_info", 
        "type": "conversation",
        "systemPrompt": "Acknowledge the user'\''s voice agent use case, then ask for information about the user. Ask for their first name and what city they'\''re in.",
        "extractVariables": [
          {
            "name": "first_name",
            "type": "string",
            "description": "the user'\''s first name"
          },
          {
            "name": "city",
            "type": "string",
            "description": "the user'\''s city"
          }
        ]
      },
      {
        "id": "dynamic_response",
        "type": "conversation", 
        "systemPrompt": "Say \"Thanks {{first_name}}, {{city}} is great!\" Then say a few nice words about the {{city}}. Keep it brief. After that, ask the user if there'\''s anything you can help with and help them, unless they no longer need help."
      },
      {
        "id": "escalation",
        "type": "conversation",
        "isGlobal": true,
        "systemPrompt": "Confirm that the user wants to speak to a human and ask them what would they like to talk to the human about.",
        "condition": "User wants to speak to a human"
      },
      {
        "id": "transfer",
        "type": "transferCall",
        "destination": "+1-555-DEMO-123",
        "transferPlan": {
          "message": "The user wants to speak with a human agent."
        }
      }
    ],
    "edges": [
      {
        "from": "start",
        "to": "collect_info", 
        "condition": "User describes their voice agent"
      },
      {
        "from": "collect_info",
        "to": "dynamic_response"
      },
      {
        "from": "escalation",
        "to": "transfer"
      }
    ]
  }'
```

Developers can specify a phone number destination and a [transfer plan](/call-forwarding#call-transfers-mode), which lets them specify a message or a summary of the call to the person or agent picking up in the destination number before actually connecting the call.

***

## 6. Add Call Termination

Add an **End Call Node** at the end of your main flow:

**First Message**:

```txt
Alright, have a nice day!
```

Update the edge leading to the End Call node:

* **Condition**: `User does not need any help`
* Click **Save**

```typescript
async function addEndCallNode(workflowId: string) {
  try {
    // Get current workflow
    const currentWorkflow = await vapi.workflows.get(workflowId);
    
    // Add end call node
    const updatedNodes = [
      ...currentWorkflow.nodes,
      {
        id: 'end_call',
        type: 'endCall',
        firstMessage: 'Alright, have a nice day!'
      }
    ];

    // Add edge with condition
    const updatedEdges = [
      ...currentWorkflow.edges,
      {
        from: 'dynamic_response',
        to: 'end_call',
        condition: 'User does not need any help'
      }
    ];

    const updatedWorkflow = await vapi.workflows.update(workflowId, {
      nodes: updatedNodes,
      edges: updatedEdges
    });

    console.log('End call node added successfully');
    return updatedWorkflow;
  } catch (error) {
    console.error('Error adding end call node:', error);
    throw error;
  }
}

// Add call termination
addEndCallNode('your-workflow-id');
```

```python
def add_end_call_node(workflow_id: str):
    try:
        # Get current workflow
        current_workflow = client.workflows.get(workflow_id)
        
        # Add end call node
        updated_nodes = current_workflow.nodes + [
            {
                "id": "end_call",
                "type": "endCall",
                "firstMessage": "Alright, have a nice day!"
            }
        ]

        # Add edge with condition
        updated_edges = current_workflow.edges + [
            {
                "from": "dynamic_response",
                "to": "end_call",
                "condition": "User does not need any help"
            }
        ]

        updated_workflow = client.workflows.update(
            workflow_id,
            nodes=updated_nodes,
            edges=updated_edges
        )

        print("End call node added successfully")
        return updated_workflow
    except Exception as error:
        print(f"Error adding end call node: {error}")
        raise error

# Add call termination
add_end_call_node("your-workflow-id")
```

```bash
curl -X PATCH "https://api.vapi.ai/workflow/your-workflow-id" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nodes": [
      {
        "id": "start",
        "type": "conversation",
        "firstMessage": "Hey there!",
        "systemPrompt": "Ask users what kind of voice agent they want to build. Be friendly and conversational."
      },
      {
        "id": "collect_info",
        "type": "conversation",
        "systemPrompt": "Acknowledge the user'\''s voice agent use case, then ask for information about the user. Ask for their first name and what city they'\''re in.",
        "extractVariables": [
          {
            "name": "first_name",
            "type": "string",
            "description": "the user'\''s first name"
          },
          {
            "name": "city",
            "type": "string",
            "description": "the user'\''s city"
          }
        ]
      },
      {
        "id": "dynamic_response",
        "type": "conversation",
        "systemPrompt": "Say \"Thanks {{first_name}}, {{city}} is great!\" Then say a few nice words about the {{city}}. Keep it brief. After that, ask the user if there'\''s anything you can help with and help them, unless they no longer need help."
      },
      {
        "id": "escalation",
        "type": "conversation",
        "isGlobal": true,
        "systemPrompt": "Confirm that the user wants to speak to a human and ask them what would they like to talk to the human about.",
        "condition": "User wants to speak to a human"
      },
      {
        "id": "transfer",
        "type": "transferCall",
        "destination": "+1-555-DEMO-123",
        "transferPlan": {
          "message": "The user wants to speak with a human agent."
        }
      },
      {
        "id": "end_call",
        "type": "endCall",
        "firstMessage": "Alright, have a nice day!"
      }
    ],
    "edges": [
      {
        "from": "start",
        "to": "collect_info",
        "condition": "User describes their voice agent"
      },
      {
        "from": "collect_info",
        "to": "dynamic_response"
      },
      {
        "from": "dynamic_response",
        "to": "end_call",
        "condition": "User does not need any help"
      },
      {
        "from": "escalation",
        "to": "transfer"
      }
    ]
  }'
```

***

## 7. Test Your Workflow

Click **Call** in the top right to test your workflow:

* Verify the greeting works
* Test variable extraction by providing your name and city
* Confirm the dynamic response uses your information
* Test the global escalation by saying "I want to speak to a human"

Your final workflow should have:

* **Start Node**: Greeting and use case inquiry
* **Collection Node**: Information gathering with variable extraction
* **Response Node**: Dynamic response using extracted variables
* **Global Node**: Human escalation available from anywhere
* **Transfer Node**: Routes to human agent when needed
* **End Node**: Natural conversation termination

```typescript
async function testWorkflow(workflowId: string) {
  try {
    // Create phone number for workflow testing
    const phoneNumber = await vapi.phoneNumbers.create({
      name: 'Workflow Test Number',
      workflowId: workflowId,
    });

    console.log('Phone number created:', phoneNumber.number);

    // Make an outbound test call
    const testCall = await vapi.calls.create({
      workflowId: workflowId,
      customer: {
        number: '+1234567890', // Replace with your test number
      },
    });

    console.log('Test call initiated:', testCall.id);
    return { phoneNumber, testCall };
  } catch (error) {
    console.error('Error testing workflow:', error);
    throw error;
  }
}

// Test your workflow
testWorkflow('your-workflow-id');
```

```python
def test_workflow(workflow_id: str):
    try:
        # Create phone number for workflow testing
        phone_number = client.phone_numbers.create(
            name="Workflow Test Number",
            workflow_id=workflow_id,
        )

        print(f"Phone number created: {phone_number.number}")

        # Make an outbound test call
        test_call = client.calls.create(
            workflow_id=workflow_id,
            customer={
                "number": "+1234567890",  # Replace with your test number
            },
        )

        print(f"Test call initiated: {test_call.id}")
        return {"phone_number": phone_number, "test_call": test_call}
    except Exception as error:
        print(f"Error testing workflow: {error}")
        raise error

# Test your workflow
test_workflow("your-workflow-id")
```

```bash
# Create phone number with workflow
curl -X POST "https://api.vapi.ai/phone-number" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Workflow Test Number",
    "workflowId": "your-workflow-id"
  }'

# Make an outbound test call
curl -X POST "https://api.vapi.ai/call" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": "your-workflow-id",
    "customer": {
      "number": "+1234567890"
    }
  }'
```

## Next Steps

* [**Workflows overview**](/workflows/overview) - Learn about all node types and advanced configuration options
* [**Workflow examples**](/workflows/examples) - Explore pre-built workflows for common business use cases
* [**Custom Tools**](/tools/custom-tools) - Integrate external APIs and services into your workflows
* [**Dynamic Variables**](/assistants/dynamic-variables) - Advanced variable usage and personalization techniques