This workflow follows the Chainllm → Gmail 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": "RiadOps",
"nodes": [
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4.1-mini",
"mode": "list",
"cachedResultName": "gpt-4.1-mini"
},
"builtInTools": {},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.3,
"position": [
2976,
-288
],
"id": "451eb388-a6db-4d8a-adb7-58c9fc79d13a",
"name": "OpenAI Chat Model"
},
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4.1-mini",
"mode": "list",
"cachedResultName": "gpt-4.1-mini"
},
"builtInTools": {},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.3,
"position": [
3712,
-256
],
"id": "5c64bb2c-39d6-45e1-aff0-173148c19a79",
"name": "OpenAI Chat Model1"
},
{
"parameters": {
"httpMethod": "POST",
"path": "riadops/booking-intake",
"responseMode": "lastNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-64,
128
],
"id": "48f88709-e4b8-4669-81f3-100e7a98a89e",
"name": "RO-01 | Booking Event Webhook"
},
{
"parameters": {
"jsCode": "const items = $input.all();\n\nfunction cleanString(value) {\n if (value === undefined || value === null) return \"\";\n return String(value).trim();\n}\n\nfunction normalizeEmail(email) {\n return cleanString(email).toLowerCase();\n}\n\nfunction normalizePhone(phone) {\n return cleanString(phone).replace(/\\s+/g, \"\");\n}\n\nfunction normalizeStatus(status) {\n const value = cleanString(status).toLowerCase();\n\n const allowed = [\"confirmed\", \"modified\", \"cancelled\"];\n\n if (allowed.includes(value)) {\n return value;\n }\n\n return \"needs_review\";\n}\n\nfunction normalizeLanguage(language) {\n const value = cleanString(language).toLowerCase();\n\n if ([\"fr\", \"en\", \"ar\", \"es\"].includes(value)) {\n return value;\n }\n\n return \"fr\";\n}\n\nfunction toArray(value) {\n if (Array.isArray(value)) return value;\n if (!value) return [];\n return [value];\n}\n\nfunction createGuestId(email, phone) {\n const key = email || phone || \"unknown\";\n const cleanKey = key.replace(/[^a-zA-Z0-9]/g, \"\").slice(0, 8).toUpperCase();\n return `GST-${cleanKey}`;\n}\n\nreturn items.map((item) => {\n const body = item.json.body || item.json;\n\n const guest = body.guest || {};\n const amount = body.amount || {};\n\n const email = normalizeEmail(guest.email);\n const phone = normalizePhone(guest.phone);\n const guestId = createGuestId(email, phone);\n\n const now = new Date().toISOString();\n\n return {\n json: {\n booking_id: cleanString(body.booking_id),\n status: normalizeStatus(body.status),\n\n guest_id: guestId,\n guest_name: cleanString(guest.name),\n email,\n phone,\n language: normalizeLanguage(guest.language),\n\n check_in: cleanString(body.check_in),\n check_out: cleanString(body.check_out),\n\n adults: Number(body.adults || 0),\n children: Number(body.children || 0),\n\n room_type: cleanString(body.room_type),\n\n amount_value: Number(amount.value || 0),\n amount_currency: cleanString(amount.currency || \"MAD\").toUpperCase(),\n\n arrival_time: cleanString(body.arrival_time),\n\n special_requests: toArray(body.special_requests).join(\", \"),\n\n source: cleanString(body.source || \"unknown\"),\n\n journey_status: \"received\",\n\n created_at: now,\n updated_at: now,\n\n raw_booking: body\n }\n };\n});"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
176,
128
],
"id": "885458cb-86e4-4c84-934f-3dc1f8339393",
"name": "RO-02 | Normalize Booking"
},
{
"parameters": {
"jsCode": "const booking = $json;\n\nconst errors = [];\nconst warnings = [];\nconst missing_fields = [];\n\n// -------------------------\n// Required fields\n// -------------------------\nconst requiredFields = [\n \"booking_id\",\n \"status\",\n \"guest_name\",\n \"email\",\n \"check_in\",\n \"check_out\",\n \"room_type\"\n];\n\nfor (const field of requiredFields) {\n const value = booking[field];\n\n if (\n value === undefined ||\n value === null ||\n String(value).trim() === \"\"\n ) {\n missing_fields.push(field);\n }\n}\n\n// -------------------------\n// Email validation\n// -------------------------\nif (\n booking.email &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(booking.email)\n) {\n errors.push(\"Invalid email address.\");\n}\n\n// -------------------------\n// Booking Status\n// -------------------------\nconst allowedStatus = [\n \"confirmed\",\n \"modified\",\n \"cancelled\"\n];\n\nif (!allowedStatus.includes(booking.status)) {\n errors.push(\"Invalid booking status.\");\n}\n\n// -------------------------\n// Dates\n// -------------------------\nif (\n booking.check_in &&\n booking.check_out &&\n new Date(booking.check_out) <= new Date(booking.check_in)\n) {\n errors.push(\"Check-out date must be after check-in.\");\n}\n\n// -------------------------\n// Adults\n// -------------------------\nif (Number(booking.adults) < 1) {\n errors.push(\"At least one adult is required.\");\n}\n\n// -------------------------\n// Children\n// -------------------------\nif (Number(booking.children) < 0) {\n errors.push(\"Children cannot be negative.\");\n}\n\n// -------------------------\n// Amount\n// -------------------------\nif (Number(booking.amount_value) < 0) {\n errors.push(\"Amount cannot be negative.\");\n}\n\n// -------------------------\n// Arrival Time\n// -------------------------\nif (!booking.arrival_time) {\n warnings.push(\"Arrival time not provided.\");\n}\n\n// -------------------------\n// Final validation\n// -------------------------\nconst is_valid =\n missing_fields.length === 0 &&\n errors.length === 0;\n\nlet validation_status = \"valid\";\n\nif (!is_valid) {\n validation_status = \"needs_review\";\n} else if (!booking.arrival_time) {\n validation_status = \"valid_missing_arrival_time\";\n} else if (booking.status === \"cancelled\") {\n validation_status = \"valid_cancelled_booking\";\n} else if (booking.status === \"modified\") {\n validation_status = \"valid_modified_booking\";\n} else if (booking.status === \"confirmed\") {\n validation_status = \"valid_confirmed_booking\";\n}\n\nreturn {\n json: {\n ...booking,\n\n is_valid,\n\n validation_status,\n\n errors,\n\n missing_fields,\n\n warnings,\n\n validated_at: new Date().toISOString()\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
384,
128
],
"id": "86f9a8dc-4b7f-49ca-a51c-fcfffd658297",
"name": "RO-03 | Validate Booking"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "d85bc6dd-8cff-4a23-92e1-b2a25e90f9ae",
"leftValue": "={{ $json.is_valid }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
608,
128
],
"id": "504428fc-e394-4126-b525-34e9399f34b2",
"name": "RO-04 | Is Booking Valid?"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"leftValue": "={{ $json.status }}",
"rightValue": "confirmed",
"operator": {
"type": "string",
"operation": "equals"
},
"id": "c4fdbe63-b0d3-4a24-b7e8-e001aa5ff3c2"
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Confirmed"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "91068d4b-2435-45bd-8f1f-2feabd730278",
"leftValue": "={{ $json.status }}",
"rightValue": "modified",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Modified"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "c899cad6-91e4-405f-8fc1-a9edde54f751",
"leftValue": "={{ $json.status }}",
"rightValue": "cancelled",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Cancelled"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.4,
"position": [
832,
112
],
"id": "d5422f68-65a2-4fc2-91e0-6265f2db571d",
"name": "RO-05 | Route Booking Status"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "4c9fb4c1-dc9c-4d1e-a7bc-853b95d786da",
"leftValue": "={{ $json.guest_id }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1248,
-448
],
"id": "a890173a-720d-4b30-a17e-e2651f14778d",
"name": "RO-07 | Guest Exists?"
},
{
"parameters": {
"documentId": {
"__rl": true,
"value": "YOUR_GUESTS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "guests",
"mode": "name",
"cachedResultName": "guests"
},
"filtersUI": {
"values": [
{
"lookupColumn": "email",
"lookupValue": "={{ $json.email }}"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1040,
-448
],
"id": "c6589169-f53a-4d32-be59-574bd1439402",
"name": "RO-06 | Find Existing Guest",
"alwaysOutputData": true
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_GUESTS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "guests",
"mode": "name",
"cachedResultName": "guests"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"guest_id": "={{ $('RO-05 | Route Booking Status').item.json.guest_id }}",
"guest_name": "={{ $('RO-05 | Route Booking Status').item.json.guest_name }}",
"email": "={{ $('RO-05 | Route Booking Status').item.json.email }}",
"phone": "={{ $('RO-05 | Route Booking Status').item.json.phone }}",
"language": "={{ $('RO-05 | Route Booking Status').item.json.language }}",
"created_at": "={{ $('RO-05 | Route Booking Status').item.json.created_at }}",
"updated_at": "={{ $('RO-05 | Route Booking Status').item.json.updated_at }}"
},
"matchingColumns": [],
"schema": [
{
"id": "guest_id",
"displayName": "guest_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "guest_name",
"displayName": "guest_name",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "email",
"displayName": "email",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "phone",
"displayName": "phone",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "language",
"displayName": "language",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "updated_at",
"displayName": "updated_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1472,
-384
],
"id": "f970d2fb-855d-4f90-9e88-b0d4a302c187",
"name": "RO-08 | Create Guest"
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_BOOKINGS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "bookings",
"mode": "name",
"cachedResultName": "bookings"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"booking_id": "={{ $('RO-05 | Route Booking Status').item.json.booking_id }}",
"guest_id": "={{ $json.guest_id }}",
"status": "={{ $('RO-05 | Route Booking Status').item.json.status }}",
"check_in": "={{ $('RO-05 | Route Booking Status').item.json.check_in }}",
"check_out": "={{ $('RO-05 | Route Booking Status').item.json.check_out }}",
"adults": "={{ $('RO-05 | Route Booking Status').item.json.adults }}",
"children": "={{ $('RO-05 | Route Booking Status').item.json.children }}",
"room_type": "={{ $('RO-05 | Route Booking Status').item.json.room_type }}",
"amount_value": "={{ $('RO-05 | Route Booking Status').item.json.amount_value }}",
"amount_currency": "={{ $('RO-05 | Route Booking Status').item.json.amount_currency }}",
"arrival_time": "={{ $('RO-05 | Route Booking Status').item.json.arrival_time }}",
"special_requests": "={{ $('RO-05 | Route Booking Status').item.json.special_requests }}",
"source": "={{ $('RO-05 | Route Booking Status').item.json.source }}",
"journey_status": "={{ $('RO-05 | Route Booking Status').item.json.journey_status }}",
"created_at": "={{ $('RO-05 | Route Booking Status').item.json.created_at }}",
"updated_at": "={{ $('RO-05 | Route Booking Status').item.json.updated_at }}"
},
"matchingColumns": [],
"schema": [
{
"id": "booking_id",
"displayName": "booking_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "guest_id",
"displayName": "guest_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "status",
"displayName": "status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "check_in",
"displayName": "check_in",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "check_out",
"displayName": "check_out",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "adults",
"displayName": "adults",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "children",
"displayName": "children",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "room_type",
"displayName": "room_type",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "amount_value",
"displayName": "amount_value",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "amount_currency",
"displayName": "amount_currency",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "arrival_time",
"displayName": "arrival_time",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "special_requests",
"displayName": "special_requests",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "source",
"displayName": "source",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "journey_status",
"displayName": "journey_status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "updated_at",
"displayName": "updated_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1696,
-464
],
"id": "bef15b83-9145-4db1-ab53-83c1ba77af07",
"name": "RO-09 | Store Booking"
},
{
"parameters": {
"jsCode": "const booking = $json;\n\nfunction addDays(dateString, days) {\n const d = new Date(dateString);\n d.setDate(d.getDate() + days);\n return d.toISOString().split(\"T\")[0];\n}\n\nconst events = [];\n\nevents.push({\n booking_id: booking.booking_id,\n event_type: \"pre_arrival_email\",\n scheduled_date: addDays(booking.check_in, -2),\n status: \"scheduled\",\n message_type: \"guest_email\"\n});\n\nevents.push({\n booking_id: booking.booking_id,\n event_type: \"arrival_brief\",\n scheduled_date: booking.check_in,\n status: \"scheduled\",\n message_type: \"team_email\"\n});\n\nevents.push({\n booking_id: booking.booking_id,\n event_type: \"review_request\",\n scheduled_date: addDays(booking.check_out, 1),\n status: \"scheduled\",\n message_type: \"guest_email\"\n});\n\nreturn events.map((event, index) => ({\n json: {\n event_id: `EVT-${booking.booking_id}-${index + 1}`,\n created_at: new Date().toISOString(),\n sent_at: \"\",\n ...event\n }\n}));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1904,
-464
],
"id": "142bb669-bc45-4bba-9980-d4ee32ce0eb5",
"name": "RO-10 | Build Journey Schedule"
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_JOURNEY_EVENTS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "journey_events",
"mode": "name",
"cachedResultName": "journey_events"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"event_id": "={{ $json.event_id }}",
"booking_id": "={{ $json.booking_id }}",
"event_type": "={{ $json.event_type }}",
"scheduled_date": "={{ $json.scheduled_date }}",
"status": "={{ $json.status }}",
"message_type": "={{ $json.message_type }}",
"created_at": "={{ $json.created_at }}",
"sent_at": "={{ $json.sent_at }}"
},
"matchingColumns": [],
"schema": [
{
"id": "event_id",
"displayName": "event_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "booking_id",
"displayName": "booking_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "event_type",
"displayName": "event_type",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "scheduled_date",
"displayName": "scheduled_date",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "status",
"displayName": "status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "message_type",
"displayName": "message_type",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "sent_at",
"displayName": "sent_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
2112,
-464
],
"id": "3b322d3d-2ec1-4c28-ad9b-a048817fda95",
"name": "RO-11 | Store Journey Events"
},
{
"parameters": {
"jsCode": "const items = $input.all();\nconst output = [];\n\nfor (const item of items) {\n\n const e = item.json;\n\n let owner = \"Reception\";\n let title = \"\";\n let description = \"\";\n\n switch (e.event_type) {\n\n case \"pre_arrival_email\":\n owner = \"Reception\";\n title = \"Pr\u00e9parer l'arriv\u00e9e du client\";\n description = \"V\u00e9rifier les informations avant l'arriv\u00e9e.\";\n break;\n\n case \"arrival_brief\":\n owner = \"Operations\";\n title = \"Pr\u00e9parer la chambre\";\n description = \"Pr\u00e9parer la chambre avant le check-in.\";\n break;\n\n case \"review_request\":\n owner = \"Marketing\";\n title = \"Suivi apr\u00e8s s\u00e9jour\";\n description = \"V\u00e9rifier l'envoi de la demande d'avis.\";\n break;\n\n }\n\n output.push({\n\n json: {\n\n task_id: `TASK-${e.event_id}`,\n\n booking_id: e.booking_id,\n\n task_type: e.event_type,\n\n task_title: title,\n\n task_description: description,\n\n due_date: e.scheduled_date,\n\n owner,\n\n status: \"open\",\n\n created_at: new Date().toISOString()\n\n }\n\n });\n\n}\n\nreturn output;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2320,
-464
],
"id": "22e90b14-f167-4486-9f87-a574d66c5c16",
"name": "RO-12 | Build Internal Tasks"
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_INTERNAL_TASKS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "internal_tasks",
"mode": "name",
"cachedResultName": "internal_tasks"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"task_id": "={{ $json.task_id }}",
"booking_id": "={{ $json.booking_id }}",
"task_type": "={{ $json.task_type }}",
"task_title": "={{ $json.task_title }}",
"task_description": "={{ $json.task_description }}",
"due_date": "={{ $json.due_date }}",
"owner": "={{ $json.owner }}",
"status": "={{ $json.status }}",
"created_at": "={{ $json.created_at }}"
},
"matchingColumns": [],
"schema": [
{
"id": "task_id",
"displayName": "task_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "booking_id",
"displayName": "booking_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "task_type",
"displayName": "task_type",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "task_title",
"displayName": "task_title",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "task_description",
"displayName": "task_description",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "due_date",
"displayName": "due_date",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "owner",
"displayName": "owner",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "status",
"displayName": "status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
2528,
-464
],
"id": "e42834f1-6ee7-4bf3-8225-538a75169fd4",
"name": "RO-13 | Store Internal Tasks"
},
{
"parameters": {
"promptType": "define",
"text": "=Booking ID:\n{{ $('RO-02 | Normalize Booking').item.json.booking_id }}\n\nGuest:\n{{ $('RO-02 | Normalize Booking').item.json.guest_name }}\n\nSpecial Requests:\n{{ $('RO-02 | Normalize Booking').item.json.special_requests }}\n\nArrival:\n{{ $('RO-02 | Normalize Booking').item.json.arrival_time }}\n\nRoom:\n{{ $('RO-02 | Normalize Booking').item.json.room_type }}",
"messages": {
"messageValues": [
{
"message": "You are an AI Concierge Assistant for a luxury riad. Your role is to analyze guest booking information and special requests, then provide actionable recommendations for the hotel staff. Your response will be used by an automation workflow, so it MUST always be valid JSON. Rules: - Return ONLY valid JSON. - Do NOT use Markdown. - Do NOT wrap the JSON inside ```json. - Do NOT add explanations, comments, or extra text. - Always return exactly one JSON object. - If there are no special requests, still return a valid JSON object. - Be concise and practical. - Focus on operational actions for the staff. Priority levels: - low - medium - high Departments: - Reception - Housekeeping - Kitchen - Management - Maintenance Determine the priority based on the guest's requests. Examples: Airport transfer \u2192 Reception Late check-in \u2192 Reception Extra cleaning \u2192 Housekeeping Vegan breakfast \u2192 Kitchen Birthday / Honeymoon \u2192 Management Maintenance issue \u2192 Maintenance The JSON schema is: { \"priority\": \"low | medium | high\", \"department\": \"Reception | Housekeeping | Kitchen | Management | Maintenance\", \"summary\": \"Short operational summary for the staff.\", \"recommended_actions\": [ \"Action 1\", \"Action 2\", \"Action 3\" ] } The summary must be less than 30 words. Each recommended action must: - be short; - start with a verb; - be immediately actionable; - contain no numbering. Never invent information that is not present in the booking."
}
]
},
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
3008,
-464
],
"id": "da2ff77a-f79d-4e13-96f7-67c85da17fc7",
"name": "RO-14 | AI Guest Request Analyzer"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "let text = $json.text || \"\";\n\n// Supprime les balises Markdown\ntext = text\n .replace(/```json/g, \"\")\n .replace(/```/g, \"\")\n .trim();\n\nlet parsed;\n\ntry {\n parsed = JSON.parse(text);\n} catch (e) {\n throw new Error(\"Invalid JSON returned by AI:\\n\" + text);\n}\n\nreturn {\n json: {\n analysis_id: `AI-${Date.now()}`,\n booking_id: $('RO-02 | Normalize Booking').item.json.booking_id,\n\n priority: parsed.priority,\n\n department: parsed.department,\n\n summary: parsed.summary,\n\n recommended_actions: parsed.recommended_actions,\n\n created_at: new Date().toISOString()\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
3360,
-464
],
"id": "14ed376e-0546-4f77-a354-827a7e33bc23",
"name": "RO-15 | Parse AI Analysis"
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_GUEST_AI_ANALYSIS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "guest_ai_analysis",
"mode": "name",
"cachedResultName": "guest_ai_analysis"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"analysis_id": "={{ $json.analysis_id }}",
"booking_id": "={{ $json.booking_id }}",
"priority": "={{ $json.priority }}",
"department": "={{ $json.department }}",
"summary": "={{ $json.summary }}",
"recommended_actions": "={{ $json.recommended_actions }}",
"created_at": "={{ $json.created_at }}"
},
"matchingColumns": [],
"schema": [
{
"id": "analysis_id",
"displayName": "analysis_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "booking_id",
"displayName": "booking_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "priority",
"displayName": "priority",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "department",
"displayName": "department",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "summary",
"displayName": "summary",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "recommended_actions",
"displayName": "recommended_actions",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
3568,
-464
],
"id": "0a2eb542-82e4-4d70-92a0-1ac2ad008918",
"name": "RO-16 | Save AI Analysis"
},
{
"parameters": {
"promptType": "define",
"text": "=Booking ID:\n{{ $('RO-02 | Normalize Booking').item.json.booking_id }}\n\nGuest Name:\n{{ $('RO-02 | Normalize Booking').item.json.guest_name }}\n\nRoom:\n{{ $('RO-02 | Normalize Booking').item.json.room_type }}\n\nCheck-in:\n{{ $('RO-02 | Normalize Booking').item.json.check_in }}\n\nArrival Time:\n{{ $('RO-02 | Normalize Booking').item.json.arrival_time }}\n\nSpecial Requests:\n{{ $('RO-02 | Normalize Booking').item.json.special_requests }}\n\nAI Summary:\n{{ $('RO-15 | Parse AI Analysis').item.json.summary }}",
"messages": {
"messageValues": [
{
"message": "You are the concierge of a luxury Moroccan riad. Write a warm, elegant and professional pre-arrival email. Your objective is to welcome the guest and reassure them before arrival. Rules: - Return ONLY valid JSON. - Do not use markdown. - Do not use ```json. - Do not add explanations. - Keep the email under 180 words. - Use a warm and welcoming tone. - Mention only information available in the booking. - If there are no special requests, simply welcome the guest. - If there are special requests, reassure the guest that they have been noted. - Never invent information. Return exactly this schema: { \"subject\": \"\", \"body\": \"\" }"
}
]
},
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
3776,
-464
],
"id": "6bc3bf13-9fb9-48e7-81bd-11b20577f960",
"name": "RO-17 | Generate Guest Email"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "let text = $json.text || \"\";\n\ntext = text\n .replace(/```json/g, \"\")\n .replace(/```/g, \"\")\n .trim();\n\nconst email = JSON.parse(text);\n\nreturn {\n json: {\n subject: email.subject,\n body: email.body,\n booking_id: $('RO-02 | Normalize Booking').item.json.booking_id,\n guest_name: $('RO-02 | Normalize Booking').item.json.guest_name,\n email: $('RO-02 | Normalize Booking').item.json.email\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
4128,
-464
],
"id": "94d179f8-4f34-4564-9304-5656e21a0d42",
"name": "RO-18 | Parse Guest Email"
},
{
"parameters": {
"sendTo": "={{ $('RO-02 | Normalize Booking').item.json.email }}",
"subject": "={{ $json.subject }}",
"emailType": "text",
"message": "={{ $json.body }}",
"options": {}
},
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.2,
"position": [
4336,
-464
],
"id": "6521da07-cfdc-4646-ab9b-8d0f83ff2503",
"name": "RO-19 | Send Guest Email"
},
{
"parameters": {
"documentId": {
"__rl": true,
"value": "YOUR_BOOKINGS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "bookings",
"mode": "name",
"cachedResultName": "bookings"
},
"filtersUI": {
"values": [
{
"lookupColumn": "booking_id",
"lookupValue": "={{ $json.booking_id }}"
}
]
},
"options": {
"returnFirstMatch": true
}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1136,
80
],
"id": "d8a8c5f4-de77-4dc2-85f9-6895cc4931c8",
"name": "RO-20 | Find Existing Booking"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "2c3460de-eef9-4368-9eda-dcf4cc6574a2",
"leftValue": "={{ $json.booking_id }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1360,
-32
],
"id": "a5181713-848c-4d77-b3ac-2f79c0be18ce",
"name": "RO-21 | Booking Exists?"
},
{
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "YOUR_BOOKINGS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "bookings",
"mode": "name",
"cachedResultName": "bookings"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"booking_id": "={{ $json.booking_id }}",
"guest_id": "={{ $json.guest_id }}",
"status": "={{ $('RO-05 | Route Booking Status').item.json.status }}",
"check_in": "={{ $('RO-05 | Route Booking Status').item.json.check_in }}",
"check_out": "={{ $('RO-05 | Route Booking Status').item.json.check_out }}",
"adults": "={{ $json.adults }}",
"children": "={{ $('RO-05 | Route Booking Status').item.json.children }}",
"room_type": "={{ $('RO-05 | Route Booking Status').item.json.room_type }}",
"amount_value": "={{ $('RO-05 | Route Booking Status').item.json.amount_value }}",
"amount_currency": "={{ $json.amount_currency }}",
"arrival_time": "={{ $('RO-05 | Route Booking Status').item.json.arrival_time }}",
"special_requests": "={{ $('RO-05 | Route Booking Status').item.json.special_requests }}",
"source": "={{ $('RO-05 | Route Booking Status').item.json.source }}",
"journey_status": "={{ $('RO-05 | Route Booking Status').item.json.journey_status }}",
"created_at": "={{ $('RO-05 | Route Booking Status').item.json.created_at }}",
"updated_at": "={{ $('RO-05 | Route Booking Status').item.json.updated_at }}"
},
"matchingColumns": [
"booking_id"
],
"schema": [
{
"id": "booking_id",
"displayName": "booking_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "guest_id",
"displayName": "guest_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "status",
"displayName": "status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "check_in",
"displayName": "check_in",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "check_out",
"displayName": "check_out",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "adults",
"displayName": "adults",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "children",
"displayName": "children",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "room_type",
"displayName": "room_type",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "amount_value",
"displayName": "amount_value",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "amount_currency",
"displayName": "amount_currency",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "arrival_time",
"displayName": "arrival_time",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "special_requests",
"displayName": "special_requests",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "source",
"displayName": "source",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "journey_status",
"displayName": "journey_status",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "updated_at",
"displayName": "updated_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "row_number",
"displayName": "row_number",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"canBeUsedToMatch": true,
"readOnly": true,
"removed": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1616,
-96
],
"id": "b00c4d1a-07b0-4e97-9431-31e0541ede7a",
"name": "RO-22 | Update Booking"
},
{
"parameters": {
"promptType": "define",
"text": "=Booking ID: {{$json.booking_id}}\n\nGuest:\n{{$json.guest_name}}\n\nRoom:\n{{$json.room_type}}\n\nCheck-in:\n{{$json.check_in}}\n\nCheck-out:\n{{$json.check_out}}\n\nAdults:\n{{$json.adults}}\n\nChildren:\n{{$json.children}}\n\nArrival time:\n{{$json.arrival_time}}\n\nSpecial Requests:\n{{$json.special_requests}}\n\nReservation Status:\nModified\n\nAnalyze this updated reservation.",
"messages": {
"messageValues": [
{
"message": "You are an AI Concierge Assistant for a luxury Moroccan riad. Analyze the updated reservation. Determine: - priority (Low, Medium, High) - department responsible - short summary - recommended actions Return ONLY valid JSON. { \"priority\": \"\", \"department\": \"\", \"summary\": \"\", \"recommended_actions\": [] }"
}
]
},
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
1824,
-64
],
"id": "c198c9e5-602a-44dd-ba44-c7083ad4b778",
"name": "RO-23 | AI Guest Request Analyzer"
},
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4.1-mini",
"mode": "list",
"cachedResultName": "gpt-4.1-mini"
},
"builtInTools": {},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.3,
"position": [
1760,
192
],
"id": "c50e0f6d-67fb-4a5a-81fd-ccee75a886c6",
"name": "OpenAI Chat Model2"
},
{
"parameters": {
"jsCode": "let output = $json.output || $json.text || $json.response || \"\";\n\noutput = output\n .replace(/```json/g, \"\")\n .replace(/```/g, \"\")\n .trim();\n\nconst analysis = JSON.parse(output);\n\nreturn {\n json: {\n booking_id: $('RO-22 | Update Booking').first().json.booking_id,\n\n priority: analysis.priority,\n\n department: analysis.department,\n\n summary: analysis.summary,\n\n recommended_actions: Array.isArray(analysis.recommended_actions)\n ? analysis.recommended_actions.join(\", \")\n : analysis.recommended_actions,\n\n updated_at: new Date().toISOString()\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2176,
-16
],
"id": "89f3c8cf-f8a5-4a89-a958-0917f3a68d72",
"name": "RO-24 | Parse AI Analysis"
},
{
"parameters": {
"documentId": {
"__rl": true,
"value": "YOUR_GUEST_AI_ANALYSIS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "guest_ai_analysis",
"mode": "name",
"cachedResultName": "guest_ai_analysis"
},
"filtersUI": {
"values": [
{
"lookupColumn": "booking_id",
"lookupValue": "={{ $('RO-21 | Booking Exists?').item.json.booking_id }}"
}
]
},
"options": {
"returnFirstMatch": true
}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
2384,
-16
],
"id": "e2881750-9e87-4739-8a57-3fe0e26fa0b5",
"name": "RO-25 | Find AI Analysis"
},
{
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "YOUR_GUEST_AI_ANALYSIS_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "guest_ai_analysis",
"mode": "name",
"cachedResultName": "guest_ai_analysis"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"analysis_id": "={{ $json.analysis_id }}",
"booking_id": "={{ $json.booking_id }}",
"priority": "={{ $json.priority }}",
"department": "={{ $json.department }}",
"summary": "={{ $json.summary }}",
"recommended_actions": "={{ $json.recommended_actions }}",
"created_at": "={{ $json.created_at }}"
},
"matchingColumns": [
"analysis_id"
],
"schema": [
{
"id": "analysis_id",
"displayName": "analysis_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "booking_id",
"displayName": "booking_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "priority",
"displayName": "priority",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "department",
"displayName": "department",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "summary",
"displayName": "summary",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "recommended_actions",
"displayName": "recommended_actions",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "row_number",
"displayName": "row_number",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"canBeUsedToMatch": true,
"readOnly": true,
"removed": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
2592,
-16
],
"id": "e572ea33-9633-480f-841b-14cba7a74e7f",
"name": "RO-26 | Update AI Analysis"
},
{
"parameters": {
"promptType": "define",
"text": "=Guest: {{$('RO-22 | Update Booking').first().json.guest_name}}\n\nBooking ID:\n{{$('RO-22 | Update Booking').first().json.booking_id}}\n\nCheck-in:\n{{$('RO-22 | Update Booking').first().json.check_in}}\n\nCheck-out:\n{{$('RO-22 | Update Booking').first().json.check_out}}\n\nRoom:\n{{$('RO-22 | Update Booking').first().json.room_type}}\n\nArrival:\n{{$('RO-22 | Update Booking').first().json.arrival_time}}\n\nSpecial Requests:\n{{$('RO-22 | Update Booking').first().json.special_requests}}\n\nWrite the updated confirmation email.",
"messages": {
"messageValues": [
{
"message": "You are the concierge of a luxury Moroccan riad. Write a professional email informing the guest that their reservation has been successfully updated. Return ONLY valid JSON. { \"subject\":\"\", \"body\":\"\" }"
}
]
},
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
2800,
-16
],
"id": "90b05556-7015-4301-a015-d0481352a831",
"name": "RO-27 | Generate Updated Guest Email"
},
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4.1-mini",
"mode": "list",
"cachedResultName": "gpt-4.1-mini"
},
"builtInTools": {},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.3,
"position": [
2736,
192
],
"id": "b53b42ff-0111-4bbe-b98d-1b31bdb365ae",
"name": "OpenAI Chat Model3"
},
{
"parameters": {
"jsCode": "let text = $json.text || \"\";\n\ntext = text\n .replace(/```json/g, \"\")\n .replace(/```/g, \"\")\n .trim();\n\nconst email = JSON.parse(text);\n\nreturn {\n json: {\n subject: email.subject,\n body: email.body,\n booking_id: $('RO-02 | Normalize Booking').item.json.booking_id,\n guest_name: $('RO-02 | Normalize Booking').item.json.guest_name,\n email: $('RO-02 | Normalize Booking').item.json.email\n }\n};"
},
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
RiadOps. Uses lmChatOpenAi, googleSheets, chainLlm, gmail. Webhook trigger; 41 nodes.
Source: https://github.com/1liasx/riadops-n8n/blob/main/workflows/riadops-public.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.
leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.
This workflow automates document processing using LlamaParse to extract and analyze text from various file formats. It intelligently processes documents, extracts structured data, and delivers actiona
AI Contract Reviewer. Uses chainLlm, lmChatOpenAi, outputParserStructured, googleSheets. Webhook trigger; 31 nodes.
Description
AI Customer Service Automation - Portfolio. Uses googleSheets, httpRequest, agent, memoryBufferWindow. Webhook trigger; 91 nodes.