Skip to content

Repository files navigation

agentic-career-search

CI Python 3.11+ FastAPI License

AI-agent backend for autonomous job discovery, explainable decisions, and production-style operations.

Demo Gallery

Core Agent Loop

LLM Provider Flow

Ops Reliability Loop

JazzHR Source Adapter

Phenom People Source Adapter

Skills Profile Fit

Application Draft HITL

Application Stage Tracker

Salary Band Estimator

Interview Prep Brief

Cross-Source Job Dedup

ATS Keyword Coverage

Company Research Brief

Recruiter Outreach Draft

Referral Intro Draft

Negotiation Talking Points

Interview Feedback Synth

Offer Deadline Tracker

Portfolio Project Matcher

Interview Schedule Conflict Guard

Thank-You Note Outline Planner

Application Ghosting Detector

Weekly Application Pace Advisor

Rejection Pattern Analyzer JD Culture Signal Extractor

Application Follow-Up Cadence

Why this exists

Most job-search automation demos fail in real usage because they:

  • cannot explain why a role is ranked highly,
  • cannot recover cleanly when providers fail,
  • have no durable event trace for debugging,
  • become hard to maintain once features grow.

This project solves those issues with explicit agent engineering primitives:

  • deterministic decision engine with rationale traces,
  • state-machine run lifecycle and durable event log,
  • tool/adapters abstraction for external integrations,
  • safety controls (timeouts, bounded scope, cancellation),
  • optional LLM enrichment via multiple providers,
  • skills-profile fit scoring (fit_score 0–1 + matched/missing) — see docs/guides/SKILLS_PROFILE_FIT_GUIDE.md,
  • assistive USD salary-band estimates from title/location heuristics — see docs/guides/SALARY_BAND_ESTIMATOR_GUIDE.md,
  • HITL application drafts (resume bullets + cover notes) with no auto-submit — see docs/guides/APPLICATION_DRAFT_SERVICE_GUIDE.md,
  • CRM-lite application stage tracker (saved→applied→interview→offer) — see docs/guides/APPLICATION_STAGE_TRACKER_GUIDE.md,
  • interview-prep briefs (likely questions + STAR prompts + focus gaps) — see docs/guides/INTERVIEW_PREP_BRIEF_GUIDE.md,
  • cross-source fuzzy dedup (title+company beyond URL) — see docs/guides/CROSS_SOURCE_JOB_DEDUP_GUIDE.md,
  • ATS keyword coverage (resume text ↔ JD keywords) — see docs/guides/ATS_KEYWORD_COVERAGE_GUIDE.md,
  • company research briefs (talking points + JD signals, HITL) — see docs/guides/COMPANY_RESEARCH_BRIEF_GUIDE.md,
  • HITL recruiter outreach drafts (email + LinkedIn DM, never auto-send) — see docs/guides/RECRUITER_OUTREACH_DRAFT_GUIDE.md,
  • HITL referral intro drafts (warm email + LinkedIn, never auto-send) — see docs/guides/REFERRAL_INTRO_DRAFT_GUIDE.md,
  • negotiation talking points (total-comp counters, HITL) — see docs/guides/NEGOTIATION_TALKING_POINTS_GUIDE.md,
  • post-interview debrief briefs (strengths + gaps + follow-ups, HITL) — see docs/guides/INTERVIEW_FEEDBACK_SYNTH_GUIDE.md,
  • offer deadline countdowns + HITL reminders (never auto-decline) — see docs/guides/OFFER_DEADLINE_TRACKER_GUIDE.md,
  • portfolio bullet ↔ JD theme matching (HITL token overlap) — see docs/guides/PORTFOLIO_PROJECT_MATCHER_GUIDE.md,
  • interview schedule conflict advisory (local overlap detection; never writes calendars) — see docs/guides/INTERVIEW_SCHEDULE_CONFLICT_GUARD_GUIDE.md,
  • HITL rejection-pattern themes from offline notes (never auto-rewrites resumes) — see docs/guides/REJECTION_PATTERN_ANALYZER_GUIDE.md,
  • HITL post-apply follow-up cadence (day offsets + channels; never auto-nudge) — see docs/guides/APPLICATION_FOLLOWUP_CADENCE_GUIDE.md,

Real use cases (problem -> solution)

