Building a Resume Review Agent System with CrewAI

Apoorv Vishnoi Last Updated : 13 Feb, 2025
12 min read

Crafting the perfect resume is a tedious task – whether you’re a fresh graduate stepping into the job market, or a seasoned professional aiming for that next big career move. But what if you could have a personal resume reviewer at your fingertips – without spending any money on LinkedIn Premium or hiring a pricey professional? Enter the world of AI-powered solutions for resume optimisation! With the power of Large Language Models (LLMs) and innovative libraries like CrewAI, you can now build your very own resume review agent. In this blog, I’ll show you how to build an agentic system with CrewAI for reviewing and optimizing resumes.

Structure of the Resume Reviewer Agentic System

Before getting into the coding part, it is important to understand how to structure an AI system for resume optimisation. The best way to do this would be by noting down the tasks that we need the agent to perform. So, I’m assuming you have already made a resume (else you can download one resume from here). Now, we would want our resume review agentic system to perform 3 tasks:

  1. Read through and provide feedback on the resume.
  2. Improve or re-write the resume based on the feedback.
  3. Suggest appropriate jobs based on the improved resume and specified location.

Now that we have our requirements clearly written, we can decide on the number of agents and their tasks. Ideally, it is recommended we go with one task per agent to avoid overburdening any agent. This translates to us building 3 agents for our CrewAI-based resume review agent system:

  1. The first agent will provide feedback on the resume.
  2. The second agent will improve the resume based on the feedback.
  3. And, the third agent would suggest appropriate jobs based on the improved resume and specified location.

Also Read: Building a RAG-Based Research Assistant Using o3-mini and CrewAI

Now that you understand how we can use AI for resume optimisation, let’s jump to the Python code and build our resume reviewer agent.

Python Code to Build Resume Reviewer Agentic System with CrewAI

Here are the step-by-step instructions to build a resume review agent with CrewAI. To better follow these steps, I suggest you watch this hands-on video parallelly.

So let’s begin!

Step 1: Install and Import Relevant Libraries

We will begin with installing the PyMuPDF, python-docx and most importantly CrewAI.

  • The PyMuPDF library is used for reading PDF documents.
  • The python-docx library is used for creating, reading, and modifying Microsoft Word (.docx) documents.
  • Also, ensure CrewAI is installed in your system. It is one of the most popular agentic frameworks to build multi-agent systems.
#!pip install PyMuPDF
#!pip install python-docx
#!pip install crewai crewai-tools

Step 2: Loading the Resume

The next step is to import the fitz and docx modules. Here ‘fitz’ is the name you use to import PyMuPDF, and ‘docx’ is to import the python-docx library.

import fitz  # PyMuPDF for PDF processing
import docx  # python-docx for DOCX processing

We will now define the following three functions to enable our agentic system to extract text from resumes saved in various formats.

  • The first function – “extract_text_from_pdf” will extract contents from the resume in PDF format.
  • The second function – “extract_text_from_docx” will extract contents from the resume in docx format.
  • The third function – “extract_text_from_resume” wraps the first two functions and uses the respective function based on whether the document is a PDF or docx.

Let’s run this.

def extract_text_from_pdf(file_path):
    """Extracts text from a PDF file using PyMuPDF."""
    doc = fitz.open(file_path)
    text = ""
    for page in doc:
        text += page.get_text()
    return text

def extract_text_from_docx(file_path):
    """Extracts text from a DOCX file using python-docx."""
    doc = docx.Document(file_path)
    fullText = []
    for para in doc.paragraphs:
        fullText.append(para.text)
    return "\n".join(fullText)

def extract_text_from_resume(file_path):
    """Determines file type and extracts text."""
    if file_path.endswith(".pdf"):
        return extract_text_from_pdf(file_path)
    elif file_path.endswith(".docx"):
        return extract_text_from_docx(file_path)
    else:
        return "Unsupported file format."

Next, let’s test this function with 2 resumes. The first one will be a resume in PDF format of a person named Bruce Wayne (not the superhero).

res1 = extract_text_from_resume('/Users/admin/Desktop/YT Long/Bruce Wayne.pdf')
print(res1)

Now, we view the second resume.

res2 = extract_text_from_resume('/Users/admin/Desktop/YT Long/Anita Sanjok.docx')
print(res2)

Step 3: Preparing the Agents and Tasks

This step is where CrewAI enters the scene. We will now import crewai and start building the agentic system. For this, we will need 3 components from CrewAI, namely- Agent, Task and Crew.

  • Agent represents an AI assistant with a specific role and goal.
  • Task defines an objective that the agent needs to accomplish.
  • And finally, Crew is used to bundle multiple agents and their respective tasks together to work and achieve the set objective.
import os
from crewai import Agent, Task, Crew

Next, we need to add the OpenAI API key, which I have saved in a separate file. So, we need to read the API key from the file and set it as an environment variable. In this case we are using GPT-4o-mini as the LLM.

with open('/Users/apoorv/Desktop/AV/Code/GAI/keys/openai.txt', 'r') as file:
    openai_key = file.read()
os.environ['OPENAI_API_KEY'] = openai_key
os.environ["OPENAI_MODEL_NAME"] = 'gpt-4o-mini'

Next, we define the agents and their respective tasks.

1. Resume Feedback Agent

Our first agent will be the “resume_feedback” agent. The agent class has some parameters which help us define the objective of the agent. Lets look at them:

  • The role parameter defines the agent’s function and expertise within the crew. Here the agent’s role is that of a “Professional Resume Advisor”.
  • The goal is the sole objective that guides agents’ decision-making.
  • Verbose = True enables detailed execution logs for debugging.
  • The backstory gives a detailed description of the characteristics of the agent. It is similar to defining the context and personality of the agent.

Let’s run this.

# Agent 1: Resume Strategist
resume_feedback = Agent(
    role="Professional Resume Advisor",
    goal="Give feedback on the resume to make it stand out in the job market.",
    verbose=True,
    backstory="With a strategic mind and an eye for detail, you excel at providing feedback on resumes to highlight the most relevant skills and experiences."
    )

Now let’s define the task for the resume_feedback agent. The task is nothing but the specific assignment that needs to be completed by the agent to which this task is assigned.

  • We will add a detailed description which should be a clear, and concise statement of what the task entails. You must note that the {resume} written in curly braces is a placeholder that will be dynamically replaced with an actual resume input when the task runs. You can pause reading here, go through the description and make changes as per your requirements.
  • The expected output parameter helps us determine the format of the output. You can get the output in various formats such as  json, markdown or bullet points
  • The agent parameter highlights the name of the agent to which this task is assigned.
# Task for Resume Strategist Agent: Align Resume with Job Requirements
resume_feedback_task = Task(
    description=(
        """Give feedback on the resume to make it stand out for recruiters. 
        Review every section, inlcuding the summary, work experience, skills, and education. Suggest to add relevant sections if they are missing.  
        Also give an overall score to the resume out of 10.  This is the resume: {resume}"""
    ),
    expected_output="The overall score of the resume followed by the feedback in bullet points.",
    agent=resume_feedback
)

2. Resume Advisor Agent

We will do the same for the next agent, that is, the resume_advisor agent which writes a resume incorporating the feedback from the resume_feedback agent and defines its task in the resume_advisor_task. Feel free to go through it.

# Agent 2: Resume Strategist
resume_advisor = Agent(
    role="Professional Resume Writer",
    goal="Based on the feedback recieved from Resume Advisor, make changes to the resume to make it stand out in the job market.",
    verbose=True,
    backstory="With a strategic mind and an eye for detail, you excel at refining resumes based on the feedback to highlight the most relevant skills and experiences."
)
# Task for Resume Strategist Agent: Align Resume with Job Requirements
resume_advisor_task = Task(
    description=(
        """Rewrite the resume based on the feedback to make it stand out for recruiters. You can adjust and enhance the resume but don't make up facts. 
        Review and update every section, including the summary, work experience, skills, and education to better reflect the candidates abilities. This is the resume: {resume}"""
    ),
    expected_output= "Resume in markdown format that effectively highlights the candidate's qualifications and experiences",
    # output_file="improved_resume.md",
    context=[resume_feedback_task],
    agent=resume_advisor
)

3. Job Researcher Agent

Now, the third agent should be able to suggest jobs based on the qualifications and the preferred job location of the candidate. For this, we will grant a tool to our next agent that enables it to search the internet for job postings at a location.

We will use CrewAI’s SerperDevTool which integrates with Serper.dev for real-time web search functionality.

from crewai_tools import SerperDevTool

Now we import the API key from Serper. You can generate your free Serper API key from https://serper.dev/api-key.

with open('/Users/apoorv/Desktop/AV/Code/GAI/keys/serper.txt', 'r') as file:
    serper_key = file.read()

os.environ["SERPER_API_KEY"] = serper_key

search_tool = SerperDevTool()

Now we define our final agent which is the job_researcher agent. This agent will search for jobs at the location based on the resume improved by the resume_advisor agent. The structure of the agent is similar to the above agents with the only difference being the addition of a new parameter, which is tools. Tools help you assign the necessary tools to an agent which helps in the completion of the task. Also, in the task we have added {location} in curly braces for dynamically changing it.

# Agent 3: Researcher
job_researcher = Agent(
    role = "Senior Recruitment Consultant",
    goal = "Find the 5 most relevant, recently posted jobs based on the improved resume recieved from resume advisor and the location preference",
    tools = [search_tool],
    verbose = True,
    backstory = """As a senior recruitment consultant your prowess in finding the most relevant jobs based on the resume and location preference is unmatched. 
    You can scan the resume efficiently, identify the most suitable job roles and search for the best suited recently posted open job positions at the preffered location."""
    )
research_task = Task(
    description = """Find the 5 most relevant recent job postings based on the resume recieved from resume advisor and location preference. This is the preferred location: {location} . 
    Use the tools to gather relevant content and shortlist the 5 most relevant, recent, job openings. Also provide the links to the job postings.""",
    expected_output=(
        "A bullet point list of the 5 job openings, with the appropriate links and detailed description about each job, in markdown format" 
    ),
#    output_file="relevant_jobs.md",
    agent=job_researcher
)

Step 4: Creating the Crew and Reviewing the Output

Now we reach the final step where we bundle the agents and the tasks in order within the Crew functionality of crewAI. It has 3 parameters:

  • The agents parameter lists the agents in the order in which they will be called and executed.
  • The tasks argument lists the tasks defined for each agent in the order of execution.
  • And finally, Verbose=True lets you see the detailed output so you can see what the agents are doing.

Let’s run this.

crew = Crew(
    agents=[resume_feedback, resume_advisor, job_researcher],
    tasks=[resume_feedback_task, resume_advisor_task, research_task],
    verbose=True
)

And we finally launched our agentic system with the kickoff functionality.

  • crew.kickoff(inputs={…}): Starts the CrewAI execution, and takes in 2 inputs, resume and location.
  • “resume”: res2: Helps you specify the resume for which the agentix system needs to work. In our case, we are working on Anita’s resume.
  • “location”: ‘New Delhi’: Specifies where Anita is looking for a job. And this will be New Delhi in our case.
result1 = crew.kickoff(inputs={"resume": res2, "location": 'New Delhi'})

Seems like our crew functions perfectly. Let’s print each agent’s output individually.

from IPython.display import Markdown, display

First, we will print resume_feedback agent’s output.

markdown_content = resume_feedback_task.output.raw.strip("```markdown").strip("```").strip()
# Display the Markdown content
display(Markdown(markdown_content))

Then we print the resume_advisor agent’s output.

markdown_content = resume_advisor_task.output.raw.strip("```markdown").strip("```").strip()
# Display the Markdown content
display(Markdown(markdown_content))
Build an AI Resume Review Agentic System with CrewAI

And finally, we print the research_task agent’s output.

markdown_content = research_task.output.raw.strip("```markdown").strip("```").strip()
# Display the Markdown content
display(Markdown(markdown_content))
Build an AI Resume Review Agentic System with CrewAI

And there you have it. Your fully functional resume review agentic system with CrewAI.

Also Read: Automating Email Responses Using CrewAI

Turning your CrewAI Resume Reviewer Agentic System into a Web App

One interesting thing we can do with our AI-driven resume optimization system is building a web-application for it.

Here’s the interface of the app I built:

Build an AI Resume Review Agentic System with CrewAI

We have wrapped our code for resume review agent with CrewAI in Gradio and hosted the final product on Hugging Face Spaces which has a liberal free tier.

