This workflow corresponds to n8n.io template #13646 — we link there as the canonical source.
This workflow follows the Chainllm → Google Drive 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 →
{
"id": "5oLwg1O1MGSXCCCN",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI Palm Health Tracker \u2013 LINE Image Comparison & Gemini Analysis Workflow",
"tags": [],
"nodes": [
{
"id": "8cfdd2db-3d1e-4155-9700-83cc529c54c3",
"name": "LINE_trigger",
"type": "n8n-nodes-base.webhook",
"position": [
-704,
-64
],
"parameters": {
"path": "=8b88a8c6-b25c-43c1-b7fd-351dbf0311bd",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "5aa86fd1-9c40-4be4-99fc-c2c70d389e90",
"name": "config",
"type": "n8n-nodes-base.set",
"position": [
-544,
-64
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1cf28177-ed02-4b3b-954c-17d7a764a640",
"name": "LINE_ACCESS_TOKEN",
"type": "string",
"value": "=YOUR_ACCESS_TOKEN"
},
{
"id": "1ef2320e-492a-4d88-a018-694a7ce76c77",
"name": "USERID",
"type": "string",
"value": "={{ $json.body.events[0].source.userId }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "2fb65e3e-6ac1-4aa3-80d6-009eb3337720",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1664,
-96
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "26f6e2ca-cf26-4a05-9bf4-db10d62b031b",
"name": "PIC_check",
"type": "n8n-nodes-base.if",
"position": [
-416,
-64
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "81323972-ddbc-43c2-9299-e332500576c7",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('LINE_trigger').item.json.body.events[0].message.type }}",
"rightValue": "image"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "717cd96c-d1c9-4fce-8fb7-1f2caff2485c",
"name": "LINE_input",
"type": "n8n-nodes-base.httpRequest",
"position": [
0,
-80
],
"parameters": {
"url": "=https://api-data.line.me/v2/bot/message/{{ $('LINE_trigger').item.json.body.events[0].message.id }}/content",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "=Authorization",
"value": "=Bearer {{ $('config').item.json.LINE_ACCESS_TOKEN }}"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "7133bbc4-7897-4f27-b0de-73a6b6239367",
"name": "LINE_output",
"type": "n8n-nodes-base.httpRequest",
"position": [
2432,
112
],
"parameters": {
"url": "=https://api.line.me/v2/bot/message/push",
"method": "POST",
"options": {},
"jsonBody": "={\n \"to\":\"{{$node['config'].json.USERID}}\",\n \"messages\": [\n {\n \"type\": \"text\",\n \"text\":\"{{ $('Massege_check').item.json.text }}\"\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "=Authorization",
"value": "=Bearer {{ $node['config'].json.LINE_ACCESS_TOKEN}}"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "6d0ef990-ea33-4893-82b6-621555c265b0",
"name": "Analyze",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1664,
-272
],
"parameters": {
"text": "=You are a health advisor with knowledge of both Western and Eastern medicine.\n\nTreat the first item as today\u2019s palm image and the second item as a previous palm image.\nIf the first image cannot be identified as a palm, output:\n\u201cUnable to detect a palm.\u201d\nDo not perform any of the following evaluations.\n\nThen, compare the two palm images and provide health advice within 200 characters based on palm lines, dryness, and color tone.\n\nIf the second image does not exist or is not a palm image, do not perform any further evaluation.\n\nDo not make a medical diagnosis. Write the text as general health awareness or observations about physical condition.\n\nOutput format:\n\u3010Today\u2019s Health Check\u3011Body text\n\nNo reply to me is required.\n",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "c16fcffc-e3b1-4187-99f4-8b29538b72cd",
"name": "PIC_upload",
"type": "n8n-nodes-base.googleDrive",
"position": [
192,
-80
],
"parameters": {
"name": "={{ $('LINE_trigger').item.json.body.events[0].message.id }}.jpg",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive",
"cachedResultUrl": "https://drive.google.com/drive/my-drive",
"cachedResultName": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "1xR4KZbVauD6_J0t5YbPBvFSS1dxPLuWu",
"cachedResultUrl": "https://drive.google.com/drive/folders/1xR4KZbVauD6_J0t5YbPBvFSS1dxPLuWu",
"cachedResultName": "LINE_PIC"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "47706f63-23f3-4cd2-bfae-3fa6b7e8f144",
"name": "Massege_check",
"type": "n8n-nodes-base.code",
"position": [
2080,
112
],
"parameters": {
"jsCode": "return[{\n text:$input.first().json.text.replace(/\\r?\\n/g,\"\\\\n\").replace(/\"/g,'\\\\\"')\n}];"
},
"typeVersion": 2
},
{
"id": "ae482352-c0a5-4f02-bcec-30508d187911",
"name": "DATA_upload",
"type": "n8n-nodes-base.googleSheets",
"position": [
2256,
112
],
"parameters": {
"columns": {
"value": {
"pic": "={{ $('PIC_upload').first().json.id }}",
"url": "={{ $('PIC_upload').first().json.webViewLink }}",
"days": "={{$now.format(\"yyyy-MM-dd HH:mm:ss\")}}",
"message": "={{ $json.text }}"
},
"schema": [
{
"id": "days",
"type": "string",
"display": true,
"required": false,
"displayName": "days",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "pic",
"type": "string",
"display": true,
"required": false,
"displayName": "pic",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "url",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "message",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "message",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1XnHEybPiJ25j1dnEWxAIhBY8ZLy5bOhUHVvxF2R1aPA/edit#gid=0",
"cachedResultName": "sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1XnHEybPiJ25j1dnEWxAIhBY8ZLy5bOhUHVvxF2R1aPA",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1XnHEybPiJ25j1dnEWxAIhBY8ZLy5bOhUHVvxF2R1aPA/edit?usp=drivesdk",
"cachedResultName": "Health check cheet"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "44c5a80b-40b4-42f8-a742-d9bbd11f453d",
"name": "PIC_Search",
"type": "n8n-nodes-base.googleDrive",
"position": [
992,
-96
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.pic }}"
},
"options": {},
"operation": "download"
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "39cd4459-452f-4f49-aad8-4be255055198",
"name": "DATA_download",
"type": "n8n-nodes-base.googleSheets",
"position": [
320,
-80
],
"parameters": {
"options": {
"returnFirstMatch": false
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1XnHEybPiJ25j1dnEWxAIhBY8ZLy5bOhUHVvxF2R1aPA/edit#gid=0",
"cachedResultName": "sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1XnHEybPiJ25j1dnEWxAIhBY8ZLy5bOhUHVvxF2R1aPA",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1XnHEybPiJ25j1dnEWxAIhBY8ZLy5bOhUHVvxF2R1aPA/edit?usp=drivesdk",
"cachedResultName": "Health check cheet"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7,
"alwaysOutputData": true
},
{
"id": "f90adbd0-7f90-446c-ad04-70d61736b49e",
"name": "Get latest DATA",
"type": "n8n-nodes-base.code",
"position": [
832,
-96
],
"parameters": {
"jsCode": "const items = $('DATA_download').all();\n\nif (items.length === 0) return [];\n\nconst latestItem = items[items.length - 1];\n\nreturn [\n {\n json: {\n pic: latestItem.json.pic,\n url: latestItem.json.url,\n message: latestItem.json.message\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "277dd2f1-dbd9-48e8-9ca2-326f6bd48744",
"name": "Check Previous Record Exists",
"type": "n8n-nodes-base.if",
"position": [
656,
-80
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "1d866bad-857d-4770-9674-a720a4da2c52",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.recordCount>0 }}",
"rightValue": "={{ 0 }}"
}
]
},
"looseTypeValidation": true
},
"typeVersion": 2.3,
"alwaysOutputData": false
},
{
"id": "14486f32-d6ab-43fd-8fa8-fb26a3ac3ab4",
"name": "Google Gemini Chat Model1",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1536,
320
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "b975d90a-a57e-456f-9cb6-12d0f9ad4be0",
"name": "First_Analyze",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1536,
112
],
"parameters": {
"text": "=You are an excellent palm reader.\n\nThe image sent is a palm image.\nIf it cannot be identified as a palm, output:\n\u3010Unable to identify the image as a palm\u3011\nDo not perform any of the following processing.\n\nIf the image is identified as a palm, provide the following output based on palm reading.\n\nNo reply to me is required.\n\nOutput content:\n\uff5eFor the first session, I will tell your fortune based on your palm\uff5e\n\u3010Life Line\u3011 - (Score out of 10)\n\u3010Heart Line\u3011 - (Score out of 10)\n\u3010Head Line\u3011 - (Score out of 10)\n\u3010Fate Line\u3011 - (Score out of 10)\n\u3010Overall Fortune\u3011Provide overall advice based on the palm reading within 150 characters.",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "143ac698-ee26-46e9-964b-f2f7b5dd915e",
"name": "Reply_Text_Instructions",
"type": "n8n-nodes-base.httpRequest",
"position": [
0,
96
],
"parameters": {
"url": "=https://api.line.me/v2/bot/message/reply",
"method": "POST",
"options": {},
"jsonBody": "={\n \"replyToken\": \"{{ $('LINE_trigger').item.json.body.events[0].replyToken }}\",\n \"messages\": [\n {\n \"type\": \"text\",\n \"text\": \"Please send a photo of the palm of your hand.\"\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "=Authorization",
"value": "=Bearer {{ $('config').item.json.LINE_ACCESS_TOKEN }}"
},
{
"name": "=Content-Type",
"value": "=application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "dffb7343-031a-4cd9-b940-d0b413587f00",
"name": "DATA_counting",
"type": "n8n-nodes-base.code",
"position": [
448,
-80
],
"parameters": {
"jsCode": "const items = $input.all();\n\nconst validItems = items.filter(item => \n item.json && Object.keys(item.json).length > 0\n);\n\nreturn [\n {\n json: {\n recordCount: validItems.length\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "7200479b-2697-4d96-941a-660a89b46053",
"name": "Validate Image Pair",
"type": "n8n-nodes-base.merge",
"position": [
1216,
-272
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "f468a6a2-1465-41a7-91b6-99ec4d6dfb56",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1296,
-496
],
"parameters": {
"width": 528,
"height": 880,
"content": "## AI Palm Health Tracker \u2013 Overview\n\nThis workflow receives palm images sent via LINE and provides AI-generated health insights.\n\n## Step-by-step process:\n1.User sends a palm image via LINE\n2.Webhook receives the image\n3.Image is saved to Google Drive\n4.Past records are checked in Google Sheets\n\nIf this is the first submission:\n\u2192 AI will perform a palm reading\n\nIf previous records exist:\n\u2192 Retrieve the latest saved image\n\u2192 Validate that two images are available\n\u2192 AI performs a comparison analysis\n\nAll results are saved in Google Sheets and sent back to the user via LINE.\n\n## Setup Steps\n\n1. Create a LINE Messaging API channel and obtain the Channel Access Token.\n2. Create a Google Spreadsheet with the following columns: \u201cdays (date), pic (image ID), url (destination link), message (advice)\u201d.\n3. Create a Google Drive folder to store palm photos.\n4. Add the Channel Access Token information to the Config node.\n5. Set the Webhook URL in the LINE Developers Console.\n\n## Key points:\n\u2022 If a non-image message is sent, the user is prompted to send a palm image.\n\u2022 If two images are not available, the comparison analysis is skipped.\n\u2022 The advice provided does not constitute a medical diagnosis. It is intended solely as general health awareness guidance.\n\n"
},
"typeVersion": 1
},
{
"id": "1d9aebf0-e553-4536-9c54-c47eeeabcb6e",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-720,
-400
],
"parameters": {
"color": 7,
"width": 864,
"height": 672,
"content": "## LINE Webhook Trigger\n\nThis workflow is triggered via the LINE Messaging API webhook.\nIt receives palm images submitted by users and performs AI-based health analysis.\n\nIf the message type is not \"image,\" the workflow responds with an instructional message.\n\n**Security Note:**\nAccess tokens should be stored as environment variables within the config node.\n"
},
"typeVersion": 1
},
{
"id": "983655f1-4708-44d6-85e9-0d0f717c806d",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
160,
-464
],
"parameters": {
"color": 7,
"width": 416,
"height": 544,
"content": "## Image Storage Layer\n\nUploaded images are saved to Google Drive for historical comparison. Next, data stored in Google Sheets is retrieved.\n\nThe stored data includes:\n* Timestamp\n* Drive File ID\n* Public viewing link\n* AI response message\n\nThis makes it possible to track the condition of the palm over the long term. After that, the system checks whether any stored data exists.\n\n"
},
"typeVersion": 1
},
{
"id": "cf8f6a70-ebe1-45b5-a6fa-5b85b12689fe",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
592,
-480
],
"parameters": {
"color": 7,
"width": 528,
"height": 560,
"content": "## Historical Record Retrieval Logic\n\nThe workflow checks if previous palm records exist.\n\nIf no previous record:\n\u2192 Execute First-Time Palm Analysis\n\nIf previous record exists:\n\u2192 Retrieve the most recent image\n\u2192 Prepare for comparison analysis\n\nThis ensures adaptive AI behavior.\n"
},
"typeVersion": 1
},
{
"id": "c3f26bb0-913c-4329-beda-6df43ab4cedc",
"name": "image_counting",
"type": "n8n-nodes-base.code",
"position": [
1424,
-272
],
"parameters": {
"jsCode": "const items = $input.all();\n\nconst imageItems = items.filter(item => item.binary);\n\nif (imageItems.length < 2) {\n return [];\n}\n\nreturn items;\n"
},
"typeVersion": 2
},
{
"id": "9f132b8a-b21f-4075-bcdf-178cc0c2c03b",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1136,
-560
],
"parameters": {
"color": 7,
"width": 768,
"height": 608,
"content": "## AI Comparison Analysis\n\nGoogle Gemini Vision model performs comparative analysis\nbetween current and previous palm images.\n\nThe model:\n- Detects palm presence\n- Compares lines, dryness, and color tone\n- Generates non-medical health insights (\u2264200 characters)\n\nNo medical diagnosis is provided.\n"
},
"typeVersion": 1
},
{
"id": "0c76414f-5888-4582-a211-62fc03746c4d",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
976,
96
],
"parameters": {
"color": 7,
"width": 864,
"height": 384,
"content": "## First-Time Palm Fortune Analysis\n\nIf this is the user's first submission,\nthe workflow performs a standalone palm reading.\n\nOutputs:\n- Life Line Score\n- Heart Line Score\n- Head Line Score\n- Fate Line Score\n- Overall Advice\n\nThis creates an engaging onboarding experience.\n"
},
"typeVersion": 1
},
{
"id": "32d3abe3-9536-43ce-9ba6-28c357e6652e",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1920,
-192
],
"parameters": {
"color": 7,
"width": 736,
"height": 448,
"content": "## Health Log Recording\n\nAll AI outputs are appended to Google Sheets.\n\nThis enables:\n\n* Progress tracking\n* Data auditing\n* User history management\n* Future analytics expansion\n\nThe message part of the AI output is also sent as a reply to the LINE user who submitted the image.\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "3a2559d1-38f8-4626-987d-7b49c95873e6",
"connections": {
"config": {
"main": [
[
{
"node": "PIC_check",
"type": "main",
"index": 0
}
]
]
},
"Analyze": {
"main": [
[
{
"node": "Massege_check",
"type": "main",
"index": 0
}
]
]
},
"PIC_check": {
"main": [
[
{
"node": "LINE_input",
"type": "main",
"index": 0
}
],
[
{
"node": "Reply_Text_Instructions",
"type": "main",
"index": 0
}
]
]
},
"LINE_input": {
"main": [
[
{
"node": "PIC_upload",
"type": "main",
"index": 0
},
{
"node": "Validate Image Pair",
"type": "main",
"index": 0
}
]
]
},
"PIC_Search": {
"main": [
[
{
"node": "Validate Image Pair",
"type": "main",
"index": 1
}
]
]
},
"PIC_upload": {
"main": [
[
{
"node": "DATA_download",
"type": "main",
"index": 0
}
]
]
},
"DATA_upload": {
"main": [
[
{
"node": "LINE_output",
"type": "main",
"index": 0
}
]
]
},
"LINE_trigger": {
"main": [
[
{
"node": "config",
"type": "main",
"index": 0
}
]
]
},
"DATA_counting": {
"main": [
[
{
"node": "Check Previous Record Exists",
"type": "main",
"index": 0
}
]
]
},
"DATA_download": {
"main": [
[
{
"node": "DATA_counting",
"type": "main",
"index": 0
}
]
]
},
"First_Analyze": {
"main": [
[
{
"node": "Massege_check",
"type": "main",
"index": 0
}
]
]
},
"Massege_check": {
"main": [
[
{
"node": "DATA_upload",
"type": "main",
"index": 0
}
]
]
},
"image_counting": {
"main": [
[
{
"node": "Analyze",
"type": "main",
"index": 0
}
]
]
},
"Get latest DATA": {
"main": [
[
{
"node": "PIC_Search",
"type": "main",
"index": 0
}
]
]
},
"Validate Image Pair": {
"main": [
[
{
"node": "image_counting",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Analyze",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Google Gemini Chat Model1": {
"ai_languageModel": [
[
{
"node": "First_Analyze",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Check Previous Record Exists": {
"main": [
[
{
"node": "Get latest DATA",
"type": "main",
"index": 0
}
],
[
{
"node": "First_Analyze",
"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.
googleDriveOAuth2ApigooglePalmApigoogleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow receives palm images sent via LINE and provides AI-generated health insights.
Source: https://n8n.io/workflows/13646/ — 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.
ANIS_HUB 1. Uses gmail, googleDrive, googleSheets, httpRequest. Webhook trigger; 89 nodes.
Resume Screening & Behavioral Interviews with Gemini, Elevenlabs, & Notion ATS copy. Uses outputParserStructured, chainLlm, googleDrive, stickyNote. Webhook trigger; 67 nodes.
Candidate Engagement | Resume Screening | AI Voice Interviews | Applicant Insights
Categories: Accounting Automation • OCR Processing • AI Data Extraction • Business Tools
This workflow converts handwritten memo images sent via LINE into structured, searchable knowledge using AI.Users simply send a handwritten memo photo. The workflow automatically performs OCR, summari