Problem Why it hurts How this repo solves it
Teams can scrape jobs but cannot justify recommendations Low trust from users and reviewers AgentDecisionEngine stores score, matched terms, priority tier, and rationale
Background runs are hard to debug Silent failures block iteration speed Durable run events (run.*, source.*, agent.*) support replay-style troubleshooting
Vendor lock-in around one model provider High migration cost and brittle integrations Configurable LLM enrichment supports GPT-5.5, Claude Sonnet 4.6, Gemini 3.x, and Kimi K2-style APIs
Model/API outages break the entire flow System appears unreliable Graceful fallback preserves deterministic baseline output when LLM enrichment is unavailable
Scraped jobs pile up without a pipeline CRM Candidates lose track of where each role stands ApplicationStageTracker enforces an auditable saved→offer stage machine
Postings omit pay and scrapers leave empty salary fields Candidates cannot triage roles by compensation SalaryBandEstimator produces an auditable USD band from title/location heuristics
Candidates discover roles but arrive unprepared for interviews Weak signal conversion after outreach InterviewPrepBriefService builds likely questions, STAR prompts, and focus gaps for human review
Same role appears on Indeed + LinkedIn with different URLs Duplicate noise in triage and CRM CrossSourceJobDeduper clusters fuzzy title+company near-duplicates after URL pass
Resume free text is not scored against JD keywords ATS rejection risk is opaque AtsKeywordCoverageScorer reports coverage + present/missing JD keywords
Candidates research companies ad hoc before outreach Inconsistent talking points and invented facts CompanyResearchBriefService builds offline HITL briefs from JD signals
Multiple offers lack a side-by-side total-comp view Hard to triage cash vs equity trade-offs offline OfferCompareMatrix ranks offers by cash+equity heuristic without auto-accept
RemoteOK-style location prefs are board-UI-only Hard to reuse geo/remote filters in agent triage LocationRemoteFitScorer scores candidate prefs vs posting location/policy
Offer Compare Matrix
Outreach templates and Easy Apply auto-send without review Accidental spam and irreversible messages RecruiterOutreachDraftService builds email/LinkedIn drafts that always require human review
Warm intros are ad-hoc or auto-sent via InMail templates Burned connectors and irreversible messages ReferralIntroDraftService builds email/LinkedIn intro drafts that always require human review
Counter-offers are improvised from Levels.fyi / Blind threads Inconsistent anchors and accidental over-ask NegotiationTalkingPointsService builds HITL talking points from current vs target total-comp
Interview notes stay unstructured after loops Weak conversion and lost signal InterviewFeedbackSynthesizer builds HITL debriefs with strengths/gaps/follow-ups
Offer deadlines are tracked only in Teal/Huntr without local countdown Missed responses or accidental auto-decline risk OfferDeadlineTracker computes offline urgency + HITL reminders and never auto-declines
Portfolio bullets are hand-aligned to JD themes in Teal/Jobscan UIs Hard to reuse theme mapping in agentic triage PortfolioProjectMatcher scores offline bullet↔theme token overlap for HITL review
Teal/Huntr calendar sync auto-writes interview events Accidental double-booking without local HITL review InterviewScheduleConflictGuard detects offline overlaps and never mutates calendars
Teal/Careerflow thank-you templates encourage one-click sends Accidental recruiter spam after interviews ThankYouNoteOutlinePlanner builds offline email/LinkedIn outlines and never auto-sends
Teal/Huntr show quiet apps only inside proprietary CRM UIs Follow-ups are ad-hoc or accidentally auto-sent ApplicationGhostingDetector computes offline stall urgency + HITL suggestions and never auto-nudges
Teal Insights / Huntr analytics keep apply-volume coaching in closed UIs Burnout from spray-and-pray without local pace bands WeeklyApplicationPaceAdvisor compares planned vs target apps offline and never auto-submits
Teal Insights / Huntr keep rejection analytics in closed dashboards Candidates repeat the same miss without a local theme map RejectionPatternAnalyzer clusters offline rejection reasons into HITL themes and never auto-rewrites resumes
Teal/LinkedIn bury JD culture cues inside proprietary insight panels Candidates miss pace/on-call/collab signals before applying JdCultureSignalExtractor extracts offline culture cues for HITL review and never auto-applies
Simplify/Teal/LinkedIn bury visa sponsorship filters behind login walls Candidates waste cycles on citizenship-only or no-sponsor roles VisaSponsorshipSignalExtractor extracts offline work-auth cues for HITL review and never auto-applies
Visa Sponsorship Signal Extractor
Teal Insights / Jobscan / Resume Worded lock bullet-impact scoring in closed UIs Candidates keep weak adjective-only bullets without a local metric map ResumeBulletImpactScorer scores offline %/$/scale cues for HITL edits and never auto-rewrites
Resume Bullet Impact Scorer
Teal/Huntr/Superhuman keep recruiter-reply intent labels in proprietary inboxes Candidates misread scheduling vs rejection tone without a local classifier RecruiterReplyIntentClassifier classifies offline reply intents for HITL responses and never auto-sends
Teal/Rezi/Kickresume lock cover-letter tone matchers in closed UIs Candidates send mismatched tone vs JD pace/culture CoverLetterToneAligner scores offline tone bands for HITL edits and never auto-sends
Cover Letter Tone Aligner
Careerflow/Taplio/LinkedIn Premium lock headline graders in closed UIs Candidates publish keyword-weak headlines without a local coverage map LinkedInHeadlineKeywordScorer scores offline headline↔role keywords for HITL edits and never auto-posts
LinkedIn Headline Keyword Scorer
Interviewing.io/Exponent/Teal lock phone-screen agendas in closed UIs Candidates improvise screens without a local minute map PhoneScreenAgendaPlanner builds offline JD-driven agendas for HITL rehearsal and never auto-books
Phone Screen Agenda Planner
Interviewing.io/Exponent/Teal lock behavioral STAR banks in closed UIs Candidates improvise stories without a local competency map StarBehavioralStoryMatcher matches offline STAR banks to JD cues for HITL rehearsal and never auto-sends
StarBehavioralStoryMatcher
Teal/Huntr/Simplify lock packet checklists in closed CRMs Candidates submit incomplete packets without a local gate ApplicationPacketCompletenessGate checks offline resume/cover/portfolio readiness for HITL submit and never auto-submits
ApplicationPacketCompletenessGate
RemoteOK/FlexJobs/WWR bury timezone filters behind proprietary boards Candidates misjudge remote sync fit across offsets RemoteTimezoneOverlapAdvisor bands offline weekday overlap hours for HITL review and never auto-applies
RemoteTimezoneOverlapAdvisor
Huntr/Teal/Jobtracker lock multi-round interview boards in closed CRMs Candidates lose track of phone→HM→onsite→offer without a local state machine InterviewRoundProgressTracker tracks offline allowed round transitions for HITL review and never auto-advances
InterviewRoundProgressTracker
Levels.fyi/Candor/Carta lock vesting calculators in closed UIs Candidates misread cliff/unvested risk without a local schedule EquityVestingCliffAdvisor bands offline cliff + linear vest progress for HITL review and never auto-accepts
EquityVestingCliffAdvisor
Blind/Levels.fyi/RemoteOK bury commute vs stipend math in closed UIs Candidates accept office terms without a local commute-cost band CommuteCostTradeoffAdvisor bands offline commute vs stipend tradeoffs for HITL review and never auto-accepts
CommuteCostTradeoffAdvisor
Rippling/Gusto/Candor bury PTO cash-out calculators in closed UIs Employees misjudge payout vs use-it without a local cash-out band PtoCashOutValueAdvisor bands offline unused-PTO cash-out value for HITL review and never auto-cashes
PtoCashOutValueAdvisor
Levels.fyi/Fidelity/Candor bury 401(k) match calculators in closed UIs Employees under-contribute without a local match-gap band FourOhOneKMatchGapAdvisor bands offline employer vs market match dollars for HITL review and never auto-enrolls
FourOhOneKMatchGapAdvisor
Levels.fyi/Blind/Candor bury parental-leave week math in closed UIs Candidates accept thin leave without a local coverage band ParentalLeaveGapAdvisor bands offline offered vs market leave weeks for HITL review and never auto-accepts
ParentalLeaveGapAdvisor
Levels.fyi/Carta/Candor bury ESPP discount contribution math in closed UIs Employees under-contribute without a local discount-value band EsppDiscountValueAdvisor bands offline look-through discount value for HITL review and never auto-enrolls
EsppDiscountValueAdvisor
Huntr/Teal/Levels.fyi bury counter-offer leverage scoring in closed UIs Candidates under-negotiate without a local leverage band CounterOfferLeverageAdvisor bands offline competing-offer leverage for HITL review and never auto-sends
CounterOfferLeverageAdvisor
Levels.fyi/Carta/Candor bury RSU refresh planners in closed UIs Employees miss overdue refresh conversations without a local cadence band RsuRefreshCadenceAdvisor bands offline years-since-refresh for HITL review and never auto-accepts
RsuRefreshCadenceAdvisor
Huntr/Teal/Greenhouse bury notice vs start-date planners in closed UIs Candidates accept starts that collide with contractual notice NoticePeriodConflictFlagger bands offline notice vs preferred-start slack for HITL review and never auto-accepts
NoticePeriodConflictFlagger
Levels.fyi/Blind/Candor bury severance week math in closed UIs Candidates accept under-tenure packages without a local coverage band SeverancePackageGapAdvisor bands offline offered vs expected weeks for HITL review and never auto-accepts
SeverancePackageGapAdvisor
Levels.fyi/Candor/Blind bury signing-bonus clawback math in closed UIs Candidates misjudge repayment risk if they leave early SigningBonusClawbackAdvisor bands offline remaining clawback liability for HITL review and never auto-accepts
SigningBonusClawbackAdvisor
Huntr/Teal/Levels.fyi bury relocation stipend math in closed UIs Candidates accept underfunded moves without a local coverage band RelocationPackageGapAdvisor bands offline stipend vs move-cost coverage for HITL review and never auto-accepts
RelocationPackageGapAdvisor
Blind/Levels.fyi/Candor leave non-compete severity buried in closed UIs Candidates accept long/broad covenants without a local severity band NonCompeteRestrictivenessFlagger flags offline duration/geo/garden-leave cues for HITL review and never auto-accepts
NonCompeteRestrictivenessFlagger
Teal/Simplify/Huntr bury ghost-job detectors behind proprietary boards Candidates waste cycles on evergreen/vague listings GhostJobSignalFlagger flags offline evergreen/repost/vague-comp cues for HITL review and never auto-applies
GhostJobSignalFlagger
Recruiter Reply Intent Classifier
Teal/Huntr bury post-apply follow-up calendars in closed CRMs Candidates either spam or go silent without a local cadence ApplicationFollowUpCadencePlanner emits offline day+channel HITL steps and never auto-nudges
Teal/Huntr bury post-interview reflection checklists in closed UIs Lost signal and ad-hoc follow-ups after loops InterviewDebriefChecklist builds offline what-went-well/gaps/follow-up checklists and never auto-sends
Teal/Simplify keep skill learning plans inside closed dashboards Fit scores alone do not produce a practice path SkillGapLearningPathPlanner emits ordered HITL milestones from have vs required skills and never enrolls
Teal/Huntr/Simplify hide posting age inside proprietary boards Candidates waste time on stale evergreen listings JobPostingFreshnessScorer bands age_days offline (fresh/aging/stale/expired) and never auto-applies
Repo quality degrades over time Contributors lose confidence CI checks + daily automation loop maintain quality and push incremental improvements

