{
  "schemaVersion": "1.0",
  "item": {
    "slug": "linkedin-dm",
    "name": "LinkedIn DM",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/10Madh/linkedin-dm",
    "canonicalUrl": "https://clawhub.ai/10Madh/linkedin-dm",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/linkedin-dm",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=linkedin-dm",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "references/browser-workflow.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/linkedin-dm"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/linkedin-dm",
    "agentPageUrl": "https://openagent3.xyz/skills/linkedin-dm/agent",
    "manifestUrl": "https://openagent3.xyz/skills/linkedin-dm/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/linkedin-dm/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "LinkedIn DM",
        "body": "Sends personalized LinkedIn messages to existing 1st-degree connections. Each message has:\n\nA personalized opening unique to each person (based on their profile + relationship to the sender)\nA consistent product/pitch section confirmed once by the user and reused for all messages"
      },
      {
        "title": "1. Connection List",
        "body": "Ask the user for their data file or list. Must include (or be added):\n\nPerson Name — full name\nCompany/Role — their current company or role\nLinkedIn URL — optional but helpful\nMessage Status — column for tracking (add if missing)\n\nIf only a plain list is provided, offer to convert to TSV."
      },
      {
        "title": "2. Read Sender's LinkedIn Profile (mandatory)",
        "body": "Before writing any messages, navigate to /in/me/ and read the sender's profile:\n\nName and current role/company\nCareer history — companies, roles, years\nEducation — college, degree, batch years\nLocation\n\nStore these facts. They are used to identify relationship hooks with each connection."
      },
      {
        "title": "3. Confirm the Pitch (once, upfront)",
        "body": "Ask the user:\n\n\"What's your pitch / product message? This will be the consistent part of every message. Describe it in 1–2 sentences.\"\n\nThen 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.\n\nExample prompt: \"Here's the pitch I'll use for everyone — confirm or edit:\n\n'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.'\""
      },
      {
        "title": "4. Browser Setup",
        "body": "Option A — Chrome Browser Relay (profile=\"chrome\"): extension attached to LinkedIn tab (badge ON) — recommended for flagged accounts\nOption B — OpenClaw Isolated Browser (profile=\"openclaw\"): openclaw-managed Chrome, LinkedIn logged in"
      },
      {
        "title": "5. CRM Sheet",
        "body": "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).\n\nIf the user skips this, fall back to local linkedin_dm_progress.json but remind them the follow-up skill needs the sheet."
      },
      {
        "title": "6. Ready Check",
        "body": "Only proceed once:\n\n✅ List is ready\n✅ Sender profile has been read\n✅ Pitch is confirmed by user\n✅ Browser is open with LinkedIn logged in\n✅ Sheet ID confirmed (or sidecar fallback acknowledged)"
      },
      {
        "title": "Relationship Analysis (per person)",
        "body": "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:\n\nPriorityHookExample opener1Same company (current or past)\"You and I both spent time at CRED…\"2Same college + overlapping years\"Fellow BITS Goa 2018 batch here…\"3Same college (different years)\"BITS connect here — saw your journey from…\"4Same industry/function\"Both been in fintech/product for a while…\"5Mutual connection\"We're both connected to [Name]…\"6Their work context (no personal hook)\"Seen what you've built at [Company]…\"\n\nCombine the hook with a line about their current work to show you know what they do."
      },
      {
        "title": "Message Structure",
        "body": "Send as two separate messages per person, back to back:\n\nMessage 1 — Personalized opener (unique per person)\n\n[Relationship hook — 1 sentence]\n[Acknowledgement of their work/role — 1 sentence]\n\nTarget: 100–180 chars. Feels like a genuine reach-out from someone who knows them.\n\nMessage 2 — Pitch (identical for everyone, confirmed upfront)\n\n[Product description — 1–2 sentences]\n[Relevant use case for their role — 1 sentence]\n[Soft CTA — 1 sentence]\n\nTarget: 150–250 chars. Clear, punchy, no filler.\n\nWhy two messages?\n\nOpener lands first — they see it before the pitch, feels more personal\nPitch is clearly a separate thought, not buried at the end\nMirrors how a human would actually message a connection\n\nFallback: 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.\n\nDo not:\n\nOpen with \"I hope you're well\" or \"I came across your profile\"\nUse the same opening for multiple people\nChange the pitch section per person"
      },
      {
        "title": "Batch Preview Before Sending",
        "body": "Generate messages for the entire list first. Present them in a table:\n\nNameCompanyRelationship Hook UsedMessage PreviewShorya SainiRazorpaySame BITS batchHey Shorya, BITS Goa 2018 batch…\n\nGet user approval on the full batch before opening the browser. Allow edits per row."
      },
      {
        "title": "Sending Flow (Per Person)",
        "body": "Navigate to /feed/ — mandatory, no exceptions, no skipping\nWait 3–5 seconds\nSearch connections at linkedin.com/mynetwork/invite-connect/connections/ — type name in \"Search by name\"\nHandle results:\n\n1 match → confirm name + headline → click to open profile\nMultiple matches → show user, ask which one\n0 matches → mark Not a Connection, skip\n\n\nRead their profile if not already done (for personalisation)\nClick Message button on their profile\nSend Message 1 — personalized opener only, send it\nSend Message 2 — pitch only, send it immediately after\nConfirm both delivered\nLog to CRM sheet — append row via gog sheets append with all fields (see CRM Tracking section)\n\nSee references/browser-workflow.md for exact browser automation steps."
      },
      {
        "title": "Status Values",
        "body": "StatusMeaningSentMessage delivered this sessionAlready MessagedRecent conversation exists — skipNot a ConnectionNo Message button or not in connections searchProfile Not FoundCould not identify the right personSkippedUser chose to skipFailedBrowser error — retry next session"
      },
      {
        "title": "Anti-Detection Rules",
        "body": "/feed/ before every single profile — non-negotiable\n3–5 second wait after feed loads\nMax 15–20 messages per session\nStop immediately if LinkedIn warns about messaging rate — tell the user"
      },
      {
        "title": "CRM Tracking — Google Sheet",
        "body": "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."
      },
      {
        "title": "Sheet Setup",
        "body": "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:\n\nColFieldNotesADate SentISO date, e.g. 2026-02-13BPerson NameFull nameCRole / TitleTheir current headline from LinkedInDCompanyCurrent companyELinkedIn URLProfile URLFRelationship HookWhat hook was used (e.g. \"Same batch BITS Goa 2018\", \"Both at CRED 2022–23\")GOpener SentExact text of Message 1HPitch SentExact text of Message 2ICampaignShort label for this batch (e.g. \"AI Calling - Feb 2026\")JStatusAlways Sent when first logged — updated by follow-up skillKNotesAnything notable (prior conversation, context, mutual connection used)LLast UpdatedTimestamp of last status change\n\nColumn I (Status) lifecycle — only Sent is written by this skill. The follow-up skill will update to:\nReplied · Call Scheduled · Demo Done · Follow Up Sent · No Response · Closed Won · Closed Lost"
      },
      {
        "title": "Appending a Row",
        "body": "After each message pair is sent, run:\n\ngog sheets append <SHEET_ID> \"Outreach!A:L\" \\\n  --values-json '[[\"<date>\",\"<name>\",\"<role>\",\"<company>\",\"<url>\",\"<hook>\",\"<opener>\",\"<pitch>\",\"<campaign>\",\"Sent\",\"<notes>\",\"<timestamp>\"]]' \\\n  --insert INSERT_ROWS"
      },
      {
        "title": "First-Time Setup",
        "body": "If no sheet exists yet, tell the user:\n\n\"I'll need a Google Sheet to track outreach. Share an existing sheet ID/URL, or I can create one with the right columns.\"\n\nTo create a new sheet, use Drive (or ask user to create one and share the ID). Then write the header row:\n\ngog sheets update <SHEET_ID> \"Outreach!A1:L1\" \\\n  --values-json '[[\"Date Sent\",\"Person Name\",\"Role / Title\",\"Company\",\"LinkedIn URL\",\"Relationship Hook\",\"Opener Sent\",\"Pitch Sent\",\"Campaign\",\"Status\",\"Notes\",\"Last Updated\"]]' \\\n  --input USER_ENTERED"
      },
      {
        "title": "Local Sidecar (fallback)",
        "body": "If Google Sheets is not set up, fall back to a local linkedin_dm_progress.json:\n\n{\n  \"campaign\": \"AI Calling - Feb 2026\",\n  \"pitch\": \"confirmed pitch text\",\n  \"rows\": [\n    {\n      \"date\": \"2026-02-13\",\n      \"name\": \"Shorya Saini\",\n      \"role\": \"Senior Analytics Specialist\",\n      \"company\": \"Razorpay\",\n      \"url\": \"https://linkedin.com/in/shorya-saini\",\n      \"hook\": \"Same batch BITS Goa 2018\",\n      \"opener\": \"Hey Shorya...\",\n      \"pitch\": \"I'm building...\",\n      \"status\": \"Sent\",\n      \"notes\": \"\"\n    }\n  ]\n}"
      }
    ],
    "body": "LinkedIn DM\n\nSends personalized LinkedIn messages to existing 1st-degree connections. Each message has:\n\nA personalized opening unique to each person (based on their profile + relationship to the sender)\nA consistent product/pitch section confirmed once by the user and reused for all messages\n⚠️ Pre-flight Checklist — Confirm Before Starting\n1. Connection List\n\nAsk the user for their data file or list. Must include (or be added):\n\nPerson Name — full name\nCompany/Role — their current company or role\nLinkedIn URL — optional but helpful\nMessage Status — column for tracking (add if missing)\n\nIf only a plain list is provided, offer to convert to TSV.\n\n2. Read Sender's LinkedIn Profile (mandatory)\n\nBefore writing any messages, navigate to /in/me/ and read the sender's profile:\n\nName and current role/company\nCareer history — companies, roles, years\nEducation — college, degree, batch years\nLocation\n\nStore these facts. They are used to identify relationship hooks with each connection.\n\n3. Confirm the Pitch (once, upfront)\n\nAsk the user:\n\n\"What's your pitch / product message? This will be the consistent part of every message. Describe it in 1–2 sentences.\"\n\nThen 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.\n\nExample prompt: \"Here's the pitch I'll use for everyone — confirm or edit:\n\n'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.'\"\n\n4. Browser Setup\nOption A — Chrome Browser Relay (profile=\"chrome\"): extension attached to LinkedIn tab (badge ON) — recommended for flagged accounts\nOption B — OpenClaw Isolated Browser (profile=\"openclaw\"): openclaw-managed Chrome, LinkedIn logged in\n5. CRM Sheet\n\nAsk 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).\n\nIf the user skips this, fall back to local linkedin_dm_progress.json but remind them the follow-up skill needs the sheet.\n\n6. Ready Check\n\nOnly proceed once:\n\n✅ List is ready\n✅ Sender profile has been read\n✅ Pitch is confirmed by user\n✅ Browser is open with LinkedIn logged in\n✅ Sheet ID confirmed (or sidecar fallback acknowledged)\nRelationship Analysis (per person)\n\nBefore 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:\n\nPriority\tHook\tExample opener\n1\tSame company (current or past)\t\"You and I both spent time at CRED…\"\n2\tSame college + overlapping years\t\"Fellow BITS Goa 2018 batch here…\"\n3\tSame college (different years)\t\"BITS connect here — saw your journey from…\"\n4\tSame industry/function\t\"Both been in fintech/product for a while…\"\n5\tMutual connection\t\"We're both connected to [Name]…\"\n6\tTheir work context (no personal hook)\t\"Seen what you've built at [Company]…\"\n\nCombine the hook with a line about their current work to show you know what they do.\n\nMessage Structure\n\nSend as two separate messages per person, back to back:\n\nMessage 1 — Personalized opener (unique per person)\n\n[Relationship hook — 1 sentence]\n[Acknowledgement of their work/role — 1 sentence]\n\n\nTarget: 100–180 chars. Feels like a genuine reach-out from someone who knows them.\n\nMessage 2 — Pitch (identical for everyone, confirmed upfront)\n\n[Product description — 1–2 sentences]\n[Relevant use case for their role — 1 sentence]\n[Soft CTA — 1 sentence]\n\n\nTarget: 150–250 chars. Clear, punchy, no filler.\n\nWhy two messages?\n\nOpener lands first — they see it before the pitch, feels more personal\nPitch is clearly a separate thought, not buried at the end\nMirrors how a human would actually message a connection\n\nFallback: 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.\n\nDo not:\n\nOpen with \"I hope you're well\" or \"I came across your profile\"\nUse the same opening for multiple people\nChange the pitch section per person\nBatch Preview Before Sending\n\nGenerate messages for the entire list first. Present them in a table:\n\nName\tCompany\tRelationship Hook Used\tMessage Preview\nShorya Saini\tRazorpay\tSame BITS batch\tHey Shorya, BITS Goa 2018 batch…\n\nGet user approval on the full batch before opening the browser. Allow edits per row.\n\nSending Flow (Per Person)\nNavigate to /feed/ — mandatory, no exceptions, no skipping\nWait 3–5 seconds\nSearch connections at linkedin.com/mynetwork/invite-connect/connections/ — type name in \"Search by name\"\nHandle results:\n1 match → confirm name + headline → click to open profile\nMultiple matches → show user, ask which one\n0 matches → mark Not a Connection, skip\nRead their profile if not already done (for personalisation)\nClick Message button on their profile\nSend Message 1 — personalized opener only, send it\nSend Message 2 — pitch only, send it immediately after\nConfirm both delivered\nLog to CRM sheet — append row via gog sheets append with all fields (see CRM Tracking section)\n\nSee references/browser-workflow.md for exact browser automation steps.\n\nStatus Values\nStatus\tMeaning\nSent\tMessage delivered this session\nAlready Messaged\tRecent conversation exists — skip\nNot a Connection\tNo Message button or not in connections search\nProfile Not Found\tCould not identify the right person\nSkipped\tUser chose to skip\nFailed\tBrowser error — retry next session\nAnti-Detection Rules\n/feed/ before every single profile — non-negotiable\n3–5 second wait after feed loads\nMax 15–20 messages per session\nStop immediately if LinkedIn warns about messaging rate — tell the user\nCRM Tracking — Google Sheet\n\nAfter 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.\n\nSheet Setup\n\nAsk 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:\n\nCol\tField\tNotes\nA\tDate Sent\tISO date, e.g. 2026-02-13\nB\tPerson Name\tFull name\nC\tRole / Title\tTheir current headline from LinkedIn\nD\tCompany\tCurrent company\nE\tLinkedIn URL\tProfile URL\nF\tRelationship Hook\tWhat hook was used (e.g. \"Same batch BITS Goa 2018\", \"Both at CRED 2022–23\")\nG\tOpener Sent\tExact text of Message 1\nH\tPitch Sent\tExact text of Message 2\nI\tCampaign\tShort label for this batch (e.g. \"AI Calling - Feb 2026\")\nJ\tStatus\tAlways Sent when first logged — updated by follow-up skill\nK\tNotes\tAnything notable (prior conversation, context, mutual connection used)\nL\tLast Updated\tTimestamp of last status change\n\nColumn 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\n\nAppending a Row\n\nAfter each message pair is sent, run:\n\ngog sheets append <SHEET_ID> \"Outreach!A:L\" \\\n  --values-json '[[\"<date>\",\"<name>\",\"<role>\",\"<company>\",\"<url>\",\"<hook>\",\"<opener>\",\"<pitch>\",\"<campaign>\",\"Sent\",\"<notes>\",\"<timestamp>\"]]' \\\n  --insert INSERT_ROWS\n\nFirst-Time Setup\n\nIf no sheet exists yet, tell the user:\n\n\"I'll need a Google Sheet to track outreach. Share an existing sheet ID/URL, or I can create one with the right columns.\"\n\nTo create a new sheet, use Drive (or ask user to create one and share the ID). Then write the header row:\n\ngog sheets update <SHEET_ID> \"Outreach!A1:L1\" \\\n  --values-json '[[\"Date Sent\",\"Person Name\",\"Role / Title\",\"Company\",\"LinkedIn URL\",\"Relationship Hook\",\"Opener Sent\",\"Pitch Sent\",\"Campaign\",\"Status\",\"Notes\",\"Last Updated\"]]' \\\n  --input USER_ENTERED\n\nLocal Sidecar (fallback)\n\nIf Google Sheets is not set up, fall back to a local linkedin_dm_progress.json:\n\n{\n  \"campaign\": \"AI Calling - Feb 2026\",\n  \"pitch\": \"confirmed pitch text\",\n  \"rows\": [\n    {\n      \"date\": \"2026-02-13\",\n      \"name\": \"Shorya Saini\",\n      \"role\": \"Senior Analytics Specialist\",\n      \"company\": \"Razorpay\",\n      \"url\": \"https://linkedin.com/in/shorya-saini\",\n      \"hook\": \"Same batch BITS Goa 2018\",\n      \"opener\": \"Hey Shorya...\",\n      \"pitch\": \"I'm building...\",\n      \"status\": \"Sent\",\n      \"notes\": \"\"\n    }\n  ]\n}"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/10Madh/linkedin-dm",
    "publisherUrl": "https://clawhub.ai/10Madh/linkedin-dm",
    "owner": "10Madh",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/linkedin-dm",
    "downloadUrl": "https://openagent3.xyz/downloads/linkedin-dm",
    "agentUrl": "https://openagent3.xyz/skills/linkedin-dm/agent",
    "manifestUrl": "https://openagent3.xyz/skills/linkedin-dm/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/linkedin-dm/agent.md"
  }
}