Find high-intent leads from a LinkedIn post — scrape commenters and reactors, score each profile against an ICP, and launch a targeted outreach campaign on the matches. Use when the user says "high-intent leads", "scrape commenters", "engagers from post", "post reactions outreach", "warm leads from a LinkedIn post", or pastes a LinkedIn post URL and asks to find prospects.
Scanned 5/28/2026
Install via CLI
openskills install claude-dev-code/claude-skills-linkedin---
name: linkedin-high-intent
description: Find high-intent leads from a LinkedIn post — scrape commenters and reactors, score each profile against an ICP, and launch a targeted outreach campaign on the matches. Use when the user says "high-intent leads", "scrape commenters", "engagers from post", "post reactions outreach", "warm leads from a LinkedIn post", or pastes a LinkedIn post URL and asks to find prospects.
---
# High-Intent Leads from a LinkedIn Post
The premise: people who comment or react on a relevant post are 5-10× more likely to accept a connection or reply than cold outreach. This skill turns a single post URL into a filtered, ICP-matched outreach campaign.
## Required prerequisites — check before you start
1. **`linkupapi` MCP connected.** Verify with `linkupapi_list_accounts`.
- If the list is **empty**, tell the user they have two options to connect a LinkedIn account, then stop and wait:
- **Hosted UI** — open https://app.linkupapi.com/account-connection (fastest, handles checkpoints in-browser).
- **MCP login** — run `linkupapi_login` directly (platform=linkedin, with email+password OR a `login_token`). On `checkpoint_required` → run `linkupapi_checkpoint`.
2. **Pick the sending account** before Stage 1. After confirming at least one `status = connected` account exists, present the connected accounts via `AskUserQuestion` (single-select). Each option label is the account display name; description shows email + country. The chosen `account_id` is used for every subsequent tool call in this run.
3. A LinkedIn post URL the user wants to mine.
## Daily LinkedIn safety caps (MANDATORY — enforced before any tool call)
LinkedIn rate-limits per account. This skill respects:
- **20 connection requests / day** (invites)
- **100 profile gets / day** (`linkedin_profiles get`)
- **15 searches / day** (`search_people` / `search_companies`)
**Before Stage 1**, run `linkupapi_get_logs` filtered to the last 24h on the chosen account. Count today's:
- `linkedin_network/invite` calls
- `linkedin_profiles/get` calls
- `linkedin_profiles/search_*` calls
Compute remaining budget per category. **Never override the caps** — trim the run or stop. Surface remaining budget in the Stage 0 echo so the user sees it before confirming.
If `linkupapi_get_logs` is unavailable or empty, fall back to scanning `./campaigns/*.md` and `./enrichments/*.md` for today's date and counting entries.
## Stage 0 — Collect post URL + ICP
Use `AskUserQuestion` (single batched form):
1. **Post URL** — free-text (full LinkedIn post URL, must contain `/posts/` or `/feed/update/`)
2. **ICP** — same shape as `linkedin-outreach` Stage 0: titles, sectors, sizes, geo. If the user has a saved ICP file (`./icp/*.json`), offer to reuse it.
3. **Engagement type**:
- Commenters only (highest intent — recommended)
- Reactors only (broader funnel)
- Both
4. **Volume cap** — max invites this run. **Hard ceiling = today's remaining 20-invite budget**. Default = `min(10, remaining_invites)`.
5. **Note style** — same options as `linkedin-outreach`: no note / personalized / custom. Recommended here: personalized note referencing the post (accept rate is much higher when you reference the engagement).
Echo the brief with daily-cap math:
```
Post: {url}
ICP: {summary}
Engagement: commenters + reactors
Volume cap: 10 (today: 8 invites used / 12 remaining)
Profile budget: 45 used / 55 remaining today
Note style: short personalized
```
Wait for "yes" before continuing.
## Stage 1 — Pull engagers from the post
Tool: `linkedin_content`. Load schema with `ToolSearch query="select:mcp__linkupapi__linkedin_content"` to confirm action names. Likely:
- `get_post_reactions` for reactors
- `get_post_comments` for commenters
```json
{"account_id": "...", "action": "get_post_reactions", "params": {"post_url": "<url>", "limit": 100}}
```
Run the chosen action(s). Merge results, dedupe by `profile_url`. Drop:
- `LinkedIn Member` anonymized entries (URL contains `headless`)
- The post author themselves
- Profiles with missing `profile_url`
Not counted against the 15-search cap.
## Stage 2 — Pre-filter on visible signal (no enrichment yet)
Each engager comes back with `name`, `headline`, sometimes `current_company`. Score each against the ICP using ONLY visible fields:
- ✅ Clear match — headline mentions target role/industry → enqueue for enrichment
- ❌ Clear mismatch → drop without burning a profile-get
- ⚠️ Ambiguous → enqueue if remaining profile-get budget allows
Surface the triage:
```
Engagers found: 47
Clear matches (will enrich): 12
Ambiguous (will enrich): 8
Clear non-matches (dropped): 27
Profile budget: 55 remaining → fits all 20.
```
Stop here and ask if user wants to drop ambiguous to save budget when budget is tight.
## Stage 3 — Enrich matched profiles
Tool: `linkedin_profiles get`, sequential with **1-2s sleep** between calls.
**HARD CAP**: do NOT exceed today's remaining profile-get budget. If 12 strong matches but only 5 budget left, enrich the 5 strongest by visible signal (headline match + current_company match) and write the rest to a "deferred to tomorrow" list in the campaign log.
For each enriched profile, verify CURRENT role (`experience[0]`) actually matches the ICP. Drop people whose recent job changed (false positives).
## Stage 4 — Score and select for outreach
Final scoring per prospect:
- Strong match (current role + industry + size all align) → high priority
- Partial match (2 of 3) → medium
- Weak match (1 of 3) → drop unless volume target is underfilled
Select up to `min(volume_cap, remaining_invite_budget, len(strong_matches + medium_matches))`.
Show the final shortlist to the user (table: name, headline, company, match score, post engagement type) before sending. Wait for "yes".
## Stage 5 — Launch invites (cap-aware)
For each selected prospect:
1. `linkedin_network/check_invitation` → skip if PENDING / CONNECTED
2. Generate the personalized note (if user opted in). Reference the post:
> "Hi {first_name}, saw your {comment|reaction} on {post_topic_short} — same space we're operating in. Would love to connect."
Keep ≤250 chars. No links.
3. `linkedin_network/invite` with `identifier=<handle>` and `message=<note>`
4. Sleep 1-2s between invites
5. **STOP** the moment today's 20-invite budget is exhausted
Report partial completion if cap hits before the volume target.
## Stage 6 — Persist & report (mandatory)
Write `./campaigns/{YYYY-MM-DD}-high-intent-{post-slug}.md`:
1. Source post URL + author + topic
2. ICP definition
3. Engagement counts (commenters / reactors / merged / deduped)
4. Triage breakdown (matches / ambiguous / drops)
5. Enrichment results (confirmed / false positives)
6. Invites sent table: `# | Name | Company | Engagement type | Note sent | invitation_urn`
7. Daily caps remaining after this run
8. Deferred prospects list (for tomorrow)
Concise on-screen summary. Include `account_id` and daily-cap usage.
## De-dup with previous campaigns
**Before Stage 5**, glob `./campaigns/*.md` and `./enrichments/*.md` for any `profile_url` / `invitation_urn` already in the new shortlist. Drop those silently and surface the dedup count in the report.
## Common pitfalls
- **Old posts**: if the post is >30 days old, many commenters have changed jobs. Stage 3 enrichment is critical.
- **Author = ICP**: don't invite the post author themselves.
- **Same-company clustering**: if 5 of 10 matches are from the same target account, surface this — could trigger LinkedIn anti-spam.
- **Note that mentions the post**: the note is the entire reason this skill out-converts cold outreach. Don't default to "no note" here unless user insists.
- **Burning profile budget on non-matches**: Stage 2 visible-signal filter is essential.
## Tool quick reference
| Tool | Action | Daily cap |
|---|---|---|
| `linkedin_content` | `get_post_comments` / `get_post_reactions` | engagement (uncapped) |
| `linkedin_profiles` | `get` | **100/day shared** |
| `linkedin_network` | `check_invitation` | (pre-flight, no cap) |
| `linkedin_network` | `invite` | **20/day** |
| `linkupapi_get_logs` | — | run at Stage 0 |
No comments yet. Be the first to comment!