LLM API integration (consumes model outputs)

Provider integration is built into the code path:

  • Gemini API
  • Kimi (Moonshot, OpenAI-compatible)
  • Claude (Anthropic Messages API)
  • GPT-compatible APIs through OpenAI-style endpoint patterns

Enable provider enrichment:

LLM_ENABLE_ENRICHMENT=true
LLM_PROVIDER=gemini   # or kimi / claude / gpt

Then set matching API keys in .env (see CONFIGURATION.md).

Engineering standards covered

This repository follows the requested standards:

  1. standalone repo architecture (not coupled to source repo internals),
  2. AI-agent-first design with deterministic decision traces,
  3. LLM output consumption from Claude/Gemini/Kimi and GPT-style integrations,
  4. production-minded layout (src, tests, scripts, CI, env config, migrations),
  5. high-quality docs (README, QUICKSTART, CONFIGURATION, SAFETY, ARCHITECTURE),
  6. branch-based merge workflow for controlled integration (no direct unsafe merges),
  7. lint/type/test validation before finalization,
  8. no Docker requirement for standard local verification,
  9. phase branches for development roadmap (phase/01 to phase/10),
  10. commit-forward workflow with frequent incremental pushes.

API snapshot

  • POST /source-configs create source adapter configs
  • GET /source-configs list enabled sources
  • POST /runs enqueue autonomous run
  • GET /runs/{run_id} inspect run state
  • GET /runs/{run_id}/events inspect event timeline
  • POST /runs/{run_id}/cancel request cancellation
  • GET /jobs inspect normalized, scored, and enriched outputs
  • GET /health/live and GET /health/ready

