AutomationFlowsAI & RAG › Generate Personalized Sales Leads with Claude AI & Explorium for Gmail Outreach

Generate Personalized Sales Leads with Claude AI & Explorium for Gmail Outreach

Byexplorium @explorium on n8n.io

This n8n workflow transforms natural language queries into targeted B2B prospecting campaigns by combining Explorium's data intelligence with AI-powered research and personalized email generation. Simply describe your ideal customer profile in plain English, and the workflow…

Chat trigger trigger★★★★★ complexityAI-powered30 nodesMemory Buffer WindowAgentOutput Parser Structured@Exploriumai/N8N Nodes Explorium AiAnthropic ChatChat TriggerGmailMcp Client Tool
AI & RAG Trigger: Chat trigger Nodes: 30 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #10561 — 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 →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Outbound Agent",
  "tags": [],
  "nodes": [
    {
      "id": "32b82305-22c9-450d-a1ee-c9ee3410bb6a",
      "name": "API Call Validation",
      "type": "n8n-nodes-base.code",
      "position": [
        1312,
        4880
      ],
      "parameters": {
        "jsCode": "const allowedFilters = [\n  \"country_code\",\n  \"region_country_code\",\n  \"company_country_code\",\n  \"company_region_country_code\",\n  \"company_size\",\n  \"company_revenue\",\n  \"company_age\",\n  \"google_category\",\n  \"naics_category\",\n  \"linkedin_category\",\n  \"company_name\",\n  \"number_of_locations\",\n  \"city_region_country\",\n  \"website_keywords\",\n  \"has_email\",\n  \"has_phone_number\",\n  \"job_level\",\n  \"job_department\",\n  \"job_title\",\n  \"business_id\",\n  \"total_experience_months\",\n  \"current_role_months\"\n];\n\nconst validCompanySizes = ['1-10', '11-50', '51-200', '201-500', '501-1000', '1001-5000', '5001-10000', '10001+'];\nconst validAges = ['0-3', '3-6', '6-10', '10-20', '20+'];\nconst validLocations = ['0-1', '2-5', '6-20', '21-50', '51-100', '101-1000', '1001+'];\nconst validRevenue = [\n  \"0-500K\", \"500K-1M\", \"1M-5M\", \"5M-10M\", \"10M-25M\", \"25M-75M\", \"75M-200M\", \"200M-500M\",\n  \"500M-1B\", \"1B-10B\", \"10B-100B\", \"100B-1T\", \"1T-10T\", \"10T+\"\n];\nconst validJobLevel = [\"director\", \"manager\", \"vp\", \"partner\", \"cxo\", \"non-managerial\", \"senior\", \"entry\", \"training\", \"unpaid\"];\nconst validDepartment = [\n  \"customer service\", \"design\", \"education\", \"engineering\", \"finance\", \"general\", \"health\", \"human resources\",\n  \"legal\", \"marketing\", \"media\", \"operations\", \"public relations\", \"real estate\", \"sales\", \"trades\", \"unknown\"\n];\n\nconst countryCodeRegex = /^(aw|af|ao|ai|ax|al|ad|ae|ar|am|as|aq|tf|ag|au|at|az|bi|be|bj|bq|bf|bd|bg|bh|bs|ba|bl|by|bz|bm|bo|br|bb|bn|bt|bv|bw|cf|ca|cc|ch|cl|cn|ci|cm|cd|cg|ck|co|km|cv|cr|cu|cw|cx|ky|cy|cz|de|dj|dm|dk|do|dz|ec|eg|er|eh|es|ee|et|fi|fj|fk|fr|fo|fm|ga|gb|ge|gg|gh|gi|gn|gp|gm|gw|gq|gr|gd|gl|gt|gf|gu|gy|hk|hm|hn|hr|ht|hu|id|im|in|io|ie|ir|iq|is|il|it|jm|je|jo|jp|kz|ke|kg|kh|ki|kn|kr|kw|la|lb|lr|ly|lc|li|lk|ls|lt|lu|lv|mo|mf|ma|mc|md|mg|mv|mx|mh|mk|ml|mt|mm|me|mn|mp|mz|mr|ms|mq|mu|mw|my|yt|na|nc|ne|nf|ng|ni|nu|nl|no|np|nr|nz|om|pk|pa|pn|pe|ph|pw|pg|pl|pr|kp|pt|py|ps|pf|qa|re|ro|ru|rw|sa|sd|sn|sg|gs|sh|sj|sb|sl|sv|sm|so|pm|rs|ss|st|sr|sk|si|se|sz|sx|sc|sy|tc|td|tg|th|tj|tk|tm|tl|to|tt|tn|tr|tv|tw|tz|ug|ua|um|uy|us|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xk|ye|za|zm|zw)$/;\n\nconst item = $input.first().json;\nconst output = item.output || {};\nconst filters = output.filters || {};\nconst errors = [];\n\nfor (const key of Object.keys(filters)) {\n  const filter = filters[key];\n\n  if (!allowedFilters.includes(key)) {\n    errors.push(`Invalid filter key: '${key}'`);\n    continue;\n  }\n\n  if ('value' in filter) {\n    if (typeof filter.value !== 'boolean') {\n      errors.push(`Filter '${key}' has a 'value' but it's not a boolean.`);\n    }\n    continue;\n  }\n\n  if ('values' in filter) {\n    if (!Array.isArray(filter.values) || filter.values.length === 0) {\n      errors.push(`Filter '${key}' must contain a non-empty 'values' array.`);\n      continue;\n    }\n\n    // Normalize to lowercase for fields that require it\n    if ([\"job_level\", \"job_department\", \"country_code\", \"region_country_code\", \"company_country_code\", \"company_region_country_code\"].includes(key)) {\n      filter.values = filter.values.map(v => typeof v === 'string' ? v.toLowerCase() : v);\n    }\n\n    const validateValues = (validList, keyName) => {\n      const invalid = filter.values.filter(v => !validList.includes(v));\n      if (invalid.length > 0) {\n        errors.push(`Invalid ${keyName} values: ${invalid.join(', ')}. Valid values are: ${validList.join(', ')}`);\n      }\n    };\n\n    switch (key) {\n      case 'company_size':\n        validateValues(validCompanySizes, 'company_size');\n        break;\n      case 'company_age':\n        validateValues(validAges, 'company_age');\n        break;\n      case 'number_of_locations':\n        validateValues(validLocations, 'number_of_locations');\n        break;\n      case 'company_revenue':\n        validateValues(validRevenue, 'company_revenue');\n        break;\n      case 'job_level':\n        validateValues(validJobLevel, 'job_level');\n        break;\n      case 'job_department':\n        validateValues(validDepartment, 'job_department');\n        break;\n      case 'country_code':\n        const invalid = filter.values.filter(v => !countryCodeRegex.test(v));\n        if (invalid.length > 0) {\n          errors.push(`Invalid country_code values: ${invalid.join(', ')}. Must be ISO 3166-1 alpha-2 codes.`);\n        }\n        break;\n    }\n\n    const unique = new Set(filter.values);\n    if (unique.size < filter.values.length) {\n      errors.push(`Duplicate values found in filter '${key}'`);\n    }\n\n    continue;\n  }\n\n  // Handle total_experience_months and current_role_months as a range objects\n  if (key === 'total_experience_months' || key === 'current_role_months') {\n  const range = filter;\n  \n  if (!('gte' in range) && !('lte' in range)) {\n    errors.push(`Filter '${key}' must include at least 'gte' or 'lte'.`);\n    continue;\n  }\n\n  if ('gte' in range && typeof range.gte !== 'number') {\n    errors.push(`Filter '${key}' has a non-numeric 'gte' value.`);\n  }\n\n  if ('lte' in range && typeof range.lte !== 'number') {\n    errors.push(`Filter '${key}' has a non-numeric 'lte' value.`);\n  }\n\n  if ('gte' in range && 'lte' in range && range.gte > range.lte) {\n    errors.push(`Filter '${key}' has 'gte' greater than 'lte'.`);\n  }\n\n  continue;\n}\n\n  errors.push(`Filter '${key}' must include either 'value', 'values', or a valid range.`);\n}\n\nreturn [\n  {\n    json: {\n      ...item,\n      isValid: errors.length === 0,\n      validationErrors: errors\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "3953e418-7642-4480-b326-c2ac3493882e",
      "name": "Validation Prompter",
      "type": "n8n-nodes-base.code",
      "position": [
        1808,
        5104
      ],
      "parameters": {
        "jsCode": "const sessionId = $('When chat message received').first().json.sessionId;\nconst userQuery = $('When chat message received').first().json.chatInput;\nconst aiOutput = $('AI Agent').first().json.output;\nconst validationErrors = $('API Call Validation').first().json.validationErrors;\n\n// Safely stringify output and errors\nconst formattedOutput = typeof aiOutput === 'object' ? JSON.stringify(aiOutput, null, 2) : aiOutput;\nconst formattedErrors = Array.isArray(validationErrors) ? validationErrors.join('\\n- ') : validationErrors;\n\nreturn [\n  {\n    sessionId,\n    action: \"sendMessage\",\n    source: \"validation\",\n    errorInput: \n`Your response did not pass validation.\n\n\ud83d\udcdd **User Query**:\n${userQuery}\n\n\ud83e\udd16 **Your Output**:\n${formattedOutput}\n\n\u26a0\ufe0f **Validation Errors**:\n- ${formattedErrors}\n\n\ud83d\udd27 Please review the validation errors and regenerate a corrected output. \nEnsure that all values strictly match the allowed formats and valid categories.\n\nReformulate your response accordingly.`\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "e07bfe5d-738e-4c7e-b4e8-afd7a2d27c38",
      "name": "Is API Call Valid?",
      "type": "n8n-nodes-base.if",
      "position": [
        1584,
        4880
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9b2c3127-07c4-47d0-8dc3-44daa2a2d6e7",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.isValid }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "39b2bf6b-22c9-4412-905c-2ba821fc6dea",
      "name": "Chat or Refinement",
      "type": "n8n-nodes-base.code",
      "position": [
        544,
        5008
      ],
      "parameters": {
        "jsCode": "const chat = $json.chatInput;\nconst error = $json.errorInput;\n\nreturn [\n  {\n    json: {\n      ...$json,\n      combinedInput: error ?? chat\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "b1b915d5-5aa0-4af9-a212-11f3d5df699b",
      "name": "Simple Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        896,
        5056
      ],
      "parameters": {
        "contextWindowLength": 100
      },
      "typeVersion": 1.3
    },
    {
      "id": "105f1042-af38-4695-9bd8-bd7c845cb8d4",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        880,
        4880
      ],
      "parameters": {
        "text": "={{ $json.combinedInput }}",
        "options": {
          "maxIterations": 100,
          "systemMessage": "=You are an expert in interpreting natural language queries and converting them into structured JSON requests for the Explorium MCP API.\n\nYour task is to generate the **`data` portion** of a `fetch_prospects` API request, using only Explorium MCP-compatible filters and parameters. Adjust the filters based on both the query and the MCP specifications\u2014not all filters are relevant for every query.\n\n**You may also be asked to revise a previous response that failed validation due to incorrect filters or formatting.** In such cases, carefully review the error message and regenerate the JSON accordingly.\n\nYour response must be a **single JSON object** with this structure:\n\n```json\n{\n  \"mode\": \"full\",\n  \"size\": 10000,\n  \"page_size\": 100,\n  \"page\": 1,\n  \"filters\": {\n    \"has_email\": { \"value\": true },\n    \"has_phone_number\": { \"value\": true },\n    \"job_level\": { \"values\": [...] },\n    \"job_department\": { \"values\": [...] },\n    \"business_id\": { \"values\": [...] },\n    ...\n  }\n}\n```\n\n### Required Structure:\n\n* The fields `mode`, `size`, `page_size`, and `page` must appear **before** the `filters` object.\n* Default values:\n\n  * `mode`: `\"full\"`\n  * `size`: `10000` (unless otherwise specified by the user; must remain between 1 and 10000)\n  * `page_size`: `100` (**must always be less or equal to `size`**)\n  * `page`: `1`\n  * `has_email`: always `{ \"value\": true }`, unless explicitly requested otherwise\n\n---\n\n### Allowed Filters & Valid Values:\n\nIf any of the following filters appear in your output, their values **must strictly match** these lists:\n\n* **`company_size`**: `'1-10'`, `'11-50'`, `'51-200'`, `'201-500'`, `'501-1000'`, `'1001-5000'`, `'5001-10000'`, `'10001+'`\n* **`company_age`**: `'0-3'`, `'3-6'`, `'6-10'`, `'10-20'`, `'20+'`\n* **`number_of_locations`**: `'0-1'`, `'2-5'`, `'6-20'`, `'21-50'`, `'51-100'`, `'101-1000'`, `'1001+'`\n* **`company_revenue`**: `'0-500K'`, `'500K-1M'`, `'1M-5M'`, `'5M-10M'`, `'10M-25M'`, `'25M-75M'`, `'75M-200M'`, `'200M-500M'`, `'500M-1B'`, `'1B-10B'`, `'10B-100B'`, `'100B-1T'`, `'1T-10T'`, `'10T+'`\n* **`job_level`**: `'director'`, `'manager'`, `'vp'`, `'partner'`, `'cxo'`, `'non-managerial'`, `'senior'`, `'entry'`, `'training'`, `'unpaid'`\n* **`job_department`**: `'customer service'`, `'design'`, `'education'`, `'engineering'`, `'finance'`, `'general'`, `'health'`, `'human resources'`, `'legal'`, `'marketing'`, `'media'`, `'operations'`, `'public relations'`, `'real estate'`, `'sales'`, `'trades'`, `'unknown'`\n* **`country_code`** and **`company_country_code`**: Must be valid **2-letter ISO Alpha-2 codes** (e.g., `us`, `gb`, `de`, etc.)\n* **`total_experience_months`** and **`current_role_months`**: These must be objects with both a `gte` and `lte` key where `gte <= lte`, for example:\n\n```json\n\"total_experience_months\": { \"gte\": 3, \"lte\": 6 }\n```\n\nand\n\n```json\n\"current_role_months\": { \"gte\": 1, \"lte\": 10 }\n```\n\n* If a company name is mentioned (e.g., \"Microsoft\"), include its `business_id` (use a placeholder like `\"abc123\"` if unknown)\n\n---\n\n### Interpretation & Mapping:\n\n* Extract job levels from descriptions like:\n\n  * \u201cexecutives\u201d or \u201cleadership\u201d \u2192 `\"cxo\"`\n  * \u201cheads\u201d or \u201cvice presidents\u201d \u2192 `\"vp\"`\n* Map department-like terms (e.g., \u201csales\u201d, \u201cmarketing\u201d) to the `job_department` field.\n* Don\u2019t include filters with empty or unrecognized values.\n* Use plural logic: if the query includes a phrase like \u201cfinance and marketing,\u201d return both departments.\n\n---\n\n### Off-topic Handling:\n\nIf the request is unrelated to B2B data intelligence or the MCP use cases, return the following message verbatim:\n\n> I\u2019m the Explorium MCP Playground assistant, built to explore company & prospect intelligence.\n> Example queries:\n> \u2022 Find SaaS firms in New York with 50\u2011200 employees\n> \u2022 Show Microsoft\u2019s technology stack\n> \u2022 Get marketing\u2011director contacts at healthcare companies\n> \u2022 Compare funding rounds of fintech startups\n> How would you like to explore Explorium\u2019s data?"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "retryOnFail": true,
      "typeVersion": 1.7
    },
    {
      "id": "cb463c54-d5ac-40cf-819d-b2a00e99c82f",
      "name": "Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1152,
        5056
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"mode\": \"full\",\n  \"size\": 50,\n  \"page_size\": 50,\n  \"page\": 1,\n  \"filters\": {\n    \"has_email\": {\n      \"value\": true\n    },\n    \"has_phone_number\": {\n      \"value\": true\n    },\n    \"job_level\": {\n      \"values\": [\n        \"cxo\",\n        \"manager\"\n      ]\n    },\n    \"job_department\": {\n      \"values\": [\n        \"Customer service\",\n        \"Engineering\"\n      ]\n    },\n    \"business_id\": {\n      \"values\": [\n    \"8adce3ca1cef0c986b22310e369a0793\"\n      ]\n    },\n    \"total_experience_months\": {\n      \"gte\": 1,\n      \"lte\": 20\n    },\n    \"country_code\": {\n      \"values\": [\n        \"us\",\n        \"dk\",\n        \"uk\"\n      ]\n    },\n    \"region_country_code\": {\n      \"values\": [\n        \"us-ca\",\n        \"us-ny\"\n      ]\n    },\n    \"current_role_months\": {\n      \"gte\": 1,\n      \"lte\": 200\n    },\n    \"company_size\": {\n      \"values\": [\n        \"5001-10000\"\n      ]\n    },\n    \"company_revenue\": {\n      \"values\": [\n        \"500K-1M\",\n        \"5M-10M\"\n      ]\n    },\n    \"google_category\": {\n      \"values\": [\n        \"construction\"\n      ]\n    },\n    \"naics_category\": {\n      \"values\": [\n        \"541512\"\n      ]\n    },\n    \"linkedin_category\": {\n      \"values\": [\n        \"retail\",\n        \"software development\"\n      ]\n    },\n    \"job_title\": {\n      \"values\": [\n        \"Software Engineer\"\n      ]\n    },\n    \"company_country_code\": {\n      \"values\": [\n        \"us\",\n        \"jp\"\n      ]\n    },\n    \"company_region_country_code\": {\n      \"values\": [\n        \"us-ca\"\n      ]\n    },\n    \"city_region_country\": {\n      \"values\": [\n        \"Paris, FR\"\n      ]\n    },\n    \"company_name\": {\n      \"values\": [\n        \"Microsoft\"\n      ]\n    }\n  }\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "86283e10-83db-40d9-9509-4d73e52cd098",
      "name": "Explorium API: Fetch Prospects",
      "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode",
      "position": [
        1840,
        4832
      ],
      "parameters": {
        "type": "prospects",
        "jsonInput": "={{ JSON.stringify($json.output) }}",
        "operation": "fetch",
        "useJsonInput": true
      },
      "typeVersion": 1
    },
    {
      "id": "84c0cb2c-d414-471d-a333-452d9db274fd",
      "name": "Simple Memory1",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        3296,
        4928
      ],
      "parameters": {},
      "typeVersion": 1.3
    },
    {
      "id": "91f70acf-bde7-428e-9724-1f9445552230",
      "name": "Anthropic Chat Model3",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        3632,
        4928
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-20250514",
          "cachedResultName": "Claude 4 Sonnet"
        },
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "8cba4d3e-cf75-41a0-aab7-900612e25bf3",
      "name": "Pull Prospect IDs",
      "type": "n8n-nodes-base.code",
      "position": [
        2080,
        4832
      ],
      "parameters": {
        "jsCode": "return {\n  json: {\n    prospect_ids: $input.first().json.data.map(item => item.prospect_id)\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "8fc2cc87-6c20-4bf6-b15c-b622a2ad1d95",
      "name": "Clean Output Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2624,
        4832
      ],
      "parameters": {
        "jsCode": "// Get the enriched_data array from the input\nconst inputData = $json.enriched_data || [];\n\n// Clean and filter data for each prospect\nconst cleanedData = inputData.map(prospect => {\n  const data = prospect.data;\n  \n  // Extract current professional email\n  let currentEmail = null;\n  if (data.emails && Array.isArray(data.emails)) {\n    const currentProfessionalEmail = data.emails.find(\n      email => email.type === \"current_professional\" && email.address\n    );\n    currentEmail = currentProfessionalEmail?.address || null;\n  }\n  \n  // Extract most recent work experience (is_primary = true)\n  let currentExperience = null;\n  if (data.experience && Array.isArray(data.experience)) {\n    currentExperience = data.experience.find(exp => exp.is_primary === true);\n    \n    // If no primary, get the first one (usually most recent)\n    if (!currentExperience && data.experience.length > 0) {\n      currentExperience = data.experience[0];\n    }\n  }\n  \n  // Return cleaned prospect data wrapped in { json: ... } format\n  return {\n    json: {\n      prospect_id: prospect.prospect_id,\n      full_name: data.full_name,\n      email: currentEmail,\n      professional_email_status: data.professional_email_status,\n      mobile_phone: data.mobile_phone,\n      job_title: data.job_title,\n      job_department: data.job_department,\n      job_seniority_level: data.job_seniority_level,\n      company_name: data.company_name,\n      company_website: data.company_website,\n      company_linkedin: data.company_linkedin,\n      linkedin: data.linkedin,\n      location: {\n        city: data.city,\n        region: data.region_name,\n        country: data.country_name\n      },\n      current_experience: currentExperience ? {\n        company_name: currentExperience.company?.name,\n        company_website: currentExperience.company?.website,\n        title: currentExperience.title?.name,\n        seniority: currentExperience.title?.levels?.[0],\n        role: currentExperience.title?.role,\n        start_date: currentExperience.start_date,\n        end_date: currentExperience.end_date || null,\n        summary: currentExperience.summary || null\n      } : null,\n      skills: data.skills || [],\n      age_group: data.age_group,\n      gender: data.gender\n    }\n  };\n});\n\n// Return as multiple items (not wrapped in data array)\nreturn cleanedData;"
      },
      "typeVersion": 2
    },
    {
      "id": "e2efc012-3a8a-46e6-92ce-e53b24d306cb",
      "name": "Research Email",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        3216,
        4704
      ],
      "parameters": {
        "text": "=You are assisting an outbound sales agent by gathering research for the first outreach email in a cold email sequence.\n\nThe email is about using Explorium\u2019s B2B data enrichment to enhance automation workflows built with tools like n8n, Zapier, or Make.\n\nYour goal is to collect accurate and relevant information about the contact and their company, so the email can be personalized.\n\nInput:\n\nProspect name: {{ $json.full_name }}\nJob title: {{ $json.job_title }}\nCompany name: {{ $json.company_name }}\nCompany website: {{ $json.company_website }}\nLinkedIn URL: {{ $json.linkedin }}\nJob Department: {{ $json.job_department }}\nSkills: {{ $json.skills }}\n\n\nYour Output:\nReturn the research using the explorium MCP server to return research in this structured format:\n\n{\n  \"first_name\": \"\",\n  \"last_name\": \"\",\n  \"job_title\": \"\",\n  \"company_name\": \"\",\n  \"company_domain\": \"\",\n  \"industry\": \"\",\n  \"uses_automation_tools\": true,\n  \"automation_tools\": [\"n8n\", \"Zapier\", \"Make\", \"HubSpot\", \"Salesforce\"],\n  \"uses_data_enrichment\": true,\n  \"recent_activity\": \"Launched internal automation project\",\n  \"public_content\": \"Spoke at ZapConnect 2024 on data pipelines\",\n  \"tech_stack\": [\"Snowflake\", \"Segment\", \"Zapier\"],\n  \"pain_points\": \"Depends on static lead lists, poor CRM data quality\",\n  \"personalization_note\": \"Mention their interest in automation and Zapier usage\"\n}",
        "options": {
          "maxIterations": 25,
          "systemMessage": "You are a research agent that helps sales automation agents personalize outreach emails.\n\nYour job is to extract relevant insights about a prospect and their company based on their name, job title, company, and LinkedIn URL.\n\nYou must:\n\nFocus on automation tools, workflow platforms, CRMs, and B2B data use.\n\nIdentify pain points like outdated CRM data, manual enrichment, or static workflows.\n\nReturn structured JSON that includes tools, job role, and public context that would help tailor an email.\n\nDo not fabricate any information. If something isn\u2019t found, leave the field blank or write \"unknown\".\n\nYour research will help another agent write this type of email:\n\nSubject: Automate workflows with real-time, enriched B2B data\nHi {{first_name}},\nExplorium integrates with tools like n8n, Zapier, and Make to enrich B2B data in real-time. No scraping, no spreadsheets. Just better inputs for smarter workflows.\n\nYou are not writing the email \u2014 only providing research that powers it."
        },
        "promptType": "define"
      },
      "retryOnFail": true,
      "typeVersion": 2.1,
      "waitBetweenTries": 3000
    },
    {
      "id": "ff0f1d57-3e10-4307-8843-9f0e10577226",
      "name": "Email Writer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        3616,
        4704
      ],
      "parameters": {
        "text": "=prospect_data: contact info: {{ $('Loop Over Items3').item.json.email }}, expereince: {{ $('Loop Over Items3').item.json.current_experience }},skills: {{ $('Loop Over Items3').item.json.skills }}.\ncompany data: company name: {{ $('Loop Over Items3').item.json.company_name }}, company website: {{ $('Loop Over Items3').item.json.company_website }}\nResearch: {{ $json.output }}\n\n",
        "options": {
          "systemMessage": "=You are a B2B outbound sales email generator.\n\nYour task is to write a short and effective cold outbound email (under 150 words) to a specific prospect at a company. The goal is to be relevant, concise, and persuasive, while introducing Explorium in a way that aligns with the prospect\u2019s role and current company context.\n\n## Prospect Data\n{prospect_data}\n\n## Company \n{company_data}\n\n## Research\n{research}\n\n## About Explorium (Use this to inform the email \u2014 do not paste directly):\nExplorium is a data-powered intelligence platform on a mission to unlock the full potential of external data for the agent era. We serve as the infrastructure backbone for intelligent systems \u2014 helping go-to-market teams enrich company and prospect data, tap into real-time signals, and dynamically prioritize their best-fit accounts. Our platform fuels the agents and AI products that are redefining the future of sales and marketing.\n\n## MCP Playground (Link to include):\nInvite the prospect to explore Explorium\u2019s capabilities hands-on via our [MCP Playground](https://www.explorium.ai/mcp-playground/), a public environment to experience the power of enriched external data.\n\n## Output Instructions:\n- Personalize the email using the provided prospect, company, and event information\n- Tailor the message to the prospect\u2019s title, department, or function\n- Weave in how Explorium could support their work or goals based on what the company is focused on\n- The email should feel like it\u2019s written by a real SDR \u2014 confident, relevant, and human\n- End the email with a soft CTA inviting them to check out the MCP Playground link but dont forget to also ask to set up a meeting / call\n- At the top of the email, output the selected email address to use. Choose the prospect\u2019s **professional email** if available, or fallback to the next best alternative (personal, current, etc.)\n\nOutput must be JSON format, with \"email\", \"subject\" and \"message\" keys.  \n\"body\" must be in HTML format with <p> for paragraphs, DO NOT BOLD OR ITALICES, \n\nand do not sign with anythign just end the email without anything  "
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "e2b44028-5166-481a-9135-4a4e05b4187d",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        320,
        5008
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "5b95d50e-b191-4449-9eb0-5d2736b02e44",
      "name": "Create a draft",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3968,
        4832
      ],
      "parameters": {
        "message": "={{ $json.output.message }}",
        "options": {
          "sendTo": "={{ $json.output.email }}"
        },
        "subject": "={{ $json.output.subject }}",
        "resource": "draft",
        "emailType": "html"
      },
      "typeVersion": 2.1
    },
    {
      "id": "8ad162e6-c087-441f-a9ac-deca0a0dd730",
      "name": "Explorium API: Contact Enrichment",
      "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode",
      "position": [
        2336,
        4832
      ],
      "parameters": {
        "type": "prospects",
        "jsonInput": "={\n  \"prospect_ids\": {{ JSON.stringify($json.prospect_ids) }}\n}",
        "operation": "enrich",
        "enrichment": [
          "contacts",
          "profiles"
        ],
        "useJsonInput": true
      },
      "typeVersion": 1
    },
    {
      "id": "7448570e-844a-4569-852c-f460d6723c34",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        4208
      ],
      "parameters": {
        "width": 672,
        "height": 416,
        "content": "# Outbound Agent\n\n## How it works\nThis workflow turns natural language into personalized cold outreach emails. You describe your ideal prospects in plain English, and the workflow: (1) translates your request into an Explorium API call using an AI agent connected to the Explorium MCP, (2) fetches relevant prospects with enriched contact data, (3) researches each prospect using the AI Agent with the Explorium MCP, and (4) generates personalized email drafts in Gmail\u2014all automatically.\n\n## Setup steps\n1. Connect Anthropic API key (three Chat Model nodes)\n2. Add Explorium credentials (Fetch, Enrich nodes + two MCP tools)\n3. Connect Gmail account (Create draft node)\n4. Open the chat interface and describe your target prospects\n5. Review generated email drafts in your Gmail account"
      },
      "typeVersion": 1
    },
    {
      "id": "79dd2b06-f3b1-41c0-a6b9-a4a81235dc6d",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        4944
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 240,
        "content": "## Natural Language Input\nDescribe your target prospects conversationally. The AI converts your request into precise API filters.\n\n### Example Prompt:\n\"Get 5 marketing leaders at fintech startups who joined in the past year and have valid contact information\""
      },
      "typeVersion": 1
    },
    {
      "id": "9e4bea48-77d0-4177-bb9d-0a50cc9c4273",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        832,
        4704
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 144,
        "content": "## Convert to API Call\nUses Explorium MCP to translate natural language into structured prospect search filters, then validates the API request format."
      },
      "typeVersion": 1
    },
    {
      "id": "408bff93-a7be-43a1-a183-91b0f1f4ff12",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2000,
        4672
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 128,
        "content": "## Find & Enrich Prospects\nFetches prospects matching your criteria, enriches with contact details and professional profiles, then cleans the data."
      },
      "typeVersion": 1
    },
    {
      "id": "675f7a81-4c39-4b35-80f2-6a5835d5ce73",
      "name": "Anthropic Chat Model2",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        768,
        5056
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-20250514",
          "cachedResultName": "Claude Sonnet 4"
        },
        "options": {
          "thinking": false
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "c56e72c5-5d87-491a-bf2a-62d8c27c7877",
      "name": "Loop Over Items3",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2912,
        4832
      ],
      "parameters": {
        "options": {
          "reset": false
        },
        "batchSize": "=1"
      },
      "typeVersion": 3
    },
    {
      "id": "52487cb2-7251-43ae-8df3-0e3ab5170518",
      "name": "Anthropic Chat Model4",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        3152,
        4928
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-20250514",
          "cachedResultName": "Claude 4 Sonnet"
        },
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "4107a6ca-cf90-4f49-9567-9cd1c232bc9e",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4160,
        4864
      ],
      "parameters": {
        "color": 5,
        "width": 288,
        "content": "### Output to preferred email service:\n- Gmail\n- Outlook\n- Mailchimp\n- Sendgrid\n- Lemlist"
      },
      "typeVersion": 1
    },
    {
      "id": "4aef8f4b-22dc-4a85-9ee3-53de13cae0ef",
      "name": "Structured Output Parser2",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        3776,
        4928
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"email\": {\n      \"type\": \"string\",\n      \"description\": \"The prospect's email address to send to. Use professional email if available, otherwise fallback to personal or current email.\"\n    },\n    \"subject\": {\n      \"type\": \"string\",\n      \"description\": \"Personalized email subject line that's compelling and relevant to the prospect's role or company context\"\n    },\n    \"message\": {\n      \"type\": \"string\",\n      \"description\": \"Email body in HTML format using <p> tags for paragraphs. Must be under 150 words, personalized to prospect and company data, mention Explorium's value proposition naturally, include MCP Playground link, and end with soft CTA asking to set up a meeting/call. No bold, italics, or signature.\"\n    }\n  },\n  \"required\": [\"email\", \"subject\", \"message\"]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "ede2a0bf-b5d8-4e3f-a218-aecc00503d8d",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3360,
        4544
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 128,
        "content": "## Research & Write Emails\nLoops through each prospect: researches their background and company using the Explorium MCP and input data, then writes personalized cold emails."
      },
      "typeVersion": 1
    },
    {
      "id": "77ed1a79-62bf-45ae-9f9d-88ee50d28364",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4128,
        4720
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 112,
        "content": "## Create Gmail Drafts\nSaves personalized emails as Gmail drafts ready for review and sending."
      },
      "typeVersion": 1
    },
    {
      "id": "00237c49-2967-480d-9924-e443538880b1",
      "name": "Explorium MCP3",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        1024,
        5056
      ],
      "parameters": {
        "options": {},
        "endpointUrl": "https://mcp-n8n.explorium.ai/mcp",
        "authentication": "headerAuth"
      },
      "typeVersion": 1.2
    },
    {
      "id": "bf98f50e-505f-451b-822d-41792d06defe",
      "name": "MCP Client",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        3424,
        4928
      ],
      "parameters": {
        "options": {},
        "endpointUrl": "https://mcp-n8n.explorium.ai/mcp",
        "authentication": "headerAuth"
      },
      "typeVersion": 1.2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "AI Agent": {
      "main": [
        [
          {
            "node": "API Call Validation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MCP Client": {
      "ai_tool": [
        [
          {
            "node": "Research Email",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Email Writer": {
      "main": [
        [
          {
            "node": "Create a draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Create a draft": {
      "main": [
        [
          {
            "node": "Loop Over Items3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Explorium MCP3": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Research Email": {
      "main": [
        [
          {
            "node": "Email Writer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory1": {
      "ai_memory": [
        [
          {
            "node": "Research Email",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items3": {
      "main": [
        [],
        [
          {
            "node": "Research Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean Output Data": {
      "main": [
        [
          {
            "node": "Loop Over Items3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pull Prospect IDs": {
      "main": [
        [
          {
            "node": "Explorium API: Contact Enrichment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Chat or Refinement": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is API Call Valid?": {
      "main": [
        [
          {
            "node": "Explorium API: Fetch Prospects",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Validation Prompter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "API Call Validation": {
      "main": [
        [
          {
            "node": "Is API Call Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validation Prompter": {
      "main": [
        [
          {
            "node": "Chat or Refinement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model3": {
      "ai_languageModel": [
        [
          {
            "node": "Email Writer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model4": {
      "ai_languageModel": [
        [
          {
            "node": "Research Email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser2": {
      "ai_outputParser": [
        [
          {
            "node": "Email Writer",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "Chat or Refinement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Explorium API: Fetch Prospects": {
      "main": [
        [
          {
            "node": "Pull Prospect IDs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Explorium API: Contact Enrichment": {
      "main": [
        [
          {
            "node": "Clean Output Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

This n8n workflow transforms natural language queries into targeted B2B prospecting campaigns by combining Explorium's data intelligence with AI-powered research and personalized email generation. Simply describe your ideal customer profile in plain English, and the workflow…

Source: https://n8n.io/workflows/10561/ — 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

This Chatbot automates the process of discovering job openings and generating tailored job application emails.

Chat Trigger, OpenAI Chat, Mcp Client Tool +12
AI & RAG

This workflow implements an advanced AI-powered system for generating, and executing Claude Skills stored on GitHub.

Chat Trigger, Memory Buffer Window, Mcp Client Tool +9
AI & RAG

Explorium Prospects Search Chatbot

Memory Buffer Window, Chat Trigger, Agent +4
AI & RAG

This n8n workflow is designed for Shopify store owners and e-commerce managers who want to automate their store operations through an intelligent AI assistant. The workflow creates a conversational in

Shopify Tool, Discord, Telegram +10
AI & RAG

This n8n template demonstrates how to build an AI-powered Market Research Assistant using a multi-agent workflow. It helps you get a 360-degree view of a product idea or research topic by analysing: C

Chat Trigger, Memory Buffer Window, Agent +5