{
  "nodes": [
    {
      "id": "352d15f6-ecc3-4074-85ab-3b3aa2beb8a2",
      "name": "Sticky Note - Main",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        -624
      ],
      "parameters": {
        "width": 612,
        "height": 1020,
        "content": "## \ud83d\udd17 Send AI-Personalized LinkedIn Connection Requests from Google Sheets\n\n@[youtube](ZCnXr3-W8xs)\n\n### Who is this for?\nSales professionals, recruiters, and founders who want to scale personalized LinkedIn outreach without sounding robotic.\n\n### What this workflow does\n1. **Reads pending prospects** from your Google Sheet\n2. **Fetches LinkedIn profile data** via ConnectSafely.AI API\n3. **Generates personalized messages** using AI (Gemini) based on the prospect's profile\n4. **Sends connection requests** with the personalized message\n5. **Updates your sheet** with the status and message sent\n\n### Requirements\n- [ConnectSafely.AI](https://connectsafely.ai) account with API key\n- Google Sheets with columns: `First Name`, `LinkedIn Url`, `Tagline`, `Status`, `Message`\n- Google Gemini API key\n\n### Setup Instructions\n1. Create a Google Sheet with the required columns\n2. Add your ConnectSafely.AI API key as Bearer Auth credential\n3. Connect your Google Sheets account\n4. Add your Google Gemini API key\n5. Update the Google Sheets nodes to point to your sheet\n6. Customize the AI prompt with your name and context\n\n### How to customize\n- Modify the AI Agent prompt to match your personal brand\n- Adjust the Schedule Trigger interval (default: every minute)\n- Add filters in Google Sheets to target specific prospects"
      },
      "typeVersion": 1
    },
    {
      "id": "82f663c2-1b71-42a0-aa1c-0360ee4a6afa",
      "name": "Sticky Note - Triggers",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        -448
      ],
      "parameters": {
        "color": 6,
        "width": 392,
        "height": 180,
        "content": "### \u26a1 Triggers\nTwo ways to start:\n- **Schedule**: Runs automatically every minute\n- **Manual**: Click to test\n\nThe Wait node adds a random delay (1-5 min) to appear more human."
      },
      "typeVersion": 1
    },
    {
      "id": "088d4542-f0b4-481b-b750-6d820841e8b5",
      "name": "Sticky Note - Sheets",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1680,
        -224
      ],
      "parameters": {
        "color": 6,
        "width": 280,
        "height": 100,
        "content": "### \ud83d\udcca Google Sheets\nFetches one PENDING prospect, marks as IN PROGRESS to prevent duplicates."
      },
      "typeVersion": 1
    },
    {
      "id": "50f4b0db-d609-49f8-beb7-b5e3ae395174",
      "name": "Sticky Note - Profile",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2128,
        -224
      ],
      "parameters": {
        "color": 6,
        "height": 100,
        "content": "### \ud83d\udd0d Profile Lookup\nFetches full LinkedIn profile data from ConnectSafely.AI to personalize the message."
      },
      "typeVersion": 1
    },
    {
      "id": "cf419e9b-093e-4577-9d30-e35105e3f645",
      "name": "Sticky Note - AI",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2400,
        -224
      ],
      "parameters": {
        "color": 6,
        "width": 300,
        "height": 100,
        "content": "### \ud83e\udd16 AI Message Generation\nGemini creates a personalized, authentic message based on the prospect's profile. Customize the system prompt with your name and style!"
      },
      "typeVersion": 1
    },
    {
      "id": "c5c4a3f8-a6c5-4778-be4b-f89a11e59f1e",
      "name": "Sticky Note - Send",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2768,
        -224
      ],
      "parameters": {
        "color": 6,
        "width": 260,
        "height": 100,
        "content": "### \u2709\ufe0f Send & Update\nSends the connection request and updates the sheet with DONE status + the message sent."
      },
      "typeVersion": 1
    },
    {
      "id": "ddda0402-e924-4092-b805-28e1202dd154",
      "name": "Manual Trigger (for testing)",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        1248,
        0
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "fe12f8b4-c3eb-4a0e-9f02-9a4f908b27b7",
      "name": "Run Every Minute",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1248,
        -224
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 1
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "75c848cd-2a74-4743-8737-461da0b125c6",
      "name": "Random Delay (1-5 min)",
      "type": "n8n-nodes-base.wait",
      "position": [
        1472,
        -96
      ],
      "parameters": {
        "unit": "minutes",
        "amount": "={{ Math.floor(Math.random() * 4) + 1 }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "dbd651fc-eaa0-4f38-a817-2ed109fbab9d",
      "name": "Get Pending Prospect",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1712,
        -80
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "da38e988-6eaf-43bb-87e7-b124edad0608",
      "name": "Mark as In Progress",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1952,
        -80
      ],
      "parameters": {
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "07ff2c64-2f8c-4bd3-be08-e2452b166832",
      "name": "Fetch LinkedIn Profile",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2224,
        -80
      ],
      "parameters": {
        "url": "https://api.connectsafely.ai/linkedin/profile",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "profileId",
              "value": "={{ $('Get Pending Prospect').item.json['LinkedIn Url'] }}"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2309344b-11c4-487e-ac7c-39c264f96155",
      "name": "Generate Personalized Message",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2464,
        -80
      ],
      "parameters": {
        "text": "={{ $json.profile }}",
        "options": {
          "systemMessage": "Generate a conversational, authentic LinkedIn invitation message for connecting with a complete stranger. The message should feel like it's coming from a real person, not a bot.\n\nREQUIREMENTS:\n- Be between 200-250 characters (LinkedIn's limit)\n- Add an extra line break after the name\n- Include genuine, personalized elements that show you actually looked at their profile\n- Sound conversational and relatable, not corporate-speak\n- Use professional but casual language\n- Explain why you're genuinely interested in connecting\n- Focus on real mutual value, not generic networking\n- Reference something specific that caught your attention\n- End with \"- [YOUR NAME]\" on a new line\n\nMY CONTEXT:\n[CUSTOMIZE THIS: Add your name, role, and what you're looking for in connections]\n\nHUMAN STRUCTURE:\n1. Casual but professional greeting + line break\n2. Something specific that genuinely caught your eye\n3. Brief, authentic mention of your own journey\n4. Real reason you'd value the connection\n5. Genuine forward-looking statement\n6. Sign off with your name\n\nMAKE IT SOUND HUMAN:\n- Use contractions (I'm, you're, I'd)\n- Include genuine curiosity markers\n- Add relatable language\n- Show real interest, not networking checkbox-ticking\n\nAVOID:\n- \"I'd like to add you to my professional network\"\n- Corporate buzzwords like \"leverage synergies\"\n- \"Mutual beneficial relationship\"\n- Template-sounding phrases\n- Overly formal language"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "4379a09e-4be2-4daa-abb2-72f8272011bb",
      "name": "Google Gemini",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        2432,
        144
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "695fe395-e1fe-4188-acca-3564bc0cc045",
      "name": "Extract Message",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        2624,
        144
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"message\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"description\": \"The personalized LinkedIn connection message\"\n\t\t}\n\t},\n\t\"required\": [\"message\"]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "e3ff1017-4adc-4a92-8e9a-606ef3c9a855",
      "name": "Send Connection Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2784,
        -80
      ],
      "parameters": {
        "url": "https://api.connectsafely.ai/linkedin/connect",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "profileId",
              "value": "={{ $('Get Pending Prospect').item.json['LinkedIn Url'] }}"
            },
            {
              "name": "customMessage",
              "value": "={{ $json.message }}"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "68bbdd65-46c5-45d7-b39b-7d7997d1bbca",
      "name": "Mark as Complete",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3024,
        -80
      ],
      "parameters": {
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "connections": {
    "Google Gemini": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Personalized Message",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Extract Message": {
      "ai_outputParser": [
        [
          {
            "node": "Generate Personalized Message",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Run Every Minute": {
      "main": [
        [
          {
            "node": "Random Delay (1-5 min)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark as In Progress": {
      "main": [
        [
          {
            "node": "Fetch LinkedIn Profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Pending Prospect": {
      "main": [
        [
          {
            "node": "Mark as In Progress",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch LinkedIn Profile": {
      "main": [
        [
          {
            "node": "Generate Personalized Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Random Delay (1-5 min)": {
      "main": [
        [
          {
            "node": "Get Pending Prospect",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Connection Request": {
      "main": [
        [
          {
            "node": "Mark as Complete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger (for testing)": {
      "main": [
        [
          {
            "node": "Get Pending Prospect",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Personalized Message": {
      "main": [
        [
          {
            "node": "Send Connection Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}