Skip to content
Learn Agentic AI
Learn Agentic AI15 min read2 views

Build a Job Application Tracker Agent: Resume Parsing, Application Status, and Interview Prep

Create an AI agent that parses resumes, tracks job application statuses across companies, researches employers, and generates customized interview preparation questions — a complete job hunting assistant.

Why an AI Job Application Tracker

Job hunting is a multi-step process involving resume tailoring, application tracking, company research, and interview preparation. Most people manage this with spreadsheets, losing context and missing follow-ups. An AI agent can unify all these tasks: it parses your resume, tracks every application's status, researches companies, and generates targeted interview questions — all from a single conversational interface.

This tutorial builds a complete job application tracker agent with resume parsing, a status management system, company research simulation, and interview prep generation.

Project Setup

mkdir job-tracker-agent && cd job-tracker-agent
python -m venv venv && source venv/bin/activate
pip install openai-agents pydantic
mkdir -p src
touch src/__init__.py src/resume_parser.py src/tracker.py
touch src/research.py src/interview_prep.py src/agent.py

Step 1: Build the Resume Parser

The parser extracts structured data from plain-text resume content. In production you would use a PDF parsing library, but the extraction logic remains the same.

flowchart TD
    START["Build a Job Application Tracker Agent: Resume Par…"] --> A
    A["Why an AI Job Application Tracker"]
    A --> B
    B["Project Setup"]
    B --> C
    C["Step 1: Build the Resume Parser"]
    C --> D
    D["Step 2: Build the Application Tracker"]
    D --> E
    E["Step 3: Company Research and Interview …"]
    E --> F
    F["Step 4: Assemble the Agent"]
    F --> G
    G["FAQ"]
    G --> DONE["Key Takeaways"]
    style START fill:#4f46e5,stroke:#4338ca,color:#fff
    style DONE fill:#059669,stroke:#047857,color:#fff
# src/resume_parser.py
import re
from pydantic import BaseModel

class ResumeData(BaseModel):
    name: str
    email: str
    skills: list[str]
    experience_years: int
    recent_titles: list[str]
    education: str

def parse_resume(text: str) -> ResumeData:
    email_match = re.search(
        r"[\w.+-]+@[\w-]+\.[\w.]+", text
    )
    email = email_match.group(0) if email_match else "unknown"

    lines = text.strip().split("\n")
    name = lines[0].strip() if lines else "Unknown"

    skills_section = []
    in_skills = False
    for line in lines:
        if "skills" in line.lower() and ":" in line:
            raw = line.split(":", 1)[1]
            skills_section = [
                s.strip() for s in raw.split(",")
            ]
            break

    year_matches = re.findall(r"(\d{4})\s*[-–]\s*(\d{4}|present)", text.lower())
    total_years = 0
    for start, end in year_matches:
        end_yr = 2026 if end == "present" else int(end)
        total_years += end_yr - int(start)

    title_patterns = [
        "software engineer", "developer", "manager",
        "analyst", "designer", "data scientist",
        "product manager", "devops engineer",
    ]
    found_titles = []
    text_lower = text.lower()
    for title in title_patterns:
        if title in text_lower:
            found_titles.append(title.title())

    edu = "Not specified"
    for line in lines:
        ll = line.lower()
        if any(d in ll for d in ["bachelor", "master", "phd", "b.s.", "m.s."]):
            edu = line.strip()
            break

    return ResumeData(
        name=name,
        email=email,
        skills=skills_section or ["Not parsed"],
        experience_years=total_years,
        recent_titles=found_titles or ["Not parsed"],
        education=edu,
    )

Step 2: Build the Application Tracker

The tracker manages a list of applications with status transitions and timeline logging.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

flowchart LR
    S0["Step 1: Build the Resume Parser"]
    S0 --> S1
    S1["Step 2: Build the Application Tracker"]
    S1 --> S2
    S2["Step 3: Company Research and Interview …"]
    S2 --> S3
    S3["Step 4: Assemble the Agent"]
    style S0 fill:#4f46e5,stroke:#4338ca,color:#fff
    style S3 fill:#059669,stroke:#047857,color:#fff
# src/tracker.py
from datetime import datetime
from pydantic import BaseModel

