AutomationFlowsAI & RAG › Sales Voice Agent - Elevenlabs + N8n

Sales Voice Agent - Elevenlabs + N8n

Sales Voice Agent - ElevenLabs + n8n. Uses httpRequest, openAi, gmail, googleSheets. Webhook trigger; 19 nodes.

Webhook trigger★★★★☆ complexityAI-powered19 nodesHTTP RequestOpenAIGmailGoogle Sheets
AI & RAG Trigger: Webhook Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Gmail → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Sales Voice Agent - ElevenLabs + n8n",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "elevenlabs-tool",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "webhook-mid-call",
      "name": "Mid-Call Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "elevenlabs-postcall",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-postcall",
      "name": "Post-Call Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        700
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "condition-calendar",
              "leftValue": "={{ $json.body.action }}",
              "rightValue": "check_calendar",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-action-router",
      "name": "Route by Action",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        480,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://www.googleapis.com/calendar/v3/calendars/primary/freeBusy",
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "options": {},
        "headerParameters": {
          "parameters": []
        },
        "queryParameters": {
          "parameters": []
        }
      },
      "id": "check-calendar",
      "name": "Check Calendar Availability",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        200
      ],
      "notes": "Replace with your actual calendar API call. This is a placeholder \u2014 connect Google Calendar, Cal.com, or Calendly."
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ result: 'Available times: Monday 2pm, Tuesday 10am, Wednesday 3pm. Which works best for you?' }) }}",
        "options": {}
      },
      "id": "respond-calendar",
      "name": "Respond - Calendar",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        960,
        200
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ result: 'I can help with that. Let me look into it and have a specialist follow up with you.' }) }}",
        "options": {}
      },
      "id": "respond-default",
      "name": "Respond - Default",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        720,
        420
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ status: 'received' }) }}",
        "options": {}
      },
      "id": "respond-postcall-ok",
      "name": "Respond 200 OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        480,
        700
      ]
    },
    {
      "parameters": {
        "model": "gpt-4o",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a lead qualification analyst. Analyze the following sales call transcript and return a JSON object with these fields:\n- qualification_status: \"hot\", \"warm\", or \"cold\"\n- pain_points: array of strings\n- budget_range: string or null\n- timeline: string or null\n- next_steps: string\n- prospect_email: string or null\n- prospect_name: string or null\n- summary: 2-3 sentence summary of the call\n\nReturn ONLY valid JSON, no other text."
            },
            {
              "role": "user",
              "content": "=Analyze this sales call transcript:\n\n{{ $json.body.transcript || $json.body.data?.transcript || 'No transcript available' }}"
            }
          ]
        },
        "options": {
          "temperature": 0.3
        }
      },
      "id": "analyze-transcript",
      "name": "Analyze Call Transcript",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        480,
        900
      ],
      "notes": "Configure your OpenAI API credentials here. Uses GPT-4o to analyze the call transcript and qualify the lead."
    },
    {
      "parameters": {
        "jsCode": "// Parse the AI analysis and prepare data for downstream nodes\nconst aiResponse = $input.first().json;\nlet analysis;\n\ntry {\n  // Handle different response shapes from OpenAI node\n  const content = aiResponse.message?.content || aiResponse.choices?.[0]?.message?.content || aiResponse.text || '{}';\n  analysis = JSON.parse(content);\n} catch (e) {\n  analysis = {\n    qualification_status: 'warm',\n    pain_points: ['Unable to parse transcript'],\n    budget_range: null,\n    timeline: null,\n    next_steps: 'Manual review needed',\n    prospect_email: null,\n    prospect_name: null,\n    summary: 'Call transcript could not be automatically analyzed. Please review manually.'\n  };\n}\n\n// Add metadata\nanalysis.call_date = new Date().toISOString();\nanalysis.agent_id = $('Post-Call Webhook').first().json.body?.agent_id || 'unknown';\nanalysis.call_duration = $('Post-Call Webhook').first().json.body?.call_duration || null;\n\nreturn [{ json: analysis }];"
      },
      "id": "parse-analysis",
      "name": "Parse AI Analysis",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        900
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "condition-hot",
              "leftValue": "={{ $json.qualification_status }}",
              "rightValue": "hot",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-hot-lead",
      "name": "Is Hot Lead?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        960,
        900
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $json.prospect_email || 'YOUR_SALES_TEAM_EMAIL@company.com' }}",
        "subject": "=Hot Lead: {{ $json.prospect_name || 'New Prospect' }} - Follow Up ASAP",
        "emailType": "text",
        "message": "=Hi {{ $json.prospect_name || 'there' }},\n\nGreat speaking with you today! As discussed, I'd love to set up a more detailed conversation with one of our specialists.\n\nHere's a quick recap:\n{{ $json.summary }}\n\nNext steps: {{ $json.next_steps }}\n\nLooking forward to connecting again soon!\n\nBest regards,\n[Your Company Name]"
      },
      "id": "send-hot-lead-email",
      "name": "Send Hot Lead Follow-Up",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1200,
        800
      ],
      "notes": "Connect your Gmail credentials. This sends a personalized follow-up email to hot leads."
    },
    {
      "parameters": {
        "sendTo": "YOUR_SALES_TEAM_EMAIL@company.com",
        "subject": "=Lead Update: {{ $json.prospect_name || 'Unknown' }} - {{ $json.qualification_status }}",
        "emailType": "text",
        "message": "=New lead qualification result:\n\nName: {{ $json.prospect_name || 'Unknown' }}\nStatus: {{ $json.qualification_status }}\nPain Points: {{ ($json.pain_points || []).join(', ') }}\nBudget: {{ $json.budget_range || 'Not discussed' }}\nTimeline: {{ $json.timeline || 'Not discussed' }}\nNext Steps: {{ $json.next_steps }}\n\nCall Summary:\n{{ $json.summary }}\n\nCall Date: {{ $json.call_date }}\nDuration: {{ $json.call_duration || 'Unknown' }}"
      },
      "id": "notify-team",
      "name": "Notify Sales Team",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1200,
        1020
      ],
      "notes": "Sends a summary to your sales team for all leads (warm and cold)."
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "YOUR_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Sheet1",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Date": "={{ $json.call_date }}",
            "Name": "={{ $json.prospect_name || 'Unknown' }}",
            "Email": "={{ $json.prospect_email || '' }}",
            "Status": "={{ $json.qualification_status }}",
            "Pain Points": "={{ ($json.pain_points || []).join(', ') }}",
            "Budget": "={{ $json.budget_range || '' }}",
            "Timeline": "={{ $json.timeline || '' }}",
            "Next Steps": "={{ $json.next_steps }}",
            "Summary": "={{ $json.summary }}"
          }
        },
        "options": {}
      },
      "id": "log-to-sheets",
      "name": "Log to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        960,
        1140
      ],
      "notes": "Logs every call result to a Google Sheet for tracking. Replace YOUR_GOOGLE_SHEET_ID with your actual sheet ID."
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 1
            }
          ]
        }
      },
      "id": "schedule-trigger",
      "name": "Hourly Check for New Leads",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        1500
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "YOUR_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Leads",
          "mode": "list"
        },
        "filters": {
          "conditions": [
            {
              "condition": "equal",
              "value1": "={{ $json.Status }}",
              "value2": "new"
            }
          ]
        },
        "options": {}
      },
      "id": "read-new-leads",
      "name": "Read New Leads",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        480,
        1500
      ],
      "notes": "Reads leads with status 'new' from your Leads sheet. Create a sheet with columns: Name, Email, Phone, Company, Source, Status"
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {
          "reset": false
        }
      },
      "id": "batch-leads",
      "name": "Process One at a Time",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        720,
        1500
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.elevenlabs.io/v1/convai/conversations",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"agent_id\": \"YOUR_AGENT_ID\",\n  \"dynamic_variables\": {\n    \"lead_name\": \"{{ $json.Name }}\",\n    \"company_name\": \"{{ $json.Company }}\",\n    \"lead_source\": \"{{ $json.Source }}\"\n  }\n}",
        "options": {}
      },
      "id": "initiate-call",
      "name": "Initiate ElevenLabs Call",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        1500
      ],
      "notes": "Calls the ElevenLabs API to start a conversation. Set your API key in the HTTP Header Auth credential (header name: xi-api-key)."
    },
    {
      "parameters": {
        "options": {
          "waitBetweenBatches": 30000
        }
      },
      "id": "wait-between-calls",
      "name": "Wait 30s Between Calls",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1200,
        1500
      ]
    },
    {
      "parameters": {},
      "id": "noop-start",
      "name": "Start",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        40,
        300
      ]
    }
  ],
  "connections": {
    "Mid-Call Webhook": {
      "main": [
        [
          {
            "node": "Route by Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Action": {
      "main": [
        [
          {
            "node": "Check Calendar Availability",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond - Default",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Calendar Availability": {
      "main": [
        [
          {
            "node": "Respond - Calendar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post-Call Webhook": {
      "main": [
        [
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          },
          {
            "node": "Analyze Call Transcript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Call Transcript": {
      "main": [
        [
          {
            "node": "Parse AI Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Analysis": {
      "main": [
        [
          {
            "node": "Is Hot Lead?",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Hot Lead?": {
      "main": [
        [
          {
            "node": "Send Hot Lead Follow-Up",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify Sales Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hourly Check for New Leads": {
      "main": [
        [
          {
            "node": "Read New Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read New Leads": {
      "main": [
        [
          {
            "node": "Process One at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process One at a Time": {
      "main": [
        [
          {
            "node": "Initiate ElevenLabs Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initiate ElevenLabs Call": {
      "main": [
        [
          {
            "node": "Wait 30s Between Calls",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 30s Between Calls": {
      "main": [
        [
          {
            "node": "Process One at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    {
      "name": "Sales",
      "id": "1"
    },
    {
      "name": "Voice Agent",
      "id": "2"
    },
    {
      "name": "ElevenLabs",
      "id": "3"
    }
  ]
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Sales Voice Agent - ElevenLabs + n8n. Uses httpRequest, openAi, gmail, googleSheets. Webhook trigger; 19 nodes.

Source: https://github.com/venglishkc/ai-sales-voice-agent/blob/main/sales-voice-agent.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.

Supabase, Gmail, Form Trigger +13
AI & RAG

Universal Expense tracker. Uses telegram, httpRequest, openAi, googleSheets. Webhook trigger; 33 nodes.

Telegram, HTTP Request, OpenAI +7
AI & RAG

ANIS_HUB 1. Uses gmail, googleDrive, googleSheets, httpRequest. Webhook trigger; 89 nodes.

Gmail, Google Drive, Google Sheets +3
AI & RAG

This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La

Google Sheets, HTTP Request, Slack +10
AI & RAG

Inbox Guardian. Uses gmailTrigger, lmChatOpenAi, agent, textClassifier. Event-driven trigger; 66 nodes.

Gmail Trigger, OpenAI Chat, Agent +12