Skip to content

MisterStranger03/JobPilot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🧭 JobPilot - a local, tool-calling AI job-application agent

An autonomous agent that prepares a job application end-to-end: it fetches a job posting, parses your resume, runs a hybrid ATS compatibility check, and generates grounded tailoring suggestions - running 100% locally on an 8B model via Ollama. No API keys, no rate limits, and your resume never leaves your machine.

   Next.js UI ─────┐  (streams the agent trace live over NDJSON)
   Streamlit UI ───┼──▶ FastAPI / direct call
   CLI ────────────┘         │
                             ▼
              ┌───────────────────┐     ┌──────────────────────────┐
resume file ─▶│  Agent loop (LLM  │────▶│ tools                    │
 (PDF/DOCX)   │  plans each step) │◀────│  fetch_job_posting       │
job URL/text ▶│  or direct        │     │  extract_job_info  (LLM) │
              │  pipeline (ATS-   │     │  parse_resume            │
              │  only, rewrite)   │     │  run_ats_check   (hybrid)│
              └─────────┬─────────┘     │  tailor_resume     (LLM) │
                        │               │  rewrite_resume    (LLM) │
                 decision trace         │  save_report             │
                        ▼               └──────────────────────────┘
              trace + report + rewritten resume (opt-in)

Three frontends share one core: a Next.js + FastAPI web app (streaming trace), a Streamlit app, and a CLI. Two modes everywhere: full agent run or a standalone ATS test (job posting optional, without one it's a general resume health check). After any run with a job, JobPilot asks whether you want your resume rewritten for that job - the draft never invents experience.

Why it's interesting (design decisions)

  • Hand-rolled agent loop, no framework. The loop in jobpilot/agent.py is ~100 lines: model plans → tool executes → result feeds back → repeat. Includes a step cap, duplicate-call detection, and per-step error strings the model can recover from (a failed scrape tells the model to ask for pasted text instead of retrying).
  • Small tool args, shared context. An 8B model corrupts long JSON in tool arguments, so tools exchange large state (resume text, job info, ATS report) through an AgentContext object and the model only passes tiny args like a URL.
  • Hybrid ATS checker - deterministic where it matters. Keyword coverage (with a synonym table so "JS" matches "JavaScript"), section/contact/format checks, and quantified-bullet analysis are pure Python and unit-tested offline; only semantic fit uses embeddings (nomic-embed-text cosine similarity) and the score degrades gracefully if the embedding model is missing.
  • Grounded tailoring & rewriting. Tailoring and full-resume rewrites are fed the ATS gap analysis but hard-constrained to never invent experience - missing skills are never offered to the rewriter (early testing showed the model would "help" by adding them), and generic keywords are woven in only where the original resume shows evidence. Rewrites are opt-in: the app asks first.
  • Streaming agent trace. The FastAPI endpoint streams each tool call as NDJSON; the Next.js UI renders the agent's decisions live.
  • Swappable LLM provider. Everything talks to an abstract LLMClient (chat + embeddings); the Ollama implementation is ~80 lines, so pointing the agent at Anthropic/OpenAI is a one-class change.

ATS scoring rubric

Category Weight Method
Keyword coverage 40% required/preferred/other keywords, whole-word + synonym matching
Semantic fit 15% embedding cosine (resume vs posting), rescaled
Sections 15% experience / education / skills / projects detection
Contact info 10% email, phone, LinkedIn/GitHub
Content quality 20% length, quantified bullets, action verbs, dates, pronouns

Quickstart

# 1. Ollama + models (one-time, ~5.5 GB)
ollama pull qwen3:8b && ollama pull nomic-embed-text

# 2. Python env
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt

# 3a. Web app (FastAPI + Next.js)
.venv/bin/uvicorn server.main:app --port 8000        # terminal 1
cd web && npm install && npm run dev                 # terminal 2 → http://localhost:3000

# 3b. or Streamlit
.venv/bin/streamlit run app.py

# 3c. or CLI  (--ats-only for a standalone ATS test; --rewrite to skip the prompt)
.venv/bin/python cli.py --resume my_resume.pdf --job-file job.txt
.venv/bin/python cli.py --resume my_resume.pdf --ats-only

Example output

On a test run (ML-intern posting vs a student resume) the agent scored 74/100 (good): all 5 required skills matched, and it correctly flagged missing evaluation-methodology keywords (cross-validation, AUC, precision/recall) plus content issues (thin resume, weak action verbs) — see reports/ after a run.

Beyond the score

  • Detailed resume review with every ATS test - strengths, weaknesses, and prioritized fixes, quoting your actual lines.
  • Opt-in rewrite & cover letter, grounded in your real experience (never invents anything), exportable as PDF / DOCX / MD / HTML.
  • Compare mode ranks one resume against several postings, best match first.
  • Run history tracks score changes per resume/job pair over time.
  • Evaluation harness (python -m evals.run): labeled cases with expected score bands - scoring changes can't silently regress.

Limitations & Next Steps

  • JS-rendered job boards (LinkedIn, Workday) block plain HTTP fetch, paste the posting text instead. (The Next Step: Playwright-based fetcher.)
  • Keyword extraction quality depends on the local model; a cleanup pass strips company names / locations / generic terms it tends to emit.
  • Next Step: DOCX in-place resume editing, cloud-provider backends (Anthropic/OpenAI) behind the existing LLMClient interface.

Snapshots

Screenshot 2026-07-04 at 11 13 37 AM

About

Local AI job-application agent that scores your resume against any job posting with a hybrid ATS checker, then rewrites it and drafts a cover letter, grounded in your real experience. Runs 100% offline on Ollama (no API keys). Next.js + FastAPI + Streamlit.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors