Enterprise-grade AI Resume Intelligence Platform. Multi-agent orchestration via JARVIS (LangGraph), GPT-4o-mini powered semantic analysis, dynamic DOCX rendering, and ATS compliance scoring. Full request lifecycle from candidate profile → tailored .docx in under 60 seconds.
Three-tier architecture: React frontend → FastAPI backend → multi-agent AI pipeline. All agent calls route through a single OpenAI async client with structured function-calling outputs.
LangGraph compiles a directed acyclic StateGraph. Each node is an async Python function. State flows forward; no agent can modify a predecessor's output.
Every agent is an async Python function that receives the full AgentState, calls GPT-4o-mini with a structured tool schema, and returns a partial state update dict.
Converts raw candidate data into a semantic profile graph that downstream agents use for intelligent matching. Identifies seniority level, primary domains, leadership signals, quantified achievements, and career trajectory.
request.profile — CandidateProfile modelcandidate_level — Junior/Mid/Senior/Staff/Principalyears_of_experience — inferred floatprimary_domains — top 3–5 areastechnical_depth — skill → score 1–10 mapleadership_indicators — evidence stringsquantified_achievements — all measurable impactstop_differentiators — unique strengthsall_skills — comprehensive flat listParses the job description to extract hard requirements, ATS keywords, soft skills, and hidden hiring signals. Also infers company stage, engineering culture, and expected resume tone — enabling tone-matching and ATS optimization in downstream agents.
request.job_description — raw JD textrequest.target_role — optional user hintrole_title + company_namemandatory_skills — must-have listpreferred_skills — nice-to-have listats_keywords — exact ATS scan phrasesdomain_focus — primary tech/business domainscompany_stage — Startup/Growth/Enterpriseexpected_resume_tone — Quantitative/Technical/Executivekey_responsibilities — top 5–7 dutiesyears_experience_requiredThe intelligence brain of the system. Computes semantic alignment between the candidate profile and JD, scores every experience entry and project 0–100, identifies keyword gaps, and creates an injection opportunity map — telling the optimizer exactly which bullets to enrich.
semantic_profile — from Agent 1jd_analysis — from Agent 2request.profile — raw experience + projectsrequest.max_pages — 1 or 2overall_match_score — 0–100experience_relevance[] — per-role score, include bool, priority rank, inject keywordsproject_relevance[] — per-project score + include boolkeywords_matched — already present in profilekeywords_missing — critical gapsskills_to_highlight — prioritized for JDrecommended_summary_angle — tone directivekeywords_matched and keywords_missing from this agent are stored directly on AgentState and surfaced in the API response alongside the final ATS score.
Transforms raw bullets into high-impact, recruiter-friendly statements using the CAR (Challenge → Action → Result) framework. Injects missing ATS keywords naturally. Generates a tailored professional summary. Only processes roles marked include=true by the relevance engine.
relevance_map — which roles to optimizejd_analysis.ats_keywords — inject targetskeywords_missing — gap keywordsjd_analysis.expected_resume_tonerelevance_map.recommended_summary_angleprofessional_summary — 2–3 sentence tailored summaryoptimized_experience[] — company + rewritten bullets (best first)optimized_projects[] — rewritten project descriptionsThe final AI layer before rendering. Decides section ordering, bullet count per role, page-fit strategy, and produces the complete ResumeComposition JSON that the DOCX engine renders verbatim. No further AI processing after this point.
optimized_content — rewritten bullets + summaryrelevance_map — priority orderingjd_analysis — company stage, tonesemantic_profile — candidate levelrequest.max_pages — 1 or 2request.format — ats/swe/executive/startup…personal — all contact fieldssummary — final summary stringexperience[] — FINAL bullets with dates/locationsprojects[] — selected + final bulletsskill_sections[] — ordered categorieseducation[] + certifications[]section_order[] — render orderlayout — font size, margin, densityA single TypedDict flows through all 5 nodes. Each node receives the full state and returns a partial update dict. Later agents can read all earlier outputs.
| Field | Type | Set By | Used By | Description |
|---|---|---|---|---|
| request | GenerateRequest | API route | All agents | The original user request — profile, JD, options |
| semantic_profile | dict | None | Agent 1 | Agents 3,4,5 | Seniority, domains, achievements, trajectory |
| jd_analysis | dict | None | Agent 2 | Agents 3,4,5 | Keywords, culture signals, tone expectations |
| relevance_map | dict | None | Agent 3 | Agents 4,5 | Per-role scores, keyword gaps, injection map |
| optimized_content | dict | None | Agent 4 | Agent 5 | Rewritten bullets, professional summary |
| composition | dict | None | Agent 5 | DOCX + ATS engines | Final render-ready composition JSON |
| ats_score | float | Agent 3 | API response | Overall match score 0–100 |
| keywords_matched | list[str] | Agent 3 | API response | JD keywords present in profile |
| keywords_missing | list[str] | Agent 3 | Agent 4 + response | Critical keywords to inject |
| errors | list[str] | Any agent | Logging | Non-fatal errors; pipeline continues with fallback |
| current_step | str | Each agent | Observability | Tracking label for current pipeline stage |
errors[]. The pipeline continues — a failed agent doesn't crash the whole generation. The final resume may be lower quality but is still produced.
Data-driven python-docx renderer. The composition JSON from Agent 5 controls every rendering decision — section order, content, typography, and spacing. No static templates.
section_order[]. Dispatches each key to its dedicated renderer function| Element | Font | Size | Style | Alignment | Spacing |
|---|---|---|---|---|---|
| Candidate Name | Calibri | 16pt | Bold, ALL CAPS | Center | after: 2pt |
| Contact Line | Calibri | 9pt | Normal | Center | after: 6pt |
| Section Header | Calibri | 11pt | Bold + bottom border | Left | before: 7pt, after: 2pt |
| Job Title | Calibri | 11pt | Bold | Left (tab-right for date) | before: 4pt |
| Company / Location | Calibri | 10pt | Italic | Left | after: 2pt |
| Bullet Points | Calibri | 10pt | Normal | Left, 0.2" indent | after: 1.5pt |
| Skills: Category | Calibri | 10pt | Bold | Left | line spacing: 1.0 |
| Skills: Items | Calibri | 10pt | Normal | Left | inline after category |
| Degree | Calibri | 11pt | Bold | Left (tab-right for year) | before: 4pt |
Computed post-composition against the original JD analysis. Returns a 0–100 score and matched/missing keyword lists surfaced in the API response and frontend UI.
Passes most ATS systems. Strong keyword coverage.
Will pass most ATS. Add more JD keywords manually.
Profile significantly mismatched to JD. Review missing keywords.
| Component | Weight | How Computed | Penalty |
|---|---|---|---|
| ATS Keyword Coverage | 50% | matched_ats_keywords / total_ats_keywords. Includes fuzzy matching (ml↔machine learning, k8s↔kubernetes) | — |
| Mandatory Skills Coverage | 30% | matched_mandatory_skills / total_mandatory_skills from JD analysis | — |
| Structure Compliance | 20% | Starts at 100, deductions applied | No EXPERIENCE section: -20. No EDUCATION: -10. Each weak bullet (no action verb): -2, max -10 |
Separate from the resume generation pipeline. Accepts any raw text and populates the form. Uses GPT-4o-mini with section-specific JSON schemas. Available on every form step.
all — Full resume parse
Most powerful
personal — Contact extraction
name, email, phone, linkedin…
experience — Work history
Array of roles + bullets
projects — Project descriptions
name, techs, URLs, bullets
skills — Skill categorization
Auto-grouped by category
education — Degrees + certs
edu[] + certifications[]
certifications — Certs only
name, issuer, date
{ section, raw_text } → FastAPI validation → route handler{ section, data }All endpoints under http://localhost:8000. CORS enabled for localhost:3000.
download_id valid for 1 hour. Typical latency: 30–60s./api/generate response. Files expire after 1 hour (configurable via DOWNLOAD_TTL_SECONDS).section="all" to parse an entire resume at once. Typical latency: 3–8s./api/extract for structured parsing.All models defined in backend/app/models/schema.py. All nested string fields default to "" for resilience against null values from GPT.
| Field | Type | Default |
|---|---|---|
| profile | CandidateProfile | required |
| job_description | str | required |
| format | ResumeFormat | "ats" |
| max_pages | int (1–2) | 1 |
| target_role | str | None | None |
| Field | Type | Notes |
|---|---|---|
| download_id | str (UUID) | Use with /download/{id} |
| ats_score | float | 0–100 |
| keywords_matched | list[str] | From relevance agent |
| keywords_missing | list[str] | From relevance agent |
| sections_included | list[str] | From composer agent |
| generation_time_ms | int | Wall clock time |
| Field | Type |
|---|---|
| name, email | str (required) |
| phone, location, linkedin, github, website | str | None |
| summary | str | None |
| experience | list[ExperienceEntry] |
| projects | list[ProjectEntry] |
| skill_categories | list[SkillCategory] |
| flat_skills | list[str] |
| education | list[EducationEntry] |
| certifications | list[CertificationEntry] |
"ats" Maximum keyword density, ATS-safe sections"swe" Technical depth, systems language, scale metrics"executive" Business impact, P&L, team scale, board language"startup" Ownership, velocity, cross-functional scope"minimal" Clean, spare layout — achievements speak"research" Academic tone, publications, methodologyChosen for developer velocity, production scalability, and AI ecosystem depth.