{
  "id": "OS0DM1wf2h0qBhUA",
  "name": "Conference Synthetic Personas Generator TEMPLATE",
  "tags": [],
  "nodes": [
    {
      "id": "a21ef05a-1d8c-44ea-b16d-809809c0c8a7",
      "name": "Receive Slash Command",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1216,
        448
      ],
      "parameters": {
        "path": "doppelganger",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "cd617b17-9a95-48e2-84e8-fe2762408762",
      "name": "Acknowledge Slack Command",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1008,
        368
      ],
      "parameters": {
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        },
        "respondWith": "text",
        "responseBody": "=\ud83e\uddec Generating Digital Doppelg\u00e4ngers for *{{ $json.body.text }}*... This may take a minute."
      },
      "typeVersion": 1.1
    },
    {
      "id": "2d203524-3225-42af-b74c-e181b7358542",
      "name": "Parse Command Args",
      "type": "n8n-nodes-base.code",
      "position": [
        -1008,
        528
      ],
      "parameters": {
        "jsCode": "// Parse slash command: /doppelganger <event_name> <count> <source>\n// Example: /doppelganger \"TechConf 2026\" 5 hubspot\nconst text = $input.first().json.body?.text || '';\nconst channelId = $input.first().json.body?.channel_id || '';\nconst userId = $input.first().json.body?.user_id || '';\n\n// Parse arguments \u2014 supports quoted event names\nconst quotedMatch = text.match(/^\"([^\"]+)\"\\s+(\\d+)?\\s*(\\w+)?$/);\nconst simpleMatch = text.match(/^(\\S+)\\s+(\\d+)?\\s*(\\w+)?$/);\n\nlet eventName, personaCount, crmSource;\n\nif (quotedMatch) {\n  eventName = quotedMatch[1];\n  personaCount = parseInt(quotedMatch[2] || '5', 10);\n  crmSource = (quotedMatch[3] || 'sheets').toLowerCase();\n} else if (simpleMatch) {\n  eventName = simpleMatch[1];\n  personaCount = parseInt(simpleMatch[2] || '5', 10);\n  crmSource = (simpleMatch[3] || 'sheets').toLowerCase();\n} else {\n  eventName = text.trim() || 'Unnamed Event';\n  personaCount = 5;\n  crmSource = 'sheets';\n}\n\n// Clamp persona count to 3-10 range\npersonaCount = Math.max(3, Math.min(10, personaCount));\n\n// Validate CRM source\nconst validSources = ['hubspot', 'salesforce', 'sheets'];\nif (!validSources.includes(crmSource)) {\n  crmSource = 'sheets';\n}\n\nreturn [{\n  json: {\n    eventName,\n    personaCount,\n    crmSource,\n    channelId,\n    userId,\n    requestedAt: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "cc5b24c7-ca6e-407d-82e4-ecdb32896bbb",
      "name": "Route by CRM Source",
      "type": "n8n-nodes-base.switch",
      "position": [
        -720,
        512
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "HubSpot",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.crmSource }}",
                    "rightValue": "hubspot"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Salesforce",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.crmSource }}",
                    "rightValue": "salesforce"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Google Sheets",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.crmSource }}",
                    "rightValue": "sheets"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "allMatchingOutputs": false
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "99f98c74-56a2-48ed-9e2e-625d456d237a",
      "name": "Fetch HubSpot Contacts",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -480,
        320
      ],
      "parameters": {
        "url": "https://api.hubapi.com/crm/v3/objects/contacts/search",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"filterGroups\": [{\n    \"filters\": [{\n      \"propertyName\": \"event_tag\",\n      \"operator\": \"EQ\",\n      \"value\": \"{{ $('Parse Command Args').item.json.eventName }}\"\n    }]\n  }],\n  \"properties\": [\"firstname\", \"lastname\", \"jobtitle\", \"company\", \"industry\", \"city\", \"country\", \"notes_last_contacted\"],\n  \"limit\": 100\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "9b9bb280-37aa-4f22-a894-15269df30c7b",
      "name": "Fetch Salesforce Contacts",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -480,
        512
      ],
      "parameters": {
        "url": "={{ $('Parse Command Args').item.json.sfInstanceUrl || 'https://yourinstance.salesforce.com' }}/services/data/v59.0/query",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "=SELECT FirstName, LastName, Title, Account.Name, Account.Industry, MailingCity, MailingCountry FROM CampaignMember WHERE Campaign.Name = '{{ $('Parse Command Args').item.json.eventName }}'"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "82281f12-bcbd-468c-aa1e-c8219b648f8d",
      "name": "Fetch Google Sheets Contacts",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -480,
        720
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "PLACEHOLDER_AUDIENCE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "07e135ad-53f1-41bf-8612-084ac75511d3",
      "name": "Normalize Audience Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -240,
        512
      ],
      "parameters": {
        "jsCode": "// Normalize audience data from any CRM source into a common format\nconst source = $('Parse Command Args').first().json.crmSource;\nconst items = $input.all();\n\nlet attendees = [];\n\nif (source === 'hubspot') {\n  const results = items[0]?.json?.results || items.map(i => i.json);\n  attendees = results.map(r => ({\n    name: [r.properties?.firstname, r.properties?.lastname].filter(Boolean).join(' ') || 'Unknown',\n    title: r.properties?.jobtitle || '',\n    company: r.properties?.company || '',\n    industry: r.properties?.industry || '',\n    location: [r.properties?.city, r.properties?.country].filter(Boolean).join(', ')\n  }));\n} else if (source === 'salesforce') {\n  const records = items[0]?.json?.records || items.map(i => i.json);\n  attendees = records.map(r => ({\n    name: [r.FirstName, r.LastName].filter(Boolean).join(' ') || 'Unknown',\n    title: r.Title || '',\n    company: r.Account?.Name || '',\n    industry: r.Account?.Industry || '',\n    location: [r.MailingCity, r.MailingCountry].filter(Boolean).join(', ')\n  }));\n} else {\n  // Google Sheets \u2014 expects columns: Name, Title, Company, Industry, Location\n  attendees = items.map(i => ({\n    name: i.json.Name || i.json.name || 'Unknown',\n    title: i.json.Title || i.json.title || i.json['Job Title'] || '',\n    company: i.json.Company || i.json.company || i.json.Organization || '',\n    industry: i.json.Industry || i.json.industry || '',\n    location: i.json.Location || i.json.location || i.json.City || ''\n  }));\n}\n\n// Build audience summary for AI\nconst totalCount = attendees.length;\nconst titles = attendees.map(a => a.title).filter(Boolean);\nconst companies = attendees.map(a => a.company).filter(Boolean);\nconst industries = attendees.map(a => a.industry).filter(Boolean);\n\nconst titleCounts = {};\ntitles.forEach(t => { titleCounts[t] = (titleCounts[t] || 0) + 1; });\nconst industryCounts = {};\nindustries.forEach(i => { industryCounts[i] = (industryCounts[i] || 0) + 1; });\n\nreturn [{\n  json: {\n    totalAttendees: totalCount,\n    topTitles: Object.entries(titleCounts).sort((a,b) => b[1]-a[1]).slice(0, 15).map(([k,v]) => `${k} (${v})`).join(', '),\n    topIndustries: Object.entries(industryCounts).sort((a,b) => b[1]-a[1]).slice(0, 10).map(([k,v]) => `${k} (${v})`).join(', '),\n    uniqueCompanies: [...new Set(companies)].length,\n    sampleAttendees: JSON.stringify(attendees.slice(0, 20), null, 2),\n    eventName: $('Parse Command Args').first().json.eventName,\n    personaCount: $('Parse Command Args').first().json.personaCount,\n    crmSource: $('Parse Command Args').first().json.crmSource\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "8a873198-d62d-4482-8f9b-5645bb92ad3a",
      "name": "Generate Persona Archetypes",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        0,
        400
      ],
      "parameters": {},
      "typeVersion": 1.4
    },
    {
      "id": "3836dbe0-8c48-4a9a-8960-e1612f1a5c7e",
      "name": "Google Gemini for Personas",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        0,
        624
      ],
      "parameters": {
        "options": {
          "temperature": 0.8
        },
        "modelName": "models/gemini-2.5-flash-lite"
      },
      "typeVersion": 1
    },
    {
      "id": "20a6ccbc-2ed3-4750-ac1f-c0a3dd5f0ccb",
      "name": "Parse Persona JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        240,
        400
      ],
      "parameters": {
        "jsCode": "// Parse the AI-generated persona JSON from the LLM response\nconst response = $input.first().json.text || $input.first().json.response || '';\n\n// Extract JSON array from response (handle markdown code blocks)\nlet jsonStr = response;\nconst jsonMatch = response.match(/\\[\\s*\\{[\\s\\S]*\\}\\s*\\]/);\nif (jsonMatch) {\n  jsonStr = jsonMatch[0];\n}\n\nlet personas;\ntry {\n  personas = JSON.parse(jsonStr);\n} catch (e) {\n  // Try to fix common JSON issues\n  jsonStr = jsonStr.replace(/,\\s*\\]/g, ']').replace(/,\\s*\\}/g, '}');\n  personas = JSON.parse(jsonStr);\n}\n\nconst eventName = $('Parse Command Args').first().json.eventName;\nconst channelId = $('Parse Command Args').first().json.channelId;\nconst crmSource = $('Parse Command Args').first().json.crmSource;\n\n// Return each persona as a separate item for the loop\nreturn personas.map((persona, index) => ({\n  json: {\n    ...persona,\n    persona_index: index + 1,\n    persona_total: personas.length,\n    event_name: eventName,\n    channel_id: channelId,\n    crm_source: crmSource,\n    persona_json: JSON.stringify(persona),\n    created_at: new Date().toISOString()\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "0e986611-c7ad-4b75-aebe-b39eb64e7055",
      "name": "Store Persona in Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        480,
        400
      ],
      "parameters": {
        "columns": {
          "value": {
            "industry": "={{ $json.industry }}",
            "created_at": "={{ $json.created_at }}",
            "event_name": "={{ $json.event_name }}",
            "source_crm": "={{ $json.crm_source }}",
            "persona_org": "={{ $json.persona_org }}",
            "persona_json": "={{ $json.persona_json }}",
            "persona_name": "={{ $json.persona_name }}",
            "persona_title": "={{ $json.persona_title }}",
            "slack_channel": "={{ $json.channel_id }}",
            "interview_count": 0,
            "slack_thread_ts": ""
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Personas"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "PLACEHOLDER_DOPPELGANGER_SHEET_ID"
        }
      },
      "typeVersion": 4.5,
      "continueOnFail": true
    },
    {
      "id": "6a6413c9-3eed-4bc3-b35c-56482facd117",
      "name": "Format Persona Card",
      "type": "n8n-nodes-base.code",
      "position": [
        480,
        592
      ],
      "parameters": {
        "jsCode": "// Build Slack Block Kit message for this persona\nconst p = $input.first().json;\n\nconst card = `${p.emoji || '\ud83e\uddec'} *Digital Doppelg\u00e4nger #${p.persona_index}/${p.persona_total}*\n\n*${p.persona_name}* \u2014 ${p.persona_title}\n_${p.persona_org}_ (${p.org_size}) | ${p.industry}\n\n\ud83c\udfaf *Motivation:* ${p.primary_motivation}\n\n\ud83d\ude24 *Pain Points:*\n${(p.pain_points || []).map(pp => '  \u2022 ' + pp).join('\\n')}\n\n\ud83e\udde0 *Decision Style:* ${p.decision_style} | \ud83d\udcb0 *Budget Authority:* ${p.budget_authority}\n\n\ud83e\udd1d *Networking:* ${p.networking_preference}\n\ud83d\udcda *Prefers:* ${(p.content_preferences || []).join(', ')}\n\n\u26a0\ufe0f *Likely Objections:*\n${(p.likely_objections || []).map(o => '  \u2022 ' + o).join('\\n')}\n\n\ud83d\udcca *Predicted Behavior:* ${p.engagement_prediction}\n\n---\n_\ud83d\udcac Reply in this thread to interview ${p.persona_name} \u2014 ask about their preferences, concerns, or what would make this event valuable to them._\n_\ud83e\uddec Synthetic persona generated from aggregate ${p.crm_source} data for \"${p.event_name}\"_`;\n\nreturn [{\n  json: {\n    ...p,\n    slackMessage: card\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f126a2c8-666c-43a7-96fd-8f4dbde6d930",
      "name": "Post Persona to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        720,
        592
      ],
      "parameters": {
        "text": "={{ $json.slackMessage }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.channel_id }}"
        },
        "otherOptions": {
          "unfurl_links": false,
          "unfurl_media": false
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "0a78c4fa-99e4-4c27-8206-a84fa37b4a61",
      "name": "Capture Thread Timestamp",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        592
      ],
      "parameters": {
        "jsCode": "// Capture the Slack message timestamp for interview thread routing\nconst slackResponse = $input.first().json;\nconst threadTs = slackResponse.ts || slackResponse.message?.ts || '';\nconst personaData = $('Format Persona Card').first().json;\n\n// We'll update the Data Table record with the thread_ts\n// For now, store it for the summary\nreturn [{\n  json: {\n    persona_name: personaData.persona_name,\n    thread_ts: threadTs,\n    channel_id: personaData.channel_id,\n    persona_index: personaData.persona_index,\n    persona_total: personaData.persona_total\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f5ed46c9-5d92-4783-9717-4c90f510a117",
      "name": "Run Structured Interview",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1200,
        400
      ],
      "parameters": {},
      "typeVersion": 1.4
    },
    {
      "id": "0e942576-00d3-47f5-a5ea-b0ea6f8cc21a",
      "name": "Google Gemini for Auto-Interview",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1200,
        624
      ],
      "parameters": {
        "options": {
          "temperature": 0.7
        },
        "modelName": "models/gemini-2.5-flash-lite"
      },
      "typeVersion": 1
    },
    {
      "id": "6668db23-49e1-45e0-8b72-835121499589",
      "name": "Format Interview Report",
      "type": "n8n-nodes-base.code",
      "position": [
        1504,
        400
      ],
      "parameters": {
        "jsCode": "// Format the auto-interview response for this persona\nconst interviewResponse = $input.first().json.text || $input.first().json.response || '';\nconst personaData = $('Parse Persona JSON').first().json;\n\nconst report = `\ud83e\uddec *AUTO-INTERVIEW REPORT: ${personaData.persona_name}*\n_${personaData.persona_title} at ${personaData.persona_org}_ (${personaData.org_size}) | ${personaData.industry}\n\n${interviewResponse}\n\n---\n_${personaData.emoji || '\ud83e\uddec'} Digital Doppelg\u00e4nger #${personaData.persona_index}/${personaData.persona_total} | Auto-interview for \"${personaData.event_name}\"_`;\n\nreturn [{\n  json: {\n    report,\n    persona_name: personaData.persona_name,\n    persona_index: personaData.persona_index,\n    persona_total: personaData.persona_total,\n    channel_id: personaData.channel_id,\n    event_name: personaData.event_name\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "6766b486-713a-489b-b4c3-0aad6ee5a081",
      "name": "Post Interview Report to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1680,
        400
      ],
      "parameters": {
        "text": "={{ $json.report }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.channel_id }}"
        },
        "otherOptions": {
          "unfurl_links": false,
          "unfurl_media": false
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d1d6087b-6a0b-4288-bdf0-8f474e38517d",
      "name": "Post Generation Summary",
      "type": "n8n-nodes-base.slack",
      "position": [
        1872,
        400
      ],
      "parameters": {
        "text": "=\u2705 *Digital Doppelg\u00e4nger Report Complete!*\n\n\ud83e\uddec Generated and auto-interviewed *{{ $('Parse Command Args').item.json.personaCount }}* synthetic personas for *{{ $('Parse Command Args').item.json.eventName }}*\n\ud83d\udcca Data source: {{ $('Parse Command Args').item.json.crmSource }}\n\n\ud83d\udccb *14 structured questions per persona covering:*\n  \u2022 Content & Format (3 questions)\n  \u2022 Logistics & Experience (3 questions)\n  \u2022 Networking & Meetings (3 questions)\n  \u2022 ROI & Decision-Making (3 questions)\n  \u2022 Wildcard Insights (2 questions)\n\n\ud83d\udcac *Want to dig deeper?* Reply in any persona card's thread with follow-up questions.\n\n_Powered by Braia Labs | Digital Doppelg\u00e4nger Engine_",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Parse Command Args').item.json.channelId }}"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "sticky-intro-gen",
      "name": "Intro \u2014 Persona Generator",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1904,
        112
      ],
      "parameters": {
        "width": 600,
        "height": 820,
        "content": "## Digital Doppelg\u00e4nger \u2014 Persona Generator\n\n### **What it does:**\nGenerates AI-powered synthetic personas (Digital Doppelg\u00e4ngers) from your CRM attendee data that event teams can interview before the event \u2014 shifting from post-event measurement to pre-event prediction.\n\n### **Why it matters:**\nVOK DAMS' Digital Doppelg\u00e4nger concept lets you test event concepts, content strategies, and networking formats against realistic audience archetypes BEFORE committing resources. Predict what works instead of measuring what didn't.\n\n### **How it works:**\n1. Team runs `/doppelganger \"Event Name\" 5 hubspot` in Slack\n2. Workflow fetches attendee data from CRM (HubSpot, Salesforce, or Google Sheets)\n3. Gemini AI analyzes audience segments and generates synthetic personas\n4. Each persona is posted as a rich card to Slack\n5. Each persona is auto-interviewed with 14 structured questions across 5 categories\n6. Full interview reports are posted to Slack\n7. Team can still reply in persona threads for deeper follow-up questions\n\n### **Setup steps:**\n1. Connect **Slack** OAuth2 credential\n2. Connect **Google Gemini** API credential\n3. Configure CRM credentials (HubSpot API key, Salesforce OAuth, or Google Sheets)\n4. Create a Google Sheet with tabs: `Personas` and `Conversations` \u2014 update the Sheet ID placeholder\n5. Update the audience Google Sheets ID placeholder if using Sheets as CRM data source\n6. Register the `/doppelganger` slash command in your Slack app settings\n7. Set the slash command URL to this webhook's production URL"
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-slash-setup",
      "name": "Section \u2014 Slash Command",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1280,
        112
      ],
      "parameters": {
        "color": 6,
        "width": 484,
        "height": 592,
        "content": "## 1. Slack Slash Command\n\nReceives `/doppelganger` command with args:\n- **Event name** (quoted if spaces)\n- **Persona count** (3-10, default 5)\n- **CRM source** (`hubspot`, `salesforce`, `sheets`)\n\nAcknowledges immediately (Slack 3s timeout) then processes async."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-crm",
      "name": "Section \u2014 CRM Integration",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        112
      ],
      "parameters": {
        "color": 5,
        "width": 672,
        "height": 796,
        "content": "## 2. CRM Data Fetch\n\nRoutes to the correct CRM API based on source parameter:\n- **HubSpot** \u2014 Contact search by event tag\n- **Salesforce** \u2014 SOQL query on CampaignMember\n- **Google Sheets** \u2014 Direct read (CSV import fallback)\n\nAll sources are normalized to a common format for AI analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-ai-gen",
      "name": "Section \u2014 AI Persona Engine",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        112
      ],
      "parameters": {
        "color": 3,
        "width": 460,
        "height": 680,
        "content": "## 3. AI Persona Engine\n\nGoogle Gemini Flash Lite clusters attendee data into distinct archetypes and generates detailed synthetic personas with:\n- Motivations, pain points, decision style\n- Budget authority, networking preferences\n- Content format preferences\n- Likely objections and engagement predictions\n\n**GDPR Safe:** All personas are synthetic \u2014 no real PII is reproduced."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-delivery",
      "name": "Section \u2014 Store & Deliver",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        432,
        112
      ],
      "parameters": {
        "color": 4,
        "width": 680,
        "height": 680,
        "content": "## 4. Store & Deliver\n\nEach persona is:\n1. Stored in the `Digital Doppelg\u00e4ngers` Google Sheet (Personas tab)\n2. Formatted as a rich Slack Block Kit card\n3. Posted to the requesting channel\n\nInterview conversations are also logged to the Conversations tab."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-auto-interview",
      "name": "Section \u2014 Auto-Interview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        112
      ],
      "parameters": {
        "color": 5,
        "width": 944,
        "height": 680,
        "content": "## 5. Structured Auto-Interview\n\nEach persona is automatically interviewed with **14 questions** across 5 categories:\n\n| Category | Questions | Covers |\n|---|---|---|\n| **Content & Format** | Q1-Q3 | Session types, topics, depth |\n| **Logistics & Experience** | Q4-Q6 | Schedule, venue, hybrid |\n| **Networking & Meetings** | Q7-Q9 | Who to meet, formats, value |\n| **ROI & Decision-Making** | Q10-Q12 | Justification, success, objections |\n| **Wildcard** | Q13-Q14 | Pain points, ideal experience |\n\nFull reports are posted to Slack automatically \u2014 no manual questioning needed."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-contact-gen",
      "name": "Contact \u2014 Braia Labs",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2128,
        112
      ],
      "parameters": {
        "width": 560,
        "height": 1176,
        "content": "## Was this helpful? Get in touch!\n\n[![clic](https://vptkuqoipqbebipqjnqw.supabase.co/storage/v1/object/public/Milo%20Bravo/seeAxWUupcOOXY5tntexZ_video.gif)](https://tally.so/r/EkKGgB)\n\nI really hope this automation helped you. Your feedback is incredibly valuable and helps me create better resources for business and the n8n community.\n\n### **Have Feedback, a Question, or a Project Idea?**\n\nI've streamlined the way we connect. It all starts with one simple form that takes less than 10 seconds. After that, you'll chat with my AI assistant who will gather the key details and pass them directly on to me.\n\n####  **[Start the conversation here](https://tally.so/r/EkKGgB)**\n\n*   **Give Feedback:** Share your thoughts on this template\u2014whether you found a typo, encountered an unexpected error, have a suggestion, or just want to say thanks!\n\n*   **n8n Consulting:** Have a complex business challenge or need a custom workflow built from scratch? Let's partner on a powerful automation solution tailored to your specific needs.\n\n*   **Join your team:** We can work together to get you launched with confidence.\n\n---\n\nHappy Automating!\n[Milo Bravo](https://linkedin.com/in/MiloBravo/) | BRaiA Labs | Automation & BI Systems + AI Integration"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "cf9b6e46-6ebc-46c2-87eb-6523efd1eca4",
  "connections": {
    "Parse Command Args": {
      "main": [
        [
          {
            "node": "Route by CRM Source",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Persona JSON": {
      "main": [
        [
          {
            "node": "Store Persona in Google Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Format Persona Card",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Persona Card": {
      "main": [
        [
          {
            "node": "Post Persona to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by CRM Source": {
      "main": [
        [
          {
            "node": "Fetch HubSpot Contacts",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Salesforce Contacts",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Google Sheets Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post Persona to Slack": {
      "main": [
        [
          {
            "node": "Capture Thread Timestamp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Slash Command": {
      "main": [
        [
          {
            "node": "Acknowledge Slack Command",
            "type": "main",
            "index": 0
          },
          {
            "node": "Parse Command Args",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch HubSpot Contacts": {
      "main": [
        [
          {
            "node": "Normalize Audience Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Interview Report": {
      "main": [
        [
          {
            "node": "Post Interview Report to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Audience Data": {
      "main": [
        [
          {
            "node": "Generate Persona Archetypes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Capture Thread Timestamp": {
      "main": [
        [
          {
            "node": "Run Structured Interview",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Structured Interview": {
      "main": [
        [
          {
            "node": "Format Interview Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Salesforce Contacts": {
      "main": [
        [
          {
            "node": "Normalize Audience Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini for Personas": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Persona Archetypes",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate Persona Archetypes": {
      "main": [
        [
          {
            "node": "Parse Persona JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google Sheets Contacts": {
      "main": [
        [
          {
            "node": "Normalize Audience Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post Interview Report to Slack": {
      "main": [
        [
          {
            "node": "Post Generation Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini for Auto-Interview": {
      "ai_languageModel": [
        [
          {
            "node": "Run Structured Interview",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}