Job Search Agent: AI-Powered Career Pipeline
An automated job search system that monitors 1,975 companies across 11 ATS platforms, processes 58,807 jobs weekly through a 6-phase AI pipeline, and delivers 311 qualified matches for $5.04 per run.
A note on data collection ethics: This is a personal research project built as a real-world demonstration of Claude Code, Anthropic’s Agent SDK, and modern AI-assisted development. It has no commercial purpose and no collected data was shared with third parties. All job postings were retrieved from public APIs (Greenhouse, Lever, Ashby, and similar), public RSS feeds, and unauthenticated career pages, the same information available to any person visiting those websites in a browser. No logins were used, no CAPTCHAs were bypassed, and no authentication or access controls were circumvented. The pipeline runs once per week, we respected robots.txt directives, and all requests were rate-limited. This article is for educational purposes and does not constitute legal advice on data collection practices.
Overview
An end-to-end job search automation system that replaces manual career page browsing with a fully automated weekly pipeline. The system monitors 1,975 companies across 11 applicant tracking system (ATS) platforms, processes 58,807 job postings through a 6-phase pipeline, and delivers 311 qualified matches to a dark-themed ag-Grid dashboard, all for $5.04 per run. Three different Claude models handle distinct roles: Haiku 4.5 enriches every posting, Sonnet wrote 69 of the retrievers, and Claude Code maintains the pipeline when platforms change underneath it.
The Problem
The best jobs are invisible. LinkedIn, Indeed, and Glassdoor show you what companies pay to advertise, a fraction of what is actually open. The real postings live on company career pages, buried inside ATS platforms with names like Greenhouse, Workday, Lever, and Ashby. Each platform has its own portal, its own layout, its own search interface. Some expose clean APIs. Most do not.
For two CS graduates targeting AI companies, cloud platforms, and Canadian tech firms, the math was brutal. 1,975 companies across 11 different ATS portals, each requiring separate navigation, searching, and reading. Checking them all manually is a full-time job in itself, and by the time you finish the list the earliest postings are already two weeks old.
The challenge is not just the volume. It is the heterogeneity. “Just use the Greenhouse API” covers about one company in nine. The other 89% require browser automation, DOM traversal, and a tolerance for platforms that were never designed to be read by machines. Some platforms migrate from one vendor to another. Some rename their URL slugs. Some quietly deprecate endpoints. A static collection script written on Monday is often broken by Friday.
Before: Manual Career Page Browsing
| Before | After |
|---|---|
| Manually visiting career pages one by one | 1,975 companies monitored automatically across 11 ATS platforms |
| Reading every job posting to check relevance | Claude Haiku 4.5 filters and enriches 58,807 jobs down to 311 qualified matches |
| Tracking applications in scattered spreadsheets | Full-featured ag-Grid dashboard with 35+ columns, per-user state, and saved layouts |
| Hours of daily effort with incomplete coverage | 29 parallel batches complete in approximately 20 minutes for $5.04 |
| Static scripts that break when platforms change | Self-healing retrievers that diagnose failures and repair themselves |

Our Approach
Filter Ordering as the Cost Strategy
A naive pipeline would hand every one of the 58,807 weekly postings to an LLM for classification. At roughly $0.05 per job for careful extraction, that comes out to roughly $2,900 per week, or $150,000 per year, to classify postings that are mostly obvious rejects from the first sentence. The architectural pivot was to treat the LLM as the last filter, not the first. Free regex filters reject 94% of postings before any paid work begins. A SHA-256 deduplication pass removes another 16% of what remains. Only 312 postings reach Claude Haiku 4.5, and only 311 survive to the dashboard. The cheapest API call is the one you never make.

Three Claude Models, Three Roles
Rather than one generalist model doing everything, the system assigns the right Claude to the right job. Haiku 4.5 handles the high-volume, repetitive enrichment work where the per-call cost has to stay near zero. Sonnet handles the rare, high-stakes code generation work where reasoning quality matters more than per-call cost. Claude Code handles the maintenance loop, where stateful context and tool orchestration matter more than raw model calls.

