Disclaimer: use at your own risk. A master resume / CV contains personally identifiable information (name, contact details, employment history), so this tool has not been dry-run with a real resume. It was tested only with made-up sample resumes. Results with your own resume may differ, so check the parsed
master_resume/resume_data.yamland every tailored resume before you use or submit it.The tailored resume is a starting point for further editing, not a finished document. Review it, edit it (on the dashboard or in the downloaded
.docx), and make sure everything in it is accurate before you apply.
Runs on your PC every day at 11:00 AM Eastern. Everything is plain code: no AI service, no API key, and nothing per-resume to pay for. It:
- Searches 109 large employers' Workday career sites (companies.yaml) for your keywords, using Workday's own public job-search API, and skips your current employer.
- Classifies every posting: Full-Time / Contract / Temporary / Part-Time / Internship (from Workday's own job-type field), Remote / Hybrid / On-site, and salary range (parsed from the pay-transparency text).
- Filters by job type, remote-only, minimum salary, posting age, US state, title words, match score and your own mandatory / optional keywords (see below).
- Tailors your master resume for each remaining posting with rules (details below), and renders an
ATS-friendly .docx(single column, standard headings, real bullets). It never adds anything that isn't in your resume.
- Opens a dashboard where you review each job description side by side with its tailored resume, with the ATS keyword match before → after, matched and missing keywords highlighted, and job-type badges. You can edit or re-tailor the resume, skip the job, or approve it.
- On approval, a browser window opens and fills in the Workday application (sign-in or account creation, resume
upload, contact details, screening questions from your answer rules, EEO questions). By default it stops on the
Review page for you to click Submit. Set auto_submit: trueto have it submit for you.
- Archives each application to applications/<Company>/<date>_<Job title>_<Req ID>/: the tailored resume that was sent, the job description (.html+.txt), andapplication.json(salary, type, scores, link).
search.keywords decides what to search Workday for (job titles). These two lists decide which of the postings
found you see. They're checked against each posting's title and full description:
- Matching is by whole word, and any spelling the skills list knows counts: AWSfinds "Amazon Web Services",PostgreSQLfinds "Postgres", andJavadoes not match "JavaScript".
- Use |inside one keyword for either-or:AWS | Azure | GCPis satisfied by any one of them.
- Refine on the dashboard: type a keyword and press Enter (or paste a comma-separated list) to add it as a chip, and click × (or Backspace) to remove one. The list updates as you type. Save for daily runs keeps them for the 11 AM run and re-checks the jobs you haven't acted on. A tailored job that no longer qualifies moves to Filtered out with its resume kept, and comes back if you loosen the filters.
- On each job's review page, Your search keywords shows which ones the posting mentions (✓ / ✗), and they are outlined in the description.
You can also set starting values in config.yaml → filters:.
The Location row on the dashboard:
States are read from Workday's location text, whatever the company's format: US, CA, Santa Clara,
CHARLOTTE, NC; ISELIN, NJ, California - San Francisco, Newark, New Jersey, USA-Texas-Austin.
Washington, DC counts as DC, and Kansas City, MO as Missouri. Postings that fail show the reason under
Filtered out, e.g. "state: NC, TX" or "outside the US (India)". Like the other filters, changes apply to the
list instantly; Save for daily runs keeps them for the 11 AM run.
- Reading your resume. jobagent/resume_parser.pyreads .docx/.pdf/.txt/.md: it finds the section headings, then bullets, job titles, companies, dates, locations, degrees and skills. The result is saved tomaster_resume/resume_data.yaml. Check that file once and fix anything that landed in the wrong place. Every tailored resume is built only from it.
- Reading the posting. jobagent/keywords.pyfinds the skills and tools the posting mentions. It uses a built-in list of about 580 skills with their other spellings (jobagent/skills.yaml, e.g. AWS = Amazon Web Services, K8s = Kubernetes, Postgres = PostgreSQL), plus every skill on your resume. Keywords are weighted by where they appear: job title > Required / Minimum qualifications > Preferred / Nice to have. The company blurb, benefits, EEO and salary text are ignored.
- Tailoring (jobagent/tailor.py):- Headline: your own most recent job title that matches the posting's role, plus your top 3 matching skills
(e.g. Senior Data Engineer | PostgreSQL · Python · Kubernetes). It never uses a title you haven't held.
- Summary: the best of your summary_variants, ending with "Skilled in …" listing your matching skills.
- Skills: the posting's skills come first, written the way the posting writes them. If you list AWSand the posting says "Amazon Web Services", your resume showsAmazon Web Services (AWS); that's what simple ATS keyword scans look for. Matching skills that only appear in your bullets are listed under Additional Skills.
- Experience: each role's bullets are ordered by relevance. Older roles can be trimmed to their best bullets.
- Projects / certifications: most relevant first.
- Headline: your own most recent job title that matches the posting's role, plus your top 3 matching skills
(e.g.
- Checks: the tailored resume is compared with your master resume. Any changed employer, title or dates, or a
skill your master resume doesn't show, is flagged in yellow on the review page. Posting requirements you don't
have are listed as gaps. Add them to resume_data.yamlonly if they're true.
To get better matches, keep resume_data.yaml complete (extra bullets are fine; tailoring picks the best ones).
Add alternative summaries under summary_variants:, and add tools the built-in list doesn't know to
config.yaml → tailoring.extra_skills / tailoring.synonyms.
- Windows 10/11 (the daily schedule uses Windows Task Scheduler; the rest is plain Python)
- Python 3.10 or newer
- Microsoft Edge (built into Windows) for the auto-apply browser. To use Playwright's own Chromium instead, set
apply.browser_channel: chromiumand run.\.venv\Scripts\python.exe -m playwright install chromium.
git clone <this repository's URL> workday-job-agent
cd workday-job-agent
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
copy .env.example .env # then edit .env
copy config.example.yaml config.yaml # then edit config.yaml.env, config.yaml, your resume, data\ and applications\ are in .gitignore, so your personal details are
never committed.
- Resume: put your master resume (.docx,.pdf,.txtor.md) inmaster_resume\.
- .env: set- WORKDAY_EMAILand- WORKDAY_PASSWORD. Workday has a separate account per company, so use a password you don't use elsewhere.
- config.yaml: set- current_employer,- search.keywords, your- profile(name, phone, address), and fill in the- answers:for screening questions (work authorization, sponsorship, …). Unanswered questions are left for you in the browser.
- Read your resume and check the result:
It prints what it found (roles, dates, bullet counts, education). Open.\.venv\Scripts\python.exe -m jobagent init master_resume\resume_data.yamland fix anything that's off. If you later replace your resume file, runinit --reparse.
- First search (about 10 minutes across all 109 companies; later runs only fetch new postings):
.\.venv\Scripts\python.exe -m jobagent run
- Schedule the daily 11 AM Eastern run (Windows Task Scheduler; runs late if the PC was asleep at 11):
powershell -ExecutionPolicy Bypass -File scripts\install_schedule.ps1
At 11:00 the task searches, tailors, then opens http://127.0.0.1:5055. You can also open it any time with
start_dashboard.bat.
- Filter bar: toggle Full-Time / Contract / Temporary / Part-Time / Internship, Remote only, Min salary, Hide jobs with no salary listed. Changes apply to the list instantly. Save for daily runs also stops future runs from tailoring jobs you've filtered out.
- Tabs: To review · In progress · Applied · Waiting to tailor · Not applied · Skipped · Filtered out (with the reason, and you can still tailor and apply).
- Review page: job description on the left, tailored resume on the right. Approve & apply, Edit resume, Re-tailor… (choose skills to put first, or a max number of bullets per role), Download .docx, Mark as applied (if you applied yourself), Skip.
- If the browser needs you (CAPTCHA, email verification link, a question with no rule), the dashboard shows a red banner saying what to do. Do it in the open browser window and the agent continues.
(Use .venv\Scripts\python.exe in place of python.)
- Adding companies: any company on Workday works. Paste its careers URL
(https://<company>.wd<N>.myworkdayjobs.com/<Site>) into the dashboard's Add company box. Companies that use other systems (Greenhouse, Lever, iCIMS, Taleo, their own site) aren't covered.
- What rules can't do: they don't rewrite your bullets into new sentences. They choose, order and re-word skill
names. Your bullets appear as you wrote them, so write strong bullets in resume_data.yamlonce.
- Auto-apply is best-effort: every company adds its own questions and some add extra pages. The agent fills in
what it can and hands the browser to you for anything else. It never guesses an answer and never solves CAPTCHAs.
Keep auto_submit: falseuntil you've watched a few applications go through.
- Privacy: everything runs locally. Postings, resumes and the database live in data\,master_resume\andapplications\. The dashboard only listens on 127.0.0.1. Nothing is sent anywhere except Workday itself.
- Logs: data\logs\(jobagent.log,daily.log,apply.log,server.log).
- Remove the schedule: Unregister-ScheduledTask -TaskName JobAgentDaily -Confirm:$false
MIT, provided as is, without warranty of any kind (see the disclaimer at the top).
jobagent/ workday.py (Workday API) · classify.py (type/remote/salary) · geo.py (US states) · keywords.py + skills.yaml
(posting keywords) · resume_parser.py (read your resume) · tailor.py (tailoring rules)
resume.py (data model, checks, .docx) · scoring.py · pipeline.py (daily run, archive)
applier.py (browser automation) · server.py + templates/ + static/ (dashboard) · __main__.py (CLI)
companies.yaml Workday sites to search config.yaml your settings
master_resume/ your resume + resume_data.yaml data/ database, tailored drafts, logs, browser profile
applications/ one folder per submitted application