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)
init_search.pyβ Reads yourmy_profile.pdfandsearch_objectives.txt. It uses Gemini to generate optimized search parameters for.envand an AI-derived candidate profile (_candidate_profile.txt).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.dedupe_results.pyβ Consolidates all CSV files in your results folder into oneconsolidated_matches.csv, removing duplicates across multiple search runs.extract_fresh_jobs.pyβ Compares your latest search against your previous one and extracts only the newly found jobs intofresh_job.csv. This is your "to-apply" list.auto_review_jobs.pyβ Visits every job URL in your latestcurated_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.
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 |
Google Gemini:
- Go to aistudio.google.com
- Click "Get API key" β "Create API key"
Adzuna:
- Go to developer.adzuna.com
- Click "Register" and create a free account
- Go to Dashboard β My Apps β Create App
- Copy both your App ID and API Key
uv sync # Requires Python 3.10+ and uvFill 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=...| File | What to do |
|---|---|
my_profile.pdf |
Drop your resume PDF here. |
search_objectives.txt |
Write your target roles, industries, and locations. |
uv run python init_search.pyThis validates your configuration and creates your AI profile.
uv run python run_search.pyNote: The script automatically caches results. If you cancel and restart, it skips the fetching phase and resumes filtering from where you left off.
After running multiple searches, use these tools to keep your application list clean.
uv run python dedupe_results.pyThis merges all curated_matches_*.csv files into a single consolidated_matches.csv, stripping duplicates by Adzuna ID and company/role.
uv run python extract_fresh_jobs.pyThis 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.
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:
- Finding the latest canonical
curated_matches_*file inoutputs/ - Scraping each job's live URL for its full description
- Calling Gemini (
GEMINI_MODELfrom your.env) with yoursearch_objectives.txtto produce a plain-English verdict and a bullet-point list of key requirements - Skipping any row you've already filled in manually β your reviews are never overwritten
- Saving results back to the original file (with an automatic backup on the first run)
# 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.tsvNote:
--testalways 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--testis safe and repeatable.
| 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 |
βββ 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.
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 |
| 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 |
| 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 |
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 rowsBuilt 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.