The Analyst (Claude Haiku 4.5) classifies seniority, extracts salary ranges, identifies requirements, formats descriptions, and decides whether each posting is a real software role. It also re-enriches on demand. Paste a job description into the dashboard’s edit dialog, hit Save, and Haiku re-analyzes it in about 2 seconds for $0.0003.
The Builder (Claude Sonnet) writes browser-based retrievers automatically through a multi-agent system built on the Anthropic Agent SDK. An orchestrator dispatches companies to three parallel worker agents. Each worker visits the career page, analyzes the DOM, writes a retriever, tests it in a subprocess, and self-corrects until the tests pass. The key was not clever prompting. It was a 1,466-line curriculum, packaged as a Claude Code Skill with reference docs, that teaches the agent how ATS platforms actually behave. 69 production retrievers, $49.68 total, zero manual edits.
The Maintainer (Claude Code) runs the self-healing layer. Custom hooks inject failure context into every new session before the first prompt. Custom slash commands orchestrate two-agent investigation-and-repair loops. The engineer types one command and three minutes later the system reports what broke, what it changed, and how many jobs are flowing again.
The Multi-Platform Reality
Every ATS platform has exactly one quirk that will ruin the first attempt. Dayforce has persistent WebSocket connections that break page-load detection. Ashby has case-sensitive URL slugs where Jasper%20AI returns jobs but jasper returns nothing. Workday uses opaque tenant URLs where bb.wd3.myworkdayjobs.com maps to BlackBerry with no discoverable pattern. BambooHR has mojibake encoding that garbles diacritical marks. NeoGov uses /jobs/ instead of /job/, a two-hour debugging session for a single missing character.

The 11 platforms split across three tiers of difficulty:
- Tier 1 (Clean APIs): Greenhouse (177 companies), Lever (46), Workable (32), Pinpoint (4). REST or GraphQL endpoints return structured JSON.
- Tier 2 (Predictable SPAs): Ashby (1,558 companies) and Workday (15). Single-page applications with consistent DOM selectors, accessible via browser automation.
- Tier 3 (The Wild West): SAP SuccessFactors (4), SmartRecruiters (3), Dayforce (2), BambooHR (8), and one-off government portals. CGI forms, WebDynpro, legacy encodings, and pages that have not been redesigned since the early 2000s.
The 1,558 Ashby companies deserve a callout on their own. Ashby’s GraphQL API covers most of them, but a long tail of companies deploy Ashby as an embedded SPA without exposing the underlying API. Browser automation fills the gap, hitting the same data the user sees in their own browser.
Self-Healing as a First-Class Concern
Companies change platforms, rebrand, and restructure their career pages. A static collection script on 1,975 companies will always have some subset failing at any given time. The architectural decision was to stop trying to prevent failures and instead respond to them automatically.

The retriever-debugger (Haiku, approximately $0.05 per investigation) diagnoses failures. It web-searches the company, fetches the current careers page, detects ATS fingerprints in the HTML, and produces one of four verdicts: ats_fix (slug changed within the same platform), platform_migration (company moved to a different ATS entirely), new_retriever (no API available, browser automation needed), or transient (temporary issue, skip and retry). There is no “deactivate” verdict, by design. Every company stays in the pipeline.
The retriever-fixer (Sonnet, approximately $0.30 to $1.50 per repair) takes the diagnosis and applies the fix inside a 3-iteration test loop. Database updates for slug changes. Full browser-based retrievers built from scratch when APIs disappear. A PostToolUse hook runs ruff check after every file write, catching lint errors in real time so the agent sees them on the next iteration.

The Monday morning workflow tells the story. Sunday night the pipeline runs. Monday morning the engineer opens Claude Code and the SessionStart hook injects “5 failures in 72 hours” into context before the first keystroke. Running /fix-all-retrievers kicks off the investigate-fix-test loop for each failure. Roughly 15 minutes later: 4 of 5 fixed, 1 logged for manual review. Running /pipeline-review confirms a 97 of 100 health score. Total spend: around $5.
A typical repair transcript, compressed to the interesting lines:
$ /fix-retriever jasper-ai
[debugger] Fetching https://www.jasper.ai/careers...[debugger] Detected ATS fingerprint: Ashby (previous: Greenhouse)[debugger] Verdict: platform_migration
[fixer] Updating companies table: platform Greenhouse -> Ashby[fixer] Generating Ashby retriever for slug 'jasper'[fixer] Test iteration 1: 0 jobs returned (slug case mismatch)[fixer] Retrying with slug 'Jasper' (capitalized)[fixer] Test iteration 2: 13 jobs returned, schema valid[fixer] Committing retriever, updating health score
Repaired: jasper-ai (13 jobs flowing). Elapsed: 2m 47s. Cost: $0.41.AI at Six Distinct Touchpoints
AI appears across the system as a set of targeted interventions rather than a single monolithic feature. Each touchpoint has its own cost profile, latency budget, and failure mode.

