🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

LinkedIn DM

by @10madh

Send personalized LinkedIn direct messages to a list of existing 1st-degree connections via browser automation. Use when the user wants to message LinkedIn connections with AI-personalized outreach β€” e.g. nurturing leads, following up after events, reconnecting with contacts, or announcing something. Takes a data file (CSV/TSV) or plain list with connection names and companies, asks for outreach context/goal, generates a tailored message per person, and sends each one via browser automation. Han

Versionv1.0.0
Downloads1,288
Installs6
Stars⭐ 1
TERMINAL
clawhub install linkedin-dm

πŸ“– About This Skill


name: linkedin-dm description: Send personalized LinkedIn direct messages to a list of existing 1st-degree connections via browser automation. Use when the user wants to message LinkedIn connections with AI-personalized outreach β€” e.g. nurturing leads, following up after events, reconnecting with contacts, or announcing something. Takes a data file (CSV/TSV) or plain list with connection names and companies, asks for outreach context/goal, generates a tailored message per person, and sends each one via browser automation. Handles message compose flow, character limits, and incremental status tracking.

LinkedIn DM

Sends personalized LinkedIn messages to existing 1st-degree connections. Each message has:

  • A personalized opening unique to each person (based on their profile + relationship to the sender)
  • A consistent product/pitch section confirmed once by the user and reused for all messages

  • ⚠️ Pre-flight Checklist β€” Confirm Before Starting

    1. Connection List

    Ask the user for their data file or list. Must include (or be added):
  • Person Name β€” full name
  • Company/Role β€” their current company or role
  • LinkedIn URL β€” optional but helpful
  • Message Status β€” column for tracking (add if missing)
  • If only a plain list is provided, offer to convert to TSV.

    2. Read Sender's LinkedIn Profile (mandatory)

    Before writing any messages, navigate to /in/me/ and read the sender's profile:
  • Name and current role/company
  • Career history β€” companies, roles, years
  • Education β€” college, degree, batch years
  • Location
  • Store these facts. They are used to identify relationship hooks with each connection.

    3. Confirm the Pitch (once, upfront)

    Ask the user: > *"What's your pitch / product message? This will be the consistent part of every message. Describe it in 1–2 sentences."*

    Then draft a polished pitch section (2–4 sentences max, punchy and clear). Show it to the user and get explicit approval. Do not start sending until the pitch is confirmed.

    Example prompt: *"Here's the pitch I'll use for everyone β€” confirm or edit:* > *'I'm building an AI calling agent β€” you give it a phone number + context, and it handles the call end-to-end. Think customer follow-ups, research calls, vendor coordination β€” anything phone-based that eats into your day. Happy to show you a demo if this sounds useful.'"*

    4. Browser Setup

  • Option A β€” Chrome Browser Relay (profile="chrome"): extension attached to LinkedIn tab (badge ON) β€” recommended for flagged accounts
  • Option B β€” OpenClaw Isolated Browser (profile="openclaw"): openclaw-managed Chrome, LinkedIn logged in
  • 5. CRM Sheet

    Ask the user for a Google Sheet ID/URL to log outreach results. If they don't have one, offer to set one up (create tab + write headers). Confirm gog is authenticated (gog auth list).

    If the user skips this, fall back to local linkedin_dm_progress.json but remind them the follow-up skill needs the sheet.

    6. Ready Check

    Only proceed once:
  • βœ… List is ready
  • βœ… Sender profile has been read
  • βœ… Pitch is confirmed by user
  • βœ… Browser is open with LinkedIn logged in
  • βœ… Sheet ID confirmed (or sidecar fallback acknowledged)

  • Relationship Analysis (per person)

    Before writing a message, compare the connection's profile against the sender's profile to find the strongest hook. Use this hierarchy β€” pick the highest that applies:

    | Priority | Hook | Example opener | |---|---|---| | 1 | Same company (current or past) | "You and I both spent time at CRED…" | | 2 | Same college + overlapping years | "Fellow BITS Goa 2018 batch here…" | | 3 | Same college (different years) | "BITS connect here β€” saw your journey from…" | | 4 | Same industry/function | "Both been in fintech/product for a while…" | | 5 | Mutual connection | "We're both connected to [Name]…" | | 6 | Their work context (no personal hook) | "Seen what you've built at [Company]…" |

    Combine the hook with a line about their current work to show you know what they do.


    Message Structure

    Send as two separate messages per person, back to back:

    Message 1 β€” Personalized opener (unique per person)

    [Relationship hook β€” 1 sentence]
    [Acknowledgement of their work/role β€” 1 sentence]
    
    Target: 100–180 chars. Feels like a genuine reach-out from someone who knows them.

    Message 2 β€” Pitch (identical for everyone, confirmed upfront)

    [Product description β€” 1–2 sentences]
    [Relevant use case for their role β€” 1 sentence]
    [Soft CTA β€” 1 sentence]
    
    Target: 150–250 chars. Clear, punchy, no filler.

    Why two messages?

  • Opener lands first β€” they see it before the pitch, feels more personal
  • Pitch is clearly a separate thought, not buried at the end
  • Mirrors how a human would actually message a connection
  • Fallback: If sending two messages is technically difficult (e.g. bubble re-focusing issues), use Shift+Enter twice between the opener and pitch to create a paragraph break within a single message.

    Do not:

  • Open with "I hope you're well" or "I came across your profile"
  • Use the same opening for multiple people
  • Change the pitch section per person

  • Batch Preview Before Sending

    Generate messages for the entire list first. Present them in a table:

    | Name | Company | Relationship Hook Used | Message Preview | |---|---|---|---| | Shorya Saini | Razorpay | Same BITS batch | Hey Shorya, BITS Goa 2018 batch… |

    Get user approval on the full batch before opening the browser. Allow edits per row.


    Sending Flow (Per Person)

    1. Navigate to /feed/ β€” mandatory, no exceptions, no skipping 2. Wait 3–5 seconds 3. Search connections at linkedin.com/mynetwork/invite-connect/connections/ β€” type name in "Search by name" 4. Handle results: - 1 match β†’ confirm name + headline β†’ click to open profile - Multiple matches β†’ show user, ask which one - 0 matches β†’ mark Not a Connection, skip 5. Read their profile if not already done (for personalisation) 6. Click Message button on their profile 7. Send Message 1 β€” personalized opener only, send it 8. Send Message 2 β€” pitch only, send it immediately after 9. Confirm both delivered 10. Log to CRM sheet β€” append row via gog sheets append with all fields (see CRM Tracking section)

    See references/browser-workflow.md for exact browser automation steps.


    Status Values

    | Status | Meaning | |---|---| | Sent | Message delivered this session | | Already Messaged | Recent conversation exists β€” skip | | Not a Connection | No Message button or not in connections search | | Profile Not Found | Could not identify the right person | | Skipped | User chose to skip | | Failed | Browser error β€” retry next session |


    Anti-Detection Rules

  • /feed/ before every single profile β€” non-negotiable
  • 3–5 second wait after feed loads
  • Max 15–20 messages per session
  • Stop immediately if LinkedIn warns about messaging rate β€” tell the user

  • CRM Tracking β€” Google Sheet

    After each message is sent, append a row to a Google Sheet. This sheet is the source of truth for all outreach β€” current session and future follow-up.

    Sheet Setup

    Ask the user for a Google Sheet ID or URL at the start of the session (or offer to create a new one). The sheet should have a tab named Outreach with these columns:

    | Col | Field | Notes | |---|---|---| | A | Date Sent | ISO date, e.g. 2026-02-13 | | B | Person Name | Full name | | C | Role / Title | Their current headline from LinkedIn | | D | Company | Current company | | E | LinkedIn URL | Profile URL | | F | Relationship Hook | What hook was used (e.g. "Same batch BITS Goa 2018", "Both at CRED 2022–23") | | G | Opener Sent | Exact text of Message 1 | | H | Pitch Sent | Exact text of Message 2 | | I | Campaign | Short label for this batch (e.g. "AI Calling - Feb 2026") | | J | Status | Always Sent when first logged β€” updated by follow-up skill | | K | Notes | Anything notable (prior conversation, context, mutual connection used) | | L | Last Updated | Timestamp of last status change |

    Column I (Status) lifecycle β€” only Sent is written by this skill. The follow-up skill will update to: Replied Β· Call Scheduled Β· Demo Done Β· Follow Up Sent Β· No Response Β· Closed Won Β· Closed Lost

    Appending a Row

    After each message pair is sent, run:

    gog sheets append  "Outreach!A:L" \
      --values-json '[["","","","","","","","","","Sent","",""]]' \
      --insert INSERT_ROWS
    

    First-Time Setup

    If no sheet exists yet, tell the user: > "I'll need a Google Sheet to track outreach. Share an existing sheet ID/URL, or I can create one with the right columns."

    To create a new sheet, use Drive (or ask user to create one and share the ID). Then write the header row:

    gog sheets update  "Outreach!A1:L1" \
      --values-json '[["Date Sent","Person Name","Role / Title","Company","LinkedIn URL","Relationship Hook","Opener Sent","Pitch Sent","Campaign","Status","Notes","Last Updated"]]' \
      --input USER_ENTERED
    

    Local Sidecar (fallback)

    If Google Sheets is not set up, fall back to a local linkedin_dm_progress.json:

    {
      "campaign": "AI Calling - Feb 2026",
      "pitch": "confirmed pitch text",
      "rows": [
        {
          "date": "2026-02-13",
          "name": "Shorya Saini",
          "role": "Senior Analytics Specialist",
          "company": "Razorpay",
          "url": "https://linkedin.com/in/shorya-saini",
          "hook": "Same batch BITS Goa 2018",
          "opener": "Hey Shorya...",
          "pitch": "I'm building...",
          "status": "Sent",
          "notes": ""
        }
      ]
    }