from crewai import Agent, Task def cv_parsing_task(cv_path: str, agent: Agent): return Task( description=f""" Read and extract all information from the CV located at: {cv_path} Extract: - Full name and contact info - All skills (technical and soft) - Work experience with roles, companies, durations - Projects with tech stacks used - Education - Certifications Return structured, detailed summary of the entire CV. """, expected_output="Structured summary of candidate's CV including skills, experience, projects, education.", agent=agent ) def jd_analysis_task(jd_source: str, agent: Agent): return Task( description=f""" Extract full job description details from: {jd_source} If it's a URL, scrape the page content. IMPORTANT: If the scraped content contains navigation menus, footers, "Sign in" prompts, "Similar jobs" sections, or other website UI noise, IGNORE all of that. Focus ONLY on the actual job description content. Extract: - Job title and seniority level - Required skills (must-have) - Nice-to-have skills - Key responsibilities - Years of experience required - Any specific tools, frameworks, or domain knowledge mentioned Return a structured breakdown of the job requirements. Keep your response concise — focus on the extracted requirements only. """, expected_output="Structured breakdown of job role, required skills, responsibilities, and experience needed.", agent=agent ) def company_research_task(company_name: str, city: str, agent: Agent): return Task( description=f""" Research the company: {company_name} located in {city}. Make sure results are specific to this company in {city}, not other companies with similar names. Find: - What the company does and their main products - Tech stack they use - Engineering culture and team size if available - Recent news, funding, or major launches - What kind of problems they are solving Return a concise but informative company profile. Keep response under 500 words to stay within token limits. """, expected_output="Company profile covering products, tech stack, culture, and recent activities.", agent=agent ) def gap_analysis_task(agent: Agent, cv_task: Task, jd_task: Task): return Task( description=""" Using the CV summary and JD breakdown from previous tasks: - List skills present in JD but missing from CV - Identify weak or surface-level mentions that need strengthening - Highlight experience gaps (years, domain, seniority) - Rate overall match as: Strong / Moderate / Weak with reasoning Be specific and honest — don't sugarcoat gaps. Formatting rules: use ## for section headers, - for bullet points. Do not use *** or excessive bold. Plain readable text only. """, expected_output="Detailed gap analysis with missing skills, weak areas, experience gaps, and overall match rating.", context=[cv_task, jd_task], agent=agent ) def cv_optimization_task(agent: Agent, cv_task: Task, jd_task: Task, gap_task: Task, company_task: Task): return Task( description=""" Using the gap analysis and company research from previous tasks: - Suggest exact keywords and skills to add to the CV - Recommend which existing bullet points to rewrite and how - Suggest ATS-friendly improvements - Prioritize suggestions by impact — what will catch recruiter eyes first - Tailor suggestions to the specific company's culture and tech stack Be specific — give exact phrases to add, not vague advice. Formatting rules: use ## for section headers, - for bullet points. Do not use *** or excessive bold. Plain readable text only. """, expected_output="Prioritized list of specific CV improvements, keywords to add, and bullet point rewrites.", context=[cv_task, jd_task, gap_task, company_task], agent=agent ) def outreach_writing_task(agent: Agent, cv_task: Task, jd_task: Task, gap_task: Task, company_task: Task): return Task( description=""" Using all previous context — CV, JD, company research, and gap analysis: Write a personalized cold outreach message to the hiring manager. - Keep it under 150 words - Open with something specific about the company (not generic) - Connect candidate's strongest relevant experience to the role - End with a clear, low-friction call to action - Tone: confident, professional, human — not salesy Write one LinkedIn message version and one email version. Formatting rules: use ## LinkedIn Message and ## Email as headers. Do not use *** or excessive bold. Plain readable text only. """, expected_output="Two outreach messages — LinkedIn DM (under 150 words) and email version with subject line.", context=[cv_task, jd_task, gap_task, company_task], agent=agent )