- Pipeline enrichment ($5.04 per week) — bulk classification of 312 candidate postings through Haiku 4.5.
- On-demand re-enrichment ($0.0003 per job) — triggered when a user edits a description in the dashboard.
- Job capture enrichment (background task) — structured metadata for manually-added postings.
- Retriever builder ($0.72 per retriever, 69 built) — Sonnet inside the Agent SDK multi-agent system.
- Retriever fixer (3-iteration cycles, $0.30 to $1.50 each) — Sonnet applying diagnosed repairs.
- Retriever debugger (~$0.05 per investigation) — Haiku diagnosing failures before any repair is attempted.
The pattern that ties them together is deliberate model selection by cost profile. Haiku for the high-volume, lower-stakes work. Sonnet for the rare, high-stakes reasoning. No model is doing a job that a cheaper model could have done.
The Dashboard: Turning 311 Matches Into Something Usable
311 qualified jobs per week are only useful if two applicants can actually work through them without stepping on each other. The dashboard turns the firehose into something manageable.

The core is an ag-Grid Enterprise v35 table with 35+ columns, but the whole point of Enterprise is not showing all 35 at once. The Columns panel lets each user toggle any column on or off, drag to reorder, group rows by company or seniority, and save the entire layout as a named preset. Each user gets their own persistent view.

Multiple applicants share the same job data but maintain separate views, favorites, notes, and application tracking. The application status pipeline tracks each job through 13 states:
New → Saved → Applied → Screening → Round 1 → Round 2 → Round 3 → Final Round → Offer → Rejected → Withdrawn → GhostedColor-coded badges provide instant scannability across the grid.
On-demand AI enrichment. Editing a job description triggers an instant re-enrichment pass through Claude Haiku 4.5. Paste text from a company’s careers page, hit Save, and eight cells update simultaneously: seniority, salary range, requirements, employment type, and formatted description. Same model, same extraction, same $0.0003 cost as the batch pipeline, but triggered by a user clicking Save.


Jobs found outside the automated pipeline can be added through a manual entry form. After saving, Haiku 4.5 automatically enriches the posting with structured metadata.


