How the Hiring Agent Caches Data for PDFs and GitHub Information

The hiring-agent tool persists expensive PDF extraction results and GitHub API responses to local JSON files within a cache/ directory, but only when the DEVELOPMENT_MODE environment variable is truthy, allowing subsequent evaluations to skip redundant parsing and network requests.

The interviewstreet/hiring-agent repository accelerates résumé scoring workflows by storing structured representations of processed data. When analyzing candidate profiles repeatedly during development, the tool avoids re-parsing PDF documents and re-fetching GitHub profiles by reading from validated cache files instead of performing expensive operations.

Caching Architecture Overview

The hiring agent implements conditional disk-based caching for two specific high-cost operations:

  1. PDF extraction: Converting résumé PDFs into structured JSONResume models
  2. GitHub data retrieval: Fetching candidate profile information from the GitHub API

Both caches share a similar pattern but target different data sources. The cache logic resides primarily in score.py (lines 14‑20, 26‑38, 57‑65, 69‑87, and 96‑104) with supporting utilities in github.py. Caching activates exclusively when DEVELOPMENT_MODE evaluates to true, ensuring production runs always fetch fresh data.

PDF Resume Caching

Cache File Naming

When processing a PDF file, the hiring agent constructs a deterministic cache filename in score.py (lines 14‑20) using the PDF's basename:

cache_filename = f"cache/resumecache_{os.path.basename(pdf_path).replace('.pdf', '')}.json"

The cache/ directory stores JSON files prefixed with resumecache_ followed by the PDF filename without extension.

Loading and Validation

During initialization, if DEVELOPMENT_MODE is enabled and the cache file exists, the system attempts to deserialize the cached data (lines 26‑38 in score.py):

if DEVELOPMENT_MODE and os.path.exists(cache_filename):
    cached_data = json.loads(Path(cache_filename).read_text())
    if is_valid_resume_data(cached_data):
        resume_data = JSONResume(**cached_data)
    else:
        os.remove(cache_filename)

The helper function is_valid_resume_data validates core resume sections. If validation fails or JSON parsing raises an exception, the code removes the invalid cache file via os.remove(cache_filename) and proceeds with fresh PDF extraction.

Writing Cache Entries

After successful PDF processing via PDFHandler().extract_json_from_pdf(pdf_path), the tool writes the structured result to disk (lines 57‑65):

if is_valid_resume_data(resume_data.model_dump()):
    Path(cache_filename).write_text(json.dumps(resume_data.model_dump(), indent=2))

This write operation only occurs when the extracted data contains valid core sections, preventing empty or malformed entries from polluting the cache.

GitHub Data Caching

Cache Structure

The GitHub caching mechanism follows a parallel structure but stores API response dictionaries rather than Pydantic models. In score.py (lines 69‑87), the system constructs a separate cache filename:

github_cache_filename = f"cache/githubcache_{os.path.basename(pdf_path).replace('.pdf', '')}.json"

Note that despite caching GitHub profile data, the filename derives from the PDF basename, maintaining a 1:1 relationship between a résumé file and its associated cached GitHub information.

Fetch and Store Logic

When DEVELOPMENT_MODE is active and the GitHub cache exists, the system loads the JSON and verifies it contains a required "profile" key:

if DEVELOPMENT_MODE and os.path.exists(github_cache_filename):
    github_data = json.loads(Path(github_cache_filename).read_text())
    if "profile" not in github_data:
        os.remove(github_cache_filename)
        github_data = fetch_and_display_github_info(github_profile.url)
else:
    github_data = fetch_and_display_github_info(github_profile.url)

Following a successful API call, the results persist to disk (lines 96‑104):

with open(github_cache_filename, 'w') as f:
    json.dump(github_data, f, indent=2)

The github.py file contains additional cache management utilities, including the _create_cache_filename helper function.

Activating Development Mode

To enable caching during development, export the environment variable before executing the scoring script:

export DEVELOPMENT_MODE=1
python score.py candidate_resume.pdf

When this variable is unset or falsy, the tool bypasses all cache checks and performs full PDF extraction and GitHub API requests on every run.

Error Handling and Cache Invalidation

Both caching implementations follow fail-fast validation patterns:

  • Automatic invalidation: Corrupted or outdated cache files trigger immediate deletion via os.remove() rather than attempting repair
  • Schema validation: PDF caches validate against JSONResume model requirements, while GitHub caches check for specific required keys like "profile"
  • Atomic writes: Cache writes use Path.write_text() or json.dump() with explicit file handles to ensure complete data persistence

The cache directory must exist before running; the code assumes the cache/ folder is available in the working directory.

Summary

  • The hiring-agent tool caches PDF extractions and GitHub API responses in separate JSON files within the cache/ directory
  • Caching only activates when DEVELOPMENT_MODE is truthy, ensuring production runs fetch fresh data
  • PDF cache files follow the pattern cache/resumecache_<pdf-name>.json and store validated JSONResume models
  • GitHub cache files follow cache/githubcache_<pdf-name>.json and store profile dictionaries requiring a "profile" key
  • Invalid cache files are automatically removed via os.remove() when validation fails, triggering fresh data extraction
  • Primary implementation resides in score.py (lines 14‑104) with supporting logic in github.py

Frequently Asked Questions

Where does the hiring agent store cached PDF and GitHub data?

The tool stores cached data in the cache/ directory within the project root. PDF extractions save as cache/resumecache_<pdf-name>.json, while GitHub profile data saves as cache/githubcache_<pdf-name>.json, where <pdf-name> derives from the original PDF filename without the .pdf extension.

How do I enable caching in the hiring agent?

Set the DEVELOPMENT_MODE environment variable to a truthy value before running the script. For example: export DEVELOPMENT_MODE=1. When this variable is not set or evaluates to false, the tool ignores cache files and performs fresh PDF parsing and GitHub API requests.

What happens if a cache file becomes corrupted?

If JSON deserialization fails or validation checks (like is_valid_resume_data() for PDFs or the "profile" key check for GitHub data) determine the cache is invalid, the code immediately removes the file using os.remove() and proceeds with the expensive operation to regenerate valid data.

Why does the GitHub cache filename use the PDF name instead of the GitHub username?

The hiring agent associates GitHub data with specific résumé submissions rather than standalone GitHub identities. Using the PDF basename ensures that cached GitHub information remains linked to the particular candidate file being processed, preventing confusion when evaluating multiple candidates who might share similar GitHub profile data.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →