Automated candidate-job fit evaluation powered by CrewAI agents. Provide a job posting URL and a resume PDF, and three AI agents will extract requirements, analyze the candidate, and produce a structured fit report.
The system runs a CrewAI Flow with three sequential agents:
- Skill Extraction Specialist — Scrapes the job posting URL using Firecrawl and extracts the job title, company name, and required skills.
- Resume Analyzer — Extracts the full text from the candidate's PDF resume using PyMuPDF and scores the candidate against the extracted requirements, identifying strengths and gaps.
- Report Writer — Compiles findings into a structured markdown report with fitness score, strengths, missing skills, and an overall assessment.
Progress updates are delivered in real-time via webhooks and Server-Sent Events (SSE) — the flow's event listener POSTs step updates to the frontend, which pushes them to the browser as each agent starts and finishes.
template_job_fit_assessment/
├── src/template_job_fit_assessment/
│ ├── main.py # CrewAI flow with 3 agents
│ └── events/
│ └── listener.py # WebhookEventListener (posts step updates)
├── frontend/
│ ├── app.py # Flask server (webhook receiver + SSE)
│ ├── templates/index.html # Web UI
│ ├── static/style.css # Styling
│ ├── requirements.txt # Flask dependencies
│ ├── Procfile # Heroku deployment
│ └── .env # API credentials (not committed)
├── pyproject.toml # CrewAI project config
└── .env # API keys (not committed)
- Python >= 3.11
- uv package manager
- API keys:
OPENAI_API_KEY— for the LLM agentsFIRECRAWL_API_KEY— for scraping job postings
- A Heroku account for the frontend
- A CrewAI AMP deployment for the backend
crewai deploy createSet these environment variables in AMP:
OPENAI_API_KEYFIRECRAWL_API_KEYWEBHOOK_URL— your Heroku app's webhook URL (see below)
# From the project root (template_job_fit_assessment/)
git subtree push --prefix frontend heroku mainSet these config vars on Heroku:
heroku config:set CREWAI_API_URL=https://your-deployment.crewai.com
heroku config:set CREWAI_BEARER_TOKEN=your-tokenYour webhook URL is https://<your-app>.herokuapp.com/webhook/messages — set this as WEBHOOK_URL in AMP.
Once both are deployed:
- Copy your Heroku app URL (e.g.,
https://my-app.herokuapp.com) - In AMP, set
WEBHOOK_URL=https://my-app.herokuapp.com/webhook/messages - Redeploy the flow on AMP so it picks up the new env var
| Endpoint | Method | Description |
|---|---|---|
/api/warmup |
POST | Pings AMP /inputs to warm up the deployment |
/api/kickoff |
POST | Receives job URL + resume PDF, forwards to AMP, returns session_id and kickoff_id |
/api/stream/<session_id> |
GET | SSE stream — pushes real-time step updates and final report |
/api/status/<kickoff_id> |
GET | Fallback polling endpoint — proxies to AMP status API |
| Endpoint | Method | Description |
|---|---|---|
/webhook/messages |
POST | Receives step updates and final report from WebhookEventListener |
The generated report follows this structure:
- Position — Company and job title
- Candidate — Name only (PII redacted)
- Required Skills — Full list from the posting
- Fitness Score — X/100 with interpretation
- Strengths — Matched skills
- Gaps / Missing Skills — Unmatched requirements
- Summary — 2-3 sentence overall assessment