Hiring Agent turns resume PDFs and GitHub signals into explainable scores

The open-source Hiring Agent pipeline parses PDFs to JSON Resume, enriches with GitHub repo metrics, and scores candidates with role-specific rubrics. Here is the architecture and where I would add guardrails.

SaifullahSaifullah
4 min read
Hiring Agent turns resume PDFs and GitHub signals into explainable scores

Resume screening is two bad options stacked together: humans skimming PDFs in ten seconds, or black-box ATS keyword bingo. The open-source Hiring Agent project (also mirrored under interviewstreet/hiring-agent) takes a third path: structured extraction, GitHub enrichment, and explainable scoring you can run locally with Ollama or vMLX, or swap in Google Gemini.

I do not think AI should auto-reject humans. I do think engineers deserve a pipeline that reads their PDF and their commits before anyone asks them to whiteboard FizzBuzz again.

End-to-end pipeline

The orchestrator is score.py. It wires five stages:

  1. PDF to Markdown (pymupdf_rag.py) with headings, links, and tables preserved enough for LLM parsing.
  2. Sectioned JSON extraction (pdf.py + Jinja templates in prompts/templates/) into a JSONResume object (models.py).
  3. GitHub enrichment (github.py): profile fetch, repo classification, LLM picks seven meaningful projects with a minimum author-commit threshold.
  4. Role-aware evaluation (evaluator.py) with fairness constraints baked into system prompts.
  5. Stdout summary + optional CSV when DEVELOPMENT_MODE=True caches intermediates under cache/.
Hiring Agent pipeline from PDF resume through GitHub enrichment to scored evaluation

That is a clean separation of concerns. Swapping models does not require rewriting PDF parsing. Swapping rubrics means editing role YAML, not the GitHub client.

GitHub enrichment is the differentiator

Plenty of resume parsers stop at skills arrays. Hiring Agent tries to answer a harder question: what did this person actually ship?

github.py:

  • Extracts a username from resume profiles
  • Pulls profile metadata and repositories
  • Classifies each project (open source vs toy vs production-ish signals)
  • Asks the LLM to select exactly seven unique repos with meaningful author commits

That last step is important. A candidate with forty forks should not drown evaluators. The model must justify which repos represent real work.

StageOutput
PDF parseJSON Resume sections (basics, work, education, skills, projects)
GitHub fetchRepo list + commit heuristics
LLM repo pickTop 7 evidence repos
EvaluatorCategory scores + bonuses + deductions + narrative evidence

Scoring rubric and explainability

evaluator.py scores against a role you pass on the CLI. Each role loads categories and weights from roles/<role>/criteria.yaml with Jinja templates for fairness rules.

Published categories include:

  • open_source
  • self_projects
  • production
  • technical_skills

Plus explicit bonus and deduction lines. The stdout summary is meant for humans: not just a number, but why the number moved.

Hiring Agent scoring rubric with open source, projects, production, and skills categories

That design is closer to how good hiring managers already think. The LLM is doing structured note-taking, not replacing judgment.

Local vs hosted LLM providers

The README supports:

  • Ollama or vMLX for fully local runs (privacy-friendly for HR data)
  • Google Gemini when you want a stronger extractor without operating GPUs

Templates are per-section (basics.jinja, work.jinja, skills.jinja, etc.), which reduces the classic "one-shot JSON hallucination" failure mode. Each call has a narrow job.

# Example shape: see repo README for env vars and role names python score.py path/to/resume.pdf --role backend_engineer

Set DEVELOPMENT_MODE=True during tuning to append rows to resume_evaluations.csv and inspect cached JSON in cache/.

Guardrails I would add before trusting scores

Open source does not mean "ship to production HR without edits." If I were hardening this for a client:

  1. Bias audits on synthetic resumes (names, schools, gendered language) similar to what projects like Candisift document for ATS ranking.
  2. Human-in-the-loop gate: AI produces evidence packets; humans make reject/advance calls.
  3. GitHub rate limits and private repos: not every strong candidate has public code. Missing GitHub should be neutral, not punitive.
  4. PDF OCR path for scanned resumes (Hiring Agent is PyMuPDF-first; scanned docs need a fallback extractor).
  5. Retention policy: cache/ CSV defaults are great for dev; prod needs encryption and deletion workflows.

Also compare with keyword matchers like Resume-Matcher if your problem is JD tailoring, not holistic evidence scoring. Different tools, different failure modes.

Where this fits my applied AI work

Teams hire me to automate ops, not to automate ethics away. Hiring Agent is interesting because it is inspectable: templates, criteria YAML, cached JSON, CSV exports. That is the same shape I want in voice agents and CRM automations: auditable steps, explicit rubrics, local inference options.

If you are building recruiting automation, start by measuring time-to-evidence (how fast a recruiter gets a justified shortlist), not time-to-reject.

Want help wiring local LLM pipelines with audit trails for HR or ops? Book a free discovery call.

Share this post

Related posts