class Application(BaseModel):
    company: str
    role: str
    status: str  # applied, screening, interview, offer, rejected
    date_applied: str
    last_updated: str
    notes: list[str]

class ApplicationTracker:
    VALID_STATUSES = [
        "applied", "screening", "interview", "offer", "rejected",
    ]

    def __init__(self):
        self.applications: dict[str, Application] = {}

    def add_application(
        self, company: str, role: str, notes: str = "",
    ) -> str:
        key = f"{company}::{role}".lower()
        now = datetime.now().strftime("%Y-%m-%d")
        self.applications[key] = Application(
            company=company,
            role=role,
            status="applied",
            date_applied=now,
            last_updated=now,
            notes=[notes] if notes else [],
        )
        return f"Added: {role} at {company}"

    def update_status(
        self, company: str, role: str, new_status: str, note: str = "",
    ) -> str:
        key = f"{company}::{role}".lower()
        app = self.applications.get(key)
        if not app:
            return f"No application found for {role} at {company}"
        if new_status not in self.VALID_STATUSES:
            return f"Invalid status. Use: {self.VALID_STATUSES}"
        app.status = new_status
        app.last_updated = datetime.now().strftime("%Y-%m-%d")
        if note:
            app.notes.append(f"[{app.last_updated}] {note}")
        return f"Updated {role} at {company} to '{new_status}'"

    def get_summary(self) -> str:
        if not self.applications:
            return "No applications tracked yet."
        lines = []
        for app in self.applications.values():
            lines.append(
                f"- {app.role} at {app.company} | "
                f"Status: {app.status} | Applied: {app.date_applied}"
            )
        return "\n".join(lines)

tracker = ApplicationTracker()

Step 3: Company Research and Interview Prep

# src/research.py
COMPANY_DATA = {
    "google": {
        "industry": "Technology",
        "size": "180,000+ employees",
        "culture": "Innovation-driven, data-oriented, 20% projects",
        "interview_style": "Coding, system design, behavioral (Googleyness)",
        "recent_news": "Expanding AI infrastructure and Gemini platform",
    },
    "stripe": {
        "industry": "Fintech",
        "size": "8,000+ employees",
        "culture": "Writing-heavy culture, high autonomy, remote-friendly",
        "interview_style": "Practical coding, API design, debugging exercises",
        "recent_news": "Growing enterprise payment solutions globally",
    },
}

def research_company(company: str) -> dict:
    data = COMPANY_DATA.get(company.lower())
    if data:
        return data
    return {
        "industry": "Unknown",
        "size": "Unknown",
        "culture": "Research needed",
        "interview_style": "Research needed",
        "recent_news": "No data available",
    }
# src/interview_prep.py
def generate_prep_questions(
    role: str, company_data: dict, skills: list[str],
) -> list[str]:
    questions = [
        f"Tell me about a project where you used {skills[0]}."
        if skills else "Walk me through your most impactful project.",
        f"Why do you want to work in {company_data.get('industry', 'this industry')}?",
        "Describe a time you disagreed with a teammate. How did you resolve it?",
        f"How do you stay current with developments in {skills[0] if skills else 'your field'}?",
        "What is your approach to debugging a production issue under time pressure?",
    ]
    if "system design" in company_data.get("interview_style", "").lower():
        questions.append(
            "Design a URL shortener that handles 10 million requests per day."
        )
    if "coding" in company_data.get("interview_style", "").lower():
        questions.append(
            "Implement a function that finds the longest palindromic substring."
        )
    return questions

Step 4: Assemble the Agent

# src/agent.py
import asyncio
import json
from agents import Agent, Runner, function_tool
from src.resume_parser import parse_resume
from src.tracker import tracker
from src.research import research_company
from src.interview_prep import generate_prep_questions

@function_tool
def parse_my_resume(resume_text: str) -> str:
    """Parse resume text and extract structured data."""
    data = parse_resume(resume_text)
    return data.model_dump_json(indent=2)

@function_tool
def add_job_application(
    company: str, role: str, notes: str = "",
) -> str:
    """Track a new job application."""
    return tracker.add_application(company, role, notes)

