A Chrome extension + self-hosted backend that captures job postings, scores them against your resumes, finds the recruiter's email, and writes a personalised cold outreach email — in under 30 seconds.
- Visit any job posting on LinkedIn, Greenhouse, Lever, Workday, Indeed, or any job board
- Click the extension — it reads the page automatically
- Click "Capture & Process" — in 15–30 seconds you get:
- Your best-matching resume selected from all your uploaded resumes
- A match score (0–100%) with matched and missing skills
- The recruiter or hiring manager's email via Hunter.io
- A personalised cold outreach email ready to copy and send
- Day-7 and Day-14 follow-up emails scheduled automatically
- Review and send — nothing is sent without your approval
| Tool | AI resume matching | Recruiter email | Outreach email | Follow-ups | Cost |
|---|---|---|---|---|---|
| Teal / Simplify | No | No | No | No | Free |
| LazyApply | Bulk apply only | No | No | No | $40/mo |
| Sonara | Yes | No | No | No | $40/mo |
| AI Job Agent | Yes | Yes | Yes | Yes | ~$0/mo |
| Setup | What it uses | Monthly cost at 30 jobs/day |
|---|---|---|
| OpenAI only | GPT-4o + GPT-4o-mini + embeddings | ~$6.80 |
| Groq + OpenAI | Llama-3 (free) + embeddings only | ~$0.01 |
Recommended: set both GROQ_API_KEY (free, no card) and OPENAI_API_KEY (embeddings only). Costs essentially nothing.
Deploy the backend to Render's free tier in about 10 minutes.
- Fork this repository to your GitHub account
- Go to render.com and sign up (free)
- Click New → Web Service → connect your forked repo
- Set Runtime to Python, leave build/start commands as-is
- Add a free PostgreSQL database: New → PostgreSQL → copy the Internal Database URL
- Set environment variables (see Step 2)
- Click Deploy
Go to your web service → Environment tab:
| Variable | Required | Where to get it |
|---|---|---|
DATABASE_URL |
Yes | Render PostgreSQL → Internal URL |
OPENAI_API_KEY |
Yes | platform.openai.com/api-keys |
GROQ_API_KEY |
Recommended | console.groq.com — free |
HUNTER_API_KEY |
Recommended | hunter.io — free: 25 searches/month |
MATCH_SCORE_THRESHOLD |
Optional | Default 0.50 (0–1 range) |
Once deployed, open https://your-app.onrender.com/dashboard and click ⬆ Upload Resume in the top-right. Upload all your resume versions (general, backend-focused, AI-focused, etc.).
- Download or clone this repo to your computer
- Open Chrome →
chrome://extensions - Enable Developer mode (top-right toggle)
- Click Load unpacked → select the
extension/folder - Pin the extension to your toolbar
- Click the extension icon → paste your Render URL into the Backend field → Save
You're ready. Visit any job posting and click Capture & Process.
Used to embed resumes and job descriptions for similarity matching. Required even if you use Groq for the LLM — Groq has no embedding models.
- Go to platform.openai.com/api-keys → create a key
- Add $5 credit — will last years at 30 jobs/day (embeddings cost ~$0.01/month)
- Set
OPENAI_API_KEY
Runs Llama-3 for job parsing and outreach generation at no cost, no credit card required. When set, OpenAI is used only for embeddings.
- Go to console.groq.com → sign up → create a key
- Set
GROQ_API_KEY
Routing logic:
- Both keys set → Groq for LLM, OpenAI for embeddings (recommended)
- Only OpenAI → OpenAI handles everything (~$6.80/month at 30 jobs/day)
- Only Groq → won't work (no embeddings)
# 1. Clone
git clone https://github.com/YOUR_USERNAME/ai-job-agent.git
cd ai-job-agent
# 2. Virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3. Install
pip install -r requirements.txt
# 4. Configure
cp .env.example .env
# Edit .env — add OPENAI_API_KEY and optionally GROQ_API_KEY
# 5. Run
uvicorn backend.main:app --host 0.0.0.0 --port 8000Then open http://localhost:8000/dashboard to upload resumes, and load the extension pointing at http://localhost:8000.
- Navigate to any job posting
- Click the AI Job Agent icon in your toolbar
- Wait for "Ready to process" (green status)
- Click Capture & Process
- In 15–30 seconds you'll see:
- Match score + which resume was selected
- Matched and missing skills
- Outreach email — click "View email" to expand and copy
- Contacts found with LinkedIn links
- Click Mark as Applied after submitting — starts the Day-7 / Day-14 follow-up countdown
Click ⬆ Upload resume PDF at the bottom of the extension popup to upload directly without opening the dashboard.
| Score | Meaning |
|---|---|
| 75–100% | Strong match — apply with confidence |
| 55–75% | Good match — worth applying |
| 40–55% | Partial match — visible gaps |
| < 40% | Weak match — significant mismatch |
If you try to process a job you've already captured, the extension shows "Already captured — Application #N" instead of running the pipeline again.
Open https://your-app.onrender.com/dashboard to track all applications:
- Upload resumes via the ⬆ Upload Resume button
- Update status via dropdown (captured → applied → interviewing → offer / rejected)
- Filter by status with the chip strip
- Export full history as CSV
- View skill gaps — skills appearing most in jobs you're missing
Chrome Extension (popup.js + content.js)
│
│ POST /api/jobs/process
▼
FastAPI Backend
│
├─ job_parser.py → Groq Llama-3.3-70B or GPT-4o
├─ resume_matcher.py → Hybrid score: 0.4×embedding + 0.6×keyword overlap
├─ embeddings.py → OpenAI text-embedding-3-small
├─ outreach_generator → Groq Llama-3.1-8B or GPT-4o-mini
├─ recruiter_finder → Hunter.io: find + verify recruiter email
└─ database.py → Postgres (Render) / SQLite (local)
Hybrid scoring formula:
hybrid = 0.4 × norm_embedding + 0.6 × keyword_overlap
norm_embedding = clamp((cosine − 0.20) / 0.50, 0, 1)
Full interactive docs at https://your-app.onrender.com/docs.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/jobs/process |
Full pipeline — called by the extension |
GET |
/api/applications |
List all applications |
PATCH |
/api/applications/{id}/status |
Update application status |
POST |
/api/applications/{id}/apply |
Mark applied, start follow-up countdown |
POST |
/api/resumes/upload |
Upload a PDF resume |
GET |
/api/resumes |
List uploaded resumes |
GET |
/api/resumes/gaps |
Skill gap report across all jobs |
GET |
/api/export/csv |
Download all applications as CSV |
GET |
/dashboard |
HTML application dashboard |
GET |
/health |
Health check |
| Variable | Default | Description |
|---|---|---|
OPENAI_API_KEY |
— | Required. Embeddings (+ LLM if no Groq key) |
GROQ_API_KEY |
— | Recommended. Free LLM via Groq (Llama-3) |
DATABASE_URL |
SQLite locally | Postgres connection string on Render |
HUNTER_API_KEY |
— | Optional. Recruiter email finder. Free: 25/month |
API_KEY |
— | Optional. Secret to protect write endpoints |
MATCH_SCORE_THRESHOLD |
0.50 |
Min score to generate outreach (0–1) |
FOLLOWUP_DAY_1 |
7 |
Days after applying to draft first follow-up |
FOLLOWUP_DAY_2 |
14 |
Days after applying to draft final follow-up |
SCHEDULER_TIMEZONE |
America/New_York |
Timezone for follow-up scheduler |
LOG_LEVEL |
INFO |
Logging level |
LinkedIn · Greenhouse · Lever · Workday · Indeed · Ashby · any site with <main> or <article> content
See CONTRIBUTING.md for setup instructions.
Good first issues:
- Add more job board selectors to
extension/content.js - Add more skills to the vocabulary in
backend/agents/resume_matcher.py - Write integration tests for the
/api/jobs/processpipeline
- Resume text and embeddings are stored in your own database — not shared with anyone
- Job posting text is sent to OpenAI or Groq for parsing (subject to their data policies)
- Only the company domain is sent to Hunter.io — not your personal data
MIT — free to use, modify, and distribute.
Built with FastAPI · OpenAI · Groq · Hunter.io · Chrome Extensions API