Skip to content

Repository files navigation

OpenOutreach Logo

Describe your student profile, target roles, and hiring goals. The agent finds relevant recruiters and helps you follow up.

License: GPLv3


Demo:

Demo Animation

What is OpenOutreach?

OpenOutreach is a self-hosted LinkedIn outreach tool tuned for students and early-career candidates. You describe your background, target roles, locations, and companies. The system discovers relevant recruiters, hiring managers, campus recruiters, and referral contacts, then helps manage careful follow-up.

How it works:

  1. You provide your student background and campaign objective, such as "third-year CS student looking for backend internships in fintech."
  2. The AI generates LinkedIn search queries for recruiters, hiring managers, campus recruiters, and team leads.
  3. A Bayesian ML model learns which profiles match your search goal.
  4. An LLM classifies selected profiles before outreach.
  5. Qualified contacts are queued for connection requests and student-style follow-up messages.

The system starts broad, then focuses on contacts that look more relevant to your search.

Why choose OpenOutreach?

  • Recruiter discovery — No spreadsheet required; the agent finds likely recruiting and hiring contacts.
  • Student-first messaging — Prompts are written for internships, referrals, early-career roles, and career advice.
  • Self-hosted + full data ownership — Everything runs locally, with a CRM web UI for review.
  • Docker setup — Containerized deployment with interactive onboarding.
  • AI-powered follow-up — LLM-generated personalized outreach using your own model key.

Use it carefully. LinkedIn automation can put your account at risk, so keep limits conservative and review your campaign before sending messages.


📋 What You Need

# What Example
1 A LinkedIn account Your email + password
2 An LLM API key OpenAI, Anthropic, or any OpenAI-compatible endpoint
3 Student background + target roles "CS student seeking backend internships at fintech companies in India or remote"

That's it. No spreadsheets, no lead databases, no scraping setup.


⚡ Quick Start (Docker — Recommended)

Build and run the local image with Docker Compose.

docker compose -f local.yml up --build

# Open http://localhost:6080/vnc.html in your browser to watch the automation live

The interactive onboarding walks you through the three inputs above on first run. All data persists in ~/.openoutreach/data on your host across restarts.

Once the container is running, open http://localhost:6080/vnc.html in your browser to watch the browser live (noVNC). Alternatively, connect a native VNC client to localhost:5900.

For Docker Compose, build-from-source, and more options see the Docker Guide.


⚙️ Local Installation (Development)

For contributors or if you prefer running directly on your machine.

Prerequisites

1. Clone & Set Up

git clone <your-repo-url>
cd OpenOutreach

# Install deps, Playwright browsers, run migrations, and bootstrap CRM
make setup

2. Run the Daemon

make run

The interactive onboarding will prompt for LinkedIn credentials, LLM API key, and campaign details on first run. Fully resumable — stop/restart anytime without losing progress.

3. View Your Data (CRM Admin)

OpenOutreach includes a full CRM web interface powered by DjangoCRM:

# Create an admin account (first time only)
python manage.py createsuperuser

# Start the web server
make admin

Then open:


✨ Features

Feature Description
🧠 Autonomous Lead Discovery No contact lists needed — LLM generates search queries from your product description and campaign objective.
🎯 Bayesian Active Learning Gaussian Process model on profile embeddings learns which recruiter and hiring-contact profiles match your search.
🤖 Stealth Browser Automation Playwright + stealth plugins mimic real user behavior for undetectable interactions.
🛡️ Voyager API Scraping Uses LinkedIn's internal API for accurate, structured profile data (no fragile HTML parsing).
🔄 Stateful Pipeline Tracks profile states (QUALIFIED → READY_TO_CONNECT → PENDING → CONNECTED → COMPLETED) in a local DB — fully resumable.
⏱️ Smart Rate Limiting Configurable daily/weekly limits per action type, respects LinkedIn's own limits automatically.
💾 Built-in CRM Full data ownership via DjangoCRM with Django Admin UI — browse Leads, Contacts, Companies, and Deals.
🐳 One-Command Deployment Dockerized setup with interactive onboarding and VNC browser view (localhost:5900).
✍️ AI-Powered Messaging Agentic multi-turn follow-up conversations — the AI agent reads history, sends messages, and schedules future follow-ups.

