Artificial Intelligence (AI) has evolved rapidly over the last few years. From single-task large language models (LLMs) to entire systems of autonomous agents, the AI ecosystem is now enabling new classes of intelligent workflows. In this blog post, we’ll build a multi-agent AI assistant that takes in a resume profile, a resume document, and a job description link, then produces a tailored resume and interview questions. We’ll explore how to do this using CrewAI, a Python-based multi-agent framework, and run it against both local models via OLLAMA and remote LLMs like OpenAI’s API.
What are AI Agents?
An AI agent is a software program that can perform tasks independently, make decisions based on data inputs, and interact with humans or other agents. These intelligent beings can be categorized into:
- Single-Agent Systems: A single AI system designed for a specific task, such as language translation or facial recognition.
- Multi-Agent Systems: Multiple AI systems interacting with each other to achieve complex tasks, like coordination in robotics or negotiation in e-commerce.
Use Cases
AI agents have numerous applications across various industries:
- Customer Service Chatbots: Automated customer support chatbots that can route users to human representatives when necessary.
- Robotics and Automation: AI-powered robots coordinating with each other for assembly lines, warehouse management, or search-and-rescue missions.
- Healthcare: AI agents assisting medical professionals in diagnosis, treatment planning, and patient communication.
-
Resume tailoring and job prep (as we’ll see here)
What are Multi-Agent Workflows?
A single agent has limitations—multi-agent systems overcome this by dividing complex tasks among specialized agents. These agents collaborate, delegate, and verify one another’s work, creating a more powerful and flexible system. The benefits of multi-agent systems include task parallelization, which enables the completion of multiple tasks faster; building modular agent systems that can scale independently; extending the workflow with new agents; and implementing agent specialization, where each agent focuses on a specific task.
Multi-agent workflows also enable collaboration between multiple AI agents to achieve a common goal. This can involve:
- Task Delegation: Agents delegate tasks to one another based on their respective capabilities.
- Information Sharing: Agents sharing knowledge or data with each other.
- Coordination Mechanisms: Agents utilize coordination mechanisms, such as auctions, negotiations, or voting, to reach a consensus.
Introducing CrewAI
CrewAI is an open-source Python library for building multi-agent systems. It allows you to:
- Define agents with roles and goals
- Create workflows where agents collaborate to solve problems
- Assign tasks to agents
- Integrate various AI models, including language processing and computer vision, to achieve more accurate predictions.
- Design custom workflows combining multiple agents with various data sources.
CrewAI key concepts include:
- Agents: Individual AI agent designed to perform specific tasks or interact with humans.
- Task: A particular objective assigned to one or more agents.
- Crew: A group of agents that collaborates on tasks.
- Pipelines: Customizable workflows that combine multiple agents and data sources.
- Roles: Agents can assume various roles within a pipeline, including leader, follower, or coordinator.
Setting Up Your Environment
Install Python dependencies
1 2 3 |
python -m venv venv source venv/bin/activate pip install crewai langchain ollama openai |
Set up OLLAMA with LLAMA locally
Install OLLAMA and then run:
1 |
ollama run llama3 |
This downloads and serves the LLaMA 3 model locally at http://localhost:11434
.
Set up ChatGPT API
- Get your OpenAI API key from https://platform.openai.com/account/api-keys
- Set it in your environment:
1 |
export OPENAI_API_KEY=your-api-key |
Generate a CrewAI Project Skeleton with CLI
CrewAI offers a CLI that can bootstrap a new project:
1 2 3 |
pip install crewai-cli crewai create crew ai-resume cd ai-resume |
This will generate a standard directory structure with example files for agents, tasks, and workflows:
Code: Multi-Agent Resume Builder with CrewAI
Here is the Python code for the multi-agent AI that:
- Takes a resume profile and text
- Downloads a job description from a URL
- Tailors the resume
- Generates sample interview questions
src/ai-resume/crew.py
For OpenAI please ensure you have a paid account with API credits. Also, ensure the environment variables OPENAI_API_KEY and SERPER_API_KEY are set. Avoid adding them to the code files.
Update the folders to your local path
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task from crewai import LLM from langchain_openai import ChatOpenAI from crewai_tools import ( FileReadTool, ScrapeWebsiteTool, TXTSearchTool, SerperDevTool ) import boto3 from langchain_community.llms import Ollama search_tool = SerperDevTool() scrape_tool = ScrapeWebsiteTool() read_resume = FileReadTool(file_path='PATH TO LOCAL FILE /myresume.txt') semantic_search_resume = TXTSearchTool(mdx='PATH TO LOCAL FILE /myresume.txt') # Uncomment the following lines to use local LLAMA LLM # llm = LLM( # model="ollama/llama3.2", # base_url="http://localhost:11434" # ) # Uncomment the following lines to use OpenAI LLM # You need to have the OpenAI API key in your environment variables and paid API credits llm = ChatOpenAI(model="gpt-4-turbo", temperature=0.0, verbose=True) @CrewBase class AiResume(): """AiResume crew""" # Learn more about YAML configuration files here: # Agents: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended # Tasks: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended agents_config = 'config/agents.yaml' tasks_config = 'config/tasks.yaml' @agent def researcher(self) -> Agent: return Agent( config=self.agents_config['researcher'], verbose=True, tools = [scrape_tool, search_tool], llm = llm ) @agent def personal_profiler(self) -> Agent: return Agent( config=self.agents_config['personal_profiler'], tools = [scrape_tool, search_tool, read_resume, semantic_search_resume], verbose=True, llm = llm ) @agent def resume_strategist(self) -> Agent: return Agent( config=self.agents_config['resume_strategist'], tools = [scrape_tool, search_tool, read_resume, semantic_search_resume], verbose=True, llm = llm ) @agent def interview_preparer(self) -> Agent: return Agent( config=self.agents_config['interview_preparer'], tools = [scrape_tool, search_tool, read_resume, semantic_search_resume], verbose=True, llm = llm ) @task def research_task(self) -> Task: return Task( config=self.tasks_config['research_task'], ) @task def personal_profiler_task(self) -> Task: return Task( config=self.tasks_config['personal_profiler_task'], ) @task def resume_strategist_task(self) -> Task: return Task( config=self.tasks_config['resume_strategist_task'], context=[self.research_task(), self.personal_profiler_task()], output_file='tailored_resume.md' ) @task def interview_preparation_task(self) -> Task: return Task( config=self.tasks_config['interview_preparation_task'], context=[self.research_task(), self.personal_profiler_task(), self.resume_strategist_task()], output_file='interview_preparation.md' ) @crew def crew(self) -> Crew: """Creates the AiResume crew""" return Crew( agents=self.agents, # Automatically created by the @agent decorator tasks=self.tasks, # Automatically created by the @task decorator process=Process.sequential, verbose=True ) |
src/ai-resume/main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/usr/bin/env python import sys import warnings import boto3 from datetime import datetime from ai_resume.crew import AiResume warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd") # Run the crew. def run(): inputs = { 'job_posting_url': 'HTTP URL TO EXTERNAL JOB POSTING', 'personal_writeup': """ WRITE YOUR PERSONAL PROFILE HERE """ } try: AiResume().crew().kickoff(inputs=inputs) except Exception as e: raise Exception(f"An error occurred while running the crew: {e}") |
Theagents.yaml
and tasks.yaml
files
The agents.yaml
and tasks.yaml
files are used in CrewAI projects to define agent and task configurations in a structured, declarative format. These YAML files serve as an alternative to defining agents and tasks directly in Python code.
- Separation of Concerns – They allow you to separate configuration from logic. This is especially helpful in larger projects or when collaborating with non-developers.
- CLI Integration – CrewAI’s CLI (
crewai run
,crewai init
, etc.) uses these files to load agent and task definitions, enabling a full pipeline without writing much Python. - Readability and Reusability – YAML files are easy to read, modify, and version-control. They support rapid iteration and reuse across different workflows.
src/config/agents.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
researcher: role: > Executive Tech Job Researcher goal: > Your goal is to review job postings and help job applicants stand out in the job market backstory: > As a Executive Job Researcher, your prowess in navigating and extracting critical information from job postings is unmatched. Your skills help pinpoint the necessary qualifications and skills sought by employers, forming the foundation for effective application tailoring. personal_profiler: role: > Personal Profiler for Software Engineering Leaders at Sr Director and above roles goal: > Do research on job applicants to help them stand out in the job market backstory: > As a Personal Profiler, your job is to analyze and synthesize information about job applicants. Your insights help them present their skills and experiences in the best possible light, making them stand out in the job market. Equipped with analytical prowess, you dissect and synthesize information from diverse sources to craft comprehensive personal and professional profiles, laying the groundwork for personalized resume enhancements. resume_strategist: role: > Resume Strategist for Sr Director and Executive Software Engineering Leadership roles goal: > Find all the best ways to make a resume stand out in the job market. backstory: > With a strategic mind and an eye for detail, you excel at refining resumes to highlight the most relevant skills and experiences, ensuring they resonate perfectly with the job's requirements. You will take very job description and make sure the resume is tailored to the job description. You will make sure the resume is the best it can be. interview_preparer: role: > Interview Preparer for Sr Director Software Engineering Leadership roles goal: > Prepare job applicants for interviews with confidence backstory: > As an Interview Preparer, you are dedicated to helping job applicants prepare for interviews with confidence. Your expertise lies in understanding the interview process and providing tailored guidance to help candidates succeed. You help them navigate the complexities of interviews, ensuring they are well-prepared and ready to impress potential employers. With your ability to formulate key questions and talking points, you prepare candidates for success, ensuring they can confidently address all aspects of the job they are applying for. |
src/config/tasks.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
research_task: description: > Analyze the job posting provided in URL ({job_posting_url}) to extract key skills, experiences, and qualifications required. Use the tools to gather content and identify and categorize the requirements. expected_output: > A structured list of job requirements, including necessary skills, qualifications, and experiences agent: researcher async_execution: True personal_profiler_task: description: > Compile a detailed personal and professional profile using the personal write-up ({personal_writeup}). Utilize tools to extract and synthesize information from these sources. expected_output: > A comprehensive profile document that includes skills, project experiences, contributions, interests, and communication style agent: personal_profiler async_execution: True resume_strategist_task: description: > Using the profile and job requirements obtained from previous tasks, tailor the resume to highlight the most relevant areas. Employ tools to adjust and enhance the resume content. Make sure this is the best resume even but don't make up any information. Update every section, inlcuding the initial summary, work experience, skills, and education. All to better reflrect the candidates abilities and how it matches the job posting. expected_output: > An updated resume that effectively highlights the candidate's qualifications and experiences relevant to the job agent: resume_strategist async_execution: False interview_preparation_task: description: > Prepare the candidate for the interview by formulating key questions and talking points based on the job requirements and the tailored resume. Use tools to generate a list of potential interview questions and suggested responses. expected_output: > A list of potential interview questions and suggested responses tailored to the job requirements and the candidate's profile agent: interview_preparer async_execution: True |
To run the code
1 |
crewai run |
In closing…
CrewAI makes it easy to orchestrate agents into cooperative systems. This multi-agent pattern can be extended beyond resumes to applications such as coding assistants, research assistants, or customer support bots.