L

LinkedIn Outreach Platform Agentic Workflow

LinkedIn: Lead Health Check — LinkedIn Outreach Platform Agentic Workflow

>-

Available free v1.1.0 Browser LLM
$ sidebutton install linkedin
Download ZIP

The heavyweight enrichment pass. Scrolls the full profile (about, experience, education, skills, activity), extracts everything, and scores the person against the baked-in ICP with a 0–11 rubric (title fit, company size, geography, recency, warmth) into tiers A–D, plus detected signals and a suggested outreach angle.

The ICP defaults reflect the 2026-08 outreach strategy: the buyer is the owner of a queue (CEO/GF/COO/non-technical founder at 20–500 person software-enabled companies), product leaders are the operator path, agencies and fractional execs are channel, strong-eng-org CTOs get an advisor ask only. Pass icp_context to override without editing the pack.

For a single person right before writing a message, linkedin_profile_brief is the faster, lighter alternative; this one is meant for scoring lists.

Steps

  1. 1.
    Navigate to a URL
    url
    {{profile_url}}
    browser.navigate
  2. 2.
    Wait
    selector
    main
    timeout
    12000
    browser.wait
  3. 3.
    Wait
    selector
    main a[href*="/in/"], main a[href*="/company/"]
    timeout
    10000
    browser.wait
  4. 4.
    Scroll the page
    direction
    down
    amount
    1200
    browser.scroll
  5. 5.
    Wait
    selector
    main
    timeout
    1000
    browser.wait
  6. 6.
    Scroll the page
    direction
    down
    amount
    1200
    browser.scroll
  7. 7.
    Wait
    selector
    main
    timeout
    1000
    browser.wait
  8. 8.
    Scroll the page
    direction
    down
    amount
    1200
    browser.scroll
  9. 9.
    Wait
    selector
    main
    timeout
    1000
    browser.wait
  10. 10.
    Scroll the page
    direction
    down
    amount
    1200
    browser.scroll
  11. 11.
    Wait
    selector
    main
    timeout
    1000
    browser.wait
  12. 12.
    Scroll the page
    direction
    down
    amount
    1200
    browser.scroll
  13. 13.
    Wait
    selector
    main
    timeout
    1000
    browser.wait
  14. 14.
    Scroll the page
    direction
    down
    amount
    1200
    browser.scroll
  15. 15.
    Wait
    selector
    main
    timeout
    1000
    browser.wait
  16. 16.
    Extract text from a selector
    selector
    main
    as
    profile_blob
    browser.extract
  17. 17.
    llm generate
    prompt
    >
    as
    assessment
    llm.generate
  18. 18.
    control stop
    message
    {{assessment}}
    control.stop

Workflow definition

schema_version: 1
version: 0.2.0
last_verified: '2026-08-25'
id: linkedin_lead_health
title: 'LinkedIn: Lead Health Check'
description: >-
  Opens a LinkedIn profile, scrolls to trigger lazy-loaded sections (about,
  experience, education, skills, activity), extracts the full profile, and
  asks the LLM to evaluate the lead against the current SideButton ICP
  (2026-08 outreach strategy: non-technical queue owners, agent teams).
  Returns structured JSON with raw profile data, detected signals, ICP
  evaluation (score/tier), and suggested outreach angle + opener. Designed
  for batch enrichment of Max's 1st-degree connections.
overview: |
  The heavyweight enrichment pass. Scrolls the full profile (about, experience,
  education, skills, activity), extracts everything, and scores the person against
  the baked-in ICP with a 0–11 rubric (title fit, company size, geography, recency,
  warmth) into tiers A–D, plus detected signals and a suggested outreach angle.

  The ICP defaults reflect the 2026-08 outreach strategy: the buyer is the owner of
  a queue (CEO/GF/COO/non-technical founder at 20–500 person software-enabled
  companies), product leaders are the operator path, agencies and fractional execs
  are channel, strong-eng-org CTOs get an advisor ask only. Pass `icp_context` to
  override without editing the pack.

  For a single person right before writing a message, `linkedin_profile_brief` is
  the faster, lighter alternative; this one is meant for scoring lists.