Here’s how it works:

  1. First, drop your resume in a PDF or Word doc. The name of our candidate here is Bruce Wayne.
  2. Next, select the preferred job location for Bruce who is our candidate. Let’s say San Francisco
  3. And hit Submit.

Since this is using LLMs at the backend, GPT-4o-mini in our case, it will take some time to evaluate your resume, give a score, and feedback.

And as you can see, Bruce got a score of 7/10. And he has received in-depth section-wise feedback from the CrewAI agentic system. Along with that he also got the revised resume and even suggestions for jobs in San Francisco. How amazing is this!

Build an AI Resume Review Agentic System with CrewAI
Build an AI Resume Review Agentic System with CrewAI
Build an AI Resume Review Agentic System with CrewAI

If you want to replicate this CrewAI agentic system in the form of this web-application, you can simply clone this repository or duplicate this space and change the API key. Here’s how that’s done:

  1. First, click on Settings and then click on Clone repository in the dropdown.
  2. Then scroll down to the variable and secrets setting.
  3. You will already find the variables we created for the OpenAI key and Serper_Key. Simply click on Replace and add the API Key in the Value. Then click Save.

Also, you can get the code to build this app from the CrewAI agentic system along with the Gradio code in the app.py file in files section of Hugging Face spaces.

The click on app.py

Build an AI Resume Review Agentic System with CrewAI
Build an AI Resume Review Agentic System with CrewAI

Possible Improvements on the Resume Reviewer Agent

Like any other agentic system, there is a lot of scope for expanding the resume review agent we’ve just built with CrewAI. Here are a few tips to tinker around with:

  • You can build a fourth agent that customizes the resume, based on the job you select.
  • You can build another agent in the end to generate a cover letter customized for the job you want to apply.
  • You can also build another agent that will help you prepare for the job you select.

Also Read: How to Build an AI Pair Programmer with CrewAI?

Conclusion

Building a resume reviewer agentic system is a game-changer for job seekers looking for resume optimisation with AI-driven insights. This system efficiently analyzes, refines, and suggests jobs based on personalized resume feedback—all at a fraction of the cost of premium resume optimizing services. With CrewAI’s agentic capabilities, we’ve streamlined resume optimisation into an automated yet highly effective process. But this is just the beginning! CrewAI is working on automating all kinds of tasks and bringing much-needed efficiency to all industries. It is indeed exciting times ahead!

Frequently Asked Questions

Q1. What is CrewAI?

A. CrewAI is an open-source Python framework designed to support the development and management of multi-agent AI systems. Using CrewAI, you can build LLM-backed AI agents that can autonomously make decisions within an environment based on the variables present.

Q2. Can AI fix my resume?

A. Yes! An AI agent like the resume reviewer system we built using CrewAI, can help optimize your resume. It can even recommend the right jobs for you based on your qualifications, skills, and location.

Q3. What tasks can CrewAI do?

A. CrewAI can perform various tasks, including reviewing resumes, writing resumes, searching for jobs, applying for jobs, preparing cover letters and more.

Q4.  In what format should my resume be?

A. In order to use this resume reviewer agent, the uploaded resume must be in either PDF (.pdf) or Word (.docx) formats.

Q5. What AI model is used to review resumes?

A. Our resume reviewer agent uses OpenAI’s GPT-4o-mini for text processing and Serper.dev for real-time job search.

Q6. How accurate are the job recommendations provided by the system?

A. The job recommendations depend on the quality of the resume and the AI’s ability to match skills with job postings. Using Serper.dev, the system retrieves the most relevant and recent job listings.

Q7. Do I need coding knowledge to build a resume review agent?

A. Basic Python programming skills are required to set up and modify the CrewAI-based system. However, you can clone a pre-built repository and update the API keys to run it without deep coding expertise.

Apoorv is a seasoned AI and Data Science leader with over 14 years of experience, including more than a decade focused on Data Science, Machine Learning, and Deep Learning. As the Head of Training at Analytics Vidhya, he has spearheaded the development of industry-leading AI programs, including courses on Generative AI, LLM Agents, MLOps, and Advanced Machine Learning, shaping the skills of thousands of professionals.

Responses From Readers

Clear

We use cookies essential for this site to function well. Please click to help us improve its usefulness with additional cookies. Learn about our use of cookies in our Privacy Policy & Cookies Policy.

Show details