DEV Community

Cover image for Build Your First AI Agent in 30 Minutes - CrewAI + AWS Bedrock

Build Your First AI Agent in 30 Minutes - CrewAI + AWS Bedrock

👋 Hey there, Tech Enthusiasts!

I'm Sarvar, a Cloud Architect who loves turning complex tech problems into simple solutions. I've worked with AWS, Azure, DevOps, Data, Analytics, Generative-AI and Agentic-AI building real systems for real companies. In this article series, I'll share what I've learned in a way that's easy to follow, whether you're experienced or just getting started.

Let's get into it! 🚀


Hey, welcome back.

In the last article, we covered what AI agents are, how they think in loops, and why they're different from just asking ChatGPT for help. We looked at the building blocks role, goal, backstory, tasks, tools and how CrewAI lets you define all of this in simple YAML files.

We ended with a promise: we're going to build the thing.

This is that article. No more theory. We're building the resume tailor agent from scratch. By the end, you'll have a working agent with a web UI that takes a job description, analyzes it, and tailors your resume to match in seconds.


Why a Resume Tailor Agent?

This isn't a random project idea. It comes from a real problem I've faced repeatedly.

I've been working in MNCs for over 10 years. Every time a job switch comes up, the cycle is the same update the resume, start applying, wait for calls. And the calls don't come. Not because I lack the skills or experience. Not because there's a position mismatch. The problem is simpler and more frustrating than that: the things they're looking for I've actually done them. I just didn't mention them on my resume.

That's where I was lagging. My resume had my experience, but it wasn't speaking the language of the job description. The keywords weren't there. The framing wasn't right. And in today's market, where competition is fiercer than ever and most resumes go through automated screening first, that gap is enough to get you filtered out before a human ever reads your application.

Most companies today use ATS (Applicant Tracking Systems) that scan resumes for keywords before a recruiter ever sees them. If your resume doesn't have the right terms the exact ones from the job description it gets filtered out automatically. You could be a perfect fit and still never make it past the screen.

So now that we can build AI agents that actually do things why not build one that fixes this? Give it a job description, give it your resume, and in a few seconds it extracts the keywords that matter, identifies what's missing, and rewrites your bullet points to be ATS-friendly. Result: your resume actually gets past the bots and onto someone's desk.

That's what we're building. Not because it's a cool demo because I needed it.


What We're Building

A single AI agent that takes a job description (required) and optionally your resume, then gives you:

With JD + Resume (full analysis):

  1. JD Summary - what they're actually looking for (5-6 sentences)
  2. Matching Skills - key technologies to highlight in your resume (e.g., LLM, MCP, RAG, Kubernetes, Terraform)
  3. Skill Gaps - short bullet points, one gap per bullet
  4. Career Guidance - short career path bullets showing what to prepare (learn X, get certified in Y, build project with Z)
  5. Tailored Resume - rewritten bullet points ready to copy-paste

With JD only (no resume):

  1. JD Summary - what the role needs
  2. Key Technologies - tech keywords the JD demands
  3. Career Path - what to prepare for this role

Resume is optional so even if someone doesn't have one ready, they can still get value by understanding what a JD requires and what path to follow.

No fancy multi-agent setup. One agent with a good prompt handles all of this in a single pass. Simpler code, faster execution, cheaper to run.


Input & Output - What Goes In, What Comes Out

Input (what you provide):

Field Required? Description
Job Description ✅ Yes The JD you're targeting
Years of Experience ✅ Yes Helps adjust suggestions to your level
Expertise Level ✅ Yes Fresher / Junior / Mid-Level / Senior / Lead / Architect
Resume ❌ Optional Your current resume (paste as text)

Output (what you get):

If you provide JD + Resume:

Section Format Example
JD Summary 5-6 sentences "They want a senior cloud engineer who owns AWS infra end-to-end"
Matching Skills Key technology keywords Terraform, Kubernetes, Python, AWS Lambda, CloudWatch
Skill Gaps Bullet points • No Kafka experience • Missing distributed systems
Career Guidance Career path bullets • Learn Kafka basics • Get AWS Solutions Architect cert • Build a microservices project
Tailored Resume Ready to copy-paste Rewritten bullet points matching the JD

