{ "name": "Research Agent", "nodes": [ { "parameters": { "operation": "getAll", "calendar": {}, "timeMax": "={{ $now.plus({ day: 0.75 }) }}", "options": {} }, "type": "n8n-nodes-base.googleCalendar", "typeVersion": 1.3, "position": [ -1008, 1104 ], "id": "9758a62b-54fa-4291-b930-6680c111675c", "name": "Get many events" }, { "parameters": { "options": { "reset": false } }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ -560, 704 ], "id": "3ce930ef-33fd-4538-8187-e264239ef943", "name": "Loop Over Items" }, { "parameters": { "jsCode": "const items = $input.all();\nconst companies = new Set();\n\nitems.forEach(item => {\n item.json.attendees?.forEach(attendee => {\n const domain = attendee.email?.split('@')[1];\n if (domain && domain !== 'explorium.ai' && domain !== 'resource.calendar.google.com') {\n companies.add(domain);\n }\n });\n});\n\nreturn Array.from(companies).map(company => ({\n json: { company_domain: company }\n}));" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -336, 192 ], "id": "00dd18c0-24fb-4434-9db2-90afdb14af71", "name": "Extract External Company Domains" }, { "parameters": { "operation": "match", "businesses_to_match": { "businesses_to_match": [ { "domain": "={{ $json.company_domain }}" } ] } }, "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode", "typeVersion": 1, "position": [ -112, 192 ], "id": "a3d9e637-5438-45f6-8124-1f43d6894207", "name": "Explorium API: Match Business" }, { "parameters": {}, "type": "n8n-nodes-base.merge", "typeVersion": 3.2, "position": [ 560, 160 ], "id": "8ce24896-ae7e-4282-bd36-6de55228c39a", "name": "Merge" }, { "parameters": { "model": { "__rl": true, "mode": "list", "value": "claude-sonnet-4-20250514", "cachedResultName": "Claude 4 Sonnet" }, "options": {} }, "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic", "typeVersion": 1.3, "position": [ 928, 432 ], "id": "8c3a0025-d1c3-40c0-ad5f-4dbf6426c2ec", "name": "Anthropic Chat Model" }, { "parameters": { "operation": "match", "type": "prospects", "prospects_to_match": { "prospects_to_match": [ { "business_id": "={{ $json.matched_businesses[0].business_id }}", "email": "={{ $('Extract External Company Domains1').item.json.email }}" } ] } }, "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode", "typeVersion": 1, "position": [ 336, 1168 ], "id": "e89c8e93-cab3-444f-9113-0dcf0825ee16", "name": "Explorium API: Match Prospect" }, { "parameters": { "operation": "events", "business_ids": { "business_ids": [ { "id": "={{ $json.matched_businesses[0].business_id }}" } ] }, "event_types": [ "new_funding_round", "new_investment", "merger_and_acquisitions", "new_product", "new_partnership" ], "timestamp_from": "2025-09-01T00:00:00", "timestamp_to": "2025-11-04T17:30:00" }, "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode", "typeVersion": 1, "position": [ 336, 272 ], "id": "0384e6bb-f96d-4a09-b06d-615d6192ffef", "name": "Explorium API: Fetch Business Events" }, { "parameters": { "model": { "__rl": true, "mode": "list", "value": "claude-sonnet-4-20250514", "cachedResultName": "Claude 4 Sonnet" }, "options": {} }, "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic", "typeVersion": 1.3, "position": [ 1456, 1456 ], "id": "49aecea2-f129-4f4c-818a-4b674fb3b366", "name": "Anthropic Chat Model1" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "01e7bc0b-2951-456c-810a-78d3f32b8216", "leftValue": "={{ $json.matched_businesses[0].business_id }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 112, 192 ], "id": "da909acb-75db-4f88-9926-00bb3e3f9a07", "name": "If" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "01e7bc0b-2951-456c-810a-78d3f32b8216", "leftValue": "={{ $json.matched_prospects[0].prospect_id }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 560, 1168 ], "id": "df4e9a26-663b-4cda-88dd-a5146ed9cc25", "name": "If1" }, { "parameters": { "schemaType": "manual", "inputSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"company_overview\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Key facts about the company including size, industry, location, recent news, and general business context. Each item should be a concise bullet point.\"\n },\n \"website_changes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Recent updates, changes, or new content found on the company's website. Each item should be a specific, actionable bullet point.\"\n },\n \"tech_stack_product_focus\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Technologies the company uses, their product offerings, technical infrastructure, and areas of technical investment. Each item should be a concise bullet point.\"\n },\n \"potential_pain_points\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Business challenges, gaps, or problems the company might be facing based on research. Each item should identify a specific challenge.\"\n },\n \"explorium_opportunity\": {\n \"type\": \"object\",\n \"properties\": {\n \"relevance\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Why Explorium AgentSource is relevant to this company. Connect their pain points/focus areas to Explorium's capabilities.\"\n },\n \"resonant_capabilities\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Which specific Explorium APIs or capabilities would resonate most with this company (Match API, Enrich API, Event API, etc.)\"\n }\n },\n \"required\": [\"relevance\", \"resonant_capabilities\"]\n },\n \"conversation_starters\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Specific topics, recent events, or questions to reference in the sales meeting. Should be timely and relevant to help break the ice.\"\n }\n },\n \"required\": [\n \"company_overview\",\n \"website_changes\",\n \"tech_stack_product_focus\",\n \"potential_pain_points\",\n \"explorium_opportunity\",\n \"conversation_starters\"\n ]\n}" }, "type": "@n8n/n8n-nodes-langchain.outputParserStructured", "typeVersion": 1.3, "position": [ 1216, 432 ], "id": "06c1dc33-ea66-4bf9-8afe-6ae1998fa696", "name": "Structured Output Parser" }, { "parameters": { "schemaType": "manual", "inputSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"attendee_name\": {\n \"type\": \"string\",\n \"description\": \"Full name of the meeting attendee being researched\"\n },\n \"background\": {\n \"type\": \"object\",\n \"properties\": {\n \"current_role\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Current position, tenure, department, and reporting structure. Each item should be a concise bullet point.\"\n },\n \"previous_experience\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Relevant previous roles and companies that provide context. Each item should be a concise bullet point.\"\n },\n \"education\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Educational background highlights including degrees, schools, and relevant certifications. Each item should be a concise bullet point.\"\n }\n },\n \"required\": [\"current_role\", \"previous_experience\", \"education\"]\n },\n \"recent_activity_interests\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"LinkedIn post themes, engagement patterns, professional interests, and focus areas based on their online activity. Each item should be specific and actionable.\"\n },\n \"conversation_angles\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Shared connections, interests, recent projects or initiatives they've mentioned, and topics they care about. Each item should be a specific hook for conversation.\"\n },\n \"how_to_approach\": {\n \"type\": \"object\",\n \"properties\": {\n \"pain_points\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Likely challenges or pain points based on their role and recent activity. Each item should identify a specific challenge.\"\n },\n \"relevant_capabilities\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Specific Explorium AgentSource capabilities relevant to their responsibilities (Match API, Enrich API, Event API, MCP Server, etc.)\"\n },\n \"conversation_starters\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Specific opening conversation starters or questions to break the ice and demonstrate research. Should be personalized and timely.\"\n }\n },\n \"required\": [\"pain_points\", \"relevant_capabilities\", \"conversation_starters\"]\n }\n },\n \"required\": [\n \"attendee_name\",\n \"background\",\n \"recent_activity_interests\",\n \"conversation_angles\",\n \"how_to_approach\"\n ]\n}" }, "type": "@n8n/n8n-nodes-langchain.outputParserStructured", "typeVersion": 1.3, "position": [ 1760, 1456 ], "id": "7347b933-d7c1-4c40-868f-52ab78afee10", "name": "Structured Output Parser1" }, { "parameters": { "content": "### Potential Connections: \n- Google\n- Outlook", "height": 112, "width": 160, "color": 5 }, "type": "n8n-nodes-base.stickyNote", "position": [ -1040, 1264 ], "typeVersion": 1, "id": "ae9774c1-4d7c-4cbe-854b-df3b6a651ff7", "name": "Sticky Note6" }, { "parameters": { "content": "### Output Options: \n- Google Doc\n- PDF\n- CRM \n- etc.", "width": 160, "color": 5 }, "type": "n8n-nodes-base.stickyNote", "position": [ 880, 880 ], "typeVersion": 1, "id": "07dc7c0b-2788-41c2-91cd-f6aee2324a7c", "name": "Sticky Note11" }, { "parameters": { "content": "### Customize Schedule Trigger:\n- Start time\n- Time window\n- etc.", "height": 144, "width": 166, "color": 5 }, "type": "n8n-nodes-base.stickyNote", "position": [ -1456, 1072 ], "typeVersion": 1, "id": "a9a33686-a207-483f-acfe-153f426fb3b2", "name": "Sticky Note12" }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ -336, 1344 ], "id": "0da34604-f15d-4636-abef-f515a9f6e97c", "name": "Loop Over Items2" }, { "parameters": { "mode": "combine", "advanced": true, "mergeByFields": { "values": [ { "field1": "domain", "field2": "domain" } ] }, "options": {} }, "type": "n8n-nodes-base.merge", "typeVersion": 3.2, "position": [ -48, 944 ], "id": "0d7fbd00-e390-4d3a-8dd5-4999c6d182a1", "name": "Merge2" }, { "parameters": { "jsCode": "const email = $input.item.json.email;\nconst domain = email.split('@')[1];\n\nreturn [{\n json: {\n email: email,\n domain: domain\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -112, 1168 ], "id": "9ada2eb6-5303-442d-b232-f4c210390307", "name": "Extract External Company Domains1" }, { "parameters": { "operation": "match", "businesses_to_match": { "businesses_to_match": [ { "domain": "={{ $json.domain }}" } ] } }, "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode", "typeVersion": 1, "position": [ 112, 1168 ], "id": "cba9170d-ad9a-435f-a20b-1cc321fe4612", "name": "Explorium API: Match Business1" }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ 192, 944 ], "id": "a5652be1-fd15-447e-9603-c09db70f67f2", "name": "Loop Over Items1" }, { "parameters": { "rule": { "interval": [ {} ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [ -1232, 1104 ], "id": "42f18183-6ca1-468c-bf4e-2270ba72f315", "name": "Schedule Trigger", "disabled": true }, { "parameters": { "jsCode": "const items = $input.all();\nconst eventsWithExternalAttendees = [];\nitems.forEach(item => {\n // Filter attendees to only external domains --> REPLACE 'explorium.ai' with your domain\n const externalAttendees = item.json.attendees?.filter(attendee => {\n const domain = attendee.email?.split('@')[1];\n return domain && domain !== 'explorium.ai' && domain !== 'resource.calendar.google.com';\n }) || [];\n\n // Only include events that have external attendees\n if (externalAttendees.length > 0) {\n // Extract unique company domains from this event\n const companyDomains = [...new Set(externalAttendees.map(a => a.email.split('@')[1]))];\n\n eventsWithExternalAttendees.push({\n ...item.json,\n external_attendees: externalAttendees,\n company_domains: companyDomains,\n external_attendee_count: externalAttendees.length\n });\n }\n});\nreturn eventsWithExternalAttendees.map(event => ({\n json: event\n}));" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -784, 1104 ], "id": "8ebea4b5-46fb-4a4f-834b-2a642b4b3b4c", "name": "Filter for External Meetings" }, { "parameters": { "jsCode": "// Get ALL input items\nconst allItems = $input.all();\nconsole.log(\"Number of items:\", allItems.length);\n\n// First item contains enrichmentsResponse array\nconst enrichmentsArray = allItems[0]?.json?.enrichmentsResponse || [];\nconst enrichedData = allItems[0]?.json?.enriched_data?.[0]?.data;\n\n// Second item contains events\nconst eventsData = allItems[1]?.json?.output_events || [];\n\nconsole.log(\"Number of enrichments:\", enrichmentsArray.length);\nconsole.log(\"Number of events:\", eventsData.length);\n\n// Extract each enrichment by type\nconst firmographics = enrichmentsArray.find(e => e.enrichment_type === \"firmographics\")?.response?.data?.[0]?.data;\nconst websiteChanges = enrichmentsArray.find(e => e.enrichment_type === \"website_changes\")?.response?.data || [];\nconst technographics = enrichmentsArray.find(e => e.enrichment_type === \"technographics\")?.response?.data?.[0]?.data;\n\nconsole.log(\"Company:\", firmographics?.name);\nconsole.log(\"Website changes:\", websiteChanges.length);\nconsole.log(\"Tech stack items:\", technographics?.full_tech_stack?.length);\n\nconst structuredInput = {\n company_profile: {\n name: firmographics?.name || \"Unknown\",\n description: firmographics?.business_description || \"\",\n website: firmographics?.website || \"\",\n industry: firmographics?.linkedin_industry_category || \"\",\n employees: firmographics?.number_of_employees_range || \"\",\n revenue: firmographics?.yearly_revenue_range || \"\",\n headquarters: `${firmographics?.city_name || \"\"}, ${firmographics?.region_name || \"\"}, ${firmographics?.country_name || \"\"}`,\n ticker: firmographics?.ticker || \"\",\n linkedin: firmographics?.linkedin_profile || \"\",\n logo: firmographics?.business_logo || \"\"\n },\n \n recent_website_changes: websiteChanges.map(change => ({\n what_changed: change.data?.change_description || \"\",\n business_implication: change.data?.change_implication || \"\",\n detected_date: change.data?.date || \"\",\n url: change.data?.url || \"\"\n })),\n \n technology_stack: {\n full_stack: technographics?.full_tech_stack || [],\n by_category: technographics?.full_nested_tech_stack || [],\n bi_and_analytics: technographics?.bi_and_analytics || [],\n sales: technographics?.sales || [],\n marketing: technographics?.marketing || []\n },\n \n recent_events: eventsData.map(event => ({\n event_type: event.event_name || \"\",\n date: event.event_time || \"\",\n description: event.data?.description || event.data?.product_description || event.data?.award_reason || \"\",\n details: event.data || {}\n }))\n};\n\nconsole.log(\"Structured data created successfully\");\n\nreturn [{ json: structuredInput }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 784, 208 ], "id": "9c41ad79-243e-4eb1-a5c8-ada8780d1537", "name": "Cleans Merge Data Output" }, { "parameters": { "authentication": "oAuth2", "select": "user", "user": { "__rl": true, "value": "U08ANQUFTB6", "mode": "list", "cachedResultName": "jordan.golan" }, "text": "={{ $json.doc_content }}\n{{ $json.attendee_doc_content }}", "otherOptions": {} }, "type": "n8n-nodes-base.slack", "typeVersion": 2.3, "position": [ 400, 960 ], "id": "4ab5c1cb-e4b6-4834-a4af-d093ded1896c", "name": "Send a message", "webhookId": "e9fda820-3023-4196-a35d-8970d79953cb" }, { "parameters": { "jsCode": "const items = $input.all();\nconst allEmails = [];\n\nitems.forEach(item => {\n const externalAttendees = item.json.external_attendees || [];\n externalAttendees.forEach(attendee => {\n allEmails.push(attendee.email);\n });\n});\n\nconsole.log(\"Total external attendees:\", allEmails.length);\n\nreturn allEmails.map(email => ({ json: { email: email } }));" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -560, 1344 ], "id": "8acb5614-6ed8-4828-a8b6-b7f90274e197", "name": "Create List of All External Attendees" }, { "parameters": { "jsCode": "// Get all items\nconst allItems = $input.all();\nconsole.log(\"Number of items:\", allItems.length);\n\n// First item contains enrichmentsResponse array\nconst enrichmentsArray = allItems[0]?.json?.enrichmentsResponse || [];\nconsole.log(\"Number of enrichments:\", enrichmentsArray.length);\n\n// Extract each enrichment by type\nconst profileEnrichment = enrichmentsArray.find(e => e.enrichment_type === \"profiles\")?.response?.data?.[0]?.data;\nconst contactsEnrichment = enrichmentsArray.find(e => e.enrichment_type === \"contacts\")?.response?.data?.[0]?.data;\nconst postsEnrichment = enrichmentsArray.find(e => e.enrichment_type === \"linkedin_posts\")?.response?.data || [];\n\n// Use contacts for email/phone, profiles for other data\nconst profileData = profileEnrichment || contactsEnrichment;\nconst contactData = contactsEnrichment;\n\nconsole.log(\"Person:\", profileData?.full_name);\nconsole.log(\"LinkedIn posts:\", postsEnrichment.length);\n\n// Get current role (the one marked as primary or most recent)\nconst currentRole = profileData?.experience?.find(exp => exp.is_primary) || profileData?.experience?.[0];\n\nconst structuredInput = {\n personal_info: {\n name: profileData?.full_name || \"Unknown\",\n location: `${profileData?.city || \"\"}, ${profileData?.region_name || \"\"}, ${profileData?.country_name || \"\"}`.trim().replace(/^,\\s*|,\\s*$/g, ''),\n linkedin: profileData?.linkedin || \"\",\n age_group: profileData?.age_group || \"\",\n gender: profileData?.gender || \"\"\n },\n \n contact_info: {\n email: contactData?.professions_email || \"\",\n email_status: contactData?.professional_email_status || \"\",\n all_emails: contactData?.emails || [],\n mobile_phone: contactData?.mobile_phone || \"\",\n all_phones: contactData?.phone_numbers || []\n },\n \n current_role: {\n title: currentRole?.title?.name || profileData?.job_title || \"\",\n company: currentRole?.company?.name || profileData?.company_name || \"\",\n company_website: currentRole?.company?.website || profileData?.company_website || \"\",\n company_linkedin: profileData?.company_linkedin || \"\",\n department: profileData?.job_department || \"\",\n seniority: profileData?.job_seniority_level || \"\",\n start_date: currentRole?.start_date || \"\",\n summary: currentRole?.summary || \"\"\n },\n \n career_history: (profileData?.experience || [])\n .filter(exp => !exp.is_primary) // Exclude current role\n .map(exp => ({\n title: exp.title?.name || \"\",\n company: exp.company?.name || \"\",\n company_website: exp.company?.website || \"\",\n start_date: exp.start_date || \"\",\n end_date: exp.end_date || \"\",\n summary: exp.summary || \"\"\n })),\n \n education: (profileData?.education || []).map(edu => ({\n school: edu.school?.name || \"School information not available\",\n degrees: edu.degrees || [],\n majors: edu.majors || [],\n start_date: edu.start_date || \"\",\n end_date: edu.end_date || \"\"\n })),\n \n skills: profileData?.skills || [],\n \n recent_linkedin_activity: postsEnrichment.map(post => ({\n text: post.data?.post_text || \"\",\n date: post.data?.created_at || \"\",\n days_ago: post.data?.days_since_posted || 0,\n engagement: {\n likes: post.data?.number_of_likes || 0,\n comments: post.data?.number_of_comments || 0\n },\n url: post.data?.post_url || \"\"\n }))\n};\n\nconsole.log(\"Structured data for:\", structuredInput.personal_info.name);\nconsole.log(\"Email:\", structuredInput.contact_info.email);\nconsole.log(\"Current role:\", structuredInput.current_role.title);\n\nreturn [{ json: structuredInput }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1280, 1232 ], "id": "6ca05ac5-2088-4ae8-bab8-64c6f043854d", "name": "Cleans Enrichment Outputs" }, { "parameters": { "jsCode": "// Formats structured output for Google Docs with title and bold sections\nconst rawData = $input.item.json;\nconst data = Array.isArray(rawData) ? rawData[0].output : (rawData.output || rawData);\n\n// Extract company name from first bullet of company overview or use a passed parameter\nlet companyName = 'Sales Research'; // Default fallback\nif (data.company_overview && data.company_overview.length > 0) {\n // Try to extract company name from first sentence\n const firstItem = data.company_overview[0];\n const match = firstItem.match(/^([A-Z][a-zA-Z\\s&]+?)(?:\\s+is|\\s+operates|\\s+with|\\s+-)/);\n if (match) {\n companyName = match[1].trim();\n }\n}\n\n// Extract domain from calendar event\nlet domain = '';\ntry {\n const calendarEvent = $('Loop Over Items').first().json;\n // Get first domain from company_domains array\n if (calendarEvent.company_domains && calendarEvent.company_domains.length > 0) {\n domain = calendarEvent.company_domains[0];\n }\n} catch (error) {\n console.log('Could not extract domain:', error);\n}\n\nlet docContent = '';\n\n// Add title with visual emphasis (Google Docs doesn't support direct markdown)\ndocContent += '═══════════════════════════════════════\\n';\n// docContent += `${companyName.toUpperCase()}\\n`;\ndocContent += `${$('Loop Over Items').first().json.summary.toUpperCase()}\\n`;\ndocContent += '═══════════════════════════════════════\\n\\n';\n\n// Helper function to safely add section with bold-style headers\nfunction addSection(title, items) {\n if (items && Array.isArray(items) && items.length > 0) {\n docContent += `━━━ ${title.toUpperCase()} ━━━\\n`;\n items.forEach(item => {\n docContent += `• ${item}\\n`;\n });\n docContent += '\\n';\n }\n}\n\naddSection('Company Overview', data.company_overview);\naddSection('Website Changes', data.website_changes);\naddSection('Tech Stack & Product Focus', data.tech_stack_product_focus);\naddSection('Potential Pain Points', data.potential_pain_points);\n\n// Handle nested explorium_opportunity object\nif (data.explorium_opportunity) {\n docContent += '━━━ EXPLORIUM OPPORTUNITY ━━━\\n';\n \n if (data.explorium_opportunity.relevance && data.explorium_opportunity.relevance.length > 0) {\n docContent += '→ Why Explorium is relevant:\\n';\n data.explorium_opportunity.relevance.forEach(item => {\n docContent += `• ${item}\\n`;\n });\n }\n \n if (data.explorium_opportunity.resonant_capabilities && data.explorium_opportunity.resonant_capabilities.length > 0) {\n docContent += '\\n→ Best Fit Capabilities:\\n';\n data.explorium_opportunity.resonant_capabilities.forEach(item => {\n docContent += `• ${item}\\n`;\n });\n }\n docContent += '\\n';\n}\n\naddSection('Conversation Starters', data.conversation_starters);\n\nreturn [{\n json: {\n doc_content: docContent,\n company_name: companyName,\n domain: domain // Added domain key\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1472, 576 ], "id": "bb9c7378-3e2b-4110-8ccd-ee1e7b877090", "name": "Create Company Research Output" }, { "parameters": { "jsCode": "// Formats attendee research as subsection for Google Docs\nconst rawData = $input.first().json;\nconst data = Array.isArray(rawData) ? rawData[0].output : (rawData.output || rawData);\n\n// Extract domain from the Extract External Company Domains1 node\nlet domain = '';\ntry {\n domain = $('Extract External Company Domains1').first().json.domain || '';\n} catch (error) {\n console.log('Could not extract domain:', error);\n}\n\nlet docContent = '';\n\n// Add attendee name as subsection title\ndocContent += `\\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\\n`;\ndocContent += `ATTENDEE: ${data.attendee_name.toUpperCase()}\\n`;\ndocContent += `▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\\n\\n`;\n\n// Background section\nif (data.background) {\n docContent += '━━━ Background ━━━\\n';\n \n if (data.background.current_role && data.background.current_role.length > 0) {\n docContent += '→ Current Role:\\n';\n data.background.current_role.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n }\n \n if (data.background.previous_experience && data.background.previous_experience.length > 0) {\n docContent += '→ Previous Experience:\\n';\n data.background.previous_experience.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n }\n \n if (data.background.education && data.background.education.length > 0) {\n docContent += '→ Education:\\n';\n data.background.education.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n }\n \n docContent += '\\n';\n}\n\n// Recent Activity & Interests\nif (data.recent_activity_interests && data.recent_activity_interests.length > 0) {\n docContent += '━━━ Recent Activity & Interests ━━━\\n';\n data.recent_activity_interests.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n docContent += '\\n';\n}\n\n// Conversation Angles\nif (data.conversation_angles && data.conversation_angles.length > 0) {\n docContent += '━━━ Conversation Angles ━━━\\n';\n data.conversation_angles.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n docContent += '\\n';\n}\n\n// How to Approach\nif (data.how_to_approach) {\n docContent += '━━━ How to Approach ━━━\\n';\n \n if (data.how_to_approach.pain_points && data.how_to_approach.pain_points.length > 0) {\n docContent += '→ Likely Pain Points:\\n';\n data.how_to_approach.pain_points.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n }\n \n if (data.how_to_approach.relevant_capabilities && data.how_to_approach.relevant_capabilities.length > 0) {\n docContent += '→ Relevant Explorium Capabilities:\\n';\n data.how_to_approach.relevant_capabilities.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n }\n \n if (data.how_to_approach.conversation_starters && data.how_to_approach.conversation_starters.length > 0) {\n docContent += '→ Opening Conversation Starters:\\n';\n data.how_to_approach.conversation_starters.forEach(item => {\n docContent += ` • ${item}\\n`;\n });\n }\n \n docContent += '\\n';\n}\n\nreturn [{\n json: {\n attendee_doc_content: docContent, // Changed from doc_content\n attendee_name: data.attendee_name,\n domain: domain\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2032, 1472 ], "id": "00407b13-08ba-4809-a641-4d205c07d439", "name": "Create Attendee Research Output" }, { "parameters": { "promptType": "define", "text": "={{ JSON.stringify($json, null, 2) }}\n\nGenerate a sales research brief for this company using the format specified in your system instructions.", "hasOutputParser": true, "options": { "systemMessage": "=You are a sales research assistant for Explorium.ai using the Explorium Business Data Hub MCP tools.\n\n## MISSION\nResearch companies to provide actionable insights that help sales reps prepare for meetings.\n\n## ABOUT EXPLORIUM AGENTSOURCE\n**Positioning:** \"The B2B data foundation for AI agents\" - purpose-built APIs and infrastructure empowering context-aware GTM agents and AI-powered products.\n\n**Key Differentiators:**\n- 146M+ business entities, 767M+ professional profiles, 4000+ data signals from 50+ sources\n- Unified API with MCP (Model Context Protocol) and SSE (Server-Sent Events) for real-time agent integration\n- Natural language data queries - agents can ask questions in plain English\n- Real-time market signals and event-driven triggers (funding, product launches, hiring)\n- Structured, harmonized, high-quality data vs web scraping\n- Pay-as-you-go flexibility with free developer tier\n\n**AgentSource API Suite:**\n1. **Match API** - Precise business identification\n2. **Enrich API** - Multi-source firmographics, technographics, contacts, signals\n3. **Fetch API** - Identify companies with customizable filters\n4. **Event API** - Real-time GTM triggers with push notifications\n5. **Chat API (Beta)** - Natural language custom data pipelines\n6. **MCP Server** - Seamless agent connectivity\n\n## OUTPUT FORMAT\nProvide clear, actionable bullet points organized by topic:\n\n**Company Overview**\n{Company Data}\n\n**Website Changes**\n- {Website Changes}\n\n**Tech Stack & Product Focus**\n- {Technographics}\n\n**Potential Pain Points**\n- {Business Challenges}\n\n**Explorium Opportunity**\n- [Why Explorium is relevant to them]\n- [Which capabilities would resonate most]\n\n**Conversation Starters**\n- [Specific topics or recent events to reference in the meeting]\n\nKeep bullets concise, specific, and actionable. Focus on recent, relevant information." } }, "type": "@n8n/n8n-nodes-langchain.agent", "typeVersion": 2.2, "position": [ 1008, 208 ], "id": "a188f410-a377-43cf-837c-afec16fa4f86", "name": "Company Research Agent" }, { "parameters": { "promptType": "define", "text": "=Research this meeting attendee to help prepare for an upcoming conversation:\n\n{{ JSON.stringify($json, null, 2) }}\n\nGenerate an attendee research brief following the output format in your system instructions.\n\nKey areas to analyze:\n1. Their career progression and current responsibilities\n2. What their LinkedIn activity reveals about their interests and priorities\n3. Potential pain points in their role that Explorium could address\n4. Personal connection points (education, interests, previous companies)\n5. How to start a conversation that resonates with them\n\nMake this immediately useful for a sales rep meeting this person.", "hasOutputParser": true, "options": { "systemMessage": "=You are a sales research assistant preparing background research on meeting attendees for Explorium.ai sales reps.\n\n## MISSION\nResearch individuals to provide actionable insights that help sales reps build rapport and have informed, personalized conversations.\n\n## OUTPUT FORMAT\nProvide clear, actionable bullet points organized by topic:\n\n**Title**\n- {Attendee Name}\n\n**Background**\n- {Current role, tenure, department}\n- {Previous relevant experience}\n- {Education highlights}\n\n**Recent Activity & Interests**\n- {LinkedIn posts themes and engagement}\n- {Professional interests and focus areas}\n\n**Conversation Angles**\n- {Shared connections or interests}\n- {Recent projects or initiatives they've mentioned}\n- {Topics they care about based on posts/activity}\n\n**How to Approach**\n- {Their likely pain points based on role}\n- {Explorium capabilities relevant to their responsibilities}\n- {Opening conversation starters}\n\nKeep bullets concise and actionable. Focus on what's relevant for building rapport and understanding their role/needs." } }, "type": "@n8n/n8n-nodes-langchain.agent", "typeVersion": 2.2, "position": [ 1584, 1232 ], "id": "1aacbe27-db8f-4b35-a88c-3581ec286fd6", "name": "Attendee Research Agent" }, { "parameters": { "operation": "enrich", "type": "prospects", "enrichment": [ "contacts", "linkedin_posts", "profiles" ], "prospect_ids": { "prospect_ids": [ { "id": "={{ $json.matched_prospects[0].prospect_id }}" } ] } }, "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode", "typeVersion": 1, "position": [ 912, 1184 ], "id": "309fe3b2-e15d-4dc7-aaaf-478ed6afc3e3", "name": "Explorium API: Prospect Enrich" }, { "parameters": { "operation": "enrich", "enrichment": [ "firmographics", "technographics" ], "business_ids": { "business_ids": [ { "id": "={{ $json.matched_businesses[0].business_id }}" } ] } }, "type": "@exploriumai/n8n-nodes-explorium-ai.exploriumApiNode", "typeVersion": 1, "position": [ 336, 80 ], "id": "1d31092a-d1f0-413e-87ba-81d4282d0e3d", "name": "Explorium API: Business Enrich" }, { "parameters": { "content": "# Research Agent\n\n## How it works\nThis workflow automatically prepares you for your upcoming meetings each morning. It scans your calendar for external meetings, identifies the companies and attendees you're meeting with, then generates comprehensive research briefs. For each company, it pulls firmographics, tech stack, recent events, and website changes. For each attendee, it gathers their background, LinkedIn activity, and conversation angles. All research is delivered to Slack before your first meeting.\n\n## Setup steps\n1. Connect your Google Calendar (or Outlook)\n2. Add Explorium credentials (Match, Enrich, Events nodes, two MCP tools)\n3. Connect Anthropic API key (two Chat Model nodes)\n4. Connect Slack account for research delivery (or other preferred output)\n5. Update the domain filter in \"Filter for External Meetings\" node (replace 'explorium.ai' with your company domain)\n6. Set your preferred schedule (default: every morning)", "height": 496, "width": 576 }, "type": "n8n-nodes-base.stickyNote", "position": [ -1408, 128 ], "typeVersion": 1, "id": "cbe0a252-acd3-4e79-8ee7-c0e916152d4c", "name": "Sticky Note3" }, { "parameters": { "content": "## Read Daily Calendar\nPulls today's calendar events and filters for meetings with external attendees (non-company domains).", "height": 128, "width": 288, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ -1088, 944 ], "typeVersion": 1, "id": "3ece9b55-141d-4abf-a692-189e02bf9f08", "name": "Sticky Note2" }, { "parameters": { "content": "## Enrich Company Data\nMatches company domains to Explorium's database, enriches with firmographics and tech stack, and. fetches recent events.", "height": 128, "width": 400, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ -160, 16 ], "typeVersion": 1, "id": "76236d28-1b3f-48cb-970b-40acaebc190c", "name": "Sticky Note7" }, { "parameters": { "content": "## Research Company\ngenerates AI-powered company briefings highlighting pain points and Explorium fit using enrich data and the Explorium MCP", "height": 128, "width": 400, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ 944, 48 ], "typeVersion": 1, "id": "87f6cbf7-eb68-47ad-850c-42b8f0b23b5d", "name": "Sticky Note10" }, { "parameters": { "content": "## Enrich Prospect Data\nMatches meeting attendees by email, and enriches with contact information professional profiles and recent LinkedIn posts", "height": 128, "width": 368, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ 464, 1392 ], "typeVersion": 1, "id": "6a8756f9-ac8e-4f57-8562-38275a744765", "name": "Sticky Note4" }, { "parameters": { "content": "## Attendee Research\nGenerates personalized briefings with conversation starters and relevant talking points for each attendee using enrich input data and the Explorium MCP.", "height": 128, "width": 384, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ 1520, 1088 ], "typeVersion": 1, "id": "92e6f07a-f782-45f8-a301-2f2ed34cdd0d", "name": "Sticky Note8" }, { "parameters": { "content": "## Deliver to Slack\nFormats research into readable briefings and sends to your Slack DMs before meetings start.", "height": 128, "width": 288, "color": 7 }, "type": "n8n-nodes-base.stickyNote", "position": [ 560, 896 ], "typeVersion": 1, "id": "cb411e8c-f1a0-44f2-a959-742abbb14253", "name": "Sticky Note5" }, { "parameters": { "endpointUrl": "https://mcp-n8n.explorium.ai/mcp", "authentication": "headerAuth", "options": {} }, "type": "@n8n/n8n-nodes-langchain.mcpClientTool", "typeVersion": 1.2, "position": [ 1600, 1456 ], "id": "546d68b3-923f-47a5-9fc3-5c41b526271b", "name": "Explorium MCP1", "credentials": { "httpHeaderAuth": {} } }, { "parameters": { "endpointUrl": "https://mcp-n8n.explorium.ai/mcp", "authentication": "headerAuth", "options": {} }, "type": "@n8n/n8n-nodes-langchain.mcpClientTool", "typeVersion": 1.2, "position": [ 1072, 432 ], "id": "3de4986c-afd5-455c-84ef-7bfc8f8528cc", "name": "Explorium MCP", "credentials": { "httpHeaderAuth": {} } } ], "pinData": {}, "connections": { "Get many events": { "main": [ [ { "node": "Filter for External Meetings", "type": "main", "index": 0 } ] ] }, "Loop Over Items": { "main": [ [ { "node": "Merge2", "type": "main", "index": 0 } ], [ { "node": "Extract External Company Domains", "type": "main", "index": 0 } ] ] }, "Extract External Company Domains": { "main": [ [ { "node": "Explorium API: Match Business", "type": "main", "index": 0 } ] ] }, "Explorium API: Match Business": { "main": [ [ { "node": "If", "type": "main", "index": 0 } ] ] }, "Merge": { "main": [ [ { "node": "Cleans Merge Data Output", "type": "main", "index": 0 } ] ] }, "Anthropic Chat Model": { "ai_languageModel": [ [ { "node": "Company Research Agent", "type": "ai_languageModel", "index": 0 } ] ] }, "Explorium API: Match Prospect": { "main": [ [ { "node": "If1", "type": "main", "index": 0 } ] ] }, "Explorium API: Fetch Business Events": { "main": [ [ { "node": "Merge", "type": "main", "index": 1 } ] ] }, "Anthropic Chat Model1": { "ai_languageModel": [ [ { "node": "Attendee Research Agent", "type": "ai_languageModel", "index": 0 } ] ] }, "If": { "main": [ [ { "node": "Explorium API: Fetch Business Events", "type": "main", "index": 0 }, { "node": "Explorium API: Business Enrich", "type": "main", "index": 0 } ], [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "If1": { "main": [ [ { "node": "Explorium API: Prospect Enrich", "type": "main", "index": 0 } ], [ { "node": "Loop Over Items2", "type": "main", "index": 0 } ] ] }, "Structured Output Parser": { "ai_outputParser": [ [ { "node": "Company Research Agent", "type": "ai_outputParser", "index": 0 } ] ] }, "Structured Output Parser1": { "ai_outputParser": [ [ { "node": "Attendee Research Agent", "type": "ai_outputParser", "index": 0 } ] ] }, "Loop Over Items2": { "main": [ [ { "node": "Merge2", "type": "main", "index": 1 } ], [ { "node": "Extract External Company Domains1", "type": "main", "index": 0 } ] ] }, "Merge2": { "main": [ [ { "node": "Loop Over Items1", "type": "main", "index": 0 } ] ] }, "Extract External Company Domains1": { "main": [ [ { "node": "Explorium API: Match Business1", "type": "main", "index": 0 } ] ] }, "Explorium API: Match Business1": { "main": [ [ { "node": "Explorium API: Match Prospect", "type": "main", "index": 0 } ] ] }, "Loop Over Items1": { "main": [ [], [ { "node": "Send a message", "type": "main", "index": 0 } ] ] }, "Schedule Trigger": { "main": [ [ { "node": "Get many events", "type": "main", "index": 0 } ] ] }, "Filter for External Meetings": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 }, { "node": "Create List of All External Attendees", "type": "main", "index": 0 } ] ] }, "Cleans Merge Data Output": { "main": [ [ { "node": "Company Research Agent", "type": "main", "index": 0 } ] ] }, "Send a message": { "main": [ [ { "node": "Loop Over Items1", "type": "main", "index": 0 } ] ] }, "Create List of All External Attendees": { "main": [ [ { "node": "Loop Over Items2", "type": "main", "index": 0 } ] ] }, "Cleans Enrichment Outputs": { "main": [ [ { "node": "Attendee Research Agent", "type": "main", "index": 0 } ] ] }, "Create Company Research Output": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Create Attendee Research Output": { "main": [ [ { "node": "Loop Over Items2", "type": "main", "index": 0 } ] ] }, "Company Research Agent": { "main": [ [ { "node": "Create Company Research Output", "type": "main", "index": 0 } ] ] }, "Attendee Research Agent": { "main": [ [ { "node": "Create Attendee Research Output", "type": "main", "index": 0 } ] ] }, "Explorium API: Prospect Enrich": { "main": [ [ { "node": "Cleans Enrichment Outputs", "type": "main", "index": 0 } ] ] }, "Explorium API: Business Enrich": { "main": [ [ { "node": "Merge", "type": "main", "index": 0 } ] ] }, "Explorium MCP1": { "ai_tool": [ [ { "node": "Attendee Research Agent", "type": "ai_tool", "index": 0 } ] ] }, "Explorium MCP": { "ai_tool": [ [ { "node": "Company Research Agent", "type": "ai_tool", "index": 0 } ] ] } }, "active": false, "settings": { "executionOrder": "v1" }, "versionId": "", "meta": { "templateCredsSetupCompleted": true, "instanceId": "0a70652f43c1b29dd16c35b61a38fd31c8004f58bc7e723bf43262a797407c77" }, "tags": [] }