This workflow corresponds to n8n.io template #13962 — we link there as the canonical source.
This workflow follows the Agent → 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 →
{
"id": "pmdtp3MKQLEODZ4R",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Real Estate Deal-Making Agent",
"tags": [],
"nodes": [
{
"id": "380b8b66-8fdb-481f-8322-4b6df2c72d97",
"name": "\ud83d\udccb Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-800,
992
],
"parameters": {
"color": 3,
"width": 520,
"height": 984,
"content": "## \ud83c\udfe0 Real Estate Deal-Making Agent\n\n### How it works\nThis workflow automates the full real estate sales pipeline across four interconnected stages:\n\n**Pipeline 1 \u2013 Lead Deduplication:** A webhook receives incoming buyer leads. Buyer preferences (name, location, property type, budget, email) are set and passed to an AI Dedup Agent that queries the CRM sheet to detect duplicates. Exact email matches are flagged as duplicates (routed to a follow-up email); new leads are saved to the sheet for processing.\n\n**Pipeline 2 \u2013 Property Matching:** A Google Sheets Trigger fires when a new buyer row is added. An AI Property Matching Agent compares buyer requirements against the Available Property sheet and returns scored matches. Results are normalized and saved to the Property Seeing tab.\n\n**Pipeline 3 \u2013 Property Deck Delivery:** Once a match is saved, an AI Deck Agent searches Google Drive for the matching property brochure/deck. The deck details are normalized and emailed to the buyer as an attachment. The interaction is logged back to the sheet.\n\n**Pipeline 4 \u2013 Deal Scoring:** A Cron Trigger fires periodically and fetches buyer engagement records. An AI Deal Scoring Agent predicts closing probability (0\u2013100), assigns a deal stage, urgency level, and recommended next action. The score is emailed to the sales team.\n\n### Setup steps\n1. **Webhook** \u2013 Activate workflow and configure your lead form to POST buyer data to the webhook URL.\n2. **Azure OpenAI** \u2013 Add your Azure OpenAI credentials (all four AI Agent Chat Model nodes use `gpt-4o-mini`).\n3. **Google Sheets** \u2013 Connect OAuth2 to all sheet nodes. Create a spreadsheet with tabs: *Property seeing*, *Available Property*.\n4. **Google Drive** \u2013 Connect OAuth2 to the Drive tool node. Store property deck files in the root folder.\n5. **Gmail** \u2013 Connect OAuth2 to all three Gmail nodes. Update `sendTo` addresses.\n6. **Cron** \u2013 Set the desired deal-scoring frequency.\n\n### Customization\n- Swap Azure OpenAI for another LLM by replacing any Chat Model sub-node.\n- Add a Slack alert node after deal scoring for real-time sales team notifications."
},
"typeVersion": 1
},
{
"id": "4daabc69-ff0e-4d4c-b5a3-1059e6eab32d",
"name": "Section: Lead Intake & Deduplication",
"type": "n8n-nodes-base.stickyNote",
"position": [
-32,
864
],
"parameters": {
"width": 860,
"height": 260,
"content": "## \ud83d\udce5 Lead Intake & Deduplication\nReceives buyer leads via webhook, sets preferences, and uses an AI Agent to check the CRM sheet for duplicates. Exact email matches trigger a follow-up alert; genuinely new leads are saved for property matching."
},
"typeVersion": 1
},
{
"id": "c4b0d5df-3157-4463-902e-1835af88875c",
"name": "Section: Property Matching",
"type": "n8n-nodes-base.stickyNote",
"position": [
48,
1488
],
"parameters": {
"width": 860,
"height": 260,
"content": "## \ud83d\udd0d Property Matching\nFired when a new buyer row lands in Sheets. AI Agent compares buyer requirements against the Available Property database and returns scored property matches. Results are normalized and logged to the Property Seeing tab."
},
"typeVersion": 1
},
{
"id": "ac2521a8-ba54-4f54-937a-28cc1ce926de",
"name": "Section: Property Deck Delivery",
"type": "n8n-nodes-base.stickyNote",
"position": [
1056,
1472
],
"parameters": {
"width": 900,
"height": 260,
"content": "## \ud83d\udcc2 Property Deck Delivery\nAI Agent searches Google Drive for the matching property brochure based on property name/ID. The deck is normalized, emailed to the buyer as an attachment, and the send event is logged back to the sheet."
},
"typeVersion": 1
},
{
"id": "8cd8a3fc-6c74-443b-8431-b0d0280a95af",
"name": "Section: Deal Scoring & Sales Intelligence",
"type": "n8n-nodes-base.stickyNote",
"position": [
80,
2000
],
"parameters": {
"width": 860,
"height": 260,
"content": "## \ud83d\udcca Deal Scoring & Sales Intelligence\nCron-triggered pipeline that fetches buyer engagement records and runs an AI Deal Scoring Agent. Predicts closing probability (0\u2013100), assigns deal stage & urgency, and emails the recommended next action to the sales team."
},
"typeVersion": 1
},
{
"id": "f1e0ecb4-0528-4340-87d3-080c6f8d67d0",
"name": "\u26a0\ufe0f Warning: Azure OpenAI Credentials",
"type": "n8n-nodes-base.stickyNote",
"position": [
-64,
1232
],
"parameters": {
"color": 2,
"width": 300,
"content": "\u26a0\ufe0f **Azure OpenAI Credentials Required**\nAll four AI Agent nodes depend on Azure OpenAI. Ensure your API key, endpoint URL, and deployment name are correctly set. Misconfiguration will silently break dedup, matching, deck delivery, and deal scoring."
},
"typeVersion": 1
},
{
"id": "99e14c16-1a53-4f1e-aa7c-6dbed8d4e1db",
"name": "\u26a0\ufe0f Warning: Google Drive Setup Required",
"type": "n8n-nodes-base.stickyNote",
"position": [
1424,
1808
],
"parameters": {
"color": 2,
"width": 300,
"content": "\u26a0\ufe0f **Google Drive Credentials & Folder Required**\nThe Deck Search tool reads from Google Drive root. Ensure property deck files are uploaded with names matching property names or IDs in the sheet. Missing files will return `deck_not_found` status."
},
"typeVersion": 1
},
{
"id": "5a586667-24a5-420a-a90a-00de83fb26f0",
"name": "\u23f0 Deal Scoring Cron Trigger",
"type": "n8n-nodes-base.cron",
"position": [
112,
2160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "f578bbfa-ac8a-48aa-9b25-80c89f2825d9",
"name": "\ud83d\uddc2\ufe0f Set Buyer Preferences",
"type": "n8n-nodes-base.set",
"position": [
224,
1040
],
"parameters": {
"values": {
"string": [
{
"name": "buyer_name",
"value": "Rahul Sharma"
},
{
"name": "location",
"value": "Mumbai"
},
{
"name": "property_type",
"value": "2BHK"
},
{
"name": "budget",
"value": "1.5 Cr"
},
{
"name": "email",
"value": "user@example.com"
}
]
},
"options": {}
},
"typeVersion": 2
},
{
"id": "739f4aa7-3e0e-4315-95d9-d399cb388f30",
"name": "\ud83d\udd14 Buyer Lead Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
16,
1040
],
"parameters": {
"path": "6785d2b2-e74b-42e2-a6bf-a70ece1e78b9",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "f97032a7-4faa-4760-a288-01a0161e6d0d",
"name": "\ud83e\udd16 AI Dedup & CRM Check Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
432,
1040
],
"parameters": {
"text": "=Check if the following buyer lead already exists in the CRM database.\n\nBuyer Information:\n\nName: {{$json.name}}\n\nLocation: {{$json.location}}\n\nProperty Type: {{$json.property}}\n\nBudget: {{$json.budget}}\n\nEmail: {{$json.email}}\n\nUse the connected Google Sheet tool to read existing records and determine if this lead already exists.\n\nReturn the result in the required JSON format.\n",
"options": {
"systemMessage": "=You are an AI assistant responsible for checking whether a real estate buyer already exists in the CRM database.\n\nYou have access to a Google Sheet tool that contains existing buyer records.\n\nYour task is to compare the incoming buyer information with the records from the sheet and determine if the lead already exists.\n\nFollow these rules carefully:\n\n1. Always read the buyer records from the connected sheet tool before making a decision.\n\n2. Compare the following fields:\n\n * Name\n * Email\n * Location\n * Property Type\n * Budget\n\n3. The most reliable identifier is the Email field.\n\n4. If the email matches an existing record, the lead must be marked as a duplicate.\n\n5. If the email is different but the name and location are very similar, mark it as a \"possible duplicate\".\n\n6. If no matching fields are found, mark the lead as \"new\".\n\nDuplicate Rules:\n\nEmail match \u2192 Exact duplicate\nName + location match \u2192 Possible duplicate\nNo matches \u2192 New lead\n\nReturn structured JSON only.\n\nOutput format:\n\n{\n\"lead_status\": \"\",\n\"matched_record\": {\n\"name\": \"\",\n\"email\": \"\",\n\"location\": \"\",\n\"property_type\": \"\",\n\"budget\": \"\"\n},\n\"reason\": \"\",\n\"action\": \"\"\n}\n\nAllowed values for lead_status:\n\n* duplicate\n* possible_duplicate\n* new_lead\n\nAllowed values for action:\n\n* skip_record\n* review_required\n* create_new_record\n\nDo not include explanations outside JSON.\n"
},
"promptType": "define"
},
"typeVersion": 3
},
{
"id": "ca952b13-6be3-437c-880e-8b910ec8f49c",
"name": "\ud83e\udde0 Azure OpenAI \u2013 Dedup Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
"position": [
336,
1232
],
"parameters": {
"model": "gpt-4o-mini",
"options": {}
},
"credentials": {
"azureOpenAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "b94e5bb0-5f77-44ab-a5bf-332ff4df52a2",
"name": "\ud83d\udccb Read CRM Sheet for Dedup",
"type": "n8n-nodes-base.googleSheetsTool",
"position": [
592,
1248
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1955683186,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit#gid=1955683186",
"cachedResultName": "Property seeing"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit?usp=drivesdk",
"cachedResultName": "Real-estate details"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "92fe740d-f505-4ef1-a827-d8b85047f034",
"name": "\u2699\ufe0f Normalize Dedup Result",
"type": "n8n-nodes-base.code",
"position": [
784,
1040
],
"parameters": {
"jsCode": "let raw = $json;\n\n// If AI returned string instead of JSON\nif (typeof raw === \"string\") {\n try {\n raw = JSON.parse(raw);\n } catch (e) {\n const match = raw.match(/\\{[\\s\\S]*\\}/);\n if (match) {\n raw = JSON.parse(match[0]);\n } else {\n raw = {};\n }\n }\n}\n\n// Helper functions\nconst clean = (val, fallback = \"\") => {\n if (val === undefined || val === null) return fallback;\n return String(val).trim();\n};\n\nconst normalizeStatus = (status) => {\n const s = clean(status).toLowerCase();\n\n if (s.includes(\"duplicate\")) return \"duplicate\";\n if (s.includes(\"possible\")) return \"possible_duplicate\";\n if (s.includes(\"new\")) return \"new_lead\";\n\n return \"unknown\";\n};\n\nconst normalizeAction = (action) => {\n const a = clean(action).toLowerCase();\n\n if (a.includes(\"skip\")) return \"skip_record\";\n if (a.includes(\"review\")) return \"review_required\";\n if (a.includes(\"create\")) return \"create_new_record\";\n\n return \"review_required\";\n};\n\n// Extract matched record safely\nconst record = raw.matched_record || {};\n\nconst normalized = {\n lead_status: normalizeStatus(raw.lead_status),\n\n action: normalizeAction(raw.action),\n\n reason: clean(raw.reason),\n\n matched_record: {\n name: clean(record.name),\n email: clean(record.email),\n location: clean(record.location),\n property_type: clean(record.property_type),\n budget: clean(record.budget)\n }\n};\n\n// Add helper flags for workflow logic\nnormalized.is_duplicate = normalized.lead_status === \"duplicate\";\nnormalized.is_possible_duplicate =\n normalized.lead_status === \"possible_duplicate\";\nnormalized.is_new_lead = normalized.lead_status === \"new_lead\";\n\nreturn [{ json: normalized }];"
},
"typeVersion": 2
},
{
"id": "2ec4c681-6a19-4bf6-92c7-9e76dc1b6356",
"name": "\ud83d\udd00 Route: Duplicate or New Lead?",
"type": "n8n-nodes-base.if",
"position": [
992,
1040
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "43dbfd6a-585f-45a5-9eb2-1dfb46a075cc",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "Database",
"rightValue": "Yes"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "1c4b317b-1aed-4274-a0e7-9a00c149547d",
"name": "\ud83d\udce7 Send Duplicate Follow-Up Alert",
"type": "n8n-nodes-base.gmail",
"position": [
1216,
976
],
"parameters": {
"sendTo": "info@example.com",
"message": "Please take the follow-up on lead <n>",
"options": {},
"subject": "<n> ALready in the database",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "23dd1522-ad24-4827-a1ee-a4070f98df81",
"name": "\ud83d\udcdd Save New Lead to CRM Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1216,
1168
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1955683186,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit#gid=1955683186",
"cachedResultName": "Property seeing"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit?usp=drivesdk",
"cachedResultName": "Real-estate details"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "7472f5e9-b4fa-4f54-a70a-a2079b4ad53c",
"name": "\ud83d\udcca New Buyer Row Trigger",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
128,
1616
],
"parameters": {
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1955683186,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit#gid=1955683186",
"cachedResultName": "Property seeing"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit?usp=drivesdk",
"cachedResultName": "Real-estate details"
}
},
"credentials": {
"googleSheetsTriggerOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "89e81ef1-11e6-4ceb-9c9e-3dc04ffebd1c",
"name": "\ud83e\udd16 AI Property Matching Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
336,
1616
],
"parameters": {
"text": "=Buyer Requirements:\n\nName: {{ $json.buyer_name }}\nLocation Preference: {{ $json.location }}\nBudget: {{ $json.budget }}\nProperty Type: {{ $json.property_type }}\nBedrooms: {{ $json.bedrooms }}\nAdditional Requirements: {{ $json.additional_requirements }}\n\nProperty Database:\n\n{{ $json.properties }}\n\nInstructions:\nCompare the buyer requirements with the property database and return matching properties using the required JSON format.",
"options": {
"systemMessage": "=You are a Real Estate Property Matching AI Agent.\n\nYour task is to analyze buyer requirements and check if suitable properties exist in the provided property database.\n\nYou will receive:\n1. Buyer requirements (budget, location, property type, bedrooms, etc.)\n2. A dataset of available properties from a database.\n\nYour job is to:\n\u2022 Carefully analyze the buyer's requirements\n\u2022 Compare them with the property database\n\u2022 Identify properties that best match the requirements\n\u2022 Return a structured JSON response\n\nMatching Logic:\n- Location must match or be very close.\n- Budget should be within the buyer's budget range if provided.\n- Property type must match if specified.\n- Bedrooms/BHK should match if specified.\n- If multiple properties match, return the best matches.\n\nRules:\n- Only use properties from the provided database.\n- Do NOT invent properties.\n- If no properties match, return \"no_match\": true.\n- If matches exist, return them in a clean structured format.\n\nOutput format MUST be valid JSON only.\n\nOutput Structure:\n\n{\n \"match_found\": true/false,\n \"total_matches\": number,\n \"matched_properties\": [\n {\n \"property_name\": \"\",\n \"location\": \"\",\n \"price\": \"\",\n \"bedrooms\": \"\",\n \"property_type\": \"\",\n \"property_id\": \"\",\n \"match_score\": \"\"\n }\n ],\n \"message\": \"\"\n}\n\nIf no property matches:\n\n{\n \"match_found\": false,\n \"total_matches\": 0,\n \"matched_properties\": [],\n \"message\": \"No suitable property found based on buyer requirements.\"\n}"
},
"promptType": "define"
},
"typeVersion": 3
},
{
"id": "52398979-d6a4-44f9-8b8a-d93e66a1e111",
"name": "\ud83e\udde0 Azure OpenAI \u2013 Matching Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
"position": [
192,
1824
],
"parameters": {
"model": "gpt-4o-mini",
"options": {}
},
"credentials": {
"azureOpenAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "66d744f3-ed4b-4728-8d1f-f031a451ecaf",
"name": "\ud83d\udccb Read Available Properties Sheet",
"type": "n8n-nodes-base.googleSheetsTool",
"position": [
496,
1824
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 2030460387,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit#gid=2030460387",
"cachedResultName": "Available Property"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit?usp=drivesdk",
"cachedResultName": "Real-estate details"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "df4b2612-bd47-4c98-a09b-7c74f70030d2",
"name": "\u2699\ufe0f Normalize Property Match Results",
"type": "n8n-nodes-base.code",
"position": [
688,
1616
],
"parameters": {
"jsCode": "// Get AI output from previous node\nlet rawOutput = $json.output || $json.response || $json.text || \"\";\n\n// Remove markdown formatting if AI returned ```json\nif (typeof rawOutput === \"string\") {\n\trawOutput = rawOutput\n\t\t.replace(/```json/g, \"\")\n\t\t.replace(/```/g, \"\")\n\t\t.trim();\n}\n\n// Parse JSON safely\nlet parsed;\n\ntry {\n\tparsed = typeof rawOutput === \"string\" ? JSON.parse(rawOutput) : rawOutput;\n} catch (error) {\n\treturn [\n\t\t{\n\t\t\tjson: {\n\t\t\t\tstatus: \"error\",\n\t\t\t\tmessage: \"Unable to parse AI output\",\n\t\t\t\traw_output: rawOutput\n\t\t\t}\n\t\t}\n\t];\n}\n\n// If no property match\nif (!parsed.match_found) {\n\treturn [\n\t\t{\n\t\t\tjson: {\n\t\t\t\tmatch_found: false,\n\t\t\t\ttotal_matches: 0,\n\t\t\t\tmessage: parsed.message || \"No matching properties found\"\n\t\t\t}\n\t\t}\n\t];\n}\n\n// Normalize matched properties\nconst properties = parsed.matched_properties || [];\n\nconst normalized = properties.map(property => {\n\treturn {\n\t\tjson: {\n\t\t\tmatch_found: parsed.match_found,\n\t\t\ttotal_matches: parsed.total_matches || properties.length,\n\t\t\tproperty_id: property.property_id || \"\",\n\t\t\tproperty_name: property.property_name || \"\",\n\t\t\tlocation: property.location || \"\",\n\t\t\tprice: property.price || \"\",\n\t\t\tbedrooms: property.bedrooms || \"\",\n\t\t\tproperty_type: property.property_type || \"\",\n\t\t\tmatch_score: property.match_score || 0\n\t\t}\n\t};\n});\n\nreturn normalized;"
},
"typeVersion": 2
},
{
"id": "4933df2e-8134-4728-b9c5-42129c2adea1",
"name": "\ud83e\udd16 AI Property Deck Search Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1104,
1616
],
"parameters": {
"text": "=Buyer Details:\nName: {{ $json.buyer_name }}\nEmail: {{ $json.email }}\nLocation Preference: {{ $json.location }}\nBudget: {{ $json.budget }}\nProperty Type: {{ $json.property_type }}\n\nMatched Property Details:\nProperty Name: {{ $json.property_name }}\nProperty ID: {{ $json.property_id }}\nLocation: {{ $json.property_location }}\nPrice: {{ $json.price }}\n\nYour task:\n\n1. Understand the buyer requirements.\n2. Confirm that the property matches the buyer's preferences.\n3. Use the connected Google Drive tool to search for the property deck that matches the property name or property ID.\n4. Return the property deck details in structured JSON format.\n\nOutput format:\n\n{\n \"status\": \"deck_ready\",\n \"buyer_name\": \"\",\n \"buyer_email\": \"\",\n \"property_name\": \"\",\n \"property_id\": \"\",\n \"location\": \"\",\n \"price\": \"\",\n \"deck_file_name\": \"\",\n \"deck_file_id\": \"\",\n \"deck_download_link\": \"\"\n}",
"options": {
"systemMessage": "=You are an AI Real Estate Assistant responsible for preparing property decks for buyers.\n\nYour job is to analyze buyer details and the property details provided in the input.\n\nA Google Drive tool is connected that contains property decks. Each deck corresponds to a property in the database.\n\nSteps you must follow:\n\n1. Read buyer details carefully:\n - Name\n - Location\n - Budget\n - Property preference\n - Email\n\n2. Read property details provided in the input.\n\n3. Identify the correct property deck based on:\n - Property name\n - Property ID\n - Location\n\n4. Use the connected Google Drive tool to find the matching property deck file.\n\n5. Return a structured JSON response containing:\n - buyer_name\n - buyer_email\n - property_name\n - property_id\n - location\n - price\n - deck_file_name\n - deck_file_id\n - deck_download_link\n - status\n\nRules:\n- Only return valid JSON.\n- Do NOT include explanations or text outside the JSON.\n- If the deck is not found, return status = \"deck_not_found\".\n- If the deck is found, return status = \"deck_ready\"."
},
"promptType": "define"
},
"typeVersion": 3
},
{
"id": "c4f46d3b-5c36-40b7-96ba-0fefaa46af1e",
"name": "\ud83e\udde0 Azure OpenAI \u2013 Deck Search Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
"position": [
976,
1824
],
"parameters": {
"model": "gpt-4o-mini",
"options": {}
},
"credentials": {
"azureOpenAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "542c62fa-d04a-416b-b3ac-ae40837b3138",
"name": "\ud83d\udcc2 Search Property Deck in Google Drive",
"type": "n8n-nodes-base.googleDriveTool",
"position": [
1264,
1824
],
"parameters": {
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "43f3ab0d-5855-4866-9b53-6f72a1703f5c",
"name": "\ud83d\udcdd Save Matched Properties to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
896,
1616
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1955683186,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit#gid=1955683186",
"cachedResultName": "Property seeing"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit?usp=drivesdk",
"cachedResultName": "Real-estate details"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "af9eccca-3018-4c03-85de-0c72a03a3525",
"name": "\u2699\ufe0f Normalize Deck Details",
"type": "n8n-nodes-base.code",
"position": [
1456,
1616
],
"parameters": {
"jsCode": "// Get AI response\nlet raw = $json.output || $json.response || $json.text || \"\";\n\n// Remove markdown formatting\nif (typeof raw === \"string\") {\n raw = raw.replace(/```json/g, \"\").replace(/```/g, \"\").trim();\n}\n\nlet parsed;\n\ntry {\n parsed = typeof raw === \"string\" ? JSON.parse(raw) : raw;\n} catch (error) {\n return [\n {\n json: {\n status: \"error\",\n message: \"Failed to parse AI output\",\n raw_output: raw\n }\n }\n ];\n}\n\n// Normalize output\nreturn [\n {\n json: {\n status: parsed.status || \"unknown\",\n buyer_name: parsed.buyer_name || \"\",\n buyer_email: parsed.buyer_email || \"\",\n property_name: parsed.property_name || \"\",\n property_id: parsed.property_id || \"\",\n location: parsed.location || \"\",\n price: parsed.price || \"\",\n deck_file_name: parsed.deck_file_name || \"\",\n deck_file_id: parsed.deck_file_id || \"\",\n deck_download_link: parsed.deck_download_link || \"\"\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "1009d8bf-7475-4d74-acfc-29de1cc32898",
"name": "\ud83d\udce7 Send Property Deck to Buyer",
"type": "n8n-nodes-base.gmail",
"position": [
1664,
1616
],
"parameters": {
"sendTo": "info@example.com",
"message": "Thank you for showing intrest!, here is your property deck!",
"options": {
"attachmentsUi": {
"attachmentsBinary": [
{}
]
}
},
"subject": "Property deck",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "20872a57-d68a-4c6a-a1ac-cc1f05301edb",
"name": "\ud83d\udcdd Log Deck Send Event to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1888,
1616
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1955683186,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit#gid=1955683186",
"cachedResultName": "Property seeing"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit?usp=drivesdk",
"cachedResultName": "Real-estate details"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "2b28b2a2-7e9b-4849-944c-c5c196eabd1b",
"name": "\ud83e\udd16 AI Deal Scoring Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
544,
2160
],
"parameters": {
"text": "=Analyze the following buyer and engagement data to predict deal closing probability.\n\nBuyer Details:\nName: {{ $json.buyer_name }}\nLocation Preference: {{ $json.location }}\nBudget: {{ $json.budget }}\nProperty Type: {{ $json.property_type }}\n\nProperty Details:\nProperty Name: {{ $json.property_name }}\nProperty Price: {{ $json.price }}\n\nEngagement Signals:\nNumber of interactions: {{ $json.interactions }}\nProperty deck downloaded: {{ $json.deck_downloaded }}\nSite visit scheduled: {{ $json.site_visit }}\nDays since first inquiry: {{ $json.days_since_first_inquiry }}\nDays since last interaction: {{ $json.days_since_last_interaction }}\n\nBased on this information:\n\n1. Predict the deal closing probability (0\u2013100)\n2. Determine the deal stage\n3. Assign urgency level\n4. Recommend the next best action for the sales team\n\nReturn only structured JSON.",
"options": {
"systemMessage": "=You are an AI Real Estate Sales Intelligence Agent.\n\nYour task is to analyze buyer engagement data and predict the probability that a real estate deal will close.\n\nYou must evaluate the following factors:\n\nBuyer Profile\n- Budget match with property\n- Location preference match\n- Property type match\n\nBuyer Engagement\n- Number of interactions\n- Email opens or responses\n- Property deck downloads\n- Site visit scheduled or completed\n\nTimeline Signals\n- Days since first inquiry\n- Days since last interaction\n- Upcoming site visit\n\nBased on these signals, calculate:\n\n1. deal_probability (0\u2013100)\n2. deal_stage\n3. urgency_level\n4. recommended_action\n\nDeal Stage categories:\n- early_interest\n- evaluating_properties\n- site_visit_planned\n- negotiation_stage\n- high_intent\n\nUrgency Levels:\n- low\n- medium\n- high\n- immediate\n\nRecommended Actions:\n- send_followup_email\n- schedule_site_visit\n- send_discount_offer\n- prioritize_sales_call\n- nurture_lead\n\nOutput must be valid JSON only.\n\nOutput format:\n\n{\n \"deal_probability\": 0,\n \"deal_stage\": \"\",\n \"urgency_level\": \"\",\n \"recommended_action\": \"\",\n \"reasoning\": \"\"\n}"
},
"promptType": "define"
},
"typeVersion": 3
},
{
"id": "ca77669d-266a-46a1-98e0-938ed0ff939a",
"name": "\ud83e\udde0 Azure OpenAI \u2013 Deal Scoring Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
"position": [
416,
2368
],
"parameters": {
"model": "gpt-4o-mini",
"options": {}
},
"credentials": {
"azureOpenAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "aefb6dc3-0ea8-4ef7-ab33-e3ad30b4bf0f",
"name": "\u2699\ufe0f Normalize Deal Score Output",
"type": "n8n-nodes-base.code",
"position": [
896,
2160
],
"parameters": {
"jsCode": "// Get AI output\nlet rawOutput = $json.output || $json.response || $json.text || \"\";\n\n// Remove markdown formatting if present\nif (typeof rawOutput === \"string\") {\n rawOutput = rawOutput\n .replace(/```json/g, \"\")\n .replace(/```/g, \"\")\n .trim();\n}\n\nlet parsed;\n\ntry {\n parsed = typeof rawOutput === \"string\" ? JSON.parse(rawOutput) : rawOutput;\n} catch (error) {\n return [\n {\n json: {\n status: \"error\",\n message: \"Unable to parse AI output\",\n raw_output: rawOutput\n }\n }\n ];\n}\n\n// Normalize fields\nreturn [\n {\n json: {\n deal_probability: Number(parsed.deal_probability || 0),\n deal_stage: parsed.deal_stage || \"unknown\",\n urgency_level: parsed.urgency_level || \"low\",\n recommended_action: parsed.recommended_action || \"nurture_lead\",\n reasoning: parsed.reasoning || \"\"\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "82e2edbd-6544-455d-882d-bd178c60c2bc",
"name": "\ud83d\udce7 Send Deal Score to Sales Team",
"type": "n8n-nodes-base.gmail",
"position": [
1104,
2160
],
"parameters": {
"sendTo": "info@example.com",
"message": "={{ $json.message }}",
"options": {},
"subject": "Deal Predection",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "81a63552-a109-4335-9f9e-56a34c030cd0",
"name": "\ud83d\udccb Fetch Buyer Engagement Records",
"type": "n8n-nodes-base.googleSheets",
"position": [
304,
2176
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1955683186,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit#gid=1955683186",
"cachedResultName": "Property seeing"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11FL67Ph2fubYU7wMzf4gHRycD7jEs3uAb_yhnXYBiZE/edit?usp=drivesdk",
"cachedResultName": "Real-estate details"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "6f33822c-e450-4913-ae09-5342309db424",
"connections": {
"\ud83d\udd14 Buyer Lead Webhook": {
"main": [
[
{
"node": "\ud83d\uddc2\ufe0f Set Buyer Preferences",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udcca New Buyer Row Trigger": {
"main": [
[
{
"node": "\ud83e\udd16 AI Property Matching Agent",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udd16 AI Deal Scoring Agent": {
"main": [
[
{
"node": "\u2699\ufe0f Normalize Deal Score Output",
"type": "main",
"index": 0
}
]
]
},
"\u23f0 Deal Scoring Cron Trigger": {
"main": [
[
{
"node": "\ud83d\udccb Fetch Buyer Engagement Records",
"type": "main",
"index": 0
}
]
]
},
"\u2699\ufe0f Normalize Deck Details": {
"main": [
[
{
"node": "\ud83d\udce7 Send Property Deck to Buyer",
"type": "main",
"index": 0
}
]
]
},
"\u2699\ufe0f Normalize Dedup Result": {
"main": [
[
{
"node": "\ud83d\udd00 Route: Duplicate or New Lead?",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udccb Read CRM Sheet for Dedup": {
"ai_tool": [
[
{
"node": "\ud83e\udd16 AI Dedup & CRM Check Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"\ud83d\uddc2\ufe0f Set Buyer Preferences": {
"main": [
[
{
"node": "\ud83e\udd16 AI Dedup & CRM Check Agent",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udd16 AI Dedup & CRM Check Agent": {
"main": [
[
{
"node": "\u2699\ufe0f Normalize Dedup Result",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udd16 AI Property Matching Agent": {
"main": [
[
{
"node": "\u2699\ufe0f Normalize Property Match Results",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udce7 Send Property Deck to Buyer": {
"main": [
[
{
"node": "\ud83d\udcdd Log Deck Send Event to Sheet",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udde0 Azure OpenAI \u2013 Dedup Model": {
"ai_languageModel": [
[
{
"node": "\ud83e\udd16 AI Dedup & CRM Check Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"\u2699\ufe0f Normalize Deal Score Output": {
"main": [
[
{
"node": "\ud83d\udce7 Send Deal Score to Sales Team",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd00 Route: Duplicate or New Lead?": {
"main": [
[
{
"node": "\ud83d\udce7 Send Duplicate Follow-Up Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "\ud83d\udcdd Save New Lead to CRM Sheet",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udd16 AI Property Deck Search Agent": {
"main": [
[
{
"node": "\u2699\ufe0f Normalize Deck Details",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udccb Fetch Buyer Engagement Records": {
"main": [
[
{
"node": "\ud83e\udd16 AI Deal Scoring Agent",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udccb Read Available Properties Sheet": {
"ai_tool": [
[
{
"node": "\ud83e\udd16 AI Property Matching Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"\ud83e\udde0 Azure OpenAI \u2013 Matching Model": {
"ai_languageModel": [
[
{
"node": "\ud83e\udd16 AI Property Matching Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"\ud83d\udcdd Save Matched Properties to Sheet": {
"main": [
[
{
"node": "\ud83e\udd16 AI Property Deck Search Agent",
"type": "main",
"index": 0
}
]
]
},
"\u2699\ufe0f Normalize Property Match Results": {
"main": [
[
{
"node": "\ud83d\udcdd Save Matched Properties to Sheet",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udde0 Azure OpenAI \u2013 Deck Search Model": {
"ai_languageModel": [
[
{
"node": "\ud83e\udd16 AI Property Deck Search Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"\ud83e\udde0 Azure OpenAI \u2013 Deal Scoring Model": {
"ai_languageModel": [
[
{
"node": "\ud83e\udd16 AI Deal Scoring Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"\ud83d\udcc2 Search Property Deck in Google Drive": {
"ai_tool": [
[
{
"node": "\ud83e\udd16 AI Property Deck Search Agent",
"type": "ai_tool",
"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.
azureOpenAiApigmailOAuth2googleDriveOAuth2ApigoogleSheetsOAuth2ApigoogleSheetsTriggerOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automate your entire real estate sales pipeline with an AI-powered deal-making agent that captures buyer leads, matches them with suitable properties, delivers property decks, and predicts deal closing probability. 🏠🤖 This workflow intelligently deduplicates incoming leads,…
Source: https://n8n.io/workflows/13962/ — 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.
Automate post-purchase workflows by instantly fetching successful Stripe payments, matching them to corresponding automation templates in Google Sheets, and sending customers personalized access email
Automate LinkedIn comment monitoring and turn conversations into qualified sales opportunities using AI 🤖. This intelligent agent continuously scans LinkedIn posts mentioning your brand, analyzes ever
Automate your clinic’s patient intake and scheduling with an intelligent AI Healthcare Appointment Booking Agent built in n8n. 🏥 This workflow receives patient form submissions, analyzes symptoms usin
Automate patient pre-arrival intake, AI risk assessment, and real-time doctor alerts in one seamless healthcare workflow. ⏰📧 This automation sends scheduled intake reminders before appointments, analy
This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p