System Architecture
+------------------------------------------------------------------------------+ JOB SEARCH AGENT+------------------------------------------------------------------------------+ RETRIEVE PROCESS DELIVER 11 ATS Platforms -> Filter (Regex, $0) -> PostgreSQL Storage 127 Retrievers -> Deduplicate (SHA-256) -> React + ag-Grid Dashboard 29 Parallel Batches -> Enrich (Haiku 4.5) -> Per-User Views -> Persist + Auto-Repair On-Demand Enrichment+------------------------------------------------------------------------------+ AI LAYER Claude Haiku 4.5 | Pipeline enrichment ($5.04/week, 3,015 jobs scored) Claude Haiku 4.5 | On-demand re-enrichment ($0.0003/job) Claude Sonnet | Retriever builder (69 built at $0.72 each) Claude Sonnet | Retriever fixer (3-iteration repair loops) Claude Code | Hooks, subagents, skills, slash commands+------------------------------------------------------------------------------+ MAINTENANCE SessionStart Hook | Failure context injection before first prompt PostToolUse Hook | Instant ruff linting on every file save /fix-retriever | Two-agent investigate-fix-test loop /fix-all-retrievers | Batch repair with priority ordering /pipeline-review | Health score and action items+------------------------------------------------------------------------------+ INFRASTRUCTURE PostgreSQL (NAS) | Docker (NAS) | FastAPI | React + ag-Grid Windows Task Scheduler | 29 parallel batch execution+------------------------------------------------------------------------------+Everything runs on a home NAS and a laptop. No cloud compute. No Kubernetes. No monthly hosting bill beyond the electricity.
Key Achievements
| Metric | Value |
|---|---|
| Companies monitored | 1,975 across 11 ATS platforms |
| Jobs processed weekly | 58,807 through a 6-phase pipeline |
| Qualified matches per run | 311 delivered to the dashboard |
| Weekly pipeline cost | $5.04 ($262 per year) |
| Cost per processed job | $0.000086 (roughly 23,000x cheaper than human review) |
| Custom retrievers | 127 company-specific, 69 built by AI |
| AI-built retriever success rate | 100% across 69 retrievers, zero manual edits |
| Pipeline execution time | ~20 minutes across 29 parallel batches |
| Self-healing repair rate | ~80% of failures resolved without human intervention |
Technologies
Retrieval and Pipeline:
- Python 3.11 + FastAPI + asyncio (29-batch parallel orchestration)
- httpx (API-based retrievers)
- Browser automation (DOM-based retrievers for Tier 2 and Tier 3 platforms)
AI:
- Claude Haiku 4.5 (pipeline enrichment, on-demand re-enrichment, failure diagnosis)
- Claude Sonnet (retriever code generation, retriever repair)
- Anthropic Agent SDK (orchestrator + 3 parallel workers, 5 custom tools)
- Claude Code (hooks, skills, subagents, slash commands)
Data and Backend:
- PostgreSQL on Synology NAS (jobs, companies, per-user state)
- Docker on Synology NAS (FastAPI service, Postgres)
- Windows Task Scheduler (weekly pipeline trigger)
Frontend:
- React 18 + TypeScript + Vite
- ag-Grid Enterprise v35 (35+ columns, per-user layouts, row grouping)
- Tailwind CSS v4 + shadcn/ui (dark gold/amber theme)
- React Query (server state) + localStorage (per-user grid layouts)
Features
- Weekly Autonomous Operation: 58,807 jobs retrieved, filtered, deduplicated, enriched, and persisted in approximately 20 minutes without human involvement.
- Strategic Filter Ordering: Free regex and hash filters eliminate 99.5% of postings before any LLM call, cutting projected LLM spend from around $2,900/week to $5.04/week.
- Three-Model AI Architecture: Haiku for volume, Sonnet for code generation, Claude Code for maintenance. Each model assigned by cost and reasoning profile.
- AI-Generated Retrievers: 69 of 127 company-specific retrievers written autonomously by a Sonnet-powered multi-agent system at $0.72 each with a 100% success rate.
- Self-Healing Pipeline: Two-agent investigate-fix-test loop diagnoses platform migrations and rebuilds retrievers with roughly 80% autonomous repair rate.
- Context-Aware Developer Environment: SessionStart hooks surface failure context before the first prompt. PostToolUse hooks enforce lint rules in real time. Zero API cost for the hook layer itself.
- Per-User Dashboard State: Two applicants share one database with independent views, favorites, notes, grid layouts, and 13-state application tracking.
- On-Demand Re-Enrichment: Editing any job description triggers a $0.0003 Haiku pass that updates 8 metadata fields in approximately 2 seconds.
- Manual Job Capture: Jobs found outside the automated pipeline can be pasted into a form and enriched by the same model, same extraction, as the batch run.
- Home-Lab Deployment: PostgreSQL, FastAPI, and the frontend all run on a Synology NAS. No cloud compute costs beyond the weekly LLM spend.
What Happened Next
The project started as a practical answer to a practical problem and turned into a reference implementation for a set of architectural patterns that generalize beyond job searching:
- Filter ordering as the primary cost lever. In any pipeline that mixes free work with paid LLM work, the single highest-impact decision is what runs first. The 23,000x cost gap between naive and optimized pipelines came from that one choice.
- Strategic model selection. The three-model approach (Haiku for volume, Sonnet for code, Claude Code for orchestration) has since carried into other projects. Running Opus on work that Haiku could have done is the LLM equivalent of provisioning a cloud instance ten sizes too large.
- Domain knowledge as a Claude Code Skill. The 1,466-line curriculum that taught the retriever builder how ATS platforms behave was the single highest-leverage artifact in the build. Clever prompting did not move the needle. Structured, versioned domain knowledge did.
- Self-healing over defensive coding. For any system with a long tail of external dependencies, the honest architectural choice is to assume things will break and build the repair loop rather than trying to prevent every failure mode.
The broader throughline: building with AI is about architecture, not prompts. Strategic filter ordering, domain knowledge transfer via Skills, context injection via Hooks, and on-demand enrichment all share the same principle. Put the AI in the right place, at the right time, with the right context.