📖 How the ML Pipeline Works

The daemon runs a continuous task queue backed by a persistent Task model. Three task types self-schedule follow-on work:

Task Type What it does
Connect Ranks qualified profiles by GP model probability, sends connection requests (daily + weekly limits). Triggers qualification and search via composable generators when the pool is empty.
Check Pending Checks if a pending request was accepted (exponential backoff per profile)
Follow Up Runs an AI agent that manages multi-turn conversations with connected profiles

The qualification loop in detail:

Profiles discovered during navigation are automatically scraped and embedded (384-dim FastEmbed vectors). The connect task's backfill chain decides which profile to evaluate next using a balance-driven strategy:

  • When negatives outnumber positives → exploit: pick the profile with highest predicted qualification probability (seek likely positives to fill the pipeline)
  • Otherwise → explore: pick the profile with highest BALD (Bayesian Active Learning by Disagreement) score (seek the most informative label to improve the model)

All qualification decisions go through the LLM. The GP model selects which candidate to evaluate next and gates promotion from QUALIFIED to READY_TO_CONNECT (confidence threshold). Every LLM decision feeds back into the model, making candidate selection progressively smarter.

Cold start: With fewer than 2 labelled profiles, the model can't fit — candidates are selected in order and qualified via LLM. As labels accumulate, the GP becomes better at selecting high-value candidates.

Configure rate limits and behavior via Django Admin (LinkedInProfile + Campaign models).


📂 Project Structure

├── docs/
│   ├── architecture.md              # System architecture
│   ├── configuration.md             # Configuration reference
│   ├── docker.md                    # Docker setup guide
│   ├── templating.md                # Follow-up messaging guide
│   └── testing.md                   # Testing strategy
├── linkedin/
│   ├── actions/                     # Browser actions (connect, message, status, search)
│   ├── agents/                      # ReAct follow-up agent (multi-turn conversations)
│   ├── api/                         # Voyager API client + parser + messaging package
│   ├── browser/                     # Session management, login, navigation
│   ├── conf.py                      # Configuration loading (.env + defaults)
│   ├── daemon.py                    # Task queue worker loop
│   ├── db/                          # CRM-backed CRUD (leads, deals, enrichment, chat)
│   ├── django_settings.py           # Django/CRM settings (SQLite at db.sqlite3)
│   ├── management/setup_crm.py      # Idempotent CRM bootstrap (Dept, Stages, Closing Reasons)
│   ├── ml/                          # Bayesian qualifier (GPR), embeddings, profile text
│   ├── models.py                    # Django models (Campaign, LinkedInProfile, Task, etc.)
│   ├── onboarding.py                # Interactive onboarding (campaign, credentials, LLM config)
│   ├── pipeline/                    # Candidate sourcing, qualification, pool management
│   ├── setup/                       # GDPR, self-profile, freemium campaign setup
│   └── tasks/                       # Task handlers (connect, check_pending, follow_up)
├── manage.py                         # Django management (no args defaults to rundaemon)
├── local.yml                        # Docker Compose
└── Makefile                         # Shortcuts (setup, run, admin, test)

📚 Documentation


⚖️ License

GNU GPLv3 — see LICENCE.md


📜 Legal Notice

Not affiliated with LinkedIn.

By using this software you accept the Legal Notice. It covers LinkedIn ToS risks and liability disclaimers. This local fork disables the upstream freemium promotional outreach path and newsletter subscription request path.

Use at your own risk — no liability assumed.


This fork is maintained for student recruiter outreach.

About

AI-assisted recruiter outreach research tool for students. Python, Django, Playwright, Docker, LLM workflows.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages