8
n8n 中文网amn8n.com

我的工作流3

中级

这是一个AI领域的自动化工作流,包含 15 个节点。主要使用 If, Merge, Slack, Webhook, Function 等节点,结合人工智能技术实现智能自动化。 多渠道客户支持自动化套件

前置要求
  • Slack Bot Token 或 Webhook URL
  • HTTP Webhook 端点(n8n 会自动生成)
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "OUvCtjVgtro3MT2J",
  "meta": {
    "instanceId": "0d1aac533628b88b03392640352a107d7fb2b1999c77dfa29323f9815e9d2e71"
  },
  "name": "我的工作流 3",
  "tags": [],
  "nodes": [
    {
      "id": "2b5c3f5d-bf7d-41be-bae2-c5785add0f07",
      "name": "邮件触发器",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [
        220,
        240
      ],
      "parameters": {
        "options": {
          "customEmailConfig": "=[\"UNSEEN\"]"
        },
        "postProcessAction": "nothing"
      },
      "typeVersion": 2
    },
    {
      "id": "fcccc1d7-e4d6-4f40-87bf-3eebd058a62d",
      "name": "网页表单 Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        220,
        440
      ],
      "webhookId": "support-form-webhook",
      "parameters": {
        "path": "support-ticket",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 1
    },
    {
      "id": "526cdbed-260d-46e5-b47d-497a4ea1c8d8",
      "name": "标准化消息",
      "type": "n8n-nodes-base.function",
      "position": [
        600,
        340
      ],
      "parameters": {
        "functionCode": "// Normalize incoming messages from different channels\nconst items = [];\n\nfor (const item of $input.all()) {\n  const source = item.json;\n  \n  let normalizedTicket = {\n    id: 'TKT-' + Date.now() + '-' + Math.random().toString(36).substr(2, 5),\n    timestamp: new Date().toISOString(),\n    channel: '',\n    customer: {\n      name: '',\n      email: '',\n      id: ''\n    },\n    message: {\n      subject: '',\n      body: '',\n      attachments: []\n    },\n    metadata: {},\n    sourceData: source\n  };\n\n  // Check if this is from Email Trigger\n  if (source.from && source.subject) {\n    normalizedTicket.channel = 'email';\n    normalizedTicket.customer.email = source.from.value?.[0]?.address || source.from;\n    normalizedTicket.customer.name = source.from.value?.[0]?.name || 'Email Customer';\n    normalizedTicket.message.subject = source.subject;\n    normalizedTicket.message.body = source.text || source.html || '';\n    if (source.attachments) {\n      normalizedTicket.message.attachments = source.attachments.map(att => ({\n        filename: att.filename,\n        size: att.size\n      }));\n    }\n  }\n  // Check if this is from Web Form\n  else if (source.body && (source.body.email || source.body.name)) {\n    normalizedTicket.channel = 'webform';\n    normalizedTicket.customer.name = source.body.name || 'Web Form User';\n    normalizedTicket.customer.email = source.body.email || '';\n    normalizedTicket.message.subject = source.body.subject || 'Web Form Submission';\n    normalizedTicket.message.body = source.body.message || source.body.description || '';\n  }\n  // Generic webhook data\n  else {\n    normalizedTicket.channel = 'webhook';\n    normalizedTicket.customer.name = source.name || source.customerName || 'Unknown';\n    normalizedTicket.customer.email = source.email || source.customerEmail || '';\n    normalizedTicket.message.subject = source.subject || 'Support Request';\n    normalizedTicket.message.body = source.message || source.body || JSON.stringify(source);\n  }\n\n  items.push({\n    json: normalizedTicket\n  });\n}\n\nreturn items;"
      },
      "typeVersion": 1
    },
    {
      "id": "0aef988c-3364-4a9a-bbef-e2156febe585",
      "name": "分类与优先级排序",
      "type": "n8n-nodes-base.function",
      "position": [
        800,
        340
      ],
      "parameters": {
        "functionCode": "// Categorize and prioritize tickets based on content\nconst items = [];\n\nfor (const item of $input.all()) {\n  const ticket = item.json;\n  const message = (ticket.message.body + ' ' + ticket.message.subject).toLowerCase();\n  \n  let category = 'general';\n  let priority = 'medium';\n  let tags = [];\n  let sentiment = 'neutral';\n  \n  // Category detection rules\n  const categoryRules = {\n    'billing': ['invoice', 'payment', 'charge', 'refund', 'subscription', 'cancel', 'upgrade', 'downgrade', 'pricing', 'cost', 'bill'],\n    'technical': ['bug', 'error', 'broken', 'not working', 'crash', 'slow', 'issue', 'problem', 'fix', '500', '404', 'loading'],\n    'account': ['password', 'login', 'access', 'account', 'email', 'username', '2fa', 'locked', 'forgot', 'reset', 'sign in'],\n    'feature': ['feature', 'request', 'suggestion', 'improvement', 'add', 'would be nice', 'enhancement', 'idea'],\n    'complaint': ['terrible', 'awful', 'worst', 'hate', 'angry', 'frustrated', 'disappointed', 'unacceptable', 'ridiculous']\n  };\n  \n  // Check categories\n  for (const [cat, keywords] of Object.entries(categoryRules)) {\n    if (keywords.some(keyword => message.includes(keyword))) {\n      category = cat;\n      tags.push(cat);\n      break;\n    }\n  }\n  \n  // Sentiment analysis (simplified)\n  const negativeWords = ['not working', 'broken', 'error', 'angry', 'frustrated', 'terrible', 'awful', 'worst', 'hate', 'disappointed', 'unacceptable'];\n  const positiveWords = ['thank', 'great', 'excellent', 'love', 'amazing', 'fantastic', 'wonderful', 'perfect'];\n  const urgentWords = ['urgent', 'asap', 'emergency', 'critical', 'immediately', 'now', 'quickly'];\n  \n  const negativeCount = negativeWords.filter(word => message.includes(word)).length;\n  const positiveCount = positiveWords.filter(word => message.includes(word)).length;\n  \n  if (negativeCount > positiveCount + 1) {\n    sentiment = 'negative';\n    tags.push('negative_sentiment');\n  } else if (positiveCount > negativeCount + 1) {\n    sentiment = 'positive';\n    tags.push('positive_sentiment');\n  }\n  \n  // Priority rules\n  if (urgentWords.some(word => message.includes(word))) {\n    priority = 'urgent';\n    tags.push('urgent');\n  } else if (category === 'complaint' || sentiment === 'negative') {\n    priority = 'high';\n  } else if (category === 'billing' || category === 'account') {\n    priority = 'high';\n  }\n  \n  // Check for VIP customers (you can add your VIP domains here)\n  const vipDomains = ['enterprise.com', 'vip.com', 'premium.com'];\n  if (ticket.customer.email && vipDomains.some(domain => ticket.customer.email.includes(domain))) {\n    priority = priority === 'medium' ? 'high' : priority;\n    tags.push('vip_customer');\n  }\n  \n  items.push({\n    json: {\n      ...ticket,\n      category,\n      priority,\n      tags,\n      sentiment,\n      requiresHumanReview: priority === 'urgent' || sentiment === 'negative',\n      autoResponseEligible: priority !== 'urgent' && sentiment !== 'negative' && category !== 'complaint'\n    }\n  });\n}\n\nreturn items;"
      },
      "typeVersion": 1
    },
    {
      "id": "d0186a2f-34b0-4c68-921f-3050f270dd1a",
      "name": "检查自动回复",
      "type": "n8n-nodes-base.if",
      "position": [
        1000,
        340
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{$json[\"autoResponseEligible\"]}}",
              "value2": true
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fa5ecd58-23e9-4194-9bb5-954e6b1b7e05",
      "name": "生成自动回复",
      "type": "n8n-nodes-base.function",
      "position": [
        1200,
        240
      ],
      "parameters": {
        "functionCode": "// Generate auto-response based on category\nconst items = [];\n\nfor (const item of $input.all()) {\n  const ticket = item.json;\n  \n  const templates = {\n    'billing': {\n      subject: `Re: Your billing inquiry - ${ticket.id}`,\n      body: `Hello ${ticket.customer.name || 'Valued Customer'},\n\nThank you for contacting us about your billing concern. We understand how important this is.\n\nYour ticket (${ticket.id}) has been received and forwarded to our billing department. You can expect a response within 2-4 business hours.\n\nIn the meantime, you might find these resources helpful:\n- Billing FAQ: https://support.yourcompany.com/billing\n- View invoices: https://app.yourcompany.com/billing\n\nBest regards,\nCustomer Support Team`\n    },\n    'technical': {\n      subject: `Re: Technical support request - ${ticket.id}`,\n      body: `Hello ${ticket.customer.name || 'Valued Customer'},\n\nWe've received your technical support request (${ticket.id}).\n\nOur technical team is reviewing your issue. To help us resolve this faster, please ensure you've provided:\n- Description of the issue\n- Steps to reproduce\n- Any error messages\n\nExpected response time: Within 4-6 hours\n\nBest regards,\nTechnical Support Team`\n    },\n    'account': {\n      subject: `Re: Account assistance - ${ticket.id}`,\n      body: `Hello ${ticket.customer.name || 'Valued Customer'},\n\nWe've received your account-related request (${ticket.id}).\n\nFor security reasons, our account specialists will handle this personally. You'll hear from us within 1-2 business hours.\n\nBest regards,\nAccount Security Team`\n    },\n    'feature': {\n      subject: `Re: Feature request received - ${ticket.id}`,\n      body: `Hello ${ticket.customer.name || 'Valued Customer'},\n\nThank you for your feature suggestion! We love hearing from our users.\n\nYour request (${ticket.id}) has been logged and will be reviewed by our product team. We consider all feedback when planning future updates.\n\nBest regards,\nProduct Team`\n    },\n    'general': {\n      subject: `Re: ${ticket.message.subject} - ${ticket.id}`,\n      body: `Hello ${ticket.customer.name || 'Valued Customer'},\n\nThank you for contacting support. We've received your request (${ticket.id}) and our team is reviewing it.\n\nWe'll get back to you within 24 business hours.\n\nBest regards,\nCustomer Support Team`\n    }\n  };\n  \n  const template = templates[ticket.category] || templates['general'];\n  \n  items.push({\n    json: {\n      ...ticket,\n      autoResponse: {\n        to: ticket.customer.email,\n        subject: template.subject,\n        body: template.body,\n        shouldSend: !!ticket.customer.email && ticket.autoResponseEligible\n      }\n    }\n  });\n}\n\nreturn items;"
      },
      "typeVersion": 1
    },
    {
      "id": "67eeb519-d0d6-44f4-aef6-3897159621fb",
      "name": "发送自动回复",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1400,
        240
      ],
      "webhookId": "69b9ec96-0edd-4747-ab7d-d9e0006b5175",
      "parameters": {
        "text": "={{$json[\"autoResponse\"][\"body\"]}}",
        "options": {},
        "subject": "={{$json[\"autoResponse\"][\"subject\"]}}",
        "toEmail": "={{$json[\"autoResponse\"][\"to\"]}}",
        "fromEmail": "support@yourcompany.com"
      },
      "typeVersion": 2,
      "continueOnFail": true
    },
    {
      "id": "352f497d-9b66-40c5-8a0a-cfac715db269",
      "name": "通知 Slack",
      "type": "n8n-nodes-base.slack",
      "onError": "continueErrorOutput",
      "position": [
        1200,
        440
      ],
      "webhookId": "d2b03044-781c-477d-bff7-92065a35efd3",
      "parameters": {
        "text": "=🎫 New {{$json[\"priority\"]}} Priority Ticket",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "28iMYDLTDQPtb6Ew",
          "name": "O2 Personal Account"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b6eb4722-5a89-41b0-a865-f2a2ea8851c7",
      "name": "存储到 CRM",
      "type": "n8n-nodes-base.function",
      "position": [
        1400,
        440
      ],
      "parameters": {
        "functionCode": "// Store ticket in database or CRM\n// This is a placeholder - replace with your actual CRM node (Zendesk, HubSpot, etc.)\n\nconst items = [];\n\nfor (const item of $input.all()) {\n  const ticket = item.json;\n  \n  // Example structure for CRM integration\n  const crmTicket = {\n    external_id: ticket.id,\n    subject: ticket.message.subject || `Support Request from ${ticket.channel}`,\n    description: ticket.message.body,\n    priority: ticket.priority,\n    status: 'new',\n    channel: ticket.channel,\n    tags: ticket.tags,\n    custom_fields: {\n      sentiment: ticket.sentiment,\n      category: ticket.category,\n      auto_response_sent: ticket.autoResponseEligible\n    },\n    requester: {\n      name: ticket.customer.name,\n      email: ticket.customer.email\n    },\n    created_at: ticket.timestamp\n  };\n  \n  // In production, you would send this to your CRM API\n  console.log('Would create ticket in CRM:', crmTicket);\n  \n  items.push({\n    json: {\n      ...ticket,\n      crmTicket,\n      stored: true\n    }\n  });\n}\n\nreturn items;"
      },
      "typeVersion": 1
    },
    {
      "id": "92de134e-ac68-4f99-87a4-d7fcbada6a1f",
      "name": "记录成功",
      "type": "n8n-nodes-base.function",
      "position": [
        1600,
        340
      ],
      "parameters": {
        "functionCode": "// Log success metrics\nconst items = [];\n\nfor (const item of $input.all()) {\n  const ticket = item.json;\n  \n  const metrics = {\n    timestamp: new Date().toISOString(),\n    ticketId: ticket.id,\n    channel: ticket.channel,\n    category: ticket.category,\n    priority: ticket.priority,\n    sentiment: ticket.sentiment,\n    autoResponseSent: ticket.autoResponseEligible,\n    processingTime: Date.now() - new Date(ticket.timestamp).getTime(),\n    success: true\n  };\n  \n  // Log to console (in production, send to analytics platform)\n  console.log('Ticket processed successfully:', metrics);\n  \n  items.push({ json: metrics });\n}\n\nreturn items;"
      },
      "typeVersion": 1
    },
    {
      "id": "aec8fd1f-6a51-4f8b-b001-541646619b8a",
      "name": "错误处理器",
      "type": "n8n-nodes-base.function",
      "position": [
        1400,
        640
      ],
      "parameters": {
        "functionCode": "// Handle errors and log them\nconst error = $json[\"error\"];\nconst originalData = $json[\"originalData\"] || {};\n\nconst errorLog = {\n  timestamp: new Date().toISOString(),\n  workflow: 'customer-support-automation',\n  error: {\n    message: error?.message || 'Unknown error',\n    code: error?.code,\n    node: error?.node\n  },\n  ticketId: originalData.id || 'unknown',\n  channel: originalData.channel || 'unknown',\n  recovery: 'manual_intervention_required'\n};\n\n// In production, send to error tracking service (Sentry, etc.)\nconsole.error('Workflow error:', errorLog);\n\n// Could also send critical errors to Slack\nreturn [{ json: errorLog }];"
      },
      "typeVersion": 1
    },
    {
      "id": "043ceb80-fe46-4f59-8a31-dffd67144364",
      "name": "合并",
      "type": "n8n-nodes-base.merge",
      "position": [
        400,
        340
      ],
      "parameters": {},
      "typeVersion": 2
    },
    {
      "id": "fade1855-3973-493d-8d17-841cf1ad1097",
      "name": "错误通知到 Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1600,
        640
      ],
      "parameters": {
        "url": "=https://hooks.slack.com/services/YOUR/WEBHOOK/URL",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "text",
              "value": "=⚠️ Error in support automation: {{$json[\"error\"][\"message\"]}}"
            }
          ]
        }
      },
      "typeVersion": 3,
      "continueOnFail": true
    },
    {
      "id": "67fa2e0e-c3b8-47ba-807e-46af2720408e",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -300,
        140
      ],
      "parameters": {
        "width": 389,
        "height": 464,
        "content": "## 多渠道客户支持自动化"
      },
      "typeVersion": 1
    },
    {
      "id": "1eb04a7a-6519-4336-9588-f74b6528a6a7",
      "name": "Webhook响应",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1800,
        340
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d53058f5-8312-4553-913b-45de35c35900",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Normalize Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Success": {
      "main": [
        [
          {
            "node": "Webhook Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Slack": {
      "main": [
        [
          {
            "node": "Store in CRM",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Error Handler",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store in CRM": {
      "main": [
        [
          {
            "node": "Log Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Trigger": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Error Handler": {
      "main": [
        [
          {
            "node": "Notify Error to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Web Form Webhook": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Normalize Messages": {
      "main": [
        [
          {
            "node": "Categorize & Prioritize",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Auto-Response": {
      "main": [
        [
          {
            "node": "Notify Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Auto-Response": {
      "main": [
        [
          {
            "node": "Generate Auto-Response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Auto-Response": {
      "main": [
        [
          {
            "node": "Send Auto-Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Categorize & Prioritize": {
      "main": [
        [
          {
            "node": "Check Auto-Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

中级 - 人工智能

需要付费吗?

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

工作流信息
难度等级
中级
节点数量15
分类1
节点类型10
难度说明

适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

作者
Elie Kattar

Elie Kattar

@solutionflows

Multimedia Consultant Working in the Field Since 2009, Creating Simple Solutions to speed-up day-to-day tasks

外部链接
在 n8n.io 查看

分享此工作流