AI Agent for HR (Resume Screening, Candidate Responses)

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
AI Agent for HR (Resume Screening, Candidate Responses)
Medium
from 1 week to 3 months
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822

AI Agent for HR (Resume Screening, Candidate Responses)

An AI agent for HR automates high-volume tasks: initial resume screening against job criteria, candidate ranking, automated responses, interview scheduling, and feedback collection. This reduces recruiter workload and cuts time-to-hire while maintaining selection quality.

HR Agent Components

from pydantic import BaseModel
from typing import Optional, Literal
from openai import OpenAI
import json

client = OpenAI()

class CandidateScreeningResult(BaseModel):
    candidate_id: str
    overall_score: int           # 0-100
    hard_skills_match: int       # % hard skills match
    experience_match: int        # % experience match
    red_flags: list[str]         # Deal breakers
    green_flags: list[str]       # Strengths
    recommendation: Literal["strong_yes", "yes", "maybe", "no"]
    next_step: str
    personalized_rejection_reason: Optional[str]

def screen_resume(
    resume_text: str,
    job_description: str,
    required_skills: list[str],
    nice_to_have: list[str],
) -> CandidateScreeningResult:
    """Resume screening against job requirements"""

    response = client.beta.chat.completions.parse(
        model="gpt-4o",
        messages=[{
            "role": "system",
            "content": """You are an experienced recruiter. Objectively assess candidate fit for the role.
Do NOT make assumptions — if experience is not explicitly stated, consider it absent.
Be honest about red flags."""
        }, {
            "role": "user",
            "content": f"""Job posting:
{job_description}

Required skills: {required_skills}
Nice-to-have skills: {nice_to_have}

Candidate resume:
{resume_text}"""
        }],
        response_format=CandidateScreeningResult,
        temperature=0,
    )

    return response.choices[0].message.parsed

Automated Candidate Responses

def generate_candidate_response(
    candidate_name: str,
    decision: str,
    position: str,
    feedback: str = None,
) -> str:
    """Personalized response to candidate"""

    templates = {
        "invite_interview": f"""Dear {candidate_name},

Thank you for your interest in the {position} position. Your experience caught our attention, and we would like to invite you for an interview.

Available slots: [CALENDAR_LINK]

The interview will take approximately 45 minutes. Format: video call.

Best regards, Recruitment Team""",

        "rejection": None,  # Generate personalized
    }

    if decision == "rejection" and feedback:
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{
                "role": "system",
                "content": "Write a polite rejection letter to a candidate. Tone: respectful, avoid clichés like 'you don't fit us'. Provide specific reason (without humiliating wording)."
            }, {
                "role": "user",
                "content": f"Candidate: {candidate_name}, Position: {position}, Reason: {feedback}"
            }],
        )
        return response.choices[0].message.content

    return templates.get(decision, "")

Bulk Screening Pipeline

import asyncio
from typing import List

async def batch_screen_resumes(
    resumes: List[dict],
    job_description: str,
    required_skills: List[str],
    concurrency: int = 10,
) -> List[dict]:
    """Parallel screening of multiple resumes"""

    semaphore = asyncio.Semaphore(concurrency)

    async def screen_single(resume: dict) -> dict:
        async with semaphore:
            result = await asyncio.to_thread(
                screen_resume,
                resume["text"],
                job_description,
                required_skills,
                [],
            )
            return {
                "candidate_id": resume["id"],
                "name": resume["name"],
                "email": resume["email"],
                "screening": result,
            }

    results = await asyncio.gather(*[screen_single(r) for r in resumes])

    # Sort by score
    return sorted(results, key=lambda x: -x["screening"].overall_score)

Practical Case Study: Mass Hiring for Call Center

Task: Hire 80 call center operators in 3 months. Incoming flow: 600+ resumes per week. One recruiter.

Screening Criteria: customer interaction experience (required), proper written communication (required), CRM knowledge (nice-to-have), willingness to work night shifts (required).

Agent Pipeline:

  1. Parse incoming resumes from hh.ru/Avito (API)
  2. LLM screening (50 resumes in 8 minutes vs 4 hours manually)
  3. Top 30% → phone screening invitation
  4. Rejections → personalized auto-response
  5. After screening → schedule personal interview (Calendly integration)

Results:

  • Time to screen 100 resumes: 4.5h (manual) → 18min (agent)
  • Concordance rate (agent vs recruiter): 89% (verified on 200 jointly assessed)
  • False rejection rate (qualified candidates rejected): 4.1%
  • Time-to-hire: 42 days → 28 days
  • Recruiter focus: shifted to interviews and onboarding

Legal Constraint: Final hiring decision remains with the human. Agent makes recommendation, recruiter confirms.

Anti-bias Filtering

ANTI_BIAS_PROMPT_ADDENDUM = """IMPORTANT: When evaluating:
- Do NOT consider name, gender, age (if specified), nationality
- Assess only professional competencies and experience
- Do not make assumptions based on personal data
- Apply same criteria to all candidates"""

Timeline

  • HR screening agent: 2–3 weeks
  • Integration with hh.ru/job board API: 1–2 weeks
  • Automated responses + calendar: 1 week
  • Calibration with recruiter: 1–2 weeks
  • Total: 5–8 weeks