Supported job sources

Each SourceConfig selects a source adapter by source_type:

| catsone | CatsoneAdapter | Recognises CATS careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /postings/{id} URL shapes | CATS (*.catsone.com) careers boards | | adp | AdpAdapter | Recognises ADP Recruiting posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /requisitions/{id} URL shapes | ADP (*.adp.com) recruiting boards | | jibe | JibeAdapter | Recognises Jibe posting anchors by /jobs/{id}, /job/{id}, /position/{id}, /positions/{id}, or /requisition/{id} URL shapes | Jibe (*.jibe.com) recruiting boards | | hirevue | HireVueAdapter | Recognises HireVue posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /requisition/{id} URL shapes | HireVue public careers boards | | paycom | PaycomAdapter | Recognises Paycom posting anchors by /jobs/{id}, /job/{id}, /posting/{id}, /postings/{id}, or /opportunity/{id} URL shapes | Paycom public careers boards | | yello | YelloAdapter | Recognises Yello posting anchors by /jobs/{id}, /job/{id}, /position/{id}, /positions/{id}, or /opening/{id} URL shapes | Yello public careers boards | | wellfound | WellfoundAdapter | Recognises Wellfound posting anchors by /jobs/{id}, /job/{id}, /role/{id}, /roles/{id}, /startup-jobs/{id} URL shapes | Wellfound (wellfound.com / angel.co) careers boards | | otta | OttaAdapter | Recognises Otta posting anchors by /jobs/{id}, /job/{id}, /roles/{id}, /role/{id}, /openings/{id} URL shapes | Otta (otta.com) careers boards | | builtin | BuiltinAdapter | Recognises Built In posting anchors by /job/{id}, /jobs/{id}, /company-jobs/{id}, /careers/job/{id}, /role/{id} URL shapes | Built In (builtin.com / builtinnyc.com / builtinchicago.com) careers boards | | remoteok | RemoteokAdapter | Recognises RemoteOK posting anchors by /remote-jobs/{id}, /remote-job/{id}, /jobs/{id}, /job/{id} URL shapes | RemoteOK (remoteok.com) careers boards | | weworkremotely | WeworkremotelyAdapter | Recognises WeWorkRemotely posting anchors by /remote-jobs/{id}, /jobs/{id}, /job/{id}, /listings/{id}, /listing/{id} URL shapes | WeWorkRemotely (weworkremotely.com) careers boards | | welcometothejungle | WelcometothejungleAdapter | Recognises Welcome to the Jungle posting anchors by /jobs/{id}, /job/{id}, /companies/{slug}/jobs/{id}, /offers/{id}, /offer/{id} URL shapes | Welcome to the Jungle (welcometothejungle.com) careers boards | | remotive | RemotiveAdapter | Recognises Remotive posting anchors by /remote-jobs/{id}, /remote-job/{id}, /jobs/{id}, /job/{id}, /positions/{id} URL shapes | Remotive (remotive.com) careers boards | | himalayas | HimalayasAdapter | Recognises Himalayas posting anchors by /jobs/{id}, /job/{id}, /companies/{slug}/jobs/{id}, /remote-jobs/{id}, /roles/{id} URL shapes | Himalayas (himalayas.app) careers boards | | workingnomads | WorkingnomadsAdapter | Recognises Working Nomads posting anchors by /jobs/{id}, /job/{id}, /remote-jobs/{id}, /positions/{id}, /position/{id} URL shapes | Working Nomads careers boards | | justremote | JustremoteAdapter | Recognises JustRemote posting anchors by /remote-jobs/{id}, /jobs/{id}, /job/{id}, /listings/{id}, /listing/{id} URL shapes | JustRemote (justremote.co) careers boards | | nodesk | NodeskAdapter | Recognises NoDesk posting anchors by /jobs/{id}, /job/{id}, /remote/{id}, /positions/{id}, /careers/{id} URL shapes | NoDesk (nodesk.co) careers boards | | jobspresso | JobspressoAdapter | Recognises Jobspresso posting anchors by /jobs/{id}, /job/{id}, /remote-jobs/{id}, /postings/{id}, /openings/{id} URL shapes | Jobspresso (jobspresso.co) careers boards | | remoteco | RemotecoAdapter | Recognises Remote.co posting anchors by /remote-jobs/{id}, /jobs/{id}, /job/{id}, /positions/{id}, /careers/{id} URL shapes | Remote.co (remote.co) careers boards | | dynamitejobs | DynamitejobsAdapter | Recognises Dynamite Jobs posting anchors by /jobs/{id}, /job/{id}, /remote-jobs/{id}, /positions/{id}, /listings/{id} URL shapes | Dynamite Jobs (dynamitejobs.com) careers boards | | arcdev | ArcdevAdapter | Recognises Arc.dev posting anchors by /jobs/{id}, /job/{id}, /roles/{id}, /positions/{id}, /openings/{id} URL shapes | Arc.dev (arc.dev) careers boards | | flexjobs | FlexjobsAdapter | Recognises FlexJobs posting anchors by /search/{id}, /flex-jobs/{id}, /remote-job/{id}, /jobs/{id}, /job/{id} URL shapes | FlexJobs (flexjobs.com) careers boards | | radancy | RadancyAdapter | Recognises Radancy posting anchors by /jobs/{id}, /job/{id}, /search/job/{id}, /careers/{id}, or /careers/job/{id} URL shapes | Radancy (*.radancy.com, *.jobs.net) recruiting boards | | silkroad | SilkRoadAdapter | Recognises SilkRoad posting anchors by /jobs/{id}, /job/{id}, /posting/{id}, /postings/{id}, or /opportunity/{id} URL shapes | SilkRoad (*.silkroad.com) recruiting boards | | paradox | ParadoxAdapter | Recognises Paradox careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /opportunities/{id} URL shapes | Paradox Olivia (*.paradox.ai) careers boards | | applicantpro | ApplicantProAdapter | Recognises ApplicantPro careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /openings/{id} URL shapes | ApplicantPro (*.applicantpro.com) careers boards | | brassring | BrassringAdapter | Recognises BrassRing careers posting anchors by /jobs/{id}, /job/{id}, /jobdetail/{id}, /FgJobDetail/{id}, or /careers/{id} URL shapes | IBM Kenexa BrassRing (*.brassring.com) careers boards |

source_type Adapter How it parses Best for
greenhouse GreenhouseAdapter Scrapes div.opening anchors on public Greenhouse boards Greenhouse-hosted boards
lever LeverAdapter Scrapes div.posting anchors on public Lever pages Lever-hosted boards
ashby AshbyAdapter Recognises jobs.ashbyhq.com/{org}/{uuid} posting anchors by URL shape Ashby-hosted boards
workable WorkableAdapter Recognises apply.workable.com/{company}/j/{shortcode} posting anchors by URL shape Workable-hosted boards
recruitee RecruiteeAdapter Recognises {company}.recruitee.com/o/{slug} posting anchors by URL shape Recruitee-hosted careers sites
smartrecruiters SmartRecruitersAdapter Recognises jobs.smartrecruiters.com/{company}/{jobId}-{slug} posting anchors by URL shape SmartRecruiters-hosted careers sites
teamtailor TeamtailorAdapter Recognises {company}.teamtailor.com/jobs/{jobId}-{slug} posting anchors by URL shape Teamtailor-hosted careers sites
personio PersonioAdapter Recognises {tenant}.jobs.personio.de/.com/job/{jobId} posting anchors by URL shape Personio-hosted careers sites (DACH/EU)
bamboohr BambooHrAdapter Reads the public {tenant}.bamboohr.com/careers/list JSON board and maps each opening to /careers/{id} BambooHR-hosted careers sites (SMB tech/healthcare/services)
jobvite JobviteAdapter Recognises jobs.jobvite.com/{company}/job/{jobId} posting anchors by URL shape (terminal singular job, alphanumeric id) Jobvite-hosted careers sites
icims IcimsAdapter Recognises careers-{tenant}.icims.com/jobs/{jobId}/{slug}/job posting anchors by URL shape (terminal literal job, numeric id; slug optional) iCIMS-hosted careers portals (enterprise) and vanity-domain proxies
workday WorkdayAdapter POSTs the public {tenant}.wd{N}.myworkdayjobs.com/wday/cxs/{tenant}/{site}/jobs JSON CXS board (page size 20) and maps each posting to {origin}/{locale}/{site}{externalPath} Workday-hosted enterprise careers sites
oracle_taleo OracleTaleoAdapter Recognises Taleo/Oracle Cloud posting anchors via job= query ids or terminal /job/{id} / /jobs/{id} path shapes Oracle Taleo (*.taleo.net) and Oracle Cloud HCM careers portals
successfactors SuccessFactorsAdapter Recognises SuccessFactors posting anchors via jobId / career_job_req_id query ids or terminal /job/{id} / /jobs/{id} path shapes SAP SuccessFactors (*.successfactors.com / *.successfactors.eu) careers portals
zoho_recruit ZohoRecruitAdapter Recognises Zoho Recruit posting anchors via jobId / jid / job_id query ids or terminal /job/{id} / /jobs/{id} / /careers/{id} path shapes Zoho Recruit (*.zohorecruit.com) careers portals and vanity-domain proxies
jazzhr JazzHrAdapter Recognises JazzHR posting anchors via /apply/{jobId} or /apply/{jobId}/{slug} path shapes JazzHR (*.applytojob.com/apply) careers portals and vanity-domain proxies
breezyhr BreezyHrAdapter Recognises {company}.breezy.hr/p/{positionId} posting anchors by URL shape (terminal p, alphanumeric id; slug optional) Breezy HR-hosted careers sites (startup/SMB)
freshteam FreshteamAdapter Recognises Freshteam careers posting anchors by job URL shape Freshworks Freshteam-hosted careers boards
phenom PhenomPeopleAdapter Recognises Phenom posting anchors via /job/{jobId}/{slug} or /jobs/{jobId} path shapes, rejecting list/index/login/apply-step links Phenom People-hosted enterprise and branded careers sites
rippling RipplingAdapter Recognises Rippling posting anchors via terminal /jobs/{uuid} paths on *.rippling.com domains Rippling-hosted public careers boards
pinpoint PinpointAdapter Recognises Pinpoint HR careers posting anchors by /postings/{uuid} or /jobs/{id} URL shape Pinpoint (*.pinpointhq.com) careers boards
comeet ComeetAdapter Recognises Comeet careers posting anchors by /jobs/{company}/{companyId}/{jobSlug}/{jobId} URL shape Comeet (www.comeet.co / www.comeet.com) careers boards
fountain FountainAdapter Recognises Fountain careers posting anchors by /apply/{company}/{positionId}, /apply/{slug}, /jobs/{id}, /openings/{id}, or /positions/{id} URL shape Fountain (*.fountain.com, web.fountain.com) careers boards
gem GemAdapter Recognises Gem careers posting anchors by jobs.gem.com/{company}/{jobId}, /jobs/{jobId}, /openings/{id}, or {company}.gem.com/careers/... URL shapes Gem (jobs.gem.com / *.gem.com) careers boards
avature AvatureAdapter Recognises Avature careers posting anchors by /JobDetail/{id}, /JobDetail.aspx?JobId={id}, /careers/{id}, /careers/job/{id}, /careers/VacancyDetail/{id}, /Vacancy/{id}, or /vacancies/{id} URL shapes Avature-hosted public careers portals
eightfold EightfoldAdapter Recognises Eightfold careers posting anchors by /careers/job/{id}, /careers/job/{id}/{slug}, /career_detail/{id}, /position/{id}, or /jobs/{id} URL shapes Eightfold (*.eightfold.ai) careers boards
jobscore JobScoreAdapter Recognises JobScore careers posting anchors by /careers/{company}/jobs/{slug}-{id}, /careers/{company}/jobs/{id}, /jobs/{id}, /jobs/{slug}/{id}, or /position(s)/{id} URL shapes JobScore (careers.jobscore.com / *.jobscore.com) careers boards
hireology HireologyAdapter Recognises Hireology careers posting anchors by /jobs/{id}, /careers/job/{id}, or /job/{id}/{slug} URL shapes Hireology (careers.hireology.com) careers boards
dayforce DayforceAdapter Recognises Dayforce careers posting anchors by /JobDetail/{id}, /careers/job/{id}, /MyCareer/JobDetail?jobId={id}, or /positions/{id} URL shapes Dayforce (*.dayforcehcm.com) careers boards
homerun HomerunAdapter Recognises Homerun careers posting anchors by /jobs/{id}-{slug}, /o/{id}, or /vacancies/{id} URL shapes Homerun (*.homerun.co) careers boards
clearcompany ClearCompanyAdapter Recognises ClearCompany careers posting anchors by /careers/job/{id}, /careers/{id}, /jobs/{id}, /job/{id}-{slug}, or /position/{id} URL shapes ClearCompany (*.clearcompany.com) careers boards
applied AppliedAdapter Recognises Applied careers posting anchors by /jobs/{id}, /j/{id}, /role/{id}, /roles/{id}, or /job/{id} URL shapes Applied (*.applied.co) careers boards
recruiterflow RecruiterflowAdapter Recognises Recruiterflow careers posting anchors by /jobs/{id}, /job/{id}, /careers/job/{id}, /openings/{id}, or /opening/{id} URL shapes Recruiterflow (*.recruiterflow.com) careers boards
manatal ManatalAdapter Recognises Manatal careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /openings/{id} URL shapes Manatal (*.manatal.com) careers boards
join JoinAdapter Recognises Join careers posting anchors by /companies/{slug}/jobs/{id}, /jobs/{id}, /job/{id}, or /positions/{id} URL shapes Join (join.com) careers boards
softgarden SoftgardenAdapter Recognises Softgarden careers posting anchors by /job/{id}, /jobs/{id}, /vacancies/{id}, /vacancy/{id}, or /position/{id} URL shapes Softgarden (*.softgarden.io) careers boards
factorial FactorialAdapter Recognises Factorial HR careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /open-positions/{id} URL shapes Factorial (*.factorialhr.com) careers boards
ukg UkgAdapter Recognises UKG/UltiPro careers posting anchors by /jobs/{id}, /job/{id}, /opportunities/{id}, /opportunity/{id}, or /careers/job/{id} URL shapes UKG (*.ultipro.com / *.ukg.net) careers boards
bullhorn BullhornAdapter Recognises Bullhorn careers posting anchors by /jobs/{id}, /Job/{id}, /careers/{id}, /careers/job/{id}, or /position/{id} URL shapes Bullhorn (*.bullhornstaffing.com) careers boards
paylocity PaylocityAdapter Recognises Paylocity careers posting anchors by /jobs/{id}, /JobDetails/{id}, /careers/{id}, /careers/job/{id}, or /openings/{id} URL shapes Paylocity (*.paylocity.com) careers boards
polymer PolymerAdapter Recognises Polymer careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /positions/{id} URL shapes Polymer (*.polymer.co) careers boards
jobadder JobAdderAdapter Recognises JobAdder careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /position/{id} URL shapes JobAdder (*.jobadder.com) careers boards
jobylon JobylonAdapter Recognises Jobylon careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, /positions/{id}, or /vacancies/{id} URL shapes Jobylon (jobs.jobylon.com) careers boards
ceipal CeipalAdapter Recognises Ceipal careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /requisitions/{id} URL shapes Ceipal (*.ceipal.com / jobs.ceipal.com) careers boards
pageup PageUpAdapter Recognises PageUp careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /opportunities/{id} URL shapes PageUp (*.pageuppeople.com / careers.pageuppeople.com) careers boards
talentlyft TalentLyftAdapter Recognises TalentLyft careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /openings/{id} URL shapes TalentLyft (*.talentlyft.com / apply.talentlyft.com) careers boards
applicantstack ApplicantStackAdapter Recognises ApplicantStack careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /postings/{id} URL shapes ApplicantStack (*.applicantstack.com) careers boards
dover DoverAdapter Recognises Dover careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /openings/{id} URL shapes Dover (app.dover.com) careers boards
loxo LoxoAdapter Recognises Loxo careers posting anchors by /jobs/{id}, /job/{id}, /positions/{id}, /careers/{id}, or /careers/job/{id} URL shapes Loxo (*.loxo.co) careers boards
jsonld JsonLdAdapter Reads embedded schema.org/JobPosting JSON-LD Any board emitting Google-Jobs structured data (SmartRecruiters, custom career sites, ...)
hibob HibobAdapter Recognises HiBob careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /positions/{id} URL shapes HiBob (*.hibob.com) / Bob careers boards
trackerrms TrackerRmsAdapter Recognises TrackerRMS careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /vacancies/{id} URL shapes TrackerRMS (*.tracker-rms.com and branded) careers boards
careerplug CareerPlugAdapter Recognises CareerPlug careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /listings/{id} URL shapes CareerPlug (*.careerplug.com) careers boards
recruitcrm RecruitCrmAdapter Recognises RecruitCRM careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /opening/{id} URL shapes RecruitCRM (*.recruitcrm.io) careers boards
vincere VincereAdapter Recognises Vincere careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /job-detail/{id} URL shapes Vincere (*.vincere.io) careers boards
tribepad TribepadAdapter Recognises Tribepad careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /vacancy/{id} URL shapes Tribepad (*.tribepad.com) careers boards
crelate CrelateAdapter Recognises Crelate careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /opportunity/{id} URL shapes Crelate (*.crelate.com) careers boards
jobdiva JobDivaAdapter Recognises JobDiva careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /jd/{id} URL shapes JobDiva (*.jobdiva.com) careers boards
pcrecruiter PCRecruiterAdapter Recognises PCRecruiter careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /requisition/{id} URL shapes PCRecruiter (*.pcrecruiter.com) careers boards
cornerstone CornerstoneAdapter Recognises Cornerstone careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /opening/{id} URL shapes Cornerstone OnDemand (*.csod.com) careers boards
eploy EployAdapter Recognises Eploy careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /role/{id} URL shapes Eploy (*.eploy.net) careers boards
beamery BeameryAdapter Recognises Beamery careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /campaign/{id} URL shapes Beamery (*.beamery.com) careers boards
hireez HireezAdapter Recognises HireEZ careers posting anchors by /jobs/{id}, /job/{id}, /careers/{id}, /careers/job/{id}, or /positions/{id} URL shapes HireEZ / Hiretual (*.hireez.com) careers boards
authenticjobs AuthenticjobsAdapter Recognises Authentic Jobs posting anchors by /postings/{id}, /listing/{id}, /opportunities/{id}, /jobs/{id}, /job/{id} URL shapes Authentic Jobs (authenticjobs.com) careers boards
eurotechjobs EurotechjobsAdapter Recognises EuroTechJobs posting anchors by /vacancies/{id}, /offers/{id}, /tech-jobs/{id}, /jobs/{id}, /job/{id} URL shapes EuroTechJobs (eurotechjobs.com) careers boards
jobgether JobgetherAdapter Recognises Jobgether posting anchors by /roles/{id}, /openings/{id}, /positions/{id}, /jobs/{id}, /job/{id} URL shapes Jobgether (jobgether.com) careers boards
pangian PangianAdapter Recognises Pangian posting anchors by /remote-jobs/{id}, /listings/{id}, /positions/{id}, /jobs/{id}, /job/{id} URL shapes Pangian (pangian.com) careers boards
remoteleaf RemoteleafAdapter Recognises RemoteLeaf posting anchors by /remote/{id}, /leaf-jobs/{id}, /positions/{id}, /jobs/{id}, /job/{id} URL shapes RemoteLeaf (remoteleaf.com) careers boards
fourdayweek FourdayweekAdapter Recognises 4 Day Week posting anchors by /four-day/{id}, /listings/{id}, /positions/{id}, /jobs/{id}, /job/{id} URL shapes 4 Day Week (4dayweek.io) careers boards
aijobs AijobsAdapter Recognises AI Jobs posting anchors by /ai-jobs/{id}, /roles/{id}, /openings/{id}, /jobs/{id}, /job/{id} URL shapes AI Jobs (ai-jobs.net) careers boards
powertofly PowertoflyAdapter Recognises PowerToFly posting anchors by /opportunities/{id}, /women-tech/{id}, /positions/{id}, /jobs/{id}, /job/{id} URL shapes PowerToFly (powertofly.com) careers boards
nofluffjobs NofluffjobsAdapter Recognises No Fluff Jobs posting anchors by /pl/{id}, /job/{id}, /offers/{id}, /positions/{id}, /jobs/{id} URL shapes No Fluff Jobs (nofluffjobs.com) careers boards
cryptojobs CryptojobsAdapter Recognises Crypto Jobs posting anchors by /crypto-jobs/{id}, /web3/{id}, /positions/{id}, /jobs/{id}, /job/{id} URL shapes Crypto Jobs (cryptojobslist.com) careers boards
workatastartup WorkatastartupAdapter Recognises Work at a Startup posting anchors by /companies/{id}, /startups/{id}, /roles/{id}, /jobs/{id}, /job/{id} URL shapes Work at a Startup (workatastartup.com (YC)) careers boards
levelsfyi LevelsfyiAdapter Recognises Levels.fyi posting anchors by /jobs/{id}, /job/{id}, /roles/{id}, /openings/{id}, /levels/{id} URL shapes Levels.fyi (levels.fyi) careers boards
dice DiceAdapter Recognises Dice posting anchors by /positions/{id}, /jobs/{id}, /job/{id}, /listings/{id}, /tech-jobs/{id} URL shapes Dice (dice.com) tech careers boards
pythonjobs PythonjobsAdapter Recognises Python Jobs posting anchors by /python-jobs/{id}, /listings/{id}, /positions/{id}, /jobs/{id}, /job/{id} URL shapes Python Jobs (python.org/jobs) careers boards
jooble JoobleAdapter Recognises Jooble posting anchors by /jobs/{id}, /job/{id}, /vacancy/{id}, /vacancies/{id}, /listings/{id} URL shapes Jooble (jooble.org) careers boards
simplyhired SimplyhiredAdapter Recognises SimplyHired posting anchors by /job/{id}, /jobs/{id}, /listings/{id}, /positions/{id}, /openings/{id} URL shapes SimplyHired (simplyhired.com) careers boards
ziprecruiter ZiprecruiterAdapter Recognises ZipRecruiter posting anchors by /jobs/{id}, /job/{id}, /listings/{id}, /openings/{id}, /positions/{id} URL shapes ZipRecruiter (www.ziprecruiter.com) careers boards
reed ReedAdapter Recognises Reed posting anchors by /jobs/{id}, /job/{id}, /details/{id}, /vacancies/{id}, /listings/{id} URL shapes Reed (www.reed.co.uk) careers boards
themuse ThemuseAdapter Recognises TheMuse posting anchors by /jobs/{id}, /job/{id}, /positions/{id}, /openings/{id}, /roles/{id} URL shapes TheMuse (www.themuse.com) careers boards
glassdoor GlassdoorAdapter Recognises Glassdoor posting anchors by /reviews/{id}, /jobs/{id}, /job-listing/{id}, /positions/{id}, /openings/{id} URL shapes Glassdoor (www.glassdoor.com) careers boards
angellist AngellistAdapter Recognises AngelList posting anchors by /jobs/{id}, /startups/{id}, /startup-jobs/{id}, /roles/{id}, /positions/{id} URL shapes AngelList (angel.co) careers boards
indeed IndeedAdapter Recognises Indeed posting anchors by /viewjob/{id}, /jobs/{id}, /job/{id}, /rc/clk/{id}, /m/jobs/{id} URL shapes Indeed (www.indeed.com) careers boards
careerbuilder CareerbuilderAdapter Recognises CareerBuilder posting anchors by /job/{id}, /jobs/{id}, /jobseeker/jobs/{id}, /share/job/{id}, /career-jobs/{id} URL shapes CareerBuilder (www.careerbuilder.com) careers boards
handshake HandshakeAdapter Recognises Handshake posting anchors by /jobs/{id}, /job-search/{id}, /postings/{id}, /edu/jobs/{id}, /internship/{id} URL shapes Handshake (joinhandshake.com) careers boards
seek SeekAdapter Recognises Seek posting anchors by /job/{id}, /jobs/{id}, /listed-job/{id}, /jobsearch/{id}, /au/job/{id} URL shapes Seek (www.seek.com.au) careers boards
totaljobs TotaljobsAdapter Recognises Totaljobs posting anchors by /job/{id}, /jobs/{id}, /job-vacancy/{id}, /details/{id}, /uk/job/{id} URL shapes Totaljobs (www.totaljobs.com) careers boards
naukri NaukriAdapter Recognises Naukri posting anchors by /job-listings/{id}, /jobdetail/{id}, /jobs/{id}, /job-description/{id}, /recruiters/job/{id} URL shapes Naukri (www.naukri.com) careers boards
monster MonsterAdapter Recognises Monster posting anchors by /jobs/job/{id}, /job-openings/{id}, /jobs/{id}, /career/{id}, /m/job/{id} URL shapes Monster (www.monster.com) careers boards
workintheopen WorkintheopenAdapter Recognises Work in the Open posting anchors by /jobs/{id}, /job/{id}, /roles/{id}, /openings/{id}, /positions/{id} URL shapes Work in the Open careers boards

