This workflow follows the Agent → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "AI-Powered Product Exchange Marketplace Platform",
"nodes": [
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "qdrantUrl",
"value": "<__PLACEHOLDER_VALUE__Qdrant API URL (e.g., https://your-qdrant-instance.com)__>",
"type": "string"
},
{
"id": "id-2",
"name": "qdrantApiKey",
"value": "<__PLACEHOLDER_VALUE__Qdrant API Key__>",
"type": "string"
},
{
"id": "id-3",
"name": "openaiApiKey",
"value": "<__PLACEHOLDER_VALUE__OpenAI API Key__>",
"type": "string"
},
{
"id": "id-4",
"name": "qdrantCollectionName",
"value": "products",
"type": "string"
},
{
"id": "id-5",
"name": "embeddingModel",
"value": "text-embedding-3-small",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"id": "44d9ab8f-68de-4870-9599-61453d601ed1",
"name": "Workflow Configuration",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
224,
0
]
},
{
"parameters": {
"httpMethod": "POST",
"path": "product-listing",
"responseMode": "lastNode",
"options": {}
},
"id": "ed58a0da-d307-4bb5-9335-9b84a9437ed1",
"name": "Product Listing Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
0,
0
]
},
{
"parameters": {
"httpMethod": "POST",
"path": "product-search",
"responseMode": "lastNode",
"options": {}
},
"id": "13a65de1-10d4-4a93-bcdb-d39842ae11d9",
"name": "Product Search Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
0,
320
]
},
{
"parameters": {
"httpMethod": "POST",
"path": "ai-chatbot",
"responseMode": "lastNode",
"options": {}
},
"id": "9e00b1c3-9f13-4a63-8659-d528d7110885",
"name": "AI Chatbot Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
0,
752
]
},
{
"parameters": {
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"table": {
"__rl": true,
"mode": "name",
"value": "products"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"id": "={{ $json.body.id }}",
"user_id": "={{ $json.body.user_id }}",
"category": "={{ $json.body.category }}",
"title": "={{ $json.body.title }}",
"description": "={{ $json.body.description }}",
"price": "={{ $json.body.price }}",
"location_lat": "={{ $json.body.location.lat }}",
"location_lng": "={{ $json.body.location.lng }}",
"created_at": "={{ $now }}"
}
},
"options": {}
},
"id": "da739d2a-cedb-499b-b074-13b3d4aaa304",
"name": "Save Product to Aurora",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
448,
0
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "id-1",
"name": "textForEmbedding",
"value": "={{ $json.title }} - {{ $json.description }} - Category: {{ $json.category }} - Price: ${{ $json.price }}",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"id": "d76182af-a610-4ceb-9d6c-a6dcc95a8106",
"name": "Prepare Product for Embedding",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
672,
0
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const item = $input.item.json;\n\nreturn {\n json: {\n id: item.id,\n text: item.textForEmbedding,\n metadata: {\n category: item.category,\n price: item.price,\n location_lat: item.location_lat,\n location_lng: item.location_lng,\n user_id: item.user_id,\n title: item.title,\n description: item.description\n }\n }\n};"
},
"id": "157bc9a8-c7f7-4f5e-8396-bd498fa38423",
"name": "Generate JSONL Payload",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
896,
0
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.openai.com/v1/embeddings",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('Workflow Configuration').first().json.openaiApiKey }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"input\": {{ $json.text }},\n \"model\": {{ $('Workflow Configuration').first().json.embeddingModel }}\n}",
"options": {}
},
"id": "80a2498b-d718-4dab-be5f-843e1c9cffde",
"name": "Generate Embedding via OpenAI",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
1120,
0
]
},
{
"parameters": {
"method": "PUT",
"url": "={{ $('Workflow Configuration').first().json.qdrantUrl }}/collections/{{ $('Workflow Configuration').first().json.qdrantCollectionName }}/points",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api-key",
"value": "={{ $('Workflow Configuration').first().json.qdrantApiKey }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={ \"points\": [{ \"id\": {{ $('Generate JSONL Payload').first().json.id }}, \"vector\": {{ $json.data[0].embedding }}, \"payload\": {{ $('Generate JSONL Payload').first().json.metadata }} }] }",
"options": {}
},
"id": "fc6c0193-1a9d-45ff-9a3c-102a50ab25d6",
"name": "Store in Qdrant",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
1344,
0
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "=SELECT * FROM products WHERE category = '{{ $json.body.category }}' AND price BETWEEN {{ $json.body.minPrice }} AND {{ $json.body.maxPrice }} LIMIT 50",
"options": {}
},
"id": "317c0c27-49ad-4fe2-b2d5-999227da49d5",
"name": "Query Products by Filters",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.6,
"position": [
448,
224
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.openai.com/v1/embeddings",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $('Workflow Configuration').first().json.openaiApiKey }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"input\": {{ $json.body.searchQuery }},\n \"model\": {{ $('Workflow Configuration').first().json.embeddingModel }}\n}",
"options": {}
},
"id": "a69a4859-7aab-418e-8fc6-355bbba79915",
"name": "Embed Search Query",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
224,
416
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Workflow Configuration').first().json.qdrantUrl }}/collections/{{ $('Workflow Configuration').first().json.qdrantCollectionName }}/points/search",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api-key",
"value": "={{ $('Workflow Configuration').first().json.qdrantApiKey }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"vector\": {{ $json.data[0].embedding }},\n \"limit\": 20,\n \"with_payload\": true\n}",
"options": {}
},
"id": "f33dd3ec-b57d-4e3a-8d96-fff41f896ad8",
"name": "Search Qdrant",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
448,
416
]
},
{
"parameters": {
"jsCode": "const qdrantResults = $input.all().find(i => i.json.result)?.json.result || []; const dbResults = $input.all().filter(i => i.json.id && !i.json.result); const merged = {}; qdrantResults.forEach(r => { merged[r.id] = { ...r.payload, score: r.score, source: 'vector' }; }); dbResults.forEach(r => { if (!merged[r.json.id]) merged[r.json.id] = { ...r.json, score: 0.5, source: 'db' }; }); return Object.values(merged).map(item => ({ json: item }));"
},
"id": "1091daab-929a-4ff9-860b-6b182a7ab39e",
"name": "Merge and Rank Results",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
672,
320
]
},
{
"parameters": {
"promptType": "define",
"text": "You are an AI assistant for an exchange marketplace. Help users find products to exchange, compare items, recommend alternatives, and suggest fair value adjustments. Use the available tools to search products, query the database, and compare values. Provide personalized recommendations based on user preferences and product attributes.",
"options": {
"systemMessage": "=You are an AI assistant for an exchange marketplace platform. Your role is to help users find products to exchange, compare items, recommend alternatives, and suggest fair value adjustments.\n\nContext:\n- This is a product exchange marketplace where users can list items they want to trade\n- Users may provide information about their current product and what they're looking for\n- You have access to tools to search products, query the database, and compare values\n\nUser's Current Product (if provided):\n={{ $json.userProduct || 'Not specified' }}\n\nUser's Preferences (if provided):\n={{ $json.userPreferences || 'Not specified' }}\n\nProvide personalized, helpful recommendations based on the user's needs and the available products in the marketplace.",
"maxIterations": 10,
"returnIntermediateSteps": false,
"passthroughBinaryImages": true,
"enableStreaming": true
}
},
"id": "e6cd070f-d1f9-4a13-aea8-270babee1df6",
"name": "AI Recommendation Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 3,
"position": [
416,
752
]
},
{
"parameters": {
"model": {
"__rl": true,
"mode": "id",
"value": "gpt-4o"
},
"options": {}
},
"id": "e5a4f8d6-5747-486e-b8af-af10422baeee",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.2,
"position": [
224,
976
],
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $json.body.userId }}",
"tableName": "chat_history"
},
"id": "bd73684d-3f9c-4688-ba19-a7db558bab08",
"name": "Postgres Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"typeVersion": 1.3,
"position": [
352,
976
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Query the product database to find items by category, price range, location, or other filters",
"operation": "executeQuery",
"options": {}
},
"id": "dfa718b1-48fe-438f-82b7-790aea8a5a25",
"name": "Product Database Tool",
"type": "n8n-nodes-base.postgresTool",
"typeVersion": 2.6,
"position": [
480,
976
]
},
{
"parameters": {
"description": "Search for semantically similar products using vector search in Qdrant",
"jsCode": "// Search for semantically similar products using vector search in Qdrant\n\n// Step 1: Generate embedding for the search query\nconst openaiApiKey = process.env.OPENAI_API_KEY || '<__PLACEHOLDER_VALUE__OPENAI_API_KEY__>';\nconst qdrantUrl = process.env.QDRANT_URL || '<__PLACEHOLDER_VALUE__QDRANT_URL__>';\nconst qdrantApiKey = process.env.QDRANT_API_KEY || '<__PLACEHOLDER_VALUE__QDRANT_API_KEY__>';\n\n// Generate embedding using OpenAI\nconst embeddingResponse = await fetch('https://api.openai.com/v1/embeddings', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${openaiApiKey}`\n },\n body: JSON.stringify({\n model: 'text-embedding-ada-002',\n input: query\n })\n});\n\nconst embeddingData = await embeddingResponse.json();\nconst queryVector = embeddingData.data[0].embedding;\n\n// Step 2: Search Qdrant for similar products\nconst searchResponse = await fetch(`${qdrantUrl}/collections/products/points/search`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'api-key': qdrantApiKey\n },\n body: JSON.stringify({\n vector: queryVector,\n limit: 10,\n with_payload: true,\n with_vector: false\n })\n});\n\nconst searchData = await searchResponse.json();\n\n// Step 3: Format and return results\nconst results = searchData.result.map(item => ({\n id: item.id,\n score: item.score,\n product: item.payload\n}));\n\nreturn JSON.stringify(results, null, 2);"
},
"id": "2a4b4627-2487-4500-bf5f-5c02ccbb4d22",
"name": "Qdrant Search Tool",
"type": "@n8n/n8n-nodes-langchain.toolCode",
"typeVersion": 1.3,
"position": [
608,
976
]
},
{
"parameters": {
"description": "Compare two products and suggest fair value adjustments or cash top-ups for exchanges",
"jsCode": "// Compare two products and suggest fair value adjustments or cash top-ups\n// Expected input: { product1: { name, price }, product2: { name, price } }\n\nconst product1 = query.product1;\nconst product2 = query.product2;\n\nif (!product1 || !product2 || !product1.price || !product2.price) {\n return 'Error: Both products must have price information';\n}\n\nconst price1 = parseFloat(product1.price);\nconst price2 = parseFloat(product2.price);\nconst difference = Math.abs(price1 - price2);\nconst percentageDiff = ((difference / Math.max(price1, price2)) * 100).toFixed(2);\n\nlet recommendation = '';\n\nif (difference === 0) {\n recommendation = `${product1.name} and ${product2.name} have equal values ($${price1}). This is a fair direct exchange.`;\n} else if (price1 > price2) {\n recommendation = `${product1.name} ($${price1}) is worth $${difference.toFixed(2)} more than ${product2.name} ($${price2}). Suggested adjustment: ${product2.name} owner should add $${difference.toFixed(2)} cash top-up for a fair exchange. Value difference: ${percentageDiff}%`;\n} else {\n recommendation = `${product2.name} ($${price2}) is worth $${difference.toFixed(2)} more than ${product1.name} ($${price1}). Suggested adjustment: ${product1.name} owner should add $${difference.toFixed(2)} cash top-up for a fair exchange. Value difference: ${percentageDiff}%`;\n}\n\nreturn recommendation;"
},
"id": "4f4d5c56-2912-4936-9dda-932203016d79",
"name": "Value Comparison Tool",
"type": "@n8n/n8n-nodes-langchain.toolCode",
"typeVersion": 1.3,
"position": [
736,
976
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.openai.com/v1/chat/completions",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $('Workflow Configuration').first().json.openaiApiKey }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"model\": \"gpt-4o-mini\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a product ranking assistant. Your task is to rank products based on value similarity and user preferences. Analyze the candidate products and return them in order of best match, considering factors like price, condition, category relevance, and user intent. Return a JSON array of product IDs in ranked order.\"\n },\n {\n \"role\": \"user\",\n \"content\": {{ JSON.stringify('Rank these products: ' + JSON.stringify($input.all())) }}\n }\n ],\n \"temperature\": 0.3\n}",
"options": {}
},
"id": "9e1f1546-52df-4111-94e1-54932419300d",
"name": "LLM Rank Matches",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.3,
"position": [
896,
320
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\n \"success\": true,\n \"productId\": \"={{ $('Save Product to Aurora').first().json.id }}\",\n \"message\": \"Product listed successfully and indexed for search\"\n}",
"options": {}
},
"id": "ddea38c9-4a9a-4bfa-ab9f-5f440ea67f25",
"name": "Return Product Listing Response",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.4,
"position": [
1568,
0
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {}
},
"id": "2883975d-bfb9-4028-9a06-213d8dd5d108",
"name": "Return Search Results",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.4,
"position": [
1120,
320
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\n \"response\": \"={{ $json.output }}\",\n \"conversationId\": \"={{ $json.body.userId }}\"\n}",
"options": {}
},
"id": "50da821d-52f6-4972-9ac0-b1e4e38168f9",
"name": "Return AI Response",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.4,
"position": [
944,
752
]
}
],
"connections": {
"Product Listing Webhook": {
"main": [
[
{
"node": "Workflow Configuration",
"type": "main",
"index": 0
}
]
]
},
"Workflow Configuration": {
"main": [
[
{
"node": "Save Product to Aurora",
"type": "main",
"index": 0
}
]
]
},
"Save Product to Aurora": {
"main": [
[
{
"node": "Prepare Product for Embedding",
"type": "main",
"index": 0
}
]
]
},
"Prepare Product for Embedding": {
"main": [
[
{
"node": "Generate JSONL Payload",
"type": "main",
"index": 0
}
]
]
},
"Generate JSONL Payload": {
"main": [
[
{
"node": "Generate Embedding via OpenAI",
"type": "main",
"index": 0
}
]
]
},
"Generate Embedding via OpenAI": {
"main": [
[
{
"node": "Store in Qdrant",
"type": "main",
"index": 0
}
]
]
},
"Store in Qdrant": {
"main": [
[
{
"node": "Return Product Listing Response",
"type": "main",
"index": 0
}
]
]
},
"Product Search Webhook": {
"main": [
[
{
"node": "Query Products by Filters",
"type": "main",
"index": 0
},
{
"node": "Embed Search Query",
"type": "main",
"index": 0
}
]
]
},
"Embed Search Query": {
"main": [
[
{
"node": "Search Qdrant",
"type": "main",
"index": 0
}
]
]
},
"Search Qdrant": {
"main": [
[
{
"node": "Merge and Rank Results",
"type": "main",
"index": 0
}
]
]
},
"Query Products by Filters": {
"main": [
[
{
"node": "Merge and Rank Results",
"type": "main",
"index": 0
}
]
]
},
"Merge and Rank Results": {
"main": [
[
{
"node": "LLM Rank Matches",
"type": "main",
"index": 0
}
]
]
},
"LLM Rank Matches": {
"main": [
[
{
"node": "Return Search Results",
"type": "main",
"index": 0
}
]
]
},
"AI Chatbot Webhook": {
"main": [
[
{
"node": "AI Recommendation Agent",
"type": "main",
"index": 0
}
]
]
},
"AI Recommendation Agent": {
"main": [
[
{
"node": "Return AI Response",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Recommendation Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "AI Recommendation Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Product Database Tool": {
"ai_tool": [
[
{
"node": "AI Recommendation Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Qdrant Search Tool": {
"ai_tool": [
[
{
"node": "AI Recommendation Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Value Comparison Tool": {
"ai_tool": [
[
{
"node": "AI Recommendation Agent",
"type": "ai_tool",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "294d8a11-582a-4596-bacd-0f97bca11a20",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "Go2nxMgib5nfj69N",
"tags": []
}
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.
openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
AI-Powered Product Exchange Marketplace Platform. Uses postgres, httpRequest, agent, lmChatOpenAi. Webhook trigger; 23 nodes.
Source: https://gist.github.com/baverkral04/77faf8f720bf9fa70799928d87342175 — 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.
CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.
Remi 1.1. Uses lmChatOpenAi, memoryPostgresChat, openAi, postgres. Webhook trigger; 89 nodes.
my-secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 86 nodes.
🧪 LABR - nuevo asistente (REPARADO). Uses httpRequest, postgres, postgresTool, toolCalculator. Webhook trigger; 63 nodes.
🧪 LABR - nuevo asistente (REPARADO). Uses httpRequest, postgres, postgresTool, toolCalculator. Webhook trigger; 63 nodes.