@function_tool
def update_application(
    company: str, role: str, status: str, note: str = "",
) -> str:
    """Update application status."""
    return tracker.update_status(company, role, status, note)

@function_tool
def view_applications() -> str:
    """View all tracked applications."""
    return tracker.get_summary()

@function_tool
def prep_for_interview(
    company: str, role: str, skills: str,
) -> str:
    """Generate interview prep material."""
    company_data = research_company(company)
    skill_list = [s.strip() for s in skills.split(",")]
    questions = generate_prep_questions(
        role, company_data, skill_list,
    )
    lines = [f"Company Research: {json.dumps(company_data, indent=2)}"]
    lines.append("\nPractice Questions:")
    for i, q in enumerate(questions, 1):
        lines.append(f"  {i}. {q}")
    return "\n".join(lines)

job_agent = Agent(
    name="Job Application Tracker",
    instructions="""You are a job application tracking assistant.
Help users manage their job search by parsing resumes, tracking
applications, researching companies, and preparing for interviews.
Always be encouraging and provide actionable next steps.""",
    tools=[
        parse_my_resume, add_job_application,
        update_application, view_applications,
        prep_for_interview,
    ],
)

async def main():
    result = await Runner.run(
        job_agent,
        "I just applied to Google for a Senior Software Engineer role. "
        "Track it and help me prepare for the interview. "
        "My main skills are Python, system design, and distributed systems.",
    )
    print(result.final_output)

if __name__ == "__main__":
    asyncio.run(main())

The agent adds the application to the tracker, researches Google, and generates tailored interview questions based on your skills and Google's known interview style.

FAQ

How would I parse an actual PDF resume instead of plain text?

Use the PyMuPDF or pdfplumber library to extract text from PDF files first. Create a wrapper function that reads the PDF, extracts text content, and passes it to parse_resume(). The structured extraction logic stays the same because it operates on text regardless of the original document format.

Can the agent send me reminders about follow-ups?

Yes. Add a follow_up_date field to the Application model and a get_pending_followups tool that returns applications where the current date exceeds the follow-up date. Run the agent on a daily schedule using cron or a task queue to generate and send reminder emails through an SMTP tool.

How do I make the company research use real data?

Replace the static COMPANY_DATA dictionary with API calls to services like Crunchbase, Glassdoor, or LinkedIn's public company pages. You can also add a web search tool that lets the agent query recent news about the company in real time, providing up-to-date context for interview preparation.


#JobTracker #AIAgent #Python #ResumeParsing #InterviewPrep #AgenticAI #LearnAI #AIEngineering

Share
C

Written by

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.

Related Articles You May Like

AI Interview Prep

7 AI Coding Interview Questions From Anthropic, Meta & OpenAI (2026 Edition)

Real AI coding interview questions from Anthropic, Meta, and OpenAI in 2026. Includes implementing attention from scratch, Anthropic's progressive coding screens, Meta's AI-assisted round, and vector search — with solution approaches.

Learn Agentic AI

Creating an AI Email Assistant Agent: Triage, Draft, and Schedule with Gmail API

Build an AI email assistant that reads your inbox, classifies urgency, drafts context-aware responses, and schedules sends using OpenAI Agents SDK and Gmail API.

Learn Agentic AI

Building a Multi-Agent Data Pipeline: Ingestion, Transformation, and Analysis Agents

Build a three-agent data pipeline with ingestion, transformation, and analysis agents that process data from APIs, CSVs, and databases using Python.

Learn Agentic AI

Building a Research Agent with Web Search and Report Generation: Complete Tutorial

Build a research agent that searches the web, extracts and synthesizes data, and generates formatted reports using OpenAI Agents SDK and web search tools.

Learn Agentic AI

OpenAI Agents SDK in 2026: Building Multi-Agent Systems with Handoffs and Guardrails

Complete tutorial on the OpenAI Agents SDK covering agent creation, tool definitions, handoff patterns between specialist agents, and input/output guardrails for safe AI systems.

Learn Agentic AI

LangGraph Agent Patterns 2026: Building Stateful Multi-Step AI Workflows

Complete LangGraph tutorial covering state machines for agents, conditional edges, human-in-the-loop patterns, checkpointing, and parallel execution with full code examples.