Skip to content

AutoViML/job_search_agent

Repository files navigation

πŸ€– Adzuna Gemini Job Search Agent

Python Gemini Adzuna License


πŸš€ Smart, Automated, and Deeply Personalized Job Hunting

Adzuna Gemini Agent is a high-performance career tool that bridges the gap between massive job databases and your specific career stage. By combining the Adzuna API with Google's Gemini LLM, it doesn't just find jobsβ€”it understands them.

Created by Ram Seshadri (2026)


✨ How It Works

  1. init_search.py β†’ Reads your my_profile.pdf and search_objectives.txt. It uses Gemini to generate optimized search parameters for .env and an AI-derived candidate profile (_candidate_profile.txt).
  2. run_search.py β†’ The complete engine. It automatically detects your experience level using Gemini and applies one of three STRICT FILTER modes (NEW GRAD, MID-LEVEL, or SENIOR). It then fetches jobs from Adzuna and filters them in parallel.
  3. dedupe_results.py β†’ Consolidates all CSV files in your results folder into one consolidated_matches.csv, removing duplicates across multiple search runs.
  4. extract_fresh_jobs.py β†’ Compares your latest search against your previous one and extracts only the newly found jobs into fresh_job.csv. This is your "to-apply" list.
  5. auto_review_jobs.py β†’ Visits every job URL in your latest curated_matches_*.xlsx (or .csv), scrapes the live page, and uses Gemini to fill in two columns: "Fit for you" (a plain-English verdict) and "Job Requirements Comments" (the key requirements). Rows you've already reviewed manually are never overwritten.

πŸ”‘ Step 1 β€” Get Your API Keys

You need two free API keys: Google AI Studio (for Gemini) and Adzuna (for job search).

Service Where to get it Notes
Gemini aistudio.google.com Copy the key starting with AIzaSy...
Adzuna developer.adzuna.com Get your App ID and API Key

πŸ› οΈ Getting your keys:

Google Gemini:

  1. Go to aistudio.google.com
  2. Click "Get API key" β†’ "Create API key"

Adzuna:

  1. Go to developer.adzuna.com
  2. Click "Register" and create a free account
  3. Go to Dashboard β†’ My Apps β†’ Create App
  4. Copy both your App ID and API Key

βš™οΈ Step 2 β€” Configure Your Search

2a. Install dependencies

uv sync   # Requires Python 3.10+ and uv

2b. Set up your .env file

Fill in your API keys. The search parameters below will be automatically populated by the initializer.

GEMINI_API_KEY=...
ADZUNA_APP_ID=...
ADZUNA_API_KEY=...

# Optional settings
TEST_RUN=True      # True = quick 5-job test | False = full run
SEARCH_QUERIES=...
SEARCH_LOCATIONS=...

2c. Add your resume and objectives

File What to do
my_profile.pdf Drop your resume PDF here.
search_objectives.txt Write your target roles, industries, and locations.

πŸš€ Step 3 β€” Run It

Initial Setup (or when objectives change):

uv run python init_search.py

This validates your configuration and creates your AI profile.

Search & Filter:

uv run python run_search.py

Note: The script automatically caches results. If you cancel and restart, it skips the fetching phase and resumes filtering from where you left off.


🧹 Step 4 β€” Manage Results

After running multiple searches, use these tools to keep your application list clean.

Consolidate All Results:

uv run python dedupe_results.py

This merges all curated_matches_*.csv files into a single consolidated_matches.csv, stripping duplicates by Adzuna ID and company/role.

Find Only Fresh Jobs:

uv run python extract_fresh_jobs.py

This compares your latest search file against the previous one. It generates fresh_jobs.tsv (tab-separated) containing only the new jobs you haven't seen before. Use this to focus your daily applications. The TSV format avoids comma-quoting issues in complex job descriptions.


πŸ” Step 5 β€” Auto-Review Jobs with Gemini

After a search run, your curated_matches_*.xlsx file contains the filtered job list but the "Fit for you" and "Job Requirements Comments" columns are blank. auto_review_jobs.py fills them in automatically by:

  1. Finding the latest canonical curated_matches_* file in outputs/
  2. Scraping each job's live URL for its full description
  3. Calling Gemini (GEMINI_MODEL from your .env) with your search_objectives.txt to produce a plain-English verdict and a bullet-point list of key requirements
  4. Skipping any row you've already filled in manually β€” your reviews are never overwritten
  5. Saving results back to the original file (with an automatic backup on the first run)

