How interviewstreet/hiring-agent works
Purpose and entry points
Hiring Agent is a Python 3.11+ CLI pipeline that ranks resume PDFs for a selected role. Its main entry point is score.py, invoked with a PDF and required --role; it also scaffolds new role bundles via --init-role. The pipeline produces a structured evaluation with category scores, evidence, bonuses, and deductions.
Paths: score.py, roles.py, roles/software_engineering_intern/role.json
Orchestration and lifecycle
score.py coordinates the full workflow: parse PDF, optionally enrich from GitHub, evaluate against the role rubric, print a report, and—when development mode is enabled—cache intermediate data and append a role-specific CSV. config.py centralizes development-mode behavior and model/provider resolution.
Paths: score.py, config.py, evaluator.py
PDF ingestion and resume structuring
PDF content crosses an untrusted-document boundary before LLM use. pymupdf_rag.py extracts pages into Markdown-like text using PyMuPDF; pdf.py partitions content into resume sections and sends each section through prompt-driven LLM extraction. The assembled output is a typed JSON Resume-style representation, normalized from potentially loose model JSON.
Paths: pymupdf_rag.py, pdf.py, models.py, transform.py
Prompt and schema boundary
Extraction is controlled by Jinja templates per resume section, while typed models define expected LLM/provider interfaces and resume structures. This is the key boundary between probabilistic LLM responses and application data: templates constrain output, response cleanup occurs in the LLM layer, and transformation/schema logic makes it usable downstream.
Paths: prompts/template_manager.py, prompts/templates/basics.jinja, prompts/templates/projects.jinja, llm_utils.py, models.py
GitHub enrichment
If the parsed resume exposes a GitHub profile, the enrichment stage fetches profile and repository signals, classifies projects, and uses an LLM prompt to select exactly seven meaningful repositories subject to contribution criteria. GitHub is an optional external dependency; GITHUB_TOKEN improves API rate limits, and development mode caches fetched results.
Paths: github.py, prompts/templates/github_project_selection.jinja, score.py
Role-driven evaluation
Evaluation is not hardcoded to one rubric. evaluator.py loads the selected role bundle and asks the LLM to apply its criteria and fairness constraints. role.json drives categories, weight maxima, bonuses, deductions, score bounds, reporting fields, and CSV columns; role-specific Jinja files provide the scoring system message and criteria.
Paths: evaluator.py, roles.py, roles/software_engineering_intern/role.json, roles/software_engineering_intern/criteria.jinja
LLM providers and infrastructure
The application supports local Ollama and hosted Google Gemini via OpenAI-compatible endpoints behind a shared provider abstraction. providers.json maps models to provider base URLs, required API-key environment variables, and model parameters; DEFAULT_MODEL selects a configured model. Ollama runs locally (default model is gemma4:latest), while Gemini requires GEMINI_API_KEY.
Paths: providers.json, config.py, models.py, llm_utils.py
Main entry points: llm_utils.py LLM gateway · score.py score CLI · pdf.py Resume parser · github.py GitHub enricher
Components 18
CLI orchestration
- score CLI · Runs scoring or initializes role bundles.
score.py - Runtime config · Resolves development mode and selected model/provider.
config.py
Resume ingestion
Untrusted PDF is converted into structured resume data.
- PDF text extraction · Converts PDF pages to Markdown-like text.
pymupdf_rag.py - Resume parser · Partitions resume content and invokes section extraction.
pdf.py - Extraction templates · Constrain per-section resume extraction.
prompts/template_manager.py - Resume prompt examples
prompts/templates/basics.jinja - Response normalization · Makes loose model JSON usable downstream.
transform.py
GitHub enrichment
- GitHub enricher · Fetches profile and repository signals when a profile is present.
github.py - Repository selection prompt · Selects exactly seven meaningful repositories.
prompts/templates/github_project_selection.jinja
Role evaluation
- Role loader · Loads selected role definitions and scaffolds bundles.
roles.py - Intern role rubric · Defines weights, score bounds, bonuses, deductions, and report fields.
roles/software_engineering_intern/role.json - Role scoring criteria
roles/software_engineering_intern/criteria.jinja - Rubric evaluator · Applies role criteria and fairness constraints to the candidate.
evaluator.py
LLM infrastructure
- Typed models · Defines resume data and provider-facing structures.
models.py - LLM gateway · Cleans responses and sends OpenAI-compatible requests.
llm_utils.py - Provider registry · Maps models to endpoints, API-key variables, and parameters.
providers.json - Local Ollama · Default local model runtime.
- Google Gemini · Hosted provider requiring GEMINI_API_KEY.
Connections 21
- score CLI → Runtime config: loads runtime settings
- score CLI → PDF text extraction: PDF input
- PDF text extraction → Resume parser: page text
- Resume parser → Extraction templates: selects prompts
- Extraction templates → Resume prompt examples: loads section templates
- Resume parser → LLM gateway: extracts sections
- LLM gateway → Response normalization: cleaned model JSON
- Response normalization → Typed models: typed resume
- score CLI → GitHub enricher: optional profile enrichment
- GitHub enricher → Repository selection prompt: repository selection
- GitHub enricher → LLM gateway: classifies/selects projects
- score CLI → Rubric evaluator: candidate data + role
- Rubric evaluator → Role loader: loads selected bundle
- Role loader → Intern role rubric: rubric definition
- Role loader → Role scoring criteria: scoring prompt
- Rubric evaluator → LLM gateway: requests evaluation
- LLM gateway → Typed models: uses response schemas
- Runtime config → Provider registry: resolves model
- Provider registry → LLM gateway: endpoint configuration
- LLM gateway → Local Ollama: local requests
- LLM gateway → Google Gemini: hosted requests