If you provide JD only (no resume):

Section Format Example
JD Summary 5-6 sentences "Looking for a GenAI engineer with RAG and LLM experience"
Key Technologies Keywords LLM, RAG, MCP, LangChain, Vector DB, Python
Career Path Bullet points • Learn RAG patterns • Build an agent with CrewAI • Study vector databases

What You'll Need

  • An AWS account with Bedrock access (Amazon Nova Pro model enabled)
  • An EC2 instance (t3.medium or bigger) or any Linux machine with Python
  • About 30-45 minutes
  • Basic comfort with the terminal

I'm using an EC2 instance running Amazon Linux 2023. You can use Ubuntu, your local Mac, WSL doesn't matter. The commands are the same.

One thing before we start make sure you've enabled the Amazon Nova Pro model in your AWS Bedrock console. It's not enabled by default. Go to Bedrock > Model access > Request access to Nova Pro. Takes a minute to get approved.


High-Level Architecture

Before we jump into code, here's how everything fits together:

How it works:

  1. User opens the Streamlit web UI in their browser and pastes a job description, resume, and experience level
  2. Streamlit (running on EC2) passes the inputs to the CrewAI orchestrator
  3. crew.py loads the agent configuration (agents.yaml + tasks.yaml) and constructs the prompt
  4. The prompt is sent to Amazon Bedrock Nova Pro a foundation model that does the actual analysis
  5. Bedrock returns the analysis skill gaps, career guidance, and tailored resume
  6. Results flow back through CrewAI → Streamlit → displayed to the user

The entire stack runs on a single EC2 instance (t3.medium). The only external service is Amazon Bedrock, which handles the LLM inference. No databases, no queues, no complex infra just a Python app talking to a foundation model.


Setting Up the Environment

First, SSH into your server. If you're working locally, skip this.

ssh -i your-key.pem ec2-user@your-server-ip
Enter fullscreen mode Exit fullscreen mode

Install Python 3.11

CrewAI needs Python 3.11 or higher.

sudo dnf install python3.11 python3.11-pip -y
Enter fullscreen mode Exit fullscreen mode

Check it worked:

python3.11 --version
Enter fullscreen mode Exit fullscreen mode

You should see something like Python 3.11.x.

Install uv

uv is a fast Python package manager. CrewAI uses it under the hood for dependency management. Think of it like npm for Python, but faster.

curl -LsSf https://astral.sh/uv/install.sh | sh
Enter fullscreen mode Exit fullscreen mode

Now add it to your PATH so you can use it right away:

export PATH=$HOME/.local/bin:$PATH
Enter fullscreen mode Exit fullscreen mode

Verify:

uv --version
Enter fullscreen mode Exit fullscreen mode

Install CrewAI CLI

This gives you the crewai command the tool you'll use to create projects, install dependencies, and run agents.

uv tool install crewai-cli --python python3.11 --with crewai
Enter fullscreen mode Exit fullscreen mode

Two things to note here:

  • It's crewai-cli, not crewai. If you install just crewai, you get the library but not the CLI command.
  • The --with crewai flag is important it includes the crewai library in the CLI tool's environment. Without it, crewai install will fail later with a ModuleNotFoundError.

Verify:

crewai version
Enter fullscreen mode Exit fullscreen mode

That's it. Environment is ready.


Creating the Project

CrewAI has a scaffolding command that creates the entire project structure for you. No need to create folders manually.

crewai create crew resume_tailor --classic
Enter fullscreen mode Exit fullscreen mode

The --classic flag gives you the standard Python/YAML project structure (which is what we want). Without it, newer versions of CrewAI may generate a JSON-based structure instead.

It'll ask you a few questions:

  • Provider: Choose bedrock (option 9 in the menu)

  • Model: Choose bedrock/us.amazon.nova-pro-v1:0 (option 28)

  • AWS keys: Press Enter to skip we'll use the IAM role attached to the instance (or your AWS CLI credentials)

This creates a folder called resume_tailor with everything you need.

Quick fix - pyproject.toml (if needed)

Check your generated pyproject.toml. If you see a pinned pre-release version like crewai[tools]==1.14.5a2, change it to:

