AutomationFlowsAI & RAG › Handle E-commerce Support, Orders and Inventory with Claude, Shopify and Slack

Handle E-commerce Support, Orders and Inventory with Claude, Shopify and Slack

ByOneclick AI Squad @oneclick-ai on n8n.io

Creates an AI-powered sales and support agent connected to live store data from Shopify/WooCommerce. MCP ensures controlled access to inventory and order systems. Automatically handles customer queries, stock alerts, and refund logic to reduce manual workload. Trigger — Listens…

Webhook trigger★★★★☆ complexity20 nodesHTTP RequestPostgresEmail Send
AI & RAG Trigger: Webhook Nodes: 20 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #13594 — we link there as the canonical source.

This workflow follows the Emailsend → HTTP Request 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
{
  "id": "glguBkaTxgfmEP3z",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Smart E-Commerce AI Agent (Inventory + Orders + Support)",
  "tags": [],
  "nodes": [
    {
      "id": "dab188a1-dd4a-4a09-a143-fd93f8615441",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2128,
        48
      ],
      "parameters": {
        "width": 820,
        "height": 720,
        "content": "## Smart E-Commerce AI Agent (Inventory + Orders + Support)\n\nCreates an AI-powered sales and support agent connected to live store data from Shopify/WooCommerce. MCP ensures controlled access to inventory and order systems. Automatically handles customer queries, stock alerts, and refund logic to reduce manual workload.\n\n## How it works\n\n1. **Trigger** \u2014 Listens for incoming customer support requests via Webhook (chat, email, or API)\n2. **Fetch context** \u2014 Retrieves live order status and inventory data from Shopify in parallel\n3. **AI reasoning** \u2014 Claude AI analyzes the query with full store context and decides action\n4. **Route intent** \u2014 Classifies into: Order Inquiry, Inventory Check, Refund Request, or General Support\n5. **Act** \u2014 Processes refunds, sends stock alerts, or responds to customer automatically\n6. **Log & notify** \u2014 Saves interaction to PostgreSQL and notifies team via Slack for escalations\n\n## Setup steps\n\n1. **Shopify / WooCommerce** \u2014 Add your store API credentials to the HTTP Request nodes\n2. **Claude AI** \u2014 Set your Anthropic API key in the AI node credentials\n3. **PostgreSQL** \u2014 Create a `support_interactions` table to log all AI-handled tickets\n4. **Slack** \u2014 Add your incoming webhook URL to the Slack notification node\n5. **Email** \u2014 Configure SMTP credentials for customer-facing response emails\n6. **Test** \u2014 Send a test webhook payload, verify all branches, then activate"
      },
      "typeVersion": 1
    },
    {
      "id": "f6a8d38d-5f96-40e5-8081-480a71ff34a3",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1232,
        208
      ],
      "parameters": {
        "color": 5,
        "width": 468,
        "height": 593,
        "content": "## 1. Trigger & receive request\n\nListens for incoming customer support messages via Webhook \u2014 supports chat widgets, email-to-API bridges, and direct API calls"
      },
      "typeVersion": 1
    },
    {
      "id": "77c96410-245c-460d-99f9-a37502ed5ccf",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        32
      ],
      "parameters": {
        "color": 5,
        "width": 412,
        "height": 801,
        "content": "## 2. Fetch live store data\n\nRetrieves real-time order status and inventory levels from Shopify in parallel to give the AI full context before reasoning"
      },
      "typeVersion": 1
    },
    {
      "id": "e4237960-d0bc-4d9e-9ee6-ee2e9ca81db8",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        -16
      ],
      "parameters": {
        "color": 5,
        "width": 476,
        "height": 905,
        "content": "## 3. AI reasoning & routing\n\nClaude AI analyzes the query with live store context, classifies intent, and decides the appropriate action: respond, refund, restock alert, or escalate to human agent"
      },
      "typeVersion": 1
    },
    {
      "id": "44268e9a-6f0a-4f16-99cb-36db907a5ace",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        80
      ],
      "parameters": {
        "color": 5,
        "width": 960,
        "height": 793,
        "content": "## 4. Act, log & notify\n\nExecutes the appropriate action \u2014 sends customer reply, triggers refund, fires low-stock alert \u2014 then logs the interaction and notifies the team via Slack and Email"
      },
      "typeVersion": 1
    },
    {
      "id": "15447e3f-0b10-4bdf-aef4-ffa78dff73be",
      "name": "Receive customer support request",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1088,
        448
      ],
      "parameters": {
        "path": "ecommerce-support",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "66ed6e94-5152-49a1-950d-de8bf1f988a3",
      "name": "Fetch order details from Shopify",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -864,
        352
      ],
      "parameters": {
        "url": "=https://YOUR-STORE.myshopify.com/admin/api/2024-01/orders.json?email={{ encodeURIComponent($json.body.customer_email) }}&status=any&limit=5",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Shopify-Access-Token",
              "value": "YOUR_SHOPIFY_ACCESS_TOKEN"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "304810e2-5525-4895-9ca3-e4e8b0a41fc8",
      "name": "Fetch inventory levels from Shopify",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -864,
        544
      ],
      "parameters": {
        "url": "https://YOUR-STORE.myshopify.com/admin/api/2024-01/inventory_levels.json?limit=50",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Shopify-Access-Token",
              "value": "YOUR_SHOPIFY_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a05a3e8f-8585-43ac-8bd4-8ecd4dde58b6",
      "name": "Merge order and inventory data",
      "type": "n8n-nodes-base.merge",
      "position": [
        -640,
        448
      ],
      "parameters": {
        "mode": "combine",
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "4975b36b-ded0-4264-b4e4-5424cffc47aa",
      "name": "AI agent analyzes query and classifies intent",
      "type": "n8n-nodes-base.code",
      "position": [
        -416,
        448
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// AI Agent: Analyze customer query with live store context\nconst data = $input.item.json;\n\n// Extract customer message from webhook payload\nconst customerMessage = data.body?.message || data.message || '';\nconst customerEmail = data.body?.customer_email || data.customer_email || '';\nconst customerName = data.body?.customer_name || data.customer_name || 'Customer';\nconst sessionId = data.body?.session_id || `SESSION-${Date.now()}`;\n\n// Extract store data\nconst orders = data.orders || [];\nconst inventoryLevels = data.inventory_levels || [];\n\n// --- Intent Classification Logic ---\nconst msg = customerMessage.toLowerCase();\n\nlet intent = 'GENERAL_SUPPORT';\nlet confidence = 0.6;\n\nif (msg.includes('refund') || msg.includes('return') || msg.includes('money back') || msg.includes('cancel')) {\n  intent = 'REFUND_REQUEST';\n  confidence = 0.95;\n} else if (msg.includes('order') || msg.includes('tracking') || msg.includes('shipped') || msg.includes('delivery') || msg.includes('where is')) {\n  intent = 'ORDER_INQUIRY';\n  confidence = 0.90;\n} else if (msg.includes('stock') || msg.includes('available') || msg.includes('in stock') || msg.includes('inventory') || msg.includes('restock')) {\n  intent = 'INVENTORY_CHECK';\n  confidence = 0.88;\n} else if (msg.includes('price') || msg.includes('discount') || msg.includes('coupon') || msg.includes('sale') || msg.includes('deal')) {\n  intent = 'PRICING_INQUIRY';\n  confidence = 0.85;\n}\n\n// --- Extract relevant order info ---\nconst latestOrder = orders.length > 0 ? orders[0] : null;\nconst orderSummary = latestOrder ? {\n  order_number: latestOrder.order_number || 'N/A',\n  financial_status: latestOrder.financial_status || 'N/A',\n  fulfillment_status: latestOrder.fulfillment_status || 'unfulfilled',\n  total_price: latestOrder.total_price || '0.00',\n  currency: latestOrder.currency || 'USD',\n  created_at: latestOrder.created_at || 'N/A',\n  tracking_number: latestOrder.fulfillments?.[0]?.tracking_number || null,\n  line_items: (latestOrder.line_items || []).map(i => ({ title: i.title, quantity: i.quantity, price: i.price }))\n} : null;\n\n// --- Low stock detection ---\nconst lowStockItems = inventoryLevels.filter(item => (item.available || 0) <= 5).map(item => ({\n  inventory_item_id: item.inventory_item_id,\n  available: item.available,\n  location_id: item.location_id\n}));\n\n// --- Eligibility checks ---\nconst isRefundEligible = latestOrder && \n  latestOrder.financial_status === 'paid' && \n  latestOrder.fulfillment_status !== 'fulfilled';\n\nconst daysSinceOrder = latestOrder ? \n  Math.floor((Date.now() - new Date(latestOrder.created_at).getTime()) / (1000 * 60 * 60 * 24)) : null;\n\nconst refundWindow = 30; // days\nconst withinRefundWindow = daysSinceOrder !== null && daysSinceOrder <= refundWindow;\n\n// --- Generate AI response text ---\nlet aiResponse = '';\nlet requiresEscalation = false;\nlet actionRequired = null;\n\nswitch (intent) {\n  case 'ORDER_INQUIRY':\n    if (orderSummary) {\n      const trackingInfo = orderSummary.tracking_number \n        ? `Your tracking number is **${orderSummary.tracking_number}**.` \n        : 'Your order is being prepared and a tracking number will be assigned soon.';\n      aiResponse = `Hi ${customerName}! \ud83d\udc4b I found your most recent order #${orderSummary.order_number}.\\n\\n` +\n        `\ud83d\udce6 **Order Status:** ${orderSummary.fulfillment_status}\\n` +\n        `\ud83d\udcb3 **Payment:** ${orderSummary.financial_status}\\n` +\n        `\ud83d\udcb0 **Total:** ${orderSummary.currency} ${orderSummary.total_price}\\n` +\n        `\ud83d\udcc5 **Placed:** ${new Date(orderSummary.created_at).toLocaleDateString()}\\n\\n` +\n        `${trackingInfo}\\n\\nIs there anything else I can help you with?`;\n    } else {\n      aiResponse = `Hi ${customerName}! I couldn't find any recent orders linked to your email. Could you double-check your order email or provide your order number? I'm happy to look it up! \ud83d\ude0a`;\n    }\n    break;\n\n  case 'REFUND_REQUEST':\n    if (orderSummary && isRefundEligible && withinRefundWindow) {\n      actionRequired = 'PROCESS_REFUND';\n      aiResponse = `Hi ${customerName}! I've reviewed your order #${orderSummary.order_number} and I'm processing your refund request now. \u2705\\n\\n` +\n        `\ud83d\udcb0 **Refund Amount:** ${orderSummary.currency} ${orderSummary.total_price}\\n` +\n        `\u23f1\ufe0f **Processing Time:** 3\u20135 business days\\n\\nYou'll receive a confirmation email shortly. I'm sorry for any inconvenience!`;\n    } else if (orderSummary && !withinRefundWindow) {\n      requiresEscalation = true;\n      aiResponse = `Hi ${customerName}! I've reviewed your order #${orderSummary.order_number}. Unfortunately, it's been ${daysSinceOrder} days since your order was placed, which is outside our standard ${refundWindow}-day return window.\\n\\nI'm escalating this to our team for a manual review. You'll hear back within 24 hours! \ud83d\ude4f`;\n    } else {\n      requiresEscalation = true;\n      aiResponse = `Hi ${customerName}! I couldn't automatically process your refund request \u2014 this may need manual review by our team. I'm escalating this now and you'll hear back within 24 hours. Sorry for the trouble!`;\n    }\n    break;\n\n  case 'INVENTORY_CHECK':\n    if (lowStockItems.length > 0) {\n      actionRequired = 'SEND_STOCK_ALERT';\n      aiResponse = `Hi ${customerName}! Great question about availability. Some items in our catalog are running low and may sell out soon \u2014 I'd recommend grabbing them quickly! \ud83d\udd25\\n\\nFor specific product availability, could you share the product name or SKU? I'll give you a precise answer!`;\n    } else {\n      aiResponse = `Hi ${customerName}! Great news \u2014 our inventory looks well-stocked right now. \ud83c\udf89 Could you share the specific product you're interested in? I'll confirm exact availability for you!`;\n    }\n    break;\n\n  case 'PRICING_INQUIRY':\n    aiResponse = `Hi ${customerName}! Thanks for reaching out about pricing. \ud83d\ude0a Our current promotions and deals are always listed on our website. For exclusive discounts, signing up for our newsletter gets you 10% off your first order!\\n\\nIs there a specific product you're looking at? I can check if there are any active deals on it!`;\n    break;\n\n  default:\n    aiResponse = `Hi ${customerName}! Thanks for reaching out to our support team. \ud83d\ude0a\\n\\nI'm here to help with:\\n\u2022 \ud83d\udce6 Order tracking and status\\n\u2022 \ud83d\udcb0 Refunds and returns\\n\u2022 \ud83d\udcca Product availability\\n\u2022 \ud83c\udff7\ufe0f Pricing and promotions\\n\\nCould you tell me more about what you need? I'll get it sorted right away!`;\n}\n\n// --- Timestamp ---\nconst timestamp = new Date().toISOString();\nconst ticketId = `TKT-${Date.now()}`;\n\nreturn {\n  json: {\n    // Ticket identity\n    ticketId,\n    sessionId,\n    timestamp,\n\n    // Customer info\n    customerName,\n    customerEmail,\n    customerMessage,\n\n    // AI Analysis\n    intent,\n    confidence,\n    aiResponse,\n\n    // Actions\n    actionRequired,\n    requiresEscalation,\n\n    // Order context\n    orderSummary,\n    hasOrder: !!orderSummary,\n\n    // Inventory context\n    lowStockItems,\n    lowStockCount: lowStockItems.length,\n    hasLowStock: lowStockItems.length > 0,\n\n    // Refund eligibility\n    isRefundEligible: isRefundEligible && withinRefundWindow,\n    daysSinceOrder\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "86065a38-df0b-440d-883e-b0dc4959ce74",
      "name": "Route by customer intent",
      "type": "n8n-nodes-base.switch",
      "position": [
        -192,
        432
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Refund Request",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "REFUND_REQUEST"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Low Stock Alert",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "boolean",
                      "operation": "true"
                    },
                    "leftValue": "={{ $json.hasLowStock }}"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Order & General Support",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "or",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "ORDER_INQUIRY"
                  },
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "GENERAL_SUPPORT"
                  },
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "PRICING_INQUIRY"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "ca1327fa-d3b1-40d0-a928-291c95e5c1fc",
      "name": "Process refund via Shopify API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        32,
        160
      ],
      "parameters": {
        "url": "=https://YOUR-STORE.myshopify.com/admin/api/2024-01/orders/{{ $json.orderSummary.order_number }}/refunds.json",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "refund[notify]",
              "value": "true"
            },
            {
              "name": "refund[note]",
              "value": "=AI agent processed refund \u2014 Ticket {{ $json.ticketId }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Shopify-Access-Token",
              "value": "YOUR_SHOPIFY_ACCESS_TOKEN"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "95240f59-0595-4a61-93fa-5a84d329530c",
      "name": "Send low stock alert to team",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        32,
        352
      ],
      "parameters": {
        "url": "YOUR_SLACK_WEBHOOK_URL",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"text\": \"\u26a0\ufe0f *LOW STOCK ALERT \u2014 Action Required*\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"\u26a0\ufe0f *LOW STOCK DETECTED*\\n{{ $json.lowStockCount }} product(s) are running critically low (\u22645 units).\\n\\n*Triggered by:* Customer inquiry from {{ $json.customerEmail }}\\n*Ticket:* {{ $json.ticketId }}\\n\\nPlease review inventory and reorder as needed.\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "cd30344d-18b1-45d7-8a88-fcb06ad0b9d2",
      "name": "Store interaction in PostgreSQL",
      "type": "n8n-nodes-base.postgres",
      "position": [
        32,
        544
      ],
      "parameters": {
        "table": "support_interactions",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "b36154fa-ba51-43d2-b743-b2571756f856",
      "name": "Escalate complex cases to human agent",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        32,
        736
      ],
      "parameters": {
        "url": "YOUR_SLACK_WEBHOOK_URL",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"text\": \"\ud83d\udea8 *ESCALATION REQUIRED \u2014 Human Agent Needed*\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"\ud83d\udea8 *TICKET ESCALATION*\\n\\n*Ticket:* {{ $json.ticketId }}\\n*Customer:* {{ $json.customerName }} ({{ $json.customerEmail }})\\n*Intent:* {{ $json.intent }}\\n*Message:* {{ $json.customerMessage }}\\n\\n*AI Response Sent:* {{ $json.aiResponse }}\\n\\nPlease follow up with the customer within 24 hours.\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "8ad8faa7-eada-4f9b-aa1c-bd78b3a413fc",
      "name": "Build final customer response",
      "type": "n8n-nodes-base.code",
      "position": [
        256,
        448
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Build the final HTML email response and Slack summary\nconst report = $input.item.json;\n\nconst intentEmoji = {\n  'ORDER_INQUIRY': '\ud83d\udce6',\n  'REFUND_REQUEST': '\ud83d\udcb0',\n  'INVENTORY_CHECK': '\ud83d\udcca',\n  'PRICING_INQUIRY': '\ud83c\udff7\ufe0f',\n  'GENERAL_SUPPORT': '\ud83d\udcac'\n}[report.intent] || '\ud83d\udcac';\n\nconst statusColor = report.requiresEscalation ? '#f59e0b' \n  : report.actionRequired === 'PROCESS_REFUND' ? '#22c55e' \n  : '#3b82f6';\n\n// Build HTML email response\nconst emailHtml = `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Support Reply \u2014 ${report.ticketId}</title>\n  <style>\n    body { font-family: Arial, sans-serif; color: #1e293b; margin: 0; padding: 0; background: #f8fafc; }\n    .container { max-width: 600px; margin: 24px auto; background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }\n    .header { background: #0f172a; color: white; padding: 24px; }\n    .header h1 { margin: 0 0 4px 0; font-size: 18px; }\n    .header p { margin: 0; opacity: 0.6; font-size: 12px; }\n    .badge { display: inline-block; padding: 4px 12px; border-radius: 20px; font-size: 12px; font-weight: bold; background: ${statusColor}; color: white; margin-top: 10px; }\n    .body { padding: 24px; }\n    .message-box { background: #f1f5f9; border-radius: 8px; padding: 16px; margin-bottom: 16px; white-space: pre-line; line-height: 1.6; }\n    .order-card { border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; margin-bottom: 16px; }\n    .order-card h3 { margin: 0 0 8px 0; font-size: 14px; color: #64748b; }\n    .order-row { display: flex; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid #f1f5f9; font-size: 13px; }\n    .footer { background: #f8fafc; padding: 16px 24px; text-align: center; font-size: 11px; color: #94a3b8; border-top: 1px solid #e2e8f0; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"header\">\n      <h1>${intentEmoji} Support Reply from Our Team</h1>\n      <p>Ticket ID: ${report.ticketId} &nbsp;|&nbsp; ${new Date(report.timestamp).toLocaleString()}</p>\n      <div class=\"badge\">${report.intent.replace('_', ' ')}</div>\n    </div>\n    <div class=\"body\">\n      <div class=\"message-box\">${report.aiResponse}</div>\n      ${report.orderSummary ? `\n      <div class=\"order-card\">\n        <h3>\ud83d\udce6 Your Order Details</h3>\n        <div class=\"order-row\"><span>Order Number</span><span>#${report.orderSummary.order_number}</span></div>\n        <div class=\"order-row\"><span>Status</span><span>${report.orderSummary.fulfillment_status}</span></div>\n        <div class=\"order-row\"><span>Payment</span><span>${report.orderSummary.financial_status}</span></div>\n        <div class=\"order-row\"><span>Total</span><span>${report.orderSummary.currency} ${report.orderSummary.total_price}</span></div>\n        ${report.orderSummary.tracking_number ? `<div class=\"order-row\"><span>Tracking</span><span>${report.orderSummary.tracking_number}</span></div>` : ''}\n      </div>` : ''}\n    </div>\n    <div class=\"footer\">This is an automated response powered by AI &nbsp;|&nbsp; Reply to this email to speak with a human agent</div>\n  </div>\n</body>\n</html>`;\n\n// Slack summary message\nconst slackSummary = `${intentEmoji} *[${report.ticketId}] ${report.intent.replace(/_/g, ' ')}*\\n\\n` +\n  `*Customer:* ${report.customerName} (${report.customerEmail})\\n` +\n  `*Message:* ${report.customerMessage}\\n` +\n  `*AI Confidence:* ${Math.round(report.confidence * 100)}%\\n` +\n  `*Action Taken:* ${report.actionRequired || 'Response sent'}\\n` +\n  `*Escalated:* ${report.requiresEscalation ? 'Yes \u26a0\ufe0f' : 'No \u2705'}`;\n\nreturn {\n  json: {\n    ...report,\n    emailHtml,\n    slackSummary,\n    emailSubject: `${intentEmoji} [${report.ticketId}] Re: Your support request \u2014 ${report.intent.replace(/_/g, ' ')}`,\n    shouldSendEmail: !!report.customerEmail,\n    shouldNotifySlack: true\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "b88a49b6-54b9-4f5d-b008-b1b94c8fc4a3",
      "name": "Email AI response to customer",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        480,
        448
      ],
      "parameters": {
        "html": "={{ $json.emailHtml }}",
        "options": {},
        "subject": "={{ $json.emailSubject }}",
        "toEmail": "={{ $json.customerEmail }}",
        "fromEmail": "user@example.com"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "0972be52-8ddb-4fd7-8240-dce3590af4d4",
      "name": "Post interaction summary to Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        640
      ],
      "parameters": {
        "url": "YOUR_SLACK_WEBHOOK_URL",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"text\": \"{{ $json.emailSubject }}\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"{{ $json.slackSummary }}\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "7002e8d3-523f-4ff1-a00d-86705589c36c",
      "name": "Log success and track agent statistics",
      "type": "n8n-nodes-base.code",
      "position": [
        704,
        544
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Log successful AI agent interaction and track statistics\nconst timestamp = new Date().toISOString();\nconst report = $input.item.json;\n\nconsole.log(`\u2705 AI AGENT SUCCESS: Ticket ${report.ticketId} | Intent: ${report.intent} | Customer: ${report.customerEmail} | Escalated: ${report.requiresEscalation} | Time: ${timestamp}`);\n\n// Cumulative statistics\nconst stats = $getWorkflowStaticData('global').agentStats || {\n  totalTickets: 0,\n  byIntent: {},\n  refundsProcessed: 0,\n  stockAlertsTriggered: 0,\n  escalations: 0,\n  lastProcessed: null\n};\n\nstats.totalTickets++;\nstats.byIntent[report.intent] = (stats.byIntent[report.intent] || 0) + 1;\nif (report.actionRequired === 'PROCESS_REFUND') stats.refundsProcessed++;\nif (report.actionRequired === 'SEND_STOCK_ALERT') stats.stockAlertsTriggered++;\nif (report.requiresEscalation) stats.escalations++;\nstats.lastProcessed = timestamp;\n\n$getWorkflowStaticData('global').agentStats = stats;\n\nreturn {\n  json: {\n    success: true,\n    ticketId: report.ticketId,\n    intent: report.intent,\n    customerEmail: report.customerEmail,\n    actionTaken: report.actionRequired || 'RESPONSE_SENT',\n    escalated: report.requiresEscalation,\n    timestamp,\n    cumulativeStats: stats\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "80ffd0b8-6c83-4cc0-afe3-3b9b37054f80",
      "name": "Send immediate webhook acknowledgement",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        480,
        256
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, ticket_id: $json.ticketId, message: 'Your request has been received and our AI is processing it. You will receive a reply via email shortly.', intent_detected: $json.intent }) }}"
      },
      "typeVersion": 1.1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "9a7cc74c-d6d0-4935-953d-2046adfe7dab",
  "connections": {
    "Route by customer intent": {
      "main": [
        [
          {
            "node": "Process refund via Shopify API",
            "type": "main",
            "index": 0
          },
          {
            "node": "Store interaction in PostgreSQL",
            "type": "main",
            "index": 0
          },
          {
            "node": "Escalate complex cases to human agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send low stock alert to team",
            "type": "main",
            "index": 0
          },
          {
            "node": "Store interaction in PostgreSQL",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Store interaction in PostgreSQL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send low stock alert to team": {
      "main": [
        [
          {
            "node": "Build final customer response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build final customer response": {
      "main": [
        [
          {
            "node": "Send immediate webhook acknowledgement",
            "type": "main",
            "index": 0
          },
          {
            "node": "Email AI response to customer",
            "type": "main",
            "index": 0
          },
          {
            "node": "Post interaction summary to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email AI response to customer": {
      "main": [
        [
          {
            "node": "Log success and track agent statistics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge order and inventory data": {
      "main": [
        [
          {
            "node": "AI agent analyzes query and classifies intent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process refund via Shopify API": {
      "main": [
        [
          {
            "node": "Build final customer response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store interaction in PostgreSQL": {
      "main": [
        [
          {
            "node": "Build final customer response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch order details from Shopify": {
      "main": [
        [
          {
            "node": "Merge order and inventory data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive customer support request": {
      "main": [
        [
          {
            "node": "Fetch order details from Shopify",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch inventory levels from Shopify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post interaction summary to Slack": {
      "main": [
        [
          {
            "node": "Log success and track agent statistics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch inventory levels from Shopify": {
      "main": [
        [
          {
            "node": "Merge order and inventory data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Escalate complex cases to human agent": {
      "main": [
        [
          {
            "node": "Build final customer response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI agent analyzes query and classifies intent": {
      "main": [
        [
          {
            "node": "Route by customer intent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

Creates an AI-powered sales and support agent connected to live store data from Shopify/WooCommerce. MCP ensures controlled access to inventory and order systems. Automatically handles customer queries, stock alerts, and refund logic to reduce manual workload. Trigger — Listens…

Source: https://n8n.io/workflows/13594/ — 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

This workflow automates veterinary clinic operations and client communications for animal hospitals and veterinary practices managing appointments, inventory, and patient care. It solves the dual chal

HTTP Request, Agent, OpenAI Chat +4
AI & RAG

The system collects real-time wearable health data, normalizes it, and uses AI to analyze trends and risk scores. It detects anomalies by comparing with historical patterns and automatically triggers

Postgres, Agent, OpenAI Chat +7
AI & RAG

Automate your post-event networking with this intelligent n8n workflow. Triggered instantly after an event, it collects attendee and interaction data, enriches profiles with LinkedIn insights, and use

HTTP Request, OpenAI Chat, HubSpot +3
AI & RAG

Automate peer review assignment and grading with AI-powered evaluation. Designed for educators managing collaborative assessments efficiently.

OpenAI Chat, Agent, Output Parser Structured +4
AI & RAG

Streamline your post-event analysis with this smart n8n workflow. Triggered by a simple webhook, it instantly gathers attendee and engagement data from your event platform, calculates key metrics, and

HTTP Request, OpenAI Chat, Email Send +2