Usage

# Test on 3 rows first β€” saves to *_test_output.xlsx, never touches the original
python3 auto_review_jobs.py --test

# Test on a custom number of rows
python3 auto_review_jobs.py --test 5

# Full run β€” process all blank rows and update the original file
python3 auto_review_jobs.py

# Target a specific file instead of auto-detecting the latest
python3 auto_review_jobs.py --file outputs/test_results/fresh_job.tsv

Note: --test always starts from a clean slate. It copies the source file, clears the AI columns in that copy, processes N rows, and saves to *_test_output.xlsx. Re-running --test is safe and repeatable.

Output columns

Column What Gemini writes
Fit for you 1–2 sentence verdict: Yes/No + reason based on your objectives
Job Requirements Comments Bullet-point list of key requirements extracted from the live job page

πŸ“‚ Project Structure & Privacy

β”œβ”€β”€ run_search.py           # πŸš€ Main engine (Fetching + Filtering)
β”œβ”€β”€ init_search.py          # πŸ”§ Config initializer
β”œβ”€β”€ dedupe_results.py       # 🧹 Result consolidator & deduplicator
β”œβ”€β”€ extract_fresh_jobs.py   # ✨ "New-only" job extractor
β”œβ”€β”€ auto_review_jobs.py     # πŸ” AI reviewer β€” fills Fit/Requirements columns
β”œβ”€β”€ search_objectives.txt   # 🎯 Your target roles, industries & locations
β”œβ”€β”€ _candidate_profile.txt  # πŸ‘€ AI-summarized profile (Private)
β”œβ”€β”€ .env                    # πŸ”‘ API Keys & model settings (Private)
β”œβ”€β”€ outputs/                # πŸ“„ XLSX/CSV matches (Private)
β”‚   β”œβ”€β”€ test_results/       #     Results from TEST_RUN=True runs
β”‚   └── search_results/     #     Results from full runs

Privacy Note: Your PDF resume, .env keys, _candidate_profile.txt, and the entire outputs/ folder are automatically excluded from git via .gitignore. Your data stays local.


πŸŽ›οΈ Adjusting Your Search

Everything is controlled from .env and your source text files β€” no code changes needed.

Want to... Action
Change roles Edit search_objectives.txt and run init_search.py
Switch to full run Change TEST_RUN=False in .env
Widen the search radius Change DISTANCE_KM in .env
Get more results per query Change ADZUNA_LIMIT_PER_SEARCH=50 (max 50)
Update your background Edit search_objectives.txt or my_profile.pdf then run init_search.py

πŸ› Quick Troubleshooting

Error Fix
GEMINI_API_KEY missing Add it to .env
HTTP 401 from Adzuna Double-check ADZUNA_APP_ID and ADZUNA_API_KEY
0 jobs found for a query Query too specific β€” broaden it (e.g. "mechanical engineer" not "mechanical engineer semiconductor NJ")
CSV has 0 rows Gemini filtered everything out β€” widen your objectives in search_objectives.txt
Module not found Run uv sync to install dependencies

πŸ“Š API Usage Reference

Config API calls used Est. unique jobs
4 queries Γ— 1 location 4 calls ~200
4 queries Γ— 5 locations 20 calls ~700
Free tier limit 250 calls/month ~12 full runs/month

πŸ†• New User's Workflow

git clone <your-repo>
cp .env.example .env        # fill in your API keys
uv sync
uv run python init_search.py   # generate your AI candidate profile
uv run python run_search.py    # fetch & filter jobs β†’ curated_matches_*.xlsx
python3 auto_review_jobs.py --test   # test AI review on 3 rows
python3 auto_review_jobs.py          # full AI review of all rows

Built with Gemini AI + Adzuna Job Search API. This is not an endorsement of any company or organization. This is a tool created for educational purposes only.

About

Uses Adzuna and Gemini to search Jobs from multiple locations and multiple roles using your resume.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages