AutomationFlowsAI & RAG › Agent 3 - the Analyst

Agent 3 - the Analyst

Agent 3 - The Analyst. Uses supabase, httpRequest, googleGemini. Scheduled trigger; 18 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered18 nodesSupabaseHTTP RequestGoogle Gemini
AI & RAG Trigger: Cron / scheduled Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Googlegemini → 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 →

Download .json
{
  "updatedAt": "2025-12-25T01:37:37.725Z",
  "createdAt": "2025-12-25T01:02:23.691Z",
  "id": "Hqjeb2XOK4Vqka8L",
  "name": "Agent 3 - The Analyst",
  "active": false,
  "isArchived": false,
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 1
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [
        -208,
        -368
      ],
      "id": "a3006467-8ac0-4523-9de1-32c51992a348",
      "name": "Every 1 Minute"
    },
    {
      "parameters": {
        "operation": "getAll",
        "tableId": "leads",
        "limit": 5,
        "filters": {
          "conditions": [
            {
              "keyName": "status",
              "condition": "eq",
              "keyValue": "raw"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        16,
        -368
      ],
      "id": "139c86b0-c1cf-462c-9312-e37046cfc31d",
      "name": "Query Raw Leads",
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "={{ $json.website_url || 'https://' + $json.domain }}",
        "options": {
          "timeout": 15000
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        480,
        -352
      ],
      "id": "ed932258-d95c-4b6e-a4a3-0c4483eb35ed",
      "name": "Fetch Website",
      "continueOnFail": true
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.5-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "messages": {
          "values": [
            {
              "content": "=Analyze the following website content for the business: {{ $node[\"Query Raw Leads\"].json.business_name }} (Industry: {{ $node[\"Query Raw Leads\"].json.industry || \"General\" }}).\n\nWEBSITE CONTENT:\n{{ $json.data.substring(0, 5000) }}\n\nTASK:\nEvaluate if this business is a high-quality lead. Provide a fit score (0-100) based on:\n1. Legitimacy: Does the site look professional and active?\n2. Service Alignment: Does it actually provide services related to the industry?\n3. Contactability: Are there clear phone numbers, emails, or forms?\n\nOUTPUT INSTRUCTIONS:\nReturn ONLY a raw JSON object. Do not include markdown formatting, backticks, or introductory text.\n\nJSON SCHEMA:\n{\n  \"fit_score\": number,\n  \"summary\": \"string (max 2 sentences)\",\n  \"industry_match\": boolean,\n  \"is_high_ticket\": boolean\n}"
            }
          ]
        },
        "options": {
          "temperature": 0.2
        }
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        704,
        -352
      ],
      "id": "b7db33ad-1360-421f-847d-0427c5aa4afd",
      "name": "Gemini Analysis",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "update",
        "tableId": "leads",
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "condition": "eq",
              "keyValue": "={{ $node[\"Query Raw Leads\"].json.id }}"
            }
          ]
        },
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "status",
              "fieldValue": "={{ $json.status }}"
            },
            {
              "fieldId": "enrichment_score",
              "fieldValue": "={{ $json.fit_score }}"
            },
            {
              "fieldId": "score_reasoning",
              "fieldValue": "={{ $json.summary }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1312,
        -352
      ],
      "id": "f93b66ed-cb83-48ff-ae6e-b0f58eb9a2fb",
      "name": "Update Lead",
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// 1. Get all analyzed items from the Gemini output\nconst items = $input.all();\n\n// 2. Get all original lead data from the query node using the new syntax\n// Ensure the name inside $(\"...\") matches your first Supabase node exactly\nconst allLeads = $(\"Query Raw Leads\").all();\n\nreturn items.map((item, index) => {\n  // 3. Access the text deep inside the Gemini response structure\n  let rawText = item.json.content.parts[0].text;\n  \n  // 4. Remove Markdown backticks (```json or ```) if they exist\n  let cleanedText = rawText.replace(/```json/g, '').replace(/```/g, '').trim();\n  \n  // 5. Get the matching original lead from the query node by index\n  const originalLead = allLeads[index].json;\n  \n  try {\n    const analysis = JSON.parse(cleanedText);\n    \n    return {\n      json: {\n        id: originalLead.id, // Links back to the correct Supabase row\n        fit_score: analysis.fit_score,\n        summary: analysis.summary,\n        industry_match: analysis.industry_match,\n        is_high_ticket: analysis.is_high_ticket,\n        status: 'analyzed'\n      }\n    };\n  } catch (e) {\n    // Return a structured error so the Supabase update doesn't crash the loop\n    return {\n      json: {\n        id: originalLead.id,\n        fit_score: 0,\n        summary: \"Analysis parsing failed\",\n        status: 'error'\n      }\n    };\n  }\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1040,
        -352
      ],
      "id": "5a9e40fe-bb85-4eb1-a212-e016ee608eb8",
      "name": "Clean AI Output"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "part",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -80,
        -736
      ],
      "id": "aaf4ec32-7191-4fc9-b34b-1d3783b10f9e",
      "name": "Webhook"
    },
    {
      "parameters": {
        "jsCode": "// 1. Get the data from the Webhook 'body'\nconst input = $input.first().json.body || $input.first().json;\n\n// 2. Check for required technical IDs\nif (!input.user_id || !input.batch_id) {\n  throw new Error('Missing required fields: user_id and batch_id');\n}\n\n// 3. Extract industry and location from the new input structure\n// Industry replaces 'term' in your new schema\nlet industry = input.industry || \"\"; \nlet location = input.location || \"\";\n\n// 4. Return the formatted data for the next nodes\nreturn [{\n  json: {\n    term: industry,\n    location: location,\n    // Creates the string for Google Maps search, e.g., \"Restaurants Casablanca\"\n    search_query: `${industry} ${location}`.trim(), \n    batch_id: input.batch_id,\n    user_id: input.user_id,\n    started_at: new Date().toISOString(),\n    status: 'raw' // Helpful for your Airtable status column\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        352,
        -736
      ],
      "id": "e35fffd0-b4b8-4005-9f44-f8e23c6f1524",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/acts/nwua9Gu5YrADL7ZDj/runs",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "token",
              "value": "REDACTED_HEADER_VALUE"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"searchStringsArray\": [\n    \"{{ $json.search_query }}\"\n  ],\n  \"maxCrawledPlacesPerSearch\": 100,\n  \"includeWebsites\": true,\n  \"language\": \"en\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        560,
        -736
      ],
      "id": "ac0e5198-6a8b-4380-b986-0df3b2b51046",
      "name": "Start Apify Run"
    },
    {
      "parameters": {
        "jsCode": "// 1. Get the runId from the Apify \"Start Run\" node output\nconst inputJson = $input.first().json;\nconst runId = inputJson.data ? inputJson.data.id : inputJson.id;\n\n// 2. FIXED: Reference your actual validation node name: \"Code in JavaScript\"\nlet originalInput;\ntry {\n  // We use the node that contains your batch_id and user_id\n  originalInput = $node[\"Code in JavaScript\"].json;\n} catch (e) {\n  // Fallback for manual testing\n  originalInput = { message: \"Metadata not found\" };\n}\n\nconst apifyToken = 'REDACTED_BY_REGEX'; \nconst maxRetries = 60; // Increased for \"All\" results\nconst pollInterval = 5000; \n\nfor (let i = 0; i < maxRetries; i++) {\n  const response = await this.helpers.httpRequest({\n    method: 'GET',\n    url: `https://api.apify.com/v2/actor-runs/${runId}?token=${apifyToken}`\n  });\n\n  const status = response.data.status;\n\n  if (status === 'SUCCEEDED') {\n    return [{\n      json: {\n        run_id: runId,\n        dataset_id: response.data.defaultDatasetId,\n        status: 'completed',\n        ...originalInput // Now correctly spreads batch_id, user_id, etc.\n      }\n    }];\n  }\n\n  if (status === 'FAILED' || status === 'ABORTED' || status === 'TIMED-OUT') {\n    throw new Error(`Apify Run failed with status: ${status}`);\n  }\n\n  await new Promise(resolve => setTimeout(resolve, pollInterval));\n}\n\nthrow new Error('Apify timed out.');"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        -736
      ],
      "id": "7054d41c-4731-46a1-8b28-01f90801163c",
      "name": "Poll Status"
    },
    {
      "parameters": {
        "url": "=https://api.apify.com/v2/datasets/{{ $json.dataset_id }}/items",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "token",
              "value": "REDACTED_HEADER_VALUE"
            },
            {
              "name": "clean",
              "value": "true"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        992,
        -736
      ],
      "id": "7a5655be-7962-416c-8878-ac362a0deda7",
      "name": "Fetch Results"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "bb37c2f9-6c87-471e-871c-c1c7a0f24b2c",
              "name": "batch_id",
              "value": "={{ $json.body.batch_id }}",
              "type": "string"
            },
            {
              "id": "1fce52f9-5a3b-41f1-a4b8-388e97f8c331",
              "name": "user_id",
              "value": "={{ $json.body.user_id }}",
              "type": "string"
            },
            {
              "id": "cfd877ea-34fe-43a4-9cd2-e79ca2ea7b85",
              "name": "industry",
              "value": "={{ $json.body.industry }}",
              "type": "string"
            },
            {
              "id": "ff9f7a37-3078-4d81-839d-0b8cd15f01b9",
              "name": "location",
              "value": "={{ $json.body.location }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        144,
        -736
      ],
      "id": "2ed0f8f4-ec08-47c5-81cf-e6b6452ee0a8",
      "name": "Edit Fields1"
    },
    {
      "parameters": {
        "tableId": "leads",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "batch_id",
              "fieldValue": "={{ $node[\"Poll Status\"].json.batch_id }}"
            },
            {
              "fieldId": "user_id",
              "fieldValue": "={{ $node[\"Poll Status\"].json.user_id }}"
            },
            {
              "fieldId": "business_name",
              "fieldValue": "={{ $json.title }}"
            },
            {
              "fieldId": "website_url",
              "fieldValue": "={{ $json.website }}"
            },
            {
              "fieldId": "address",
              "fieldValue": "={{ $json.address }}"
            },
            {
              "fieldId": "phone_number",
              "fieldValue": "={{ $json.phone }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "=raw"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1408,
        -720
      ],
      "id": "688d376d-d841-482b-8c8b-548901dc2687",
      "name": "Create a row",
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        1200,
        -736
      ],
      "id": "433de8bb-938b-47d0-9487-84f86c7f84a3",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "mode": "raw",
        "jsonOutput": "{\n  \"batch_id\": \"a9f9e451-edeb-4d3e-9f5b-4d8535a8bf76\",\n  \"user_id\": \"f1229eb0-7283-4f13-a917-fe1d41e516fd\",\n  \"industry\": \"hotel\",\n  \"location\": \"Casablanca\",\n  \"status\": \"raw\",\n  \"started_at\": \"{{ new Date().toISOString() }}\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        144,
        -976
      ],
      "id": "9d28cf1d-dad8-4d71-9245-154963539c08",
      "name": "TEST JSON"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -64,
        -976
      ],
      "id": "f28138d9-330f-4917-a0a5-0d725c67c718",
      "name": "When clicking \u2018Execute workflow\u2019"
    },
    {
      "parameters": {
        "batchSize": 5,
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        224,
        -368
      ],
      "id": "c1254137-25a4-4878-a996-c8c3a8e99f19",
      "name": "Loop Over Items1"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1568,
        -352
      ],
      "id": "d25ea0e4-2d27-4cfe-9822-9b388cf474e7",
      "name": "Wait"
    }
  ],
  "connections": {
    "Every 1 Minute": {
      "main": [
        [
          {
            "node": "Query Raw Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Raw Leads": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Website": {
      "main": [
        [
          {
            "node": "Gemini Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Analysis": {
      "main": [
        [
          {
            "node": "Clean AI Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean AI Output": {
      "main": [
        [
          {
            "node": "Update Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Edit Fields1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Start Apify Run",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Apify Run": {
      "main": [
        [
          {
            "node": "Poll Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Status": {
      "main": [
        [
          {
            "node": "Fetch Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Results": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields1": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a row": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Create a row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "TEST JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TEST JSON": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Lead": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [],
        [
          {
            "node": "Fetch Website",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "versionId": "8b357a68-f144-40e1-8470-81a6a9a3a885",
  "activeVersionId": null,
  "triggerCount": 0,
  "shared": [
    {
      "updatedAt": "2025-12-25T01:02:23.705Z",
      "createdAt": "2025-12-25T01:02:23.705Z",
      "role": "workflow:owner",
      "workflowId": "Hqjeb2XOK4Vqka8L",
      "projectId": "HHopAZ4lOFgjhBzT"
    }
  ],
  "activeVersion": null,
  "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Agent 3 - The Analyst. Uses supabase, httpRequest, googleGemini. Scheduled trigger; 18 nodes.

Source: https://github.com/abde0112/n8n_bkv2/blob/main/agent-3---the-analyst-Hqjeb2XOK4Vqka8L.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Fully automated blog creation system using n8n + AI Agents + Image Generation

Agent, Output Parser Structured, Groq Chat +9
AI & RAG

kisisel asistan. Uses toolWorkflow, toolHttpRequest, toolCalculator, toolThink. Scheduled trigger; 43 nodes.

Tool Workflow, Tool Http Request, Tool Calculator +15
AI & RAG

Chanchito_PROD. Uses googleGemini, postgres, telegram, httpRequest. Scheduled trigger; 94 nodes.

Google Gemini, Postgres, Telegram +4
AI & RAG

Arvifund - Supabase (Fixed v6). Uses httpRequest, telegram, supabase, telegramTrigger. Event-driven trigger; 92 nodes.

HTTP Request, Telegram, Supabase +8
AI & RAG

Arvifund - Supabase (Fixed v5). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 91 nodes.

HTTP Request, Telegram, Google Sheets +9