# 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, }