GPT-4o:Twilio集成与自动跟进功能

高级

这是一个Content Creation、Multimodal AI领域的自动化工作流,包含 21 个节点。主要使用 If、Code、Wait、Merge、Slack 等节点。 GPT-4o:Twilio集成与自动跟进功能

前置要求
  • Slack Bot Token 或 Webhook URL
  • Airtable API Key
  • 可能需要目标 API 的认证凭证
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "meta": {
    "instanceId": "d23ca638a83fba54c06ee57ee6430730afe25e4177b234d2a702bd83cbe8f349"
  },
  "nodes": [
    {
      "id": "5f0e216a-ea69-4674-af22-3fe170cbd766",
      "name": "合并结果",
      "type": "n8n-nodes-base.merge",
      "position": [
        22416,
        16208
      ],
      "parameters": {},
      "typeVersion": 3
    },
    {
      "id": "b7116aa4-8d06-4ff4-8d74-da1b030a62f2",
      "name": "跟踪结果",
      "type": "n8n-nodes-base.code",
      "position": [
        22640,
        16208
      ],
      "parameters": {
        "jsCode": "// Track which channels were used\nconst items = $input.all();\n\n// Check if SMS was sent (will have twilio response)\nconst smsSent = items.some(item => item.json.sid || item.json.messageSid);\n\n// Check if Email was sent (will have email response)\nconst emailSent = items.some(item => item.json.accepted || item.json.messageId);\n\n// Get customer data from Prepare Messages node\nconst customerData = $('Prepare Messages2').first().json;\n\nreturn {\n  json: {\n    ...customerData,\n    sms_sent: smsSent,\n    email_sent: emailSent,\n    messages_sent_at: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "58a9ef5a-8fb0-4781-8eb0-b4dd3eeb6ad0",
      "name": "便签9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        19280,
        15872
      ],
      "parameters": {
        "width": 928,
        "height": 1392,
        "content": "## 📞 未接来电收入挽回机器人"
      },
      "typeVersion": 1
    },
    {
      "id": "f62d032e-17c4-498c-988a-434e2288a21c",
      "name": "检测到未接来电2",
      "type": "n8n-nodes-base.twilioTrigger",
      "position": [
        20352,
        16208
      ],
      "webhookId": "twilio-missed-call",
      "parameters": {
        "updates": [
          "com.twilio.voice.insights.call-summary.complete"
        ]
      },
      "credentials": {
        "twilioApi": {
          "id": "vDXzBZzToDaIu6Nn",
          "name": "Twilio account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fe521a57-2f91-45f5-a09d-efd7fd3cae9f",
      "name": "分析通话上下文2",
      "type": "n8n-nodes-base.code",
      "position": [
        20576,
        16208
      ],
      "parameters": {
        "jsCode": "// Extract and analyze call data\nconst callData = $input.first().json;\n\n// Twilio Call Status values:\n// 'completed' = answered and ended normally\n// 'no-answer' = no answer or rejected\n// 'busy' = busy signal\n// 'canceled' = hung up while queued/ringing\n// 'failed' = invalid number or error\n\n// Check if call was answered (CallDuration > 0 means conversation happened)\nconst callDuration = parseInt(callData.CallDuration) || 0;\nconst callStatus = callData.CallStatus || '';\n\n// Skip answered calls (completed with duration > 0)\nconst wasAnswered = callStatus === 'completed' && callDuration > 0;\n\nif (wasAnswered) {\n  return []; // Don't process answered calls\n}\n\n// Extract caller information (handle both camelCase and PascalCase)\nconst callerNumber = callData.From || callData.from || '';\nconst receiverNumber = callData.To || callData.to || '';\nconst timestamp = callData.Timestamp || callData.timestamp || new Date().toISOString();\nconst callTime = new Date(timestamp);\nconst currentHour = callTime.getHours();\n\n// Determine business context\nconst isBusinessHours = currentHour >= 9 && currentHour < 17;\nconst dayOfWeek = callTime.getDay();\nconst isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\n\nreturn {\n  json: {\n    caller_number: callerNumber,\n    receiver_number: receiverNumber,\n    call_time: callTime.toISOString(),\n    call_time_local: callTime.toLocaleString(),\n    call_status: callStatus,\n    call_duration: callDuration,\n    is_business_hours: isBusinessHours,\n    is_weekend: isWeekend,\n    call_sid: callData.CallSid || callData.callSid || '',\n    urgency_score: !isBusinessHours ? 8 : 5, // Higher urgency for after-hours calls\n    context: {\n      time_of_day: currentHour < 12 ? 'morning' : currentHour < 17 ? 'afternoon' : 'evening',\n      day_type: isWeekend ? 'weekend' : 'weekday'\n    }\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "e7a1c806-c63b-45f8-8bf5-51ffc12486d0",
      "name": "检查现有联系人2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        20800,
        16208
      ],
      "parameters": {
        "url": "=https://your-crm-api.com/contacts/search?phone={{ $json.caller_number }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4.1
    },
    {
      "id": "10faf764-b0e6-486b-92c7-8b08663af3ed",
      "name": "合并客户数据2",
      "type": "n8n-nodes-base.code",
      "position": [
        21024,
        16208
      ],
      "parameters": {
        "jsCode": "// Merge call data with CRM history\nconst callData = $('Analyze Call Context2').first().json;\nconst crmData = $input.first().json;\n\nconst hasHistory = crmData && crmData.contact;\nconst contact = crmData?.contact || {};\n\nreturn {\n  json: {\n    ...callData,\n    \n    // CRM Information\n    is_existing_customer: hasHistory,\n    customer_name: contact.name || 'Unknown',\n    customer_email: contact.email || null,\n    last_contact_date: contact.last_contact || null,\n    customer_status: contact.status || 'new',\n    previous_purchases: contact.purchase_count || 0,\n    lifetime_value: contact.lifetime_value || 0,\n    notes: contact.notes || '',\n    \n    // Prioritization\n    priority_level: hasHistory && contact.lifetime_value > 1000 ? 'high' : hasHistory ? 'medium' : 'new',\n    follow_up_urgency: hasHistory ? 'immediate' : 'standard'\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "be1b553a-725b-4a80-b901-1d469794bdaa",
      "name": "生成AI响应2",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        21280,
        16208
      ],
      "parameters": {
        "text": "=Generate a personalized missed call response for the following situation:\n\nCustomer Information:\n- Name: {{ $json.customer_name }}\n- Status: {{ $json.is_existing_customer ? 'Existing Customer' : 'New Prospect' }}\n- Priority: {{ $json.priority_level }}\n- Previous Purchases: {{ $json.previous_purchases }}\n\nCall Context:\n- Time: {{ $json.context.time_of_day }} on a {{ $json.context.day_type }}\n- Business Hours: {{ $json.is_business_hours ? 'Yes' : 'No (After Hours)' }}\n- Phone: {{ $json.caller_number }}\n\nCreate TWO versions:\n\n1. SMS_MESSAGE (160 chars max): Friendly, apologetic, includes booking link placeholder\n2. EMAIL_MESSAGE (200 words): Professional, personalized, multiple contact options\n\nReturn JSON with:\n- sms: Brief apologetic message\n- email_subject: Personalized subject line\n- email_body: Professional email with [BOOKING_LINK] placeholder\n- tone: warm/professional/urgent\n- recommended_channel: sms/email/both\n\nTone should be:\n- Warm and apologetic\n- Acknowledge their attempt to reach us\n- Offer immediate booking option\n- Personalize based on customer status",
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.4
    },
    {
      "id": "27649586-1171-4e61-8cf7-d1239ab8ce89",
      "name": "OpenAI聊天模型8",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        21248,
        16432
      ],
      "parameters": {
        "model": "gpt-4o",
        "options": {
          "maxTokens": 500,
          "temperature": 0.7
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d4e13bed-0f1b-41ea-a450-81b4e9ac5550",
      "name": "结构化输出解析器8",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        21376,
        16432
      ],
      "parameters": {
        "autoFix": true,
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"sms\": {\n      \"type\": \"string\",\n      \"description\": \"SMS message (160 chars max)\"\n    },\n    \"email_subject\": {\n      \"type\": \"string\",\n      \"description\": \"Email subject line\"\n    },\n    \"email_body\": {\n      \"type\": \"string\",\n      \"description\": \"Email body with [BOOKING_LINK] placeholder\"\n    },\n    \"tone\": {\n      \"type\": \"string\",\n      \"enum\": [\"warm\", \"professional\", \"urgent\"],\n      \"description\": \"Message tone\"\n    },\n    \"recommended_channel\": {\n      \"type\": \"string\",\n      \"enum\": [\"sms\", \"email\", \"both\"],\n      \"description\": \"Recommended communication channel\"\n    }\n  },\n  \"required\": [\"sms\", \"email_subject\", \"email_body\", \"tone\", \"recommended_channel\"]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "e16ca74e-3796-4f9f-8279-5aab98395133",
      "name": "准备消息2",
      "type": "n8n-nodes-base.code",
      "position": [
        21744,
        16208
      ],
      "parameters": {
        "jsCode": "// Parse AI response and prepare messages\nconst aiResponse = $input.first().json;\nconst customerData = $('Merge Customer Data2').first().json;\n\n// Generate booking link (Cal.com or Calendly)\nconst bookingUrl = 'https://cal.com/your-business'; // Replace with your booking link\nconst bookingLink = `${bookingUrl}?name=${encodeURIComponent(customerData.customer_name)}&phone=${encodeURIComponent(customerData.caller_number)}`;\n\n// Add booking link to messages\nconst smsWithLink = `${aiResponse.sms}\\n\\nBook instantly: ${bookingLink}`;\nconst emailWithLink = aiResponse.email_body.replace('[BOOKING_LINK]', bookingLink);\n\nreturn {\n  json: {\n    ...customerData,\n    \n    // AI-generated messages\n    sms_message: smsWithLink,\n    email_subject: aiResponse.email_subject,\n    email_body: emailWithLink,\n    message_tone: aiResponse.tone,\n    recommended_channel: aiResponse.recommended_channel,\n    \n    // Booking information\n    booking_link: bookingLink,\n    \n    // Metadata\n    response_generated_at: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "10884b30-701c-4c5f-8d92-abc00f9228a8",
      "name": "发送短信?2",
      "type": "n8n-nodes-base.if",
      "position": [
        21968,
        16112
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "sms-channel",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.recommended_channel }}",
              "rightValue": "sms"
            },
            {
              "id": "both-channels",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.recommended_channel }}",
              "rightValue": "both"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "52dce42a-1e0b-4389-bd9a-422b3dc04cba",
      "name": "发送短信2",
      "type": "n8n-nodes-base.twilio",
      "position": [
        22192,
        16112
      ],
      "parameters": {
        "to": "={{ $json.caller_number }}",
        "from": "+15551234567",
        "message": "={{ $json.sms_message }}",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "5c68f5ef-2058-4d58-a257-b6779488f3cb",
      "name": "发送邮件?2",
      "type": "n8n-nodes-base.if",
      "position": [
        21968,
        16304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-email",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.customer_email }}",
              "rightValue": ""
            },
            {
              "id": "email-channel",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.recommended_channel }}",
              "rightValue": "email"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "a76db0f7-5e55-4be4-947f-dc9921779442",
      "name": "发送邮件2",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        22192,
        16304
      ],
      "webhookId": "b3c6d8bc-0f42-4cbe-a05c-1d026f0d1c63",
      "parameters": {
        "options": {},
        "subject": "={{ $json.email_subject }}",
        "toEmail": "={{ $json.customer_email }}",
        "fromEmail": "your-business@example.com"
      },
      "credentials": {
        "smtp": {
          "id": "qmhzTud0RSbKigGt",
          "name": "SMTP account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "1ca48805-f52b-4e18-93f1-c79290d328a3",
      "name": "记录到CRM2",
      "type": "n8n-nodes-base.airtable",
      "position": [
        22864,
        16208
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_AIRTABLE_BASE_ID"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_AIRTABLE_TABLE_ID"
        },
        "columns": {
          "value": {
            "Status": "Pending Response",
            "Priority": "={{ $json.priority_level }}",
            "SMS_Sent": "={{ $json.sms_sent ? 'Yes' : 'No' }}",
            "Call_Time": "={{ $json.call_time }}",
            "Email_Sent": "={{ $json.email_sent ? 'Yes' : 'No' }}",
            "Booking_Link": "={{ $json.booking_link }}",
            "Caller_Number": "={{ $json.caller_number }}",
            "Customer_Name": "={{ $json.customer_name }}",
            "Urgency_Score": "={{ $json.urgency_score }}",
            "Follow_Up_Date": "={{ new Date(Date.now() + 86400000).toISOString() }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "upsert"
      },
      "typeVersion": 2
    },
    {
      "id": "da785def-5222-4e81-a0ed-8b9ef698732d",
      "name": "通知销售团队3",
      "type": "n8n-nodes-base.slack",
      "position": [
        23088,
        16208
      ],
      "webhookId": "3ad339ab-392a-44ad-b967-aa02e04de2af",
      "parameters": {
        "text": "=📞 *Missed Call Alert*\n\n*Customer:* {{ $json.customer_name }}{{ $json.is_existing_customer ? ' (Existing Customer 🌟)' : ' (New Prospect)' }}\n*Phone:* {{ $json.caller_number }}\n*Time:* {{ $json.call_time_local }}\n*Priority:* {{ $json.priority_level.toUpperCase() }}\n\n*Context:*\n• Call during: {{ $json.is_business_hours ? 'Business Hours' : 'After Hours ⚠️' }}\n• Customer Status: {{ $json.customer_status }}\n{{ $json.previous_purchases > 0 ? '• Previous Purchases: ' + $json.previous_purchases : '' }}\n{{ $json.lifetime_value > 0 ? '• Lifetime Value: $' + $json.lifetime_value : '' }}\n\n*Auto-Response Sent:*\n{{ $json.sms_sent ? '✅ SMS' : '❌ SMS' }} | {{ $json.email_sent ? '✅ Email' : '❌ Email' }}\n\n*Booking Link:* {{ $json.booking_link }}\n\n🎯 *Action Required:* {{ $json.follow_up_urgency === 'immediate' ? 'Call back ASAP!' : 'Follow up within 24 hours' }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_SLACK_SALES_CHANNEL_ID"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a162a326-8ad2-499a-b6a1-5d004683570f",
      "name": "等待24小时2",
      "type": "n8n-nodes-base.wait",
      "position": [
        23312,
        16208
      ],
      "webhookId": "8c3d23ad-f82f-4e2f-b4af-fb1b19e5b790",
      "parameters": {
        "unit": "hours",
        "amount": 24
      },
      "typeVersion": 1.1
    },
    {
      "id": "ed555f98-119d-4d52-822f-88730c1324e8",
      "name": "检查是否已预订2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        23536,
        16208
      ],
      "parameters": {
        "url": "=https://your-crm-api.com/contacts/{{ $json.caller_number }}/bookings",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "exVxOWDpxBu7XVql",
          "name": "nithichote.com header auth key"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "0433e538-eef4-48d8-9511-668bfe41fc27",
      "name": "无响应?2",
      "type": "n8n-nodes-base.if",
      "position": [
        23760,
        16208
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "no-booking",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.booking_count || 0 }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "5a1e4e37-abf8-4979-b90b-7ba2da1f05e7",
      "name": "发送跟进短信2",
      "type": "n8n-nodes-base.twilio",
      "position": [
        23984,
        16208
      ],
      "parameters": {
        "to": "={{ $json.caller_number }}",
        "from": "+15551234567",
        "message": "=Hi {{ $json.customer_name }},\n\nWe tried reaching you yesterday. Still interested in scheduling?\n\nBook now: {{ $json.booking_link }}\n\nOr call us: +1-555-0100\n\nThanks!\nYour Business Name",
        "options": {}
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Send SMS2": {
      "main": [
        [
          {
            "node": "Merge Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send SMS?2": {
      "main": [
        [
          {
            "node": "Send SMS2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to CRM2": {
      "main": [
        [
          {
            "node": "Notify Sales Team3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email2": {
      "main": [
        [
          {
            "node": "Merge Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Send Email?2": {
      "main": [
        [
          {
            "node": "Send Email2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Results": {
      "main": [
        [
          {
            "node": "Track Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No Response?2": {
      "main": [
        [
          {
            "node": "Send Follow-up SMS2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Track Results": {
      "main": [
        [
          {
            "node": "Log to CRM2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 24 Hours2": {
      "main": [
        [
          {
            "node": "Check if Booked2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Booked2": {
      "main": [
        [
          {
            "node": "No Response?2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Messages2": {
      "main": [
        [
          {
            "node": "Send SMS?2",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Email?2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Sales Team3": {
      "main": [
        [
          {
            "node": "Wait 24 Hours2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model8": {
      "ai_languageModel": [
        [
          {
            "node": "Generate AI Response2",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Structured Output Parser8",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Merge Customer Data2": {
      "main": [
        [
          {
            "node": "Generate AI Response2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Call Context2": {
      "main": [
        [
          {
            "node": "Check Existing Contact2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate AI Response2": {
      "main": [
        [
          {
            "node": "Prepare Messages2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Missed Call Detected2": {
      "main": [
        [
          {
            "node": "Analyze Call Context2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Existing Contact2": {
      "main": [
        [
          {
            "node": "Merge Customer Data2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser8": {
      "ai_outputParser": [
        [
          {
            "node": "Generate AI Response2",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

这是一个高级难度的工作流,适用于Content Creation、Multimodal AI等场景。适合高级用户,包含 16+ 个节点的复杂工作流

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量21
分类2
节点类型14
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
Greypillar

Greypillar

@greypillar

We design AI systems that fix hidden revenue leaks in service businesses. Every engagement starts with one guaranteed win in 30 days — no risk, just results.

外部链接
在 n8n.io 上查看 →

分享此工作流