This workflow follows the Chainllm → 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 →
{
"name": "LINE AI Sales Bot",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "line-sales-bot",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-1",
"name": "LINE Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
1080,
1400
]
},
{
"parameters": {
"jsCode": "const input = $input.first().json;\nconst body = input.body || input;\nconst events = body.events || [];\nconst event = events[0] || null;\nif (!event || !event.replyToken || (event.type !== 'message' && event.type !== 'postback')) return [{ json: { replyable: false } }];\nconst message = event.message || {};\nconst text = event.type === 'message' && message.type === 'text' ? String(message.text || '').trim() : '';\nreturn [{ json: { replyable: true, replyToken: event.replyToken, lineUserId: event.source?.userId || 'unknown', chatInput: text || 'Show me the help menu' } }];"
},
"id": "code-parse",
"name": "Parse LINE Event",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1320,
1400
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.replyable }}",
"operator": {
"type": "boolean",
"operation": "true"
},
"rightValue": true
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-1",
"name": "Is Replyable LINE Event?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1560,
1400
]
},
{
"parameters": {
"promptType": "define",
"text": "={{ $json.chatInput }}",
"hasOutputParser": true,
"messages": {
"messageValues": [
{
"message": "Classify the customer message into exactly one action: product_search, order_track, support_ticket, or hang_to_human. Detect language as Eng or Th. Return only the structured result."
}
]
},
"batching": {}
},
"id": "llm-chain",
"name": "Classify Customer Message",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
1820,
1300
]
},
{
"parameters": {
"model": "qwen3:8b",
"options": {
"temperature": 0,
"keepAlive": "30m"
}
},
"id": "model-1",
"name": "Ollama Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOllama",
"typeVersion": 1,
"position": [
2020,
1600
]
},
{
"parameters": {
"schemaType": "manual",
"inputSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"action\": { \"type\": \"string\", \"enum\": [\"product_search\", \"order_track\", \"support_ticket\", \"hang_to_human\"] },\n \"language\": { \"type\": \"string\", \"enum\": [\"Eng\", \"Th\"] }\n },\n \"required\": [\"action\", \"language\"],\n \"additionalProperties\": false\n}"
},
"id": "parser-1",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"typeVersion": 1.3,
"position": [
2200,
1600
]
},
{
"parameters": {
"jsCode": "const line = $('Parse LINE Event').first().json;\nconst result = $input.first().json.output || {};\nreturn [{ json: Object.assign({}, line, result) }];"
},
"id": "combine-1",
"name": "Combine Context + Classification",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2060,
1300
]
},
{
"parameters": {
"mode": "expression",
"output": "={{ ['product_search','order_track','support_ticket','hang_to_human'].indexOf($json.action) }}",
"looseTypeValidation": true
},
"id": "switch-1",
"name": "Route by Action",
"type": "n8n-nodes-base.switch",
"typeVersion": 3.4,
"position": [
2300,
1300
]
},
{
"parameters": {
"jsCode": "const th = $json.language === 'Th';\nreturn [{ json: { ...$json, replyText: th ? '\u0e44\u0e14\u0e49\u0e40\u0e25\u0e22\u0e04\u0e23\u0e31\u0e1a \u0e2a\u0e48\u0e07\u0e0a\u0e37\u0e48\u0e2d\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32 \u0e23\u0e38\u0e48\u0e19 \u0e2b\u0e23\u0e37\u0e2d\u0e2a\u0e34\u0e48\u0e07\u0e17\u0e35\u0e48\u0e01\u0e33\u0e25\u0e31\u0e07\u0e21\u0e2d\u0e07\u0e2b\u0e32\u0e21\u0e32\u0e44\u0e14\u0e49\u0e40\u0e25\u0e22' : 'Please send the product name, model, or what you are looking for.' } }];"
},
"id": "reply-1",
"name": "Product Search Reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2580,
1060
]
},
{
"parameters": {
"jsCode": "const th = $json.language === 'Th';\nreturn [{ json: { ...$json, replyText: th ? '\u0e01\u0e23\u0e38\u0e13\u0e32\u0e2a\u0e48\u0e07\u0e40\u0e25\u0e02\u0e04\u0e33\u0e2a\u0e31\u0e48\u0e07\u0e0b\u0e37\u0e49\u0e2d\u0e2b\u0e23\u0e37\u0e2d\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02\u0e15\u0e34\u0e14\u0e15\u0e32\u0e21\u0e1e\u0e31\u0e2a\u0e14\u0e38' : 'Please send your order number or tracking number.' } }];"
},
"id": "reply-2",
"name": "Order Tracking Reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2580,
1220
]
},
{
"parameters": {
"jsCode": "const th = $json.language === 'Th';\nreturn [{ json: { ...$json, replyText: th ? '\u0e22\u0e34\u0e19\u0e14\u0e35\u0e0a\u0e48\u0e27\u0e22\u0e04\u0e23\u0e31\u0e1a \u0e01\u0e23\u0e38\u0e13\u0e32\u0e2d\u0e18\u0e34\u0e1a\u0e32\u0e22\u0e1b\u0e31\u0e0d\u0e2b\u0e32\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e40\u0e15\u0e34\u0e21' : 'I am happy to help. Please describe your issue in more detail.' } }];"
},
"id": "reply-3",
"name": "Support Reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2580,
1380
]
},
{
"parameters": {
"jsCode": "const th = $json.language === 'Th';\nreturn [{ json: { ...$json, replyText: th ? '\u0e17\u0e35\u0e21\u0e07\u0e32\u0e19\u0e08\u0e30\u0e40\u0e02\u0e49\u0e32\u0e21\u0e32\u0e14\u0e39\u0e41\u0e25\u0e15\u0e48\u0e2d \u0e01\u0e23\u0e38\u0e13\u0e32\u0e1d\u0e32\u0e01\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e44\u0e27\u0e49\u0e44\u0e14\u0e49\u0e40\u0e25\u0e22' : 'A human agent will assist you shortly. Please leave the details here.' } }];"
},
"id": "reply-4",
"name": "Human Handoff Reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2580,
1540
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.line.me/v2/bot/message/reply",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_LINE_CHANNEL_ACCESS_TOKEN"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ { replyToken: $json.replyToken, messages: [{ type: 'text', text: $json.replyText }] } }}",
"options": {
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
}
},
"id": "http-reply",
"name": "Send LINE Reply",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
2860,
1300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": {
"ok": true
},
"options": {
"responseCode": 200
}
},
"id": "respond-1",
"name": "Respond to LINE",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
3120,
1300
]
}
],
"connections": {
"LINE Webhook": {
"main": [
[
{
"node": "Parse LINE Event",
"type": "main",
"index": 0
}
]
]
},
"Parse LINE Event": {
"main": [
[
{
"node": "Is Replyable LINE Event?",
"type": "main",
"index": 0
}
]
]
},
"Is Replyable LINE Event?": {
"main": [
[
{
"node": "Classify Customer Message",
"type": "main",
"index": 0
}
],
[]
]
},
"Classify Customer Message": {
"main": [
[
{
"node": "Combine Context + Classification",
"type": "main",
"index": 0
}
]
]
},
"Ollama Chat Model": {
"ai_languageModel": [
[
{
"node": "Classify Customer Message",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "Classify Customer Message",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Combine Context + Classification": {
"main": [
[
{
"node": "Route by Action",
"type": "main",
"index": 0
}
]
]
},
"Route by Action": {
"main": [
[
{
"node": "Product Search Reply",
"type": "main",
"index": 0
}
],
[
{
"node": "Order Tracking Reply",
"type": "main",
"index": 0
}
],
[
{
"node": "Support Reply",
"type": "main",
"index": 0
}
],
[
{
"node": "Human Handoff Reply",
"type": "main",
"index": 0
}
]
]
},
"Product Search Reply": {
"main": [
[
{
"node": "Send LINE Reply",
"type": "main",
"index": 0
}
]
]
},
"Order Tracking Reply": {
"main": [
[
{
"node": "Send LINE Reply",
"type": "main",
"index": 0
}
]
]
},
"Support Reply": {
"main": [
[
{
"node": "Send LINE Reply",
"type": "main",
"index": 0
}
]
]
},
"Human Handoff Reply": {
"main": [
[
{
"node": "Send LINE Reply",
"type": "main",
"index": 0
}
]
]
},
"Send LINE Reply": {
"main": [
[
{
"node": "Respond to LINE",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateCredsSetupCompleted": false
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
LINE AI Sales Bot. Uses chainLlm, lmChatOllama, outputParserStructured, httpRequest. Webhook trigger; 14 nodes.
Source: https://github.com/mobizmad/n8n-workflow-templates/blob/main/chatbots/line-ai-sales-bot/workflow.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
AI Customer Service Automation - Portfolio. Uses googleSheets, httpRequest, agent, memoryBufferWindow. Webhook trigger; 91 nodes.
My workflow 53. Uses formTrigger, httpRequest, lmChatOpenAi, form. Event-driven trigger; 74 nodes.
Episode 23: UGC with nanobanana. Uses lmChatOpenAi, lmChatOllama, lmChatDeepSeek, lmChatOpenRouter. Event-driven trigger; 74 nodes.
The "Short Content" automation is a powerful, all-in-one solution designed to streamline the creation of short videos for social media, marketing, or personal projects. Leveraging cutting-edge AI tool
🔥 LIMITED-TIME OFFER: AI Video Automation (Previously \$59) Previously Template