● system status: available for new workflows

Project

Agent · job search · scheduled daily

Job-Search Agent

A fully automated job-search pipeline that scans remote job boards daily, filters matches against target keywords, and generates a tailored resume and cover letter for each one — delivered by email every morning, with zero manual work and zero recurring cost. Built with Python, Groq AI, GitHub Actions, and Gmail.

← back to projects
Live — Scheduled Daily · GitHub Actions (private repo)
Type: Job Search Automation + Resume/Cover Letter Tailoring Tools: Python · Groq AI · GitHub Actions · Gmail SMTP Steps: 6 Platform: GitHub Actions (cron) Status: Live · Running Daily
✓ Fully deployed end-to-end. Runs automatically every day via GitHub Actions. Sources jobs only from platforms that offer free, scrape-free APIs — no automation runs against sites that prohibit bots. Every application still passes through manual review before it's sent.

// overview

Job hunting is repetitive by nature — the same information gets re-typed and re-tailored, posting after posting. Most "auto-apply" tools solve this by scraping platforms like LinkedIn or Indeed and submitting applications with no human involved. That approach is fast, but built on a foundation that doesn't hold — those platforms explicitly prohibit bots and actively ban accounts caught running them.

This agent takes a different path. It sources only from job boards with free, public APIs meant to be queried programmatically, filters listings against a keyword list, and for every genuine new match, uses an LLM to tailor a professional summary and reorder skills to fit that specific posting — never inventing new experience, only reframing what's already true. The tailored resume and cover letter are generated as real .docx files and emailed directly, attached and ready to send.

Runs entirely on free-tier infrastructure — no server to maintain, no recurring cost, and nothing running against a platform's Terms of Service.

// system diagram

TRIGGER 1. GitHub Actions — daily cron SOURCING 2. Fetch: Remotive, Arbeitnow, RemoteOK FILTER 3. Match keywords + dedupe vs. history AI PROCESSING 4. Groq AI — tailor summary + skills GENERATION 5. Build tailored .docx resume + letter DELIVERY Gmail — digest + attachments ARCHIVE GitHub repo — commit results LEGEND Live and working

// proof of work — live run log

Actual console output from a production run, triggered manually to verify the pipeline end-to-end before enabling the daily schedule.

[main] Searching for keywords: ['Automation Specialist', 'Workflow Automation', 'Virtual Assistant', 'Administrative Support', 'Operations Support', 'AI Agent Developer', 'No-code Automation']
[main] Found 1 total matching jobs across sources.
[main] 1 new job(s) to process this run.
[main] Tailoring documents for: Entry Level Scheduling & Coordinating Reservations Online @ Destination Careers
[send_email] Sent digest email with 1 job(s) to sadayabonjovi@gmail.com.
[main] Done.

// GitHub Actions run #1 — succeeded in 21s · install deps → run agent → commit + push results

// step breakdown

# Step Tool Status
1 GitHub Actions wakes on a daily cron schedule (or manual trigger) and checks out the repo GitHub Actions ✓ Live
2 Script queries three free job-board APIs and filters listings against the keyword list Remotive · Arbeitnow · RemoteOK ✓ Live
3 Matches are checked against a processed-jobs log so nothing gets sent twice Python — JSON log ✓ Live
4 Each new match is sent to the LLM with the base resume — returns a tailored summary, reordered skills, and a full cover letter, grounded only in real experience Groq AI (llama-3.3-70b) ✓ Live
5 Tailored content is rendered into a formatted resume and cover letter as real, downloadable Word documents python-docx ✓ Live
6 One digest email is sent — job title, company, summary, posting link, resume + cover letter attached. Results also committed to the repo as a permanent archive Gmail SMTP + Git ✓ Live

// current status

✓ Fully Working

  • Queries 3 job boards daily
  • Keyword filtering + dedupe
  • AI-tailored summary + skills
  • Never fabricates experience
  • Generates real .docx files
  • Digest email with attachments
  • Archives every result to GitHub
  • Zero manual work

✓ Full Pipeline Live

  • Scheduled via GitHub Actions cron
  • Secrets encrypted at rest
  • Runs on $0/month infrastructure
  • No scraping, no ToS violations
  • Manual trigger available anytime
  • End-to-end tested on live data