Unlike the HTML-scraping adapters, bamboohr and workday are structured-JSON sources: BambooHR and Workday careers pages are client-rendered apps, so those adapters read the tenant's public JSON listing endpoints directly (stable titles, locations, and ids) instead of parsing rendered markup. Workday uses the public CXS POST API — see docs/guides/WORKDAY_SOURCE_GUIDE.md.

The jsonld adapter is vendor-neutral: modern ATS platforms publish <script type="application/ld+json"> JobPosting payloads so their roles appear in Google Jobs, so a single adapter covers boards that would otherwise each need a bespoke scraper. It understands bare objects, arrays, @graph/ItemList containers, TELECOMMUTE remote roles, and PropertyValue identifiers, and it skips malformed blocks instead of failing the whole page.

# Register a JSON-LD source
curl -X POST localhost:8000/source-configs \
  -H 'content-type: application/json' \
  -d '{"name":"acme-careers","source_type":"jsonld","base_url":"https://acme.example.com/careers"}'

Quick start

git clone https://github.com/Francis1998/agentic-career-search.git
cd agentic-career-search
uv venv
source .venv/bin/activate
uv sync --extra dev --frozen
cp .env.example .env
uv run uvicorn autoapply_agent.main:app --reload

Documentation

Document Description
ARCHITECTURE.md Core agent architecture and lifecycle
CONFIGURATION.md Runtime and provider configuration
QUICKSTART.md Fast local setup and verification
SAFETY.md Scope boundaries and operational guardrails
docs/DEPLOYMENT.md Deployment guidance
docs/TROUBLESHOOTING.md Common failure recovery paths
CHANGELOG.md Release history

Regenerate demos

./scripts/generate_demo_gif.sh

License

MIT © Francis1998

About

Autonomous AI-agent orchestration engine for job discovery with decision traces, tool adapters, and production-grade run control.

Topics

Resources

Contributing

Stars

100 stars

Watchers

14 watching

Forks

Releases

Packages

Contributors

Languages