How the Caching Mechanism Functions in Development Mode in Hiring Agent

In development mode, the hiring-agent repository uses a lightweight file-based JSON cache to speed up résumé parsing and GitHub API calls, automatically bypassing these caches in production and self-healing by removing corrupted files.

The interviewstreet/hiring-agent repository implements a deterministic file-based caching system governed by the DEVELOPMENT_MODE configuration flag. When enabled, this mechanism stores intermediate processing results to eliminate redundant API requests and PDF parsing during iterative development. The caching mechanism functions exclusively in development environments, ensuring production deployments always retrieve fresh data directly from sources.

How Development Mode Activates the Cache

The cache system hinges on the DEVELOPMENT_MODE boolean defined in config.py. When this value is set to True (the default for local development), conditional blocks throughout the codebase activate file-based caching behaviors. In production environments where DEVELOPMENT_MODE is False, these conditional branches are skipped entirely, forcing the application to process PDFs and fetch GitHub data from live sources on every execution.

The cache directory is created dynamically using os.makedirs(..., exist_ok=True), ensuring the system fails gracefully on first run without requiring manual directory setup.

Resume Parsing Cache in score.py

The résumé parsing pipeline in score.py (specifically around lines 227-260) implements caching for parsed PDF content to avoid reprocessing identical files during development iterations.

When score.py initializes, it checks for the existence of a cache file before invoking the parser:


# development-mode cache check

if DEVELOPMENT_MODE and os.path.exists(cache_filename):
    print(f"Loading cached data from {cache_filename}")
    try:
        cached_data = json.loads(Path(cache_filename).read_text(encoding="utf-8"))
        loaded_resume = JSONResume(**cached_data)
        cache_loaded = True
    except Exception as e:
        print(f"⚠️ Warning: Invalid cache file {cache_filename}: {e}")
        print("Ignoring cache and reprocessing PDF...")
        os.remove(cache_filename)

If no valid cache exists, the system parses the PDF and writes the resulting JSON representation to cache/resumecache_*.json:

if not cache_loaded:
    # ... parsing logic ...

    if resume_data_is_valid:
        os.makedirs(os.path.dirname(cache_filename), exist_ok=True)
        Path(cache_filename).write_text(
            json.dumps(resume_dict, ensure_ascii=False, indent=2), encoding="utf-8"
        )

GitHub API Response Caching in github.py

The GitHub integration module in github.py (lines 35-50) employs an identical pattern to avoid rate-limiting issues and speed up repeated API calls during development.

Before executing an HTTP request, the code checks for a cached response:

cache_filename = _create_cache_filename(api_url, params)
if DEVELOPMENT_MODE and os.path.exists(cache_filename):
    print(f"Loading cached GitHub data from {cache_filename}")
    try:
        cached_data = json.loads(Path(cache_filename).read_text(encoding="utf-8"))
        if cached_data:
            return 200, cached_data
    except Exception as e:
        print(f"⚠️ Warning: Error reading cache file {cache_filename}: {e}")
        os.remove(cache_filename)

Successful API responses are persisted immediately upon retrieval:

if DEVELOPMENT_MODE and status_code == 200:
    os.makedirs("cache", exist_ok=True)
    Path(cache_filename).write_text(
        json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
    )

Cache Naming Conventions and Storage Structure

Cache files follow deterministic naming schemes based on input parameters to ensure consistent cache hits across application restarts. Résumé caches use the pattern resumecache_*.json derived from the source PDF filename, while GitHub caches use gh_githubcache_*.json based on the API URL and request parameters.

All cache files are stored in a cache/ subdirectory at the project root. The system automatically creates this directory when writing the first cache entry, eliminating setup friction for new development environments.

Automatic Corruption Detection and Recovery

The caching mechanism implements robust error handling to prevent stale or corrupted data from crashing the application. If json.loads() raises an exception during cache retrieval—whether due to manual file editing, disk corruption, or schema changes—the system immediately deletes the offending file using os.remove(cache_filename) and falls back to fresh processing.

This self-healing behavior ensures that developers never need to manually intervene when cache files become invalid; the system transparently reprocesses the source data and generates a new cache entry on the next successful execution.

When to Manually Clear the Development Cache

While the system handles corrupted files automatically, you should manually clear the cache directory in several specific scenarios:

  • Content updates with identical filenames: If you modify a PDF's contents but retain the original filename, the deterministic cache key will return stale parsed data. Delete the specific resumecache_*.json file to force reprocessing.
  • Schema changes: When updating the JSONResume model or GitHub response parsing logic, existing cache files may contain incompatible data structures. Clear the entire cache/ directory to prevent deserialization errors.
  • Debugging freshness issues: If you suspect cached data is masking recent changes to GitHub repositories or résumé content, removing the relevant cache files ensures you are viewing live data without disabling DEVELOPMENT_MODE.

To clear the cache, simply delete the cache/ directory or specific *.json files within it before running the application.

Summary

  • The caching mechanism functions exclusively when DEVELOPMENT_MODE is True in config.py, with production runs always fetching fresh data.
  • score.py caches parsed résumé JSON as resumecache_*.json files to avoid redundant PDF processing during development iterations.
  • github.py stores API responses as gh_githubcache_*.json to prevent repeated HTTP requests and rate-limiting delays.
  • Cache files use deterministic naming based on input parameters and are stored in an auto-generated cache/ directory.
  • Corrupted cache files trigger automatic deletion and reprocessing, while manual clearing is required when source content changes but filenames remain constant.

Frequently Asked Questions

Where are the cache files stored in the hiring-agent repository?

Cache files are stored in the cache/ directory at the project root. The system creates this directory automatically using os.makedirs(..., exist_ok=True) when writing the first cache entry, so no manual setup is required.

Does the caching mechanism work in production mode?

No. When DEVELOPMENT_MODE is set to False in config.py, all cache conditional blocks are bypassed. The application always parses PDFs fresh and makes live GitHub API requests, ensuring production data is never stale.

How does the system handle corrupted cache files?

If reading a cache file raises an exception—whether from JSON syntax errors, schema mismatches, or disk corruption—the system prints a warning message, deletes the file using os.remove(cache_filename), and immediately reprocesses the source data to generate a fresh cache entry.

When should I manually delete cache files?

Manually clear cache files when you modify PDF contents without renaming the file (since cache keys are based on filenames), when updating data models that change the expected JSON structure, or when debugging to ensure you are viewing live API responses rather than cached 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 →