// next iterations

The pipeline works end-to-end, but "working" and "finished" aren't the same thing. These are the next real improvements planned — fine-tuning an already-live system, not fixing something broken.

○ Planned Improvements

  • Expand beyond 3 sources — add more job boards with free, public APIs to widen daily coverage
  • Smarter matching — move past exact keyword strings toward broader/fuzzy matching so near-fit roles aren't silently skipped
  • ATS-friendly resume formatting — constrain the generated .docx to a clean single page, parser-safe layout (no tables/columns that break ATS parsing)
  • Configurable keyword profiles — swap search terms per role type without editing code

// what makes it different

→ Not a scraper, not an auto-submitter

  • Sources only from platforms with free, public, scrape-free APIs
  • Deliberately excludes LinkedIn and OnlineJobs.ph — no free API, so no scraping workaround was built
  • Never submits an application automatically — always prepares, never sends
  • Tailoring only rewrites summary and skill emphasis, never invents new experience
  • Runs entirely on free tiers — Groq AI, GitHub Actions, Gmail SMTP
  • Every result archived, so nothing is ever silently lost or repeated

// build story

This project didn't start with a fixed architecture. It went through a few real pivots as constraints — cost, platform rules, tool limits — came into focus.

The original plan

Full auto-apply across every platform

The first idea was the obvious one — an agent that finds jobs and submits applications everywhere automatically, LinkedIn and Indeed included. That plan didn't survive first contact with those platforms' Terms of Service, which explicitly prohibit bots and actively ban accounts caught running them.

Scope corrected

Prepare-and-review, not auto-submit

The design shifted to sourcing only from platforms with free, public APIs meant for programmatic use, and stopping short of submission entirely — the agent hands over a link, a tailored resume, and a cover letter, and a human still sends it.

Scheduler decision

Make.com vs. GitHub Actions

Make.com's free tier offered a faster visual build, but its 1,000-operations-per-month ceiling would have been exhausted almost immediately by daily runs. GitHub Actions has no such ceiling and already hosted the code, so it became the scheduler.

LLM decision

Claude API vs. Groq

Claude's writing quality is stronger, but its free allowance is a one-time trial credit, not an ongoing tier. Groq offers a genuinely free, ongoing allowance — the better fit for a tool meant to run indefinitely during an active job search.

Shipped

Live, tested against real listings, running daily

The first production run found a genuine remote administrative-support match, generated a tailored resume and cover letter, and delivered both by email — end to end, unattended, for free.

// qa case study — the html entity bug

Shipping the pipeline wasn't the end of the story. The first real run surfaced a small but visible formatting bug — the kind that's easy to miss in testing but immediately obvious once real data flows through.

⚠ The Bug

  • Job titles pulled from RemoteOK's API displayed with raw HTML entities
  • "Scheduling & Coordinating" rendered as "Scheduling & Coordinating" in the email
  • Only surfaced once a real live listing containing an ampersand was matched

→ Root Cause

  • The job board's API returns titles and descriptions HTML-encoded
  • The fetch layer stripped HTML tags but never decoded HTML entities
  • Encoded text passed untouched through filtering, tailoring, and into the final documents

✓ The Fix

  • Added a shared _clean() helper using Python's built-in html.unescape()
  • Applied to title, company, and description across all three job sources
  • Fixed once at the source, so every downstream step — filtering, tailoring, documents, email — inherits clean text

→ Why It Matters

  • Invisible in code review — only showed up once real API data flowed through the pipeline
  • Root-caused at the point text enters the system, not patched at the point it's displayed
  • The kind of small detail that separates a script that "mostly works" from one that ships clean output every time

// how it runs

⚡ Fully automated — private personal tool

This agent runs on a private GitHub repository, scheduled daily via GitHub Actions. It's not a public demo — it's a working piece of personal infrastructure, actively finding and preparing job matches every morning without any manual input.

// stack: Python · Groq AI · GitHub Actions · python-docx · Gmail SMTP — $0/month

// tools used

Python 3.12 Groq AI (llama-3.3-70b-versatile) GitHub Actions python-docx Remotive API Arbeitnow API RemoteOK API Gmail SMTP GitHub Secrets (encrypted)