This workflow corresponds to n8n.io template #8309 — we link there as the canonical source.
This workflow follows the Agent → Chat Trigger 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": "hszZbSQbmoxuYStY",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Property Finder Scraper Assistant",
"tags": [],
"nodes": [
{
"id": "d1428498-b9d0-40a6-aafe-a85095b2aeb3",
"name": "Find link",
"type": "n8n-nodes-base.code",
"position": [
-1968,
160
],
"parameters": {
"jsCode": "// This code finds the latest URL from one of two possible inputs.\n\n// Primary input: A simple text string from a specific n8n node.\nconst inputText = $('Chat input').first().json.chatInput;\n\n// Fallback input: A conversation history object.\nconst messages = $input.first().json.messages;\n\nlet lastLink = \"\";\n\n// A regex to find all URLs in a given text.\nconst urlRegex = /(https?:\\/\\/[^\\s\"'<>()]+)/g;\n\n// Function to find the last link in a piece of text.\nconst findLastLinkInText = (text) => {\n if (typeof text !== 'string') {\n return \"\";\n }\n const matches = text.match(urlRegex);\n if (matches && matches.length > 0) {\n // Get the last element from the array of matches.\n let link = matches[matches.length - 1];\n // Remove common punctuation from the end of the link.\n return link.replace(/[,.]+$/, '');\n }\n return \"\";\n};\n\n// 1. First, try to find the link in the primary input (inputText).\nlastLink = findLastLinkInText(inputText);\n\n// 2. If no link was found in inputText, and messages array exists, search it.\nif (!lastLink && messages && Array.isArray(messages) && messages.length > 0) {\n // Iterate backwards through messages to find the most recent human message with a link.\n for (let i = messages.length - 1; i >= 0; i--) {\n const humanMessage = messages[i].human;\n const foundLink = findLastLinkInText(humanMessage);\n if (foundLink) {\n lastLink = foundLink;\n // Once the most recent link is found, stop searching.\n break;\n }\n }\n}\n\n// Return the data in the format n8n expects.\n// The output will be a JSON object: { \"link\": \"http://found-link.com\" }\n// or { \"link\": \"\" } if no link was found in either source.\nreturn [{\n json: {\n link: lastLink\n }\n}];"
},
"typeVersion": 2
},
{
"id": "27e897af-338f-486a-9caf-5bf2632bc9cf",
"name": "Scrape",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-1200,
-208
],
"parameters": {
"url": "={{ $('Find link').item.json.link }}",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "User-Agent",
"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/0.0.0.0 Safari/537.36"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "2db0d053-522e-4f08-850e-af6b2fcc19ca",
"name": "Summarize",
"type": "n8n-nodes-base.code",
"position": [
-1024,
-208
],
"parameters": {
"jsCode": "// n8n Code Node\n// This code takes a large HTML string from a property listing, parses it,\n// and outputs a compact, formatted text summary. This summary is ideal for\n// direct use in an AI assistant's prompt, providing a comprehensive overview\n// without extraneous data like links or IDs.\n\n// The input to this node should be a JSON object with a 'data' property containing the HTML string.\n// For example: { \"data\": \"<!DOCTYPE html>...\" }\n\n// The output will be a single item with a 'summary' property containing the formatted string.\n// In case of an error, the 'summary' will state that the link is not supported.\n\n// Import the 'cheerio' library to parse HTML.\nconst cheerio = require('cheerio');\n\n// The main function that will be executed by the n8n node.\nconst [input] = items;\n\n// Wrap the entire logic in a try...catch block for robust error handling.\ntry {\n // Extract the HTML string from the input data.\n const html = input.json.data;\n\n // If HTML is missing, throw an error to be caught below.\n if (!html) {\n throw new Error(\"Input data is missing or empty.\");\n }\n\n // Load the HTML into cheerio for parsing.\n const $ = cheerio.load(html);\n\n // --- Data Extraction ---\n\n // Extract the main JSON data blob from the '__NEXT_DATA__' script tag.\n const nextDataScript = $('#__NEXT_DATA__').html();\n if (!nextDataScript) {\n throw new Error(\"Could not find '__NEXT_DATA__' script tag. The HTML structure may have changed.\");\n }\n const nextData = JSON.parse(nextDataScript);\n const pageProps = nextData.props.pageProps;\n const propertyData = pageProps.propertyResult.property;\n const insights = pageProps.insights;\n const priceTrends = pageProps.priceTrendsData;\n const similarTransactions = propertyData.similar_price_transactions;\n\n\n // Helper function to safely access nested properties\n const get = (p, o) => p.reduce((xs, x) => (xs && xs[x]) ? xs[x] : null, o);\n\n // --- Text Formatting ---\n\n // Use template literals to build the formatted text string.\n let summaryText = `**Property Listing Summary**\\n\\n`;\n\n // Section: Overview\n summaryText += `**Overview:**\\n`;\n // Extract specific property type (e.g., 3M) from the description if available\n const typeMatch = get(['description'], propertyData)?.match(/Type\\s*(\\w+\\d*)/i);\n summaryText += `- **Type:** ${get(['property_type'], propertyData) || 'N/A'}${typeMatch ? ` (${typeMatch[0]})` : ''}\\n`;\n const availabilityDate = get(['rental_availability_date'], propertyData);\n summaryText += `- **Status:** For Rent, Available from ${availabilityDate ? new Date(availabilityDate).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) : 'N/A'}\\n\\n`;\n\n // Section: Property Details\n const plotSize = get(['description'], propertyData)?.match(/Plot\\s*([\\d,]+)\\s*sqft/i);\n summaryText += `**Property Details:**\\n`;\n const hasStudy = get(['description'], propertyData)?.toLowerCase().includes('study');\n summaryText += `- **Bedrooms:** ${get(['bedrooms'], propertyData) || 'N/A'}${hasStudy ? ' + Study' : ''}\\n`;\n summaryText += `- **Bathrooms:** ${get(['bathrooms'], propertyData) || 'N/A'}\\n`;\n summaryText += `- **Size (BUA):** ${get(['size', 'value'], propertyData) || 'N/A'} sqft\\n`;\n if (plotSize && plotSize[1]) {\n summaryText += `- **Plot Size:** ${plotSize[1].replace(',', '')} sqft\\n`;\n }\n summaryText += `- **Furnishing:** ${get(['furnished'], propertyData) || 'N/A'}\\n`;\n if (get(['description'], propertyData)?.includes('Fully Upgraded')) {\n summaryText += `- **Condition:** Fully Upgraded with modern finishes\\n`;\n }\n summaryText += `\\n`;\n\n // Section: Location & Community\n summaryText += `**Location & Community:**\\n`;\n summaryText += `- **Area:** ${get(['location', 'full_name'], propertyData) || 'N/A'}\\n`;\n const communityInfo = get(['community'], insights);\n if (communityInfo) {\n summaryText += `- **Community Categories:** ${communityInfo.categories.join(', ')}\\n`;\n summaryText += `- **Community Review:** ${communityInfo.review.score.toFixed(1)}/5 from ${communityInfo.review.count} reviews\\n`;\n }\n summaryText += `\\n`;\n\n\n // Section: Pricing & Market Trends\n summaryText += `**Pricing & Market Trends:**\\n`;\n summaryText += `- **Rent:** ${get(['price', 'value'], propertyData)?.toLocaleString() || 'N/A'} ${get(['price', 'currency'], propertyData) || ''} per ${get(['price', 'period'], propertyData) || ''}\\n`;\n const lastTrend = get(['graph', '1Y'], priceTrends)?.slice(-1)[0];\n if (lastTrend) {\n summaryText += `- **Community Avg. Rent (as of ${lastTrend.period}):** ${lastTrend.communityPrice?.toLocaleString() || 'N/A'} AED/year\\n`;\n summaryText += `- **Sub-Community Avg. Rent (as of ${lastTrend.period}):** ${lastTrend.towerPrice?.toLocaleString() || 'N/A'} AED/year\\n`;\n }\n summaryText += `\\n`;\n\n // Section: Key Features\n const keyFeaturesMatch = get(['description'], propertyData)?.split('Key Features:')[1];\n if (keyFeaturesMatch) {\n const features = keyFeaturesMatch.split('\\n\\n')[0]\n .split('\\n- ')\n .map(item => item.trim())\n .filter(item => item && !item.toLowerCase().includes('property ref'));\n if (features.length > 0) {\n summaryText += `**Key Features & Amenities:**\\n`;\n features.forEach(feature => {\n summaryText += `- ${feature}\\n`;\n });\n summaryText += `\\n`;\n }\n }\n\n // Section: Agent & Broker\n summaryText += `**Agent & Broker:**\\n`;\n summaryText += `- **Agent:** ${get(['agent', 'name'], propertyData) || 'N/A'}\\n`;\n summaryText += `- **Brokerage:** ${get(['broker', 'name'], propertyData) || 'N/A'}\\n`;\n summaryText += `- **Agent Experience:** ${get(['agent', 'years_of_experience'], propertyData) || 'N/A'} years\\n`;\n summaryText += `- **Agent Closed Deals:** ${get(['agent', 'transactions_count'], propertyData) || 'N/A'}\\n`;\n summaryText += `- **Agent Rating:** ${get(['agent', 'avg_score'], propertyData) || 'N/A'}/5 from ${get(['agent', 'review_count'], propertyData) || 'N/A'} ratings\\n`;\n const phone = get(['contact_options'], propertyData)?.find(c => c.type === 'phone')?.value;\n const whatsapp = get(['contact_options'], propertyData)?.find(c => c.type === 'whatsapp')?.value;\n const email = get(['contact_options'], propertyData)?.find(c => c.type === 'email')?.value;\n if (phone || whatsapp || email) {\n summaryText += `- **Contact Details:**\\n`;\n if (phone) summaryText += ` - Phone: ${phone}\\n`;\n if (whatsapp) summaryText += ` - WhatsApp: ${whatsapp}\\n`;\n if (email) summaryText += ` - Email: ${email}\\n`;\n }\n\n\n // Return the formatted text summary on success.\n return [{\n json: {\n summary: summaryText.trim()\n }\n }];\n\n} catch (error) {\n // If any error occurs during the try block (e.g., parsing fails, data structure changes),\n // catch it here and return a standardized error message.\n // This prevents the node from failing and allows the workflow to handle the case gracefully.\n return [{\n json: {\n summary: \"The provided link is not supported\"\n }\n }];\n}"
},
"typeVersion": 2
},
{
"id": "38eeeba0-d1ec-4afe-bcf9-4303827451a0",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
-672,
-48
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "dba1da50-3e5b-4b45-97c6-eace9f60e3db",
"name": "Capture Incoming Message",
"type": "n8n-nodes-base.set",
"position": [
-1200,
-32
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b87137d3-5c9f-42e6-b447-5ade97f23983",
"name": "message",
"type": "string",
"value": "={{ $('Chat input').item.json.chatInput }}"
},
{
"id": "e3842972-39d2-46d9-8e06-688623b18af5",
"name": "listing_summary",
"type": "string",
"value": ""
}
]
}
},
"typeVersion": 3.4
},
{
"id": "08bef4c9-9f59-44c6-9abf-9edc039294ce",
"name": "Capture",
"type": "n8n-nodes-base.set",
"position": [
-848,
-208
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b87137d3-5c9f-42e6-b447-5ade97f23983",
"name": "message",
"type": "string",
"value": "={{ $('Chat input').item.json.chatInput }}"
},
{
"id": "e3842972-39d2-46d9-8e06-688623b18af5",
"name": "listing_summary",
"type": "string",
"value": "={{ $json.summary }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "bb16f4f4-3f1e-461b-8012-dc29320a756b",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-48,
256
],
"parameters": {
"text": "={{ $json.message }}",
"options": {
"systemMessage": "=<role name=\"UAE Real Estate AI Agent\">\n Your primary function is to assist users with inquiries about specific real estate properties and general real estate topics in the UAE. Provide accurate, relevant information as an expert assistant.\n</role>\n\n<persona>\n Friendly, concise, and helpful. Your answers must be detailed, providing all necessary information without conversational filler. Get straight to the point.\n</persona>\n\n<knowledge_base>\n{{ $json.listing_summary }}\n</knowledge_base>\n\n<tool name=\"serp_search_tool\" description=\"A search tool for public UAE real estate information.\">\n <usage>Use ONLY when the `knowledge_base` is insufficient to answer a query.</usage>\n <critical_rule>You MUST formulate a comprehensive search query by combining the user's question with context from the `knowledge_base` (e.g., property location, type).</critical_rule>\n</tool>\n\n<rules>\n <rule priority=\"1\">Always consult the `knowledge_base` first.</rule>\n <rule priority=\"2\">If a user provides a URL, assume the `knowledge_base` has been updated with its content. ALWAYS prioritize this information for your response.</rule>\n <rule priority=\"3\">If a user sends a URL with no other query, briefly acknowledge the content of the link in one sentence and then ask what specific information they need. (e.g., \"I see this is a 2-bedroom apartment in Dubai Marina. What would you like to know about it?\")</rule>\n <rule priority=\"4\">If the `knowledge_base` is insufficient, use the `serp_search_tool`.</rule>\n <rule priority=\"5\">For ambiguous queries (e.g., \"What are service charges?\"), ask for clarification: \"Are you asking about this specific property, or in general for this area?\"</rule>\n <rule priority=\"6\">For off-topic queries, pivot the conversation back to real estate.</rule>\n</rules>\n\n<output>\n - Produce clear, detailed user-facing messages.\n - NEVER output explanations about internal processes, tool usage, or actions.\n - NEVER include XML tags or meta-information in your final response to the user.\n - ALWAYS use conversation history to maintain a smooth, natural dialogue.\n</output>"
},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "7d96371d-57de-41e1-aa8d-3b4f94c33236",
"name": "Simple Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
16,
480
],
"parameters": {
"sessionKey": "={{ $('Chat input').item.json.sessionId }}",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
},
{
"id": "9ed6be30-0b8a-452f-9f8d-b61dd9825565",
"name": "OpenRouter Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"position": [
-128,
448
],
"parameters": {
"model": "google/gemini-2.5-flash",
"options": {}
},
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "346df70b-ebe1-496c-84fc-5bb0ceef02a4",
"name": "SerpAPI",
"type": "@n8n/n8n-nodes-langchain.toolSerpApi",
"position": [
144,
480
],
"parameters": {
"options": {}
},
"credentials": {
"serpApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "47efdbc8-11d2-4288-983e-d09df7cb3354",
"name": "If msg contains link",
"type": "n8n-nodes-base.if",
"position": [
-1424,
-128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "39b33b64-dfe8-4245-a6cc-be34f48c33db",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.link }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "33ceb55b-5630-4ef3-9a3a-43ae8e49c64e",
"name": "Chat Memory Manager",
"type": "@n8n/n8n-nodes-langchain.memoryManager",
"position": [
-2320,
160
],
"parameters": {
"options": {}
},
"typeVersion": 1.1
},
{
"id": "ac0e0cef-44f5-4eb4-9e74-bb753efbc56d",
"name": "Simple Memory1",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
-2256,
384
],
"parameters": {
"sessionKey": "={{ $('Chat input').item.json.sessionId }}",
"sessionIdType": "customKey",
"contextWindowLength": 30
},
"typeVersion": 1.3
},
{
"id": "99afe6a9-cf57-42aa-b453-6ec7b6a176c2",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3344,
-768
],
"parameters": {
"width": 476,
"height": 2032,
"content": "# Build AI Real Estate Agent with OpenRouter and SrpAPI to talk with property objects from propertyfinder.ae\n\nThis n8n template demonstrates a simple AI Agent that can:\n\n* Scrape information from a provided `propertyfinder.ae` listing link.\n* Answer questions about a specific property using the scraped information.\n* Use **SerpAPI** to find details that are missing from the scraped data.\n* Answer general real-estate questions using **SerpAPI**.\n\n---\n\n## Use Case\n\nThis workflow serves as a starting point for building complex AI assistants for real estate or other domains.\n\n---\n\n## Potential Enhancements\n\n* **Expand Knowledge:** Augment the workflow with your own knowledge base using a vector database (RAG approach).\n* **Add More Sources:** Adapt the scraper to support other real estate websites.\n* **Optimize Speed:** Add a cache for scraped data to reduce response latency.\n* **Improve Context Handling:** Implement reliable persistence to track the current listing instead of iterating through conversation history.\n* **Customize Prompts:** Write more tailored prompts for your specific needs (the current one is for demonstration only).\n* **Integrate Channels:** Connect the workflow to communication channels like Instagram, Telegram, or WhatsApp.\n\n---\n\n## How It Works\n\n1. The workflow is triggered by a **\"When chat message received\"** node for simple demonstration.\n2. The **`Chat Memory Manager`** node extracts the last 30 messages for the current session.\n3. A code node finds the property link, first by checking the most recent user message and then by searching the conversation history.\n4. If a link is found, an **`HTTP Request`** node scrapes the HTML content from the listing page.\n5. The **`Summarize`** code node parses the HTML, retrieves key information, and passes it to the AI Agent as a temporary knowledge base.\n6. The final **`AI Agent`** node answers user queries using the scraped knowledge base and falls back to the **SerpAPI** tool when information is missing.\n\n---\n\n## How to Use\n\n* You can test this workflow directly in n8n or integrate it into any social media channel or your website.\n* The `AI Agent` node is configured to use **OpenRouter**. Add your **OpenRouter** credentials, or replace the node with your preferred LLM provider.\n* Add your **SerpAPI** key to the `SerpAPI` tool within the AI Agent node.\n\n---\n\n## Requirements\n\n* An API key for **OpenRouter** (or credentials for your preferred LLM provider).\n* A **SerpAPI** key. You can get one from their website; a free plan is available for testing.\n\n---\n\n## Need Help Building Something More?\n\nContact me on:\n* **Telegram:** @ninesfork\n* **LinkedIn:** [George Zargaryan](https://www.linkedin.com/in/george-zargaryan-b65290367/)\n\nHappy Hacking! \ud83d\ude80"
},
"typeVersion": 1
},
{
"id": "406164c1-2803-4556-9773-b41a62322968",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2640,
-80
],
"parameters": {
"color": 7,
"width": 824,
"height": 604,
"content": "## Receiving and Preparing Data\n\nThis initial stage of the workflow prepares the data for processing:\n\n1. **Receive Message:** The `Chat Input` node triggers the workflow by receiving the user's message.\n2. **Retrieve History:** The `Chat Memory Manager` node retrieves the last 30 messages to provide conversational context.\n3. **Extract Link:** A `Code` node parses the conversation to extract the most relevant link for the next steps."
},
"typeVersion": 1
},
{
"id": "6976f31a-359d-477f-baf2-e4b6b1a75bdd",
"name": "Chat input",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-2592,
160
],
"parameters": {
"public": true,
"options": {},
"initialMessages": "Hello!"
},
"typeVersion": 1.3
},
{
"id": "cb85801e-8a1b-4469-847d-aaa78d25b502",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1472,
-528
],
"parameters": {
"color": 7,
"width": 936,
"height": 748,
"content": "## Scraping Listing Information\n\nThis stage of the workflow is responsible for scraping and processing the listing data:\n\n1. **Validate Link:** An `If` node first checks if a property link was successfully extracted.\n2. **Scrape Content:** If a link exists, an `HTTP Request` node visits the URL to retrieve the HTML content of the property listing.\n3. **Parse and Format:** A `Code` node receives the HTML and parses it into an LLM-optimized format to use as a `knowledge base` for the AI Agent. If parsing fails, it outputs a message that the link is not supported."
},
"typeVersion": 1
},
{
"id": "6661e75b-cbb8-44e7-9009-204fe35d1635",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-208,
-288
],
"parameters": {
"color": 7,
"width": 536,
"height": 908,
"content": "### AI Agent \n\nThis AI Agent is designed to act as a helpful and direct real estate specialist for the UAE market.\n\n**Core Behavior & Logic:**\n\n* **Primary Data:** The agent's first action is always to consult its internal `knowledge_base`, which is populated with data scraped from a specific property link.\n* **Fallback Search:** If the `knowledge_base` is insufficient, it uses a `serp_search_tool` to find public information online.\n* **Smart Queries:** It is required to combine the user's question with existing property context (e.g., location) to create more effective search queries.\n* **Interaction Rules:** It has specific logic for handling ambiguous questions by asking for clarification and for acknowledging new links provided by the user.\n\n**Output Constraints:**\n\n* The agent's persona is friendly, concise, and expert, avoiding conversational filler.\n* All user-facing responses must be clean and natural, strictly forbidding any mention of internal processes, tool usage, or meta-tags."
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "719e8723-1b77-42a4-9f6a-185f252540c0",
"connections": {
"Merge": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Scrape": {
"main": [
[
{
"node": "Summarize",
"type": "main",
"index": 0
}
]
]
},
"Capture": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"SerpAPI": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Find link": {
"main": [
[
{
"node": "If msg contains link",
"type": "main",
"index": 0
}
]
]
},
"Summarize": {
"main": [
[
{
"node": "Capture",
"type": "main",
"index": 0
}
]
]
},
"Chat input": {
"main": [
[
{
"node": "Chat Memory Manager",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Simple Memory1": {
"ai_memory": [
[
{
"node": "Chat Memory Manager",
"type": "ai_memory",
"index": 0
}
]
]
},
"Chat Memory Manager": {
"main": [
[
{
"node": "Find link",
"type": "main",
"index": 0
}
]
]
},
"If msg contains link": {
"main": [
[
{
"node": "Scrape",
"type": "main",
"index": 0
}
],
[
{
"node": "Capture Incoming Message",
"type": "main",
"index": 0
}
]
]
},
"OpenRouter Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Capture Incoming Message": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
}
}
}
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.
openRouterApiserpApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n template demonstrates a simple AI Agent that can: Scrape information from a provided listing link. Answer questions about a specific property using the scraped information. Use SerpAPI* to find details that are missing from the scraped data. Answer general real-estate…
Source: https://n8n.io/workflows/8309/ — 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.
This n8n automation is designed to analyze cryptocurrency trends by extracting, processing, and interpreting candlestick charts using AI-powered agents. The workflow enhances technical analysis by int
This template attempts to create an AI-powered content assistant for WordPress sites using Mistral AI, enabling article recommendations, content summarization, and contextual Q&A capabilities.
This workflow is designed for IT teams, service desk agents, and operations managers who use ServiceNow. It reduces manual effort by automatically classifying chat messages as Incidents or Requests, c
Turn any YouTube channel into a searchable knowledge base. The AI agent understands relationships between videos, topics, tools, and concepts - enabling powerful queries like "Which videos talk about
Easily Compare LLMs Using OpenAI and Google Sheets. Uses chatTrigger, splitInBatches, memoryBufferWindow, memoryManager. Chat trigger; 21 nodes.