recruiter / server /tools.py
dipsha's picture
Upload folder using huggingface_hub
a8db748 verified
Raw History Blame Contribute Delete
16.8 kB
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
"""
ToolDispatcher — deterministic probe responses driven by CandidateGroundTruth.
Each tool validates its query against the candidate profile and returns a
result consistent with the injected fake_signals. Wrong-tool / missing-data
calls charge the probe cost and return "not found" style messages.
Day-3 upgrade: swap _llm_screening_call() for a real Anthropic API call.
"""
from __future__ import annotations
from typing import Optional
try:
from ..models import (
CandidateGroundTruth,
CandidateProfile,
JobDescription,
ToolType,
)
from .scratchpad import EpisodeScratchpad
except ImportError:
from models import (
CandidateGroundTruth,
CandidateProfile,
JobDescription,
ToolType,
)
from server.scratchpad import EpisodeScratchpad
class ToolDispatcher:
"""Dispatches tool calls to deterministic per-tool handlers."""
def run(
self,
tool: ToolType,
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
scratchpad: EpisodeScratchpad,
) -> str:
handler = _HANDLERS.get(tool)
if handler is None:
return f"[{tool.value.upper()}] Tool not implemented."
return handler(query, candidate, gt, jd, scratchpad)
# ── Individual tool handlers ──────────────────────────────────────────────────
def _verify_employment(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if not query:
return "[VERIFY_EMPLOYMENT] Provide query as 'Company Name, Job Title'."
company = query.split(",")[0].strip()
if not any(e.company.lower() == company.lower() for e in candidate.work_history):
return (
f"[VERIFY_EMPLOYMENT] '{company}' not found in candidate's work history. "
"Verify the company name matches exactly."
)
for sig in gt.fake_signals:
if sig.startswith("company_nonexistent:"):
fake_co = sig.split(":", 1)[1]
if fake_co.lower() in company.lower() or company.lower() in fake_co.lower():
return (
f"[VERIFY_EMPLOYMENT] '{company}' could not be found in business "
"registries or public filings. No matching corporate entity. "
"Likely fictitious employer."
)
return (
f"[VERIFY_EMPLOYMENT] '{company}' is a registered business. "
"Role appears consistent with company profile and size."
)
def _check_employment_dates(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if not query:
return "[CHECK_EMPLOYMENT_DATES] Provide query as 'Company Name, Start–End'."
company = query.split(",")[0].strip()
if not any(e.company.lower() == company.lower() for e in candidate.work_history):
return (
f"[CHECK_EMPLOYMENT_DATES] '{company}' not found in candidate's work history."
)
if any("impossible_dates" in s or "overlap" in s for s in gt.fake_signals):
return (
f"[CHECK_EMPLOYMENT_DATES] Date inconsistency at '{company}': tenure overlaps "
"with another listed role by 14 months. Timeline is not physically possible."
)
return (
f"[CHECK_EMPLOYMENT_DATES] Dates at '{company}' are internally consistent. "
"No overlaps or impossible gaps detected."
)
def _check_linkedin(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
url = candidate.online_profiles.get("linkedin")
if not url:
return "[CHECK_LINKEDIN] No LinkedIn URL in candidate profile. Cannot verify."
if "linkedin_mismatch" in gt.fake_signals:
return (
"[CHECK_LINKEDIN] Discrepancies found: resume title and tenure differ "
"from LinkedIn profile. Example: resume states 'Lead Engineer 2019–2022'; "
"LinkedIn shows 'Junior Developer 2020–2021'. Titles and dates conflict."
)
return (
"[CHECK_LINKEDIN] LinkedIn profile is consistent with resume. "
"Titles, companies, and dates align. Endorsements match listed skills."
)
def _check_online_profile(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
# Agent should pass the URL from online_profiles relevant to the JD domain
url = query
if not url:
# Fallback: pick any non-LinkedIn profile
url = next(
(v for k, v in candidate.online_profiles.items() if k != "linkedin"), None
)
if not url:
return (
"[CHECK_ONLINE_PROFILE] No relevant online profile URL found. "
"Candidate has no GitHub, portfolio, or domain-specific profile listed."
)
if "github_burst" in gt.fake_signals and ("github" in url.lower() or "git" in url.lower()):
return (
"[CHECK_ONLINE_PROFILE] GitHub activity anomaly detected: 1,247 commits "
"concentrated in a 48-hour window 3 days before the application date. "
"Account created 5 months ago. No pull requests or collaborative "
"contributions. Commit messages are non-descriptive. "
"Profile activity pattern consistent with fabricated history."
)
if "portfolio_burst" in gt.fake_signals:
return (
"[CHECK_ONLINE_PROFILE] Portfolio domain registered 6 days before "
"application. All project dates post-date the registration. "
"Likely created specifically for this application."
)
return (
f"[CHECK_ONLINE_PROFILE] Profile at {url} shows consistent activity "
"spanning 3+ years. Contributions match claimed skill set. No anomalies."
)
def _verify_education(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if not query:
return "[VERIFY_EDUCATION] Provide query as 'Degree, Institution, Year'."
if "fake_degree" in gt.fake_signals:
parts = query.split(",")
inst = parts[1].strip() if len(parts) > 1 else "listed institution"
return (
f"[VERIFY_EDUCATION] '{inst}' does not offer the claimed degree program. "
"No public records of this degree conferred. Graduation year is also "
"inconsistent with stated class size data."
)
return (
"[VERIFY_EDUCATION] Education credentials verified. Degree and graduation "
"year are consistent with institution records."
)
def _contact_reference(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if not candidate.references:
return "[CONTACT_REFERENCE] No references listed in this candidate's profile."
referee_name = (query or "").strip() or candidate.references[0].name
# Check if this referee is in the references list
ref_match = next(
(r for r in candidate.references if referee_name.lower() in r.name.lower()),
None,
)
if ref_match is None:
return (
f"[CONTACT_REFERENCE] '{referee_name}' not found in candidate's "
"listed references. Check the name spelling."
)
for sig in gt.fake_signals:
if sig.startswith("reference_wrong_company:"):
fake_ref = sig.split(":", 1)[1]
if fake_ref.lower() in referee_name.lower() or referee_name.lower() in fake_ref.lower():
return (
f"[CONTACT_REFERENCE] {referee_name}: Contact confirmed. "
f"However, they state they worked at a different organisation — "
f"not '{ref_match.company}' as listed. No direct employment "
"overlap with candidate confirmed. Reference appears invalid."
)
return (
f"[CONTACT_REFERENCE] {referee_name}: Confirmed working relationship "
f"at {ref_match.company}. Reference is positive. "
f"Relationship described as: {ref_match.relationship}."
)
def _review_timeline(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if any("impossible" in s or "overlap" in s for s in gt.fake_signals):
return (
"[REVIEW_TIMELINE] Timeline issues detected: role overlap of 14 months "
"between two listed positions. Candidate claims 8 years experience but "
"earliest role starts only 5 years ago. At least one date range is "
"physically impossible."
)
if not candidate.work_history:
return "[REVIEW_TIMELINE] No work history to review."
total_years = len(candidate.work_history) * 2 # rough heuristic for stub
return (
f"[REVIEW_TIMELINE] Work history timeline is internally consistent. "
f"No overlaps or impossible progressions. "
f"{len(candidate.work_history)} roles covering an estimated {total_years}+ years."
)
def _check_skills_fit(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if "skills_not_in_history" in gt.fake_signals:
return (
"[CHECK_SKILLS_FIT] Significant mismatch: candidate lists "
f"{', '.join(candidate.skills[:4])} — but all roles in work history "
"are in sales/account management with no engineering responsibilities. "
"Skills appear entirely fabricated relative to work history. "
f"JD requires: {', '.join(jd.required_skills[:3])}."
)
overlap = [s for s in candidate.skills if s in jd.required_skills]
missing = [s for s in jd.required_skills if s not in candidate.skills]
return (
f"[CHECK_SKILLS_FIT] {len(overlap)}/{len(jd.required_skills)} required skills present. "
f"Match: {', '.join(overlap) or 'none'}. "
f"Missing: {', '.join(missing) or 'none'}. "
"Skills are evidenced in work history."
)
def _verify_claim(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if not query:
return "[VERIFY_CLAIM] Provide a specific bullet-point achievement string from work history."
# Check the claim exists in some bullet point
claim_text = query.lower()
found = any(
claim_text in bp.lower()
for entry in candidate.work_history
for bp in entry.bullet_points
)
if not found:
return (
f"[VERIFY_CLAIM] Claim text not found in candidate's listed work history "
"bullet points. Verify the exact text matches."
)
if "inflated_claim" in gt.fake_signals:
return (
f"[VERIFY_CLAIM] Claim appears implausible: company had ~15 employees "
f"at the time. '{query[:60]}' is inconsistent with company scale and "
"typical responsibilities at that role level."
)
return (
f"[VERIFY_CLAIM] Claim '{query[:60]}' appears consistent with "
"company size and role level. Corroborating public data found."
)
def _verify_location(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if "location_mismatch" in gt.fake_signals:
sponsorship_note = (
" ⚠ JD requires no visa sponsorship — this candidate would need sponsorship."
if not jd.sponsorship_available
else ""
)
return (
f"[VERIFY_LOCATION] Location mismatch: stated '{candidate.stated_location}' "
f"but GitHub commit timestamps and IP geolocation signals indicate "
f"actual location '{gt.true_location}'.{sponsorship_note}"
)
sponsorship_ok = (
"" if jd.sponsorship_available
else f" No sponsorship needed — consistent with JD constraint."
)
return (
f"[VERIFY_LOCATION] Location '{candidate.stated_location}' is consistent "
f"with profile signals (GitHub timezone, commit patterns, company office).{sponsorship_ok}"
)
def _search_web(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if not query:
return "[SEARCH_WEB] Provide a search query."
if gt.is_fake and any(
s.startswith("company_nonexistent") for s in gt.fake_signals
):
fake_co = next(
(s.split(":", 1)[1] for s in gt.fake_signals if s.startswith("company_nonexistent:")),
None,
)
if fake_co and fake_co.lower() in query.lower():
return (
f"[SEARCH_WEB] '{query}': No results found for this company in "
"LinkedIn, Crunchbase, or public business directories. "
"Zero press mentions. Entity appears fictitious."
)
return (
f"[SEARCH_WEB] Results for '{query}': No significant red flags in public "
"records. Candidate's stated employer and role appear in professional networks."
)
def _request_screening_round(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
_pad: EpisodeScratchpad,
) -> str:
if gt.is_fake:
return (
"[REQUEST_SCREENING_ROUND] 30-min screening call completed.\n"
"Technical section: candidate was unable to describe implementation "
"details of listed projects. Answers were vague and inconsistent under "
"follow-up probing.\n"
"Behavioural section: story changed when asked about specific timelines. "
"Claimed promotion dates conflict with dates given earlier in the call.\n"
"Competency: technical answers inconsistent with claimed senior-level "
"experience. Unable to solve a standard problem in the claimed primary language.\n"
"Overall: negative indicators across all three sections."
)
return (
"[REQUEST_SCREENING_ROUND] 30-min screening call completed.\n"
"Technical section: demonstrated strong depth. Clear explanations of "
"system design decisions and trade-offs.\n"
"Behavioural section: consistent narrative with specific examples. "
"Timelines align with resume.\n"
"Competency: solved the coding problem efficiently with good communication.\n"
"Overall: positive indicators. Recommend advancing."
)
def _note(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
pad: EpisodeScratchpad,
) -> str:
return pad.note(candidate.candidate_id, query or "")
def _recall(
query: Optional[str],
candidate: CandidateProfile,
gt: CandidateGroundTruth,
jd: JobDescription,
pad: EpisodeScratchpad,
) -> str:
return pad.recall(query)
# ── Handler dispatch table ────────────────────────────────────────────────────
_HANDLERS = {
ToolType.VERIFY_EMPLOYMENT: _verify_employment,
ToolType.CHECK_EMPLOYMENT_DATES: _check_employment_dates,
ToolType.CHECK_LINKEDIN: _check_linkedin,
ToolType.CHECK_ONLINE_PROFILE: _check_online_profile,
ToolType.VERIFY_EDUCATION: _verify_education,
ToolType.CONTACT_REFERENCE: _contact_reference,
ToolType.REVIEW_TIMELINE: _review_timeline,
ToolType.CHECK_SKILLS_FIT: _check_skills_fit,
ToolType.VERIFY_CLAIM: _verify_claim,
ToolType.VERIFY_LOCATION: _verify_location,
ToolType.SEARCH_WEB: _search_web,
ToolType.REQUEST_SCREENING_ROUND: _request_screening_round,
ToolType.NOTE: _note,
ToolType.RECALL: _recall,
}