{
  "id": "WLR3gtIRSuQet1Ka",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Who Am I Meeting - Research Assistant",
  "tags": [],
  "nodes": [
    {
      "id": "9b47767f-7cc6-4d57-9437-7c03ee5668c1",
      "name": "\ud83d\udccb Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1408,
        160
      ],
      "parameters": {
        "color": 3,
        "width": 580,
        "height": 832,
        "content": "## \ud83d\udd0d Who Am I Meeting \u2014 Research Assistant\n\n### How it works\nThis workflow automatically researches every person you are about to meet by monitoring your Google Calendar for newly created events.\n\n**Step 1 \u2014 Event Detection:** When a new calendar event is created, the workflow checks whether any external attendees are present. Events without attendees are ignored.\n\n**Step 2 \u2014 Info Extraction:** Attendee name and company are extracted from the event data for use in downstream searches.\n\n**Step 3 \u2014 Parallel Web Research:** Two simultaneous Google searches (via SerpAPI) run in parallel \u2014 one for the attendee's personal profile and one for their company. Each set of results is parsed and cleaned by a dedicated JavaScript node.\n\n**Step 4 \u2014 AI Briefing Generation:** Both search result sets are merged and fed into an Azure OpenAI agent, which summarises the person's background and company profile into a concise meeting brief.\n\n**Step 5 \u2014 Slack Delivery:** The briefing is formatted into a readable Slack message and sent as a direct message so you are prepared before the meeting starts.\n\n### Setup steps\n1. Connect **Google Calendar** OAuth2 credentials and set your calendar ID.\n2. Add your **SerpAPI** key to both search nodes.\n3. Connect **Azure OpenAI** credentials (deployment: `gpt-4o-mini`).\n4. Connect **Slack** OAuth2 and replace `YOUR_SLACK_USER_ID` with your real Slack member ID.\n5. Customise the Extract node to pull the correct attendee name and company fields from your calendar events.\n\n### Customization\n- Extend the AI prompt to include talking points or recent news about the company.\n- Add a LinkedIn search query in a third parallel SerpAPI branch for richer profiles."
      },
      "typeVersion": 1
    },
    {
      "id": "71d2751c-0af7-4c8f-afa0-cac4823257e7",
      "name": "Section: Event Detection & Filtering",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        416
      ],
      "parameters": {
        "width": 680,
        "height": 200,
        "content": "## \ud83d\udcc5 Event Detection & Filtering\nPolls Google Calendar every minute for newly created events. Skips any event with no external attendees. Extracts the attendee name and company for downstream research."
      },
      "typeVersion": 1
    },
    {
      "id": "de8ad929-3560-4de7-a01c-a3294d43ec88",
      "name": "Section: Parallel Web Research",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -128,
        304
      ],
      "parameters": {
        "width": 500,
        "height": 502,
        "content": "## \ud83d\udd0e Parallel Web Research\nRuns two SerpAPI Google searches simultaneously \u2014 one for the attendee's personal profile and one for their company. Each result set is parsed and cleaned by a dedicated JavaScript node before being merged."
      },
      "typeVersion": 1
    },
    {
      "id": "a1d8ff35-a6c2-4a50-8052-13a9ba4e7ea0",
      "name": "Section: AI Briefing Generation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        432
      ],
      "parameters": {
        "width": 700,
        "height": 466,
        "content": "## \ud83e\udd16 AI Briefing Generation\nMerges person and company research data, prepares a combined payload, and passes it to the Azure OpenAI agent. The AI produces a concise meeting brief covering background, role, and company context."
      },
      "typeVersion": 1
    },
    {
      "id": "f70a30ae-f091-4a5f-8e2c-0f167cc4ced3",
      "name": "Section: Slack Delivery",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        432
      ],
      "parameters": {
        "width": 460,
        "height": 488,
        "content": "## \ud83d\udce8 Slack Delivery\nFormats the AI-generated brief into a Slack message and delivers it as a direct message to the meeting organiser, ready before the appointment."
      },
      "typeVersion": 1
    },
    {
      "id": "13418674-a3af-4378-a552-412ae8930531",
      "name": "\u26a0\ufe0f Warning: SerpAPI",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -128,
        832
      ],
      "parameters": {
        "color": 2,
        "width": 260,
        "height": 140,
        "content": "\u26a0\ufe0f **SerpAPI Credentials Required**\nBoth search nodes require a valid SerpAPI key. Rate limits apply \u2014 high-volume calendars may exhaust your monthly quota quickly."
      },
      "typeVersion": 1
    },
    {
      "id": "c0a890c8-923a-4c17-9025-f997568a9875",
      "name": "\u26a0\ufe0f Warning: Slack DM Config",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        272
      ],
      "parameters": {
        "color": 2,
        "width": 260,
        "height": 140,
        "content": "\u26a0\ufe0f **Slack Channel Required**\nReplace `YOUR_SLACK_USER_ID` with a real Slack member ID (format: `U0XXXXXXX`). Leaving the placeholder will silently fail to deliver briefings."
      },
      "typeVersion": 1
    },
    {
      "id": "c8733caf-98c8-4d3a-9149-9d4376749f98",
      "name": "New Calendar Event Trigger",
      "type": "n8n-nodes-base.googleCalendarTrigger",
      "position": [
        -720,
        544
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "eventCreated",
        "calendarId": {
          "__rl": true,
          "mode": "list",
          "value": "user@example.com",
          "cachedResultName": "user@example.com"
        }
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4c08919c-56d4-465a-9f6e-6565405a42f8",
      "name": "Filter: Has Attendees",
      "type": "n8n-nodes-base.if",
      "position": [
        -496,
        544
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.attendees.length }}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1f34e7c0-0308-468b-949a-20bb88d616e1",
      "name": "Extract Attendee & Company Info",
      "type": "n8n-nodes-base.set",
      "position": [
        -272,
        544
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "c33b1cba-c54f-4bdd-9385-f6d3dbacf82c",
      "name": "Search Person on Google",
      "type": "n8n-nodes-serpapi.serpApi",
      "position": [
        -48,
        448
      ],
      "parameters": {
        "q": "={{ $json.person.name }}",
        "requestOptions": {},
        "additionalFields": {}
      },
      "credentials": {
        "serpApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4dab762c-e657-421b-8dd9-36a98fa9486b",
      "name": "Search Company on Google",
      "type": "n8n-nodes-serpapi.serpApi",
      "position": [
        -48,
        640
      ],
      "parameters": {
        "q": "={{ $json.company.name }}",
        "requestOptions": {},
        "additionalFields": {}
      },
      "credentials": {
        "serpApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "786579b9-b91f-4954-89c6-34f5ac79778b",
      "name": "Parse Person Search Results",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        448
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "753fef5a-4130-4cae-9778-a7fff361ada8",
      "name": "Parse Company Search Results",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        640
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "70338ed2-139e-40f0-835d-9e1710d60604",
      "name": "Merge Person & Company Data",
      "type": "n8n-nodes-base.merge",
      "position": [
        400,
        544
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "cf1e1a1c-2cd7-4f9d-9a53-ee3e13f8538e",
      "name": "Prepare Combined Research Data",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        544
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n  item.json.myNewField = 1;\n}\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "e4207c66-3454-4e36-924b-12ca6b3a6ad4",
      "name": "AI Meeting Briefing Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        848,
        544
      ],
      "parameters": {
        "text": "Summarise the company and the profile name",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "5758504b-3ef4-40ff-b62d-f4a4cc5bbfd7",
      "name": "Format Slack Briefing Message",
      "type": "n8n-nodes-base.set",
      "position": [
        1200,
        544
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "f16471af-23d0-45a8-a216-07315b9e9d12",
      "name": "Send Briefing via Slack DM",
      "type": "n8n-nodes-base.slack",
      "position": [
        1424,
        544
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "channel": "YOUR_SLACK_USER_ID",
        "attachments": [],
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "89e31858-65a3-4634-8958-1b7705c2bcf8",
      "name": "Azure OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        800,
        736
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "credentials": {
        "azureOpenAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "fde4cee6-35a9-4e8d-b49c-c65db8b1c162",
  "connections": {
    "Filter: Has Attendees": {
      "main": [
        [
          {
            "node": "Extract Attendee & Company Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Person on Google": {
      "main": [
        [
          {
            "node": "Parse Person Search Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Azure OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Meeting Briefing Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Search Company on Google": {
      "main": [
        [
          {
            "node": "Parse Company Search Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Meeting Briefing Agent": {
      "main": [
        [
          {
            "node": "Format Slack Briefing Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Calendar Event Trigger": {
      "main": [
        [
          {
            "node": "Filter: Has Attendees",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Person & Company Data": {
      "main": [
        [
          {
            "node": "Prepare Combined Research Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Person Search Results": {
      "main": [
        [
          {
            "node": "Merge Person & Company Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Company Search Results": {
      "main": [
        [
          {
            "node": "Merge Person & Company Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Format Slack Briefing Message": {
      "main": [
        [
          {
            "node": "Send Briefing via Slack DM",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Combined Research Data": {
      "main": [
        [
          {
            "node": "AI Meeting Briefing Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Attendee & Company Info": {
      "main": [
        [
          {
            "node": "Search Person on Google",
            "type": "main",
            "index": 0
          },
          {
            "node": "Search Company on Google",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}