Case study
Job Search Agent in Claude Cowork
A scheduled Cowork agent that finds, scores, and tracks job postings across three applicant tracking system (ATS) platforms and Gmail, and the debugging that made its output trustworthy.
Built for my own job search. I designed what it should do, directed the build in Claude Cowork, and debugged its output until I could trust it.
Key facts
- 3 APIs Greenhouse, Lever, and Ashby, plus Gmail alerts
- 2× a week scheduled runs Tuesdays and Sundays
- 3 failure modes found and fixed
- v6 of the versioned skill file
Problem
Job boards resurface stale listings and miss roles posted only on company career pages. Checking dozens of companies by hand twice a week wasn’t sustainable.
Who it was for
Me.
What I built
A scheduled task in Claude Cowork that runs on Tuesdays and Sundays. It pulls open roles from the Greenhouse, Lever, and Ashby job-board APIs for a target company list, parses LinkedIn alert emails from Gmail, scores each role against a fit profile, de-duplicates, and writes to a Supabase-backed dashboard.
A versioned skill file, now on v6, defines the sources, the scoring rubric, the output schema, and the validation gates.
Built with
Claude Cowork (a scheduled task and a versioned skill file), the Greenhouse, Lever, and Ashby job-board APIs, Gmail, and Supabase.
My role: deciding what it should do, directing the build, reviewing its output, and running it.
Demo
- 90-second screen recording of a run and the dashboardComing
- The skill file and LESSONS.md, with the company list removedComing
Recording of a real run. My target-company list and personal details are removed.
What happened
What went wrong, and the fix
Early runs looked fine and were wrong in ways that mattered.
| Failure | Cause | Fix |
|---|---|---|
| Invented titles like “best of 37 open” | The model summarized where it should have copied | Title must be the exact API value |
| Stale listings resurfacing | Nothing checked whether a role was still open | Re-check every URL before writing a row |
| Generic career-page URLs | The model fell back to what it knew | URL must come from the API; no URL, no row |
The lesson: an agent that produces plausible output is more dangerous than one that fails loudly.
Moves through code
Anything that must be exact: titles, URLs, dates.
Left to the model
Judgment only: fit and summary.
Results
Results coming: companies monitored, roles surfaced, applications.
What I’d change
- Move exact data out of the model from day one. Titles, URLs and dates should have gone through code from the first version, with the model only judging fit and writing summaries. I learned that across six versions instead of designing it in.