crewai[bedrock,tools]>=1.14.0,<2.0.0
Enter fullscreen mode Exit fullscreen mode

The scaffolding sometimes generates crewai[tools] with a pre-release pin. We're changing it to include the bedrock extra (since we're using Amazon Bedrock) and pinning to a stable version range.


What You Get - CrewAI Project Structure

Let's look at what was generated. This is the standard CrewAI project structure every CrewAI project looks like this:

resume_tailor/
├── src/resume_tailor/
│   ├── config/
│   │   ├── agents.yaml        ← WHO: define your agents here
│   │   └── tasks.yaml         ← WHAT: define what agents do
│   ├── tools/
│   │   └── custom_tool.py     ← HOW: custom tools (we won't need this)
│   ├── crew.py                ← WIRING: connects agents to tasks
│   └── main.py                ← START: entry point, kicks everything off
├── knowledge/                 ← FACTS: files agents can read
├── .env                       ← SECRETS: API keys, model config
└── pyproject.toml             ← DEPENDENCIES: Python packages
Enter fullscreen mode Exit fullscreen mode

Here's how to think about it:

  • agents.yaml - you're writing a job description for your AI worker. Who are they? What's their expertise?
  • tasks.yaml - you're writing a work order. What exactly should they do? What should the output look like?
  • crew.py - you're the manager connecting the worker to the work order.
  • main.py - you're pressing the "start" button.

That's the whole framework. Four files that matter.

Now let's go into the project:

cd resume_tailor
Enter fullscreen mode Exit fullscreen mode

Configuring the Agent

Open src/resume_tailor/config/agents.yaml. This is where you define WHO your agent is.

Replace everything in the file with this:

resume_tailor:
  role: >
    Senior Resume Tailor & Career Advisor
  goal: >
    Analyze the job description, compare it with the candidate's resume,
    identify skill gaps, and rewrite the resume to match the job requirements.
  backstory: >
    You're a seasoned career advisor with 15+ years of experience in tech recruiting.
    You've reviewed thousands of resumes and job descriptions. You know exactly what
    hiring managers look for, can instantly spot skill gaps, and you rewrite resumes
    that get interviews. You're direct, practical, and never give generic fluff.
Enter fullscreen mode Exit fullscreen mode

Three things here:

  • Role - tells the agent who it is. "Senior Resume Tailor & Career Advisor" not just "helper" or "assistant." The more specific the role, the better the output.
  • Goal - tells it what to achieve. This is the finish line.
  • Backstory - gives it personality. "15+ years in tech recruiting" makes it write like someone who's actually done this, not like a generic chatbot.

Think of it like hiring a contractor. You wouldn't say "do some work." You'd say "You're a senior plumber. Your job is to fix the kitchen leak. You've been doing this for 20 years." Same idea.


Configuring the Task

Open src/resume_tailor/config/tasks.yaml. This is the work order what exactly should the agent do?

Replace everything with this:

tailor_resume_task:
  description: >
    Analyze the following job description and produce career guidance.

    Job Description:
    {job_description}

    Candidate's Resume:
    {resume}

    Years of Experience: {years_experience}
    Expertise Level: {expertise_level}

    IMPORTANT: Tailor your suggestions based on the candidate's experience and expertise level.
    A Fresher needs different guidance than a Senior or Architect. Adjust complexity, depth, and expectations accordingly.

    IMPORTANT: If the candidate's resume is "Not provided", skip sections 2, 3, and 5.
    Instead, provide: JD Summary, Key Technologies, and Career Path.

    If the resume IS provided, include all 5 sections:

    1. JD Summary - One or two sentences max. What role/expertise are they looking for?

    2. Matching Skills - List as key technologies/keywords the candidate should highlight in their resume (e.g., LLM, MCP, RAG, Kubernetes, Terraform, CrewAI). Just the tech keywords, no sentences.

    3. Skill Gaps - Bullet points, short and simple. One gap per bullet. No paragraphs.

    4. Career Guidance - Short bullet points showing the preparation path for this JD based on their expertise level. Like a career roadmap with heads/topics to learn. Example:
       - Learn X
       - Get certified in Y
       - Build a project using Z

    5. Tailored Resume - Rewrite the candidate's resume bullet points to match the job description. Adjust tone and depth based on expertise level. Ready to copy-paste.

  expected_output: >
    If resume provided: JD Summary, Matching Skills (key technologies as keywords), Skill Gaps (bullet points), Career Guidance (short career path bullets based on expertise level), Tailored Resume.
    If resume not provided: JD Summary, Key Technologies, Career Path (adjusted for expertise level).
  agent: resume_tailor
Enter fullscreen mode Exit fullscreen mode

A few things to notice:

  • {job_description}, {resume}, {years_experience}, {expertise_level} these are variables. They get filled in at runtime when you pass inputs. CrewAI handles the interpolation.
  • The agent adapts based on expertise level a Fresher gets beginner-friendly guidance, a Senior gets advanced recommendations.
  • The resume is optional if "Not provided", the agent adapts and gives a shorter but still useful output (JD Summary, Key Technologies, Career Path).
  • Matching Skills outputs key technology keywords (like LLM, RAG, Kubernetes) that the candidate should add to their resume.
  • Skill Gaps are short bullet points one gap per bullet, no paragraphs.
  • Career Guidance gives a career roadmap with actionable steps tailored to your level.
  • agent: resume_tailor this connects the task to the agent we defined in agents.yaml. The names must match.


Wiring It Up - crew.py

Open src/resume_tailor/crew.py. This is where you connect the agent to the task.

Replace everything with this:

from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent


@CrewBase
class ResumeTailor():
    """ResumeTailor crew"""

    agents: list[BaseAgent]
    tasks: list[Task]

    @agent
    def resume_tailor(self) -> Agent:
        return Agent(
            config=self.agents_config['resume_tailor'],  # type: ignore[index]
            verbose=True
        )

    @task
    def tailor_resume_task(self) -> Task:
        return Task(
            config=self.tasks_config['tailor_resume_task'],  # type: ignore[index]
            output_file='tailored_resume.md'
        )

    @crew
    def crew(self) -> Crew:
        return Crew(
            agents=self.agents,
            tasks=self.tasks,
            process=Process.sequential,
            verbose=True,
        )
Enter fullscreen mode Exit fullscreen mode

What's happening here:

  • @CrewBase - tells CrewAI this class is a crew. It automatically loads your YAML configs.
  • @agent method - creates the agent from the YAML config. The method name resume_tailor must match the key in agents.yaml.
  • @task method - creates the task from the YAML config. Same rule tailor_resume_task must match tasks.yaml.
  • output_file='tailored_resume.md' - saves the result to a file. Nice for reviewing later.
  • Process.sequential - tasks run one after another. We only have one task, so this doesn't matter much here. But if you add more agents later, this controls the order.
  • verbose=True - shows you what the agent is thinking while it works. Great for debugging. Turn it off in production.


Setting Up the Entry Point - main.py

Open src/resume_tailor/main.py. This is where you pass inputs and kick off the agent.

Replace everything with this:

#!/usr/bin/env python
import warnings

from resume_tailor.crew import ResumeTailor

warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")


def run():
    inputs = {
        'job_description': 'We are looking for a Senior Cloud Engineer with experience in AWS, Terraform, Kubernetes, and CI/CD pipelines. Must have 5+ years experience with cloud infrastructure, strong Python skills, and experience with monitoring tools like Datadog or CloudWatch.',
        'resume': 'Cloud Engineer with 3 years experience. Skills: AWS (EC2, S3, Lambda), Docker, Jenkins, Python, CloudFormation. Built CI/CD pipelines for microservices. Managed monitoring with CloudWatch. Deployed applications on ECS.',
        'years_experience': '3',
        'expertise_level': 'Mid-Level',
    }

    try:
        ResumeTailor().crew().kickoff(inputs=inputs)
    except Exception as e:
        raise Exception(f"An error occurred while running the crew: {e}")
Enter fullscreen mode Exit fullscreen mode

This is just for testing. We're hardcoding a sample resume and job description so we can verify everything works before adding the UI. The Streamlit app will replace these hardcoded inputs with whatever the user types.


Configuring the Environment

Open the .env file in the project root. Remove anything that was auto-generated and just keep these two lines:

MODEL=bedrock/us.amazon.nova-pro-v1:0
AWS_REGION_NAME=us-east-1
Enter fullscreen mode Exit fullscreen mode

That's it. The model to use and the AWS region.

If you're on EC2 with an IAM role attached, you don't need AWS keys the SDK picks up credentials automatically from the instance profile. Don't put AWS access keys in this file if you're using an IAM role it's unnecessary and a security risk. If you're running locally without an IAM role, make sure your AWS CLI is configured:

aws configure
Enter fullscreen mode Exit fullscreen mode

When it asks for region, set it to us-east-1.

Don't pass a region parameter in the model name Nova Pro is a cross-region model and adding a region breaks it. Just set AWS_REGION_NAME in the .env and leave it at that.


Installing Dependencies and Running

First, lock and install all the dependencies:

crewai install
Enter fullscreen mode Exit fullscreen mode

This creates a uv.lock file and installs everything the project needs.

Now add Bedrock support if you already updated your pyproject.toml to include crewai[bedrock,tools], you can skip this step. Otherwise, add it now:

uv add "crewai[bedrock]"
Enter fullscreen mode Exit fullscreen mode

Now, the moment of truth:

crewai run
Enter fullscreen mode Exit fullscreen mode

You'll see the agent start up, show you what it's thinking, and then produce the output. The whole thing takes about 20-30 seconds.

The result also gets saved to tailored_resume.md in your project folder.

If you got output congratulations. You just built your first AI agent. It read a job description, compared it to a resume, found the gaps, and rewrote the resume to match. All on its own.


Adding a Streamlit UI

Running agents from the terminal is fine for testing. But try showing that to someone who doesn't code. "Look at this terminal output!" doesn't impress anyone.

Streamlit gives us a web interface in about 30 lines of code. Two text boxes, a button, results on screen. Anyone can use it.

Install Streamlit

uv add streamlit
Enter fullscreen mode Exit fullscreen mode

Create the UI

Create a file called streamlit_app.py in the project root (not inside src/):

import streamlit as st
from resume_tailor.crew import ResumeTailor

st.set_page_config(page_title="Resume Tailor Agent", page_icon="📄", layout="wide")

# Header
st.markdown("""
<h1 style='text-align: center;'>📄 Resume Tailor Agent</h1>
<p style='text-align: center; color: gray; font-size: 1.1em;'>Paste a job description → Get career guidance, skill gaps, and a tailored resume in seconds.</p>
<hr>
""", unsafe_allow_html=True)

# Input section
st.subheader("📥 Input")

col1, col2 = st.columns(2)
with col1:
    job_description = st.text_area("Job Description *", height=250, placeholder="Paste the job description here (required)...")
with col2:
    resume = st.text_area("Your Resume (Optional)", height=250, placeholder="Paste your resume here leave empty if you don't have one yet...")

col3, col4, col5 = st.columns(3)
with col3:
    years_experience = st.number_input("Years of Experience *", min_value=0, max_value=40, value=3)
with col4:
    expertise_level = st.selectbox("Expertise Level *", ["Fresher", "Junior", "Mid-Level", "Senior", "Lead", "Architect"])
with col5:
    st.markdown("<br>", unsafe_allow_html=True)
    analyze_btn = st.button("🚀 Analyze", type="primary", use_container_width=True)

# Info box
if not job_description:
    st.info("💡 **Tip:** Even without a resume, you'll get JD analysis, key technologies, and a career path to follow.")

# Process
if analyze_btn:
    if not job_description:
        st.error("⚠️ Please paste the job description to continue.")
    else:
        st.divider()
        st.subheader("📊 Analysis Results")
        with st.spinner("🤖 Agent is analyzing... this takes about 30 seconds."):
            inputs = {
                "job_description": job_description,
                "resume": resume if resume else "Not provided",
                "years_experience": str(years_experience),
                "expertise_level": expertise_level,
            }
            result = ResumeTailor().crew().kickoff(inputs=inputs)

        st.success("✅ Analysis complete!")
        st.markdown(result.raw)

        # Download button
        st.download_button(
            label="📥 Download Results",
            data=result.raw,
            file_name="resume_analysis.md",
            mime="text/markdown",
        )

# Footer
st.divider()
st.markdown("""
<p style='text-align: center; color: gray; font-size: 0.85em;'>
Built with CrewAI + Amazon Bedrock Nova Pro | By <a href="https://sarvarnadaf.com">Sarvar Nadaf</a>
</p>
""", unsafe_allow_html=True)
Enter fullscreen mode Exit fullscreen mode

A few things to notice compared to a bare-bones approach:

  • Wide layout and styled header for a cleaner look
  • An info tip box when JD is empty reminds users they can still get value without a resume
  • A download button so users can save the analysis as a markdown file
  • A footer with attribution

If you're on EC2, make sure port 8501 is open in your security group before running. Go to EC2 console > your instance > Security > Security group > Edit inbound rules > Add rule: Custom TCP, port 8501, source 0.0.0.0/0. Save. (For production, restrict this to your IP instead of opening to the world.)

Run It

uv run streamlit run streamlit_app.py --server.address 0.0.0.0 --server.port 8501
Enter fullscreen mode Exit fullscreen mode

Open your browser and go to http://your-server-ip:8501.

Paste a job description on the left, your resume on the right, click the button, and watch the agent work.


Let's Test It - Real Input, Real Output

Now that it's working, let's throw some real-ish data at it and see how good the output actually is.

For this test, I'm using a resume of an AI Engineer with 6 years of total experience, applying for a Senior GenAI Developer role. Both are kept short 5-6 bullet points each. I'm using random data here; you can use your own.

The Resume (what we already have):

- Developed machine learning and Generative AI solutions using Python, TensorFlow, PyTorch, Scikit-learn, and LLM frameworks.
- Built and deployed RAG-based chatbots, AI assistants, and NLP applications using LangChain, LangGraph, and vector databases.
- Designed and optimized data pipelines, performed feature engineering, and trained predictive models for business use cases.
- Developed REST APIs with FastAPI/Flask and deployed AI applications on AWS, Azure, or Google Cloud using Docker and Kubernetes.
- Integrated foundation models, embeddings, prompt engineering, and MCP-based tools into enterprise AI workflows.
- Worked with SQL/NoSQL databases, data visualization tools, and cloud-native services to support AI and analytics solutions.
- Collaborated with cross-functional teams to deliver scalable, production-ready AI applications while following MLOps and DevOps best practices.
Enter fullscreen mode Exit fullscreen mode

The Job Description (what we're targeting):

- Design, develop, and deploy enterprise-grade Generative AI applications using Large Language Models (LLMs).
- Build AI agents, RAG pipelines, and MCP-based integrations using frameworks such as LangChain, LangGraph, and LlamaIndex.
- Develop scalable backend services and REST APIs using Python, FastAPI, or Flask, and deploy them on cloud platforms (AWS/Azure/GCP).
- Integrate vector databases, embeddings, and foundation models to deliver intelligent search and conversational AI solutions.
- Optimize AI applications for performance, scalability, security, cost efficiency, and responsible AI practices.
- Implement CI/CD pipelines, containerization (Docker/Kubernetes), monitoring, and MLOps/LLMOps best practices.
- Collaborate with cross-functional teams, mentor junior developers, and contribute to solution architecture and technical design.
Enter fullscreen mode Exit fullscreen mode

The Settings:

  • Years of Experience: 6
  • Expertise Level: Mid-Level

A quick note on expertise level this isn't your total years in tech. It's how deep you are specifically in the GenAI space. You might have 6 years overall but still be mid-level when it comes to GenAI work. The agent adjusts its guidance and resume rewriting based on this, so set it based on your domain expertise, not your total career length.

The Results

Let's see what the agent gives us. Remember the output has five sections when you provide both a JD and a resume.

1. JD Summary

2. Matching Skills

3. Skill Gaps

4. Career Guidance

5. Tailored Resume

Why This Test Matters

You might be wondering - why pick two slightly different skill sets? The resume is an AI Engineer. The JD is a Senior GenAI Developer. They overlap, but they're not identical.

That's the point. I wanted to see how the agent handles the gap between "close but not quite" - and the results are genuinely impressive. It identified exactly where the resume falls short, suggested a clear path to bridge the gap, and rewrote the bullet points to speak the JD's language.

And here's the thing - you can customize the output further. Want exactly 8 tailored resume points? Add that to the task description. Want the career guidance to focus only on certifications? Tweak the prompt. The agent does what you tell it to. You control the output by controlling the instructions.


What Just Happened

Let's step back and look at what we built:

  1. One YAML file to define the agent (who it is, what it's good at)
  2. One YAML file to define the task (what to do, what the output should look like)
  3. One Python file to wire them together
  4. One Python file for the web UI

Four files. That's a working AI agent with a web interface.

The agent reads the job description, compares it to the resume (if provided), identifies key technologies to highlight, lists skill gaps as clean bullet points, gives a career roadmap, and rewrites the entire resume to match all in one pass, in about 30 seconds.

Even without a resume, it still delivers value JD analysis, key technologies, and a preparation path. So anyone can use it, whether they have a resume ready or not.

No training data. No fine-tuning. No complex pipelines. Just a well-written prompt, a good LLM, and a framework that handles the plumbing.


Source Code

The complete source code for this project is available on GitHub:

GitHub logo simplynadaf / resume-tailor-agent

AI agent that analyzes job descriptions, identifies skill gaps, and tailors your resume - built with CrewAI and Amazon Bedrock.

📄 Resume Tailor Agent

AI-powered resume tailoring — paste a job description, get a perfect match in seconds.

CrewAI Amazon Bedrock Streamlit Python License: MIT

Stars Forks Issues


⭐ If this helped you, give it a star! It helps others find it.

Getting StartedHow It WorksDemoContributing


🤔 The Problem

You're job hunting. Every company wants something slightly different. You've done the work — but your resume doesn't say it in the JD's language. ATS systems scan for keywords before a human ever sees your application. Wrong framing = filtered out automatically.

One application = 30 minutes of tweaking. Multiply that by 10+ applications.

This agent does it in 30 seconds.


✨ What It Does

One agent. One pass. Five powerful outputs.




🎯 With JD + Resume

Output What You Get
📋 JD Summary What they're actually looking for
🔑 Matching Skills ATS keywords to highlight (e.g., LLM, RAG, K8s)
⚠️ Skill





Getting Started

Follow these steps to run the project on your machine:

  1. Clone the repository:
git clone https://github.com/simplynadaf/resume-tailor-agent.git
Enter fullscreen mode Exit fullscreen mode
  1. Navigate to the project and set up:
cd resume-tailor-agent
cp .env.example .env
crewai install
uv add "crewai[bedrock]"
Enter fullscreen mode Exit fullscreen mode
  1. Run the agent:
crewai run
Enter fullscreen mode Exit fullscreen mode
  1. Or launch the web UI:
uv run streamlit run streamlit_app.py --server.address 0.0.0.0 --server.port 8501
Enter fullscreen mode Exit fullscreen mode

What's Next

We built one agent that does everything analyzes the JD, finds gaps, rewrites the resume. It works. But what if we split the work across specialists? A recruiter who decodes the JD, an analyst who finds the gaps, and a writer who nails the rewrite. Each one focused, each one sharper.

In the next article, we're upgrading to a multi-agent crew and you'll see how collaboration between specialized agents produces noticeably better results than one agent doing it all.

Until then try it with your own resume. Paste a real job description you're interested in. See what the agent comes up with. You might be surprised how good it is


📌 Wrapping Up

Thanks for reading! If this was helpful:

  • ❤️ Like if it added value
  • 💾 Save for later
  • 🔄 Share with your team

Follow me for more on: AWS architecture, FinOps, DevOps, and AI Infrastructure.

👉 Visit my website | Connect on LinkedIn | Email: simplynadaf@gmail.com

Happy Learning 🚀

Top comments (1)

Collapse
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders

🚀 𝗟𝗶𝘃𝗲 𝗣𝗿𝗲𝘃𝗶𝗲𝘄 𝗔𝘃𝗮𝗶𝗹𝗮𝗯𝗹𝗲!

You can now try the AI Resume Tailoring Agent featured in the article.

🔗 resume-agent.sarvarnadaf.com/

⏳ The preview will be available only for the next 24 hours. I'd love to hear your feedback after trying it!