category:
  level: task
  domain: sales
  reusable: true
params:
  profile_url:
    type: string
    description: Full LinkedIn profile URL (e.g. https://www.linkedin.com/in/username/)
    required: true
  icp_context:
    type: string
    description: Optional override for ICP definition. Defaults to the 2026-08 SideButton outreach ICP baked into the prompt.
    required: false
  max_scrolls:
    type: string
    description: Number of scroll steps to trigger lazy-load. Default 6.
    required: false
policies:
  allowed_domains:
    - '*.linkedin.com'
steps:
  - type: browser.navigate
    url: '{{profile_url}}'
  - type: browser.wait
    selector: main
    timeout: 12000
  - type: browser.wait
    selector: main a[href*="/in/"], main a[href*="/company/"]
    timeout: 10000

  - type: browser.scroll
    direction: down
    amount: 1200
  - type: browser.wait
    selector: main
    timeout: 1000
  - type: browser.scroll
    direction: down
    amount: 1200
  - type: browser.wait
    selector: main
    timeout: 1000
  - type: browser.scroll
    direction: down
    amount: 1200
  - type: browser.wait
    selector: main
    timeout: 1000
  - type: browser.scroll
    direction: down
    amount: 1200
  - type: browser.wait
    selector: main
    timeout: 1000
  - type: browser.scroll
    direction: down
    amount: 1200
  - type: browser.wait
    selector: main
    timeout: 1000
  - type: browser.scroll
    direction: down
    amount: 1200
  - type: browser.wait
    selector: main
    timeout: 1000

  - type: browser.extract
    selector: main
    as: profile_blob

  - type: llm.generate
    prompt: >
      You are evaluating a LinkedIn profile as a potential SideButton lead.


      ## SideButton ICP (2026-08 outreach strategy)

      {{icp_context}}

      Thesis: we sell the first agent team; the buyer is the owner of a queue,
      not the owner of a codebase. Primary buyer: CEO / Geschäftsführer / COO /
      CIO / non-technical founder at a 20–500 person software-enabled company
      whose engineering is weak, absent, or fully booked on the core product.
      Operator persona (second entry path, budget usually elsewhere): Head of
      Product / CPO / PM who can describe work precisely.

      Channel (not buyer, still valuable): agencies, dev shops, IT-Systemhäuser,
      consultancies, fractional/interim execs — white-label angle. Multipliers:
      investors, analysts, coaches, community and event owners — reach and
      intros, advisor-style ask only.

      Deprioritize as a pitch: CTOs / VPs Eng / staff engineers of strong
      engineering organisations (five nos on record), anyone whose only angle
      would be "make your developers faster", recruiters, competitors.

      Geography: DACH-first, UK/NL/Nordics secondary.

      Proof assets: public Felix Ohswald post — a product lead closed 456 Jira
      tickets in a month, about 7 engineers of output (GoStudent, PAST TENSE
      only, never present-tense); 92.5% first-pass on senior review (technical
      readers only). Never lead with parallelism, VM counts, 24/7, or
      orchestration.

      Commercials: Agent Launch 10–15k EUR one-off (design partners 5k or
      credited); monthly agent teams Team ~2.5k / Fleet ~6k / Scale from 12k.


      ## Scoring rubric (total 0–11)

      - title_fit (0–3): 3 = CEO/GF/COO/owner of a 20–500 person non-eng-led
        company (queue owner); 2.5 = non-technical or commercial founder;
        2 = Head of Product / CPO / senior PM (operator); 1.5 = agency,
        consultancy, or fractional exec (channel); 1 = founder-CTO with a tiny
        or fully booked team; 0.5 = CTO/VP Eng of a strong engineering org
        (advisor ask only); 0 = unrelated/irrelevant
      - size_fit (0–3): 3 = 20–500 emp; 2 = 500–1000; 1.5 = <20; 1 = 1000+;
        0 = solo/unclear
      - geo (0–2): 2 = DACH; 1.5 = UK/NL/Nordics; 1 = US; 0.5 = other; 0 = unclear
      - recency (0–1): 1 = active/posting within 90 days; 0.8 = within 1 year;
        0.5 = dormant/no activity visible
      - warmth (0–2): 2 = strong mutual signal (shared employer, evident collaboration,
        prior thread); 1.5 = many mutual connections or shared industry events;
        1 = some mutuals; 0.5 = weak/none visible

      Tiers: A = 9–11, B = 6–8, C = 4–5, D < 4.


      ## Raw profile data

      Profile URL: {{profile_url}}


      Main content (newline-delimited; line 1 = name, then pronouns, headline,
      location, connections, About, Activity, Experience, Education, Skills,
      Languages, Interests. Parse this to fill the schema below.):

      ---

      {{profile_blob}}

      ---


      ## Your task

      Respond with RAW JSON ONLY — no prose before, no markdown fences, no
      comments. Match this exact schema (leave a field null if data is not
      visible on the profile rather than guessing):


      {
        "profile_url": "{{profile_url}}",
        "name": "string",
        "headline": "string",
        "location": "string | null",
        "connection_degree": "1st | 2nd | 3rd | out-of-network | unknown",
        "mutual_connections_count": number | null,
        "followers": "string | null",
        "has_open_to_work_banner": boolean,
        "has_provides_services": boolean,
        "has_hiring_banner": boolean,
        "about_summary": "first 500 chars of about section, or null",
        "current_role": {
          "title": "string",
          "company": "string",
          "employment_type": "string | null",
          "start_date": "YYYY-MM | null",
          "duration": "e.g. 1 yr 3 mos | null",
          "location": "string | null",
          "description_snippet": "first 200 chars or null"
        },
        "prior_roles": [
          {"title": "string", "company": "string", "start": "YYYY-MM | null", "end": "YYYY-MM | null", "duration": "string | null"}
        ],
        "prior_roles_count": number,
        "total_years_experience": number | null,
        "career_arc_signal": "repeat-CTO | first-time-CTO | IC-to-leader | founder | specialist | unclear",
        "education": [
          {"institution": "string", "degree": "string | null", "field": "string | null", "end": "YYYY | null"}
        ],
        "top_skills": ["string", "..."],
        "recent_activity": {
          "posted_within_90d": boolean,
          "recent_topics": ["string", "..."],
          "engagement_level": "active | sporadic | dormant | unknown"
        },
        "languages": ["string", "..."],
        "detected_signals": {
          "likely_dach": boolean,
          "likely_scaleup": boolean,
          "likely_buyer": boolean,
          "likely_influencer_only": boolean,
          "just_joined_role_90d": boolean,
          "posting_about_ai": boolean,
          "posting_about_hiring": boolean,
          "posting_about_qa_or_backlog": boolean,
          "stealth_mode": boolean,
          "too_big_for_icp": boolean,
          "too_small_for_icp": boolean
        },
        "icp_evaluation": {
          "cluster": "CTO | VP-Eng | Dir-Eng | QA-lead | CPO | VP-Product | PM-senior | Founder | COO | Investor | Other",
          "segment": "Founder-CTO-small | Scaleup-CTO | Enterprise-CTO | CPO-scaleup | Founder-PM | QA-lead-scaleup | not-icp | unclear",
          "company_size_estimate": "<50 | 50-100 | 100-1000 | 1000+ | unknown",
          "geography": "DACH | UK | NL | Nordics | US | Other | unknown",
          "score": {
            "title_fit": 0,
            "size_fit": 0,
            "geo": 0,
            "recency": 0,
            "warmth": 0,
            "total": 0
          },
          "tier": "A | B | C | D"
        },
        "outreach": {
          "suggested_angle": "builder-entry-buyer | operator-pm-entry | channel-white-label | advisor-ask-V0 | speaking-or-community | coordinate-before-touch | not-now",
          "opening_line": "one sentence tailored to this specific person — reference something concrete from their profile, not a template",
          "flags": ["string", "..."],
          "followup_notes": "2-3 sentence rationale for the tier and angle"
        },
        "confidence": 0.0,
        "extraction_notes": "anything the LLM could not reliably extract or had to infer"
      }
    as: assessment

  - type: control.stop
    message: '{{assessment}}'