AutomationFlowsGeneral › Chain LLM Example: Customer Email Triage (groq)

Chain LLM Example: Customer Email Triage (groq)

Chain LLM Example: Customer Email Triage (Groq). Uses informationExtractor, lmChatGroq, chainLlm. Webhook trigger; 8 nodes.

Webhook trigger★★★★☆ complexityAI-powered8 nodesInformation ExtractorGroq ChatChain Llm
General Trigger: Webhook Nodes: 8 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Chainllm → Informationextractor 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": "Chain LLM Example: Customer Email Triage (Groq)",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "customer-email-triage",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000001",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"customer_name\": { \"type\": \"string\" },\n    \"product_mentioned\": { \"type\": \"string\" },\n    \"language\": { \"type\": \"string\", \"enum\": [\"en\", \"es\", \"pt\", \"fr\", \"de\", \"other\"] },\n    \"sentiment\": { \"type\": \"string\", \"enum\": [\"positive\", \"neutral\", \"negative\"] },\n    \"urgency_score\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 10 },\n    \"contains_pii\": { \"type\": \"boolean\" }\n  },\n  \"required\": [\"customer_name\", \"sentiment\", \"urgency_score\"]\n}",
        "text": "={{ $json.body.email_content }}",
        "options": {
          "systemPromptTemplate": "You extract structured data from customer emails. Extract only what is explicitly stated. Do not infer or guess. If a field is not present in the email, omit it. Detect language from the actual email content. PII includes phone numbers, addresses, full credit card numbers, or government IDs."
        }
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000002",
      "name": "Stage 1: Information Extractor",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "typeVersion": 1,
      "position": [
        480,
        300
      ]
    },
    {
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {
          "temperature": 0,
          "maxTokensToSample": 500
        }
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000003",
      "name": "Groq Chat (Stage 1)",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "typeVersion": 1,
      "position": [
        480,
        480
      ],
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Validate Stage 1 output before passing to Stage 2\nconst data = $input.item.json.output;\n\nif (!data || !data.customer_name || !data.sentiment || data.urgency_score == null) {\n  throw new Error(`Stage 1 missing required fields: ${JSON.stringify(data)}`);\n}\n\nif (data.urgency_score < 0 || data.urgency_score > 10) {\n  throw new Error(`urgency_score out of range: ${data.urgency_score}`);\n}\n\nreturn { json: { extracted: data, original_email: $('Webhook').item.json.body.email_content } };"
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000004",
      "name": "Validate Stage 1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        300
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Given this extracted customer data:\n\n{{ JSON.stringify($json.extracted, null, 2) }}\n\nClassify into one of: technical_issue, billing_question, cancellation_risk, upsell_opportunity, compliment, other.\n\nThen identify the single most important next action (one short sentence).\n\nReturn JSON with keys: category, next_action, reasoning. No prose, no markdown.",
        "options": {
          "systemMessage": "You are a customer support triage analyst. You return only valid JSON. You do not invent categories outside the allowed list."
        }
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000005",
      "name": "Stage 2: Classify + Action",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.4,
      "position": [
        960,
        300
      ]
    },
    {
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {
          "temperature": 0.2,
          "maxTokensToSample": 400,
          "responseFormat": "json_object"
        }
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000006",
      "name": "Groq Chat (Stage 2)",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "typeVersion": 1,
      "position": [
        960,
        480
      ],
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Stage 3: Deterministic scoring (NO LLM \u2014 math goes in Code, not in LLM)\nconst stage1 = $('Validate Stage 1').item.json.extracted;\nconst stage2 = JSON.parse($input.item.json.text);\n\n// Composite priority score: 0.5 * urgency + 0.3 * sentiment_weight + 0.2 * category_weight\nconst sentimentWeight = stage1.sentiment === 'negative' ? 10 : stage1.sentiment === 'neutral' ? 5 : 1;\nconst categoryWeight = {\n  cancellation_risk: 10,\n  technical_issue: 8,\n  billing_question: 6,\n  upsell_opportunity: 4,\n  compliment: 1,\n  other: 3\n}[stage2.category] ?? 3;\n\nconst priority = (0.5 * stage1.urgency_score) + (0.3 * sentimentWeight) + (0.2 * categoryWeight);\nconst routeTo = priority >= 7 ? 'urgent_queue' : priority >= 4 ? 'standard_queue' : 'low_queue';\n\nreturn {\n  json: {\n    customer: stage1.customer_name,\n    language: stage1.language,\n    contains_pii: stage1.contains_pii ?? false,\n    sentiment: stage1.sentiment,\n    category: stage2.category,\n    next_action: stage2.next_action,\n    priority_score: Number(priority.toFixed(2)),\n    route_to: routeTo,\n    reasoning: stage2.reasoning,\n    processed_at: new Date().toISOString()\n  }\n};"
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000007",
      "name": "Stage 3: Score + Route (Code)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        300
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($json) }}"
      },
      "id": "a1b2c3d4-0001-0001-0001-000000000008",
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1440,
        300
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Stage 1: Information Extractor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 1: Information Extractor": {
      "main": [
        [
          {
            "node": "Validate Stage 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat (Stage 1)": {
      "ai_languageModel": [
        [
          {
            "node": "Stage 1: Information Extractor",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Validate Stage 1": {
      "main": [
        [
          {
            "node": "Stage 2: Classify + Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stage 2: Classify + Action": {
      "main": [
        [
          {
            "node": "Stage 3: Score + Route (Code)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat (Stage 2)": {
      "ai_languageModel": [
        [
          {
            "node": "Stage 2: Classify + Action",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Stage 3: Score + Route (Code)": {
      "main": [
        [
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "tags": [
    {
      "name": "chain-llm-pattern"
    },
    {
      "name": "example"
    }
  ]
}

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

Chain LLM Example: Customer Email Triage (Groq). Uses informationExtractor, lmChatGroq, chainLlm. Webhook trigger; 8 nodes.

Source: https://github.com/masteranime/n8n-claude-skills/blob/4cb50176ad2fedf010bbfb5a5d1f6b049a90348c/examples/groq-chain-example.json — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

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

General

Create and publish Instagram carousels using OpenAI gpt-image-1 and AI caption. Uses chainLlm, outputParserItemList, lmChatOpenAi, splitInBatches. Scheduled trigger; 32 nodes.

Chain Llm, Output Parser Item List, OpenAI Chat +3
General

Vacancy Launch: Calendar, ClickUp & AI LinkedIn Post. Uses googleCalendar, stickyNote, clickUp, linkedIn. Webhook trigger; 18 nodes.

Google Calendar, ClickUp, LinkedIn +1
General

Sia — Portal de Expansão de Terrenos (Principal). Uses chainLlm, lmChatGroq, googleSheets. Webhook trigger; 12 nodes.

Chain Llm, Groq Chat, Google Sheets
General

GiveWP Donations to Beacon. Uses httpRequest, stopAndError. Webhook trigger; 43 nodes.

HTTP Request, Stop And Error
General

Use this workflow to book, cancel, or reschedule appointments using Vapi and Google Calendar

Google Calendar