| # Open Recruiter: Adversary Trained Recruitment agents |
|
|
| *Submitted to the Apr 2026 OpenEnv Hackathon — Theme 3.1: World Modeling / Professional Tasks + Theme 4: Self-Improvement* |
|
|
| --- |
|
|
| ## Problem Statement |
|
|
| Hiring is a uniquely adversary problem. The candidates are trying to fool the companies and wiggle their way into the interview by hook or by crook. In fact, many people encourage lying or overexaggeration on their resumes. On the other hand, recrutiers write vast JDs which would require an entire IT departments. This also includes unrealistic requirements e.g. 5 years of experience on OpenEnv. |
| A human recruiter generally relies on ATS and their own judgement. This comes with it's own limitations, Resumes can be tailored for ATS and recruiters and miss signals or red flags. |
| Resume fraud costs US companies an estimated **$600M/year** in bad hires, onboarding failures, and legal exposure. A human recruiter has roughly 6 seconds to scan a resume before making a first-pass decision. They are operating under time pressure, information asymmetry, and cognitive load — conditions where fabricated credentials, inflated timelines, and ghost employers routinely slip through. |
|
|
| The core challenge is not classification — it's **strategic investigation under a budget**. A good recruiter doesn't verify everything; they allocate their attention surgically, chasing the signals most likely to expose fraud. This is exactly the kind of behaviour that current LLMs struggle with: they either spray tools indiscriminately or skip verification entirely and guess. |
|
|
| **Open Recruiter** is an OpenEnv-compliant environment that puts an LLM agent in the recruiter's seat and rewards it for learning to do the job well. |
|
|
| --- |
|
|
| ## Motivation |
|
|
| Most LLM benchmarks test *knowledge* — what does the model know? Recruiter tests *judgment under constraint* — what does the model choose to do, and in what order, when it can't afford to do everything? |
|
|
| The environment is designed around three observations: |
|
|
| 1. **Partial observability is the default in professional work.** Candidate profiles are incomplete by design; the agent must decide which gaps are worth investigating. |
| 2. **Budget forces prioritization.** With 6 cost-units per candidate and 12 tools of varying cost, the agent cannot brute-force every profile. It must learn which tool catches which fraud signal. |
| 3. **The output is a ranked shortlist, not a binary label.** Ranking quality (nDCG@5) matters more than per-candidate accuracy — the agent must weigh candidates *against each other*, not just against a fixed threshold. |
|
|
| The environment generalises directly to any triage workflow: grant review, academic admissions, vendor shortlisting, insurance claim triage. The ranked-shortlist-under-budget pattern is domain-agnostic. |
|
|
| --- |
|
|
| ## Environment Design |
|
|
| The agent screens a **cohort of 10 candidates** applying for the same role. Some are legitimate; some are adversarially injected fakes. The episode runs in two phases: |
|
|
| **Phase A — Investigate** |
| The agent works through candidates sequentially. For each, it selects from 12 structured verification tools: |
|
|
| | Tool | Cost | What it catches | |
| |------|------|-----------------| |
| | `verify_employment` | 1 | Non-existent employers | |
| | `check_employment_dates` | 1 | Impossible timelines | |
| | `check_linkedin` | 1 | Resume vs LinkedIn mismatches | |
| | `check_online_profile` | 1 | GitHub/portfolio activity bursts | |
| | `verify_education` | 1 | Fake degrees | |
| | `contact_reference` | 1 | References at wrong companies | |
| | `review_timeline` | 1 | Overlapping/impossible dates | |
| | `check_skills_fit` | 1 | Skills absent from work history | |
| | `verify_claim` | 1 | Implausible achievements | |
| | `verify_location` | 1 | Location fraud under sponsorship constraints | |
| | `search_web` | 2 | Open-ended research | |
| | `request_screening_round` | 3 | Story inconsistency under live questioning | |
|
|
| Per-candidate budget: **6 cost-units**. Episode budget: **30 cost-units**. |
|
|
| **Phase B — Rank** |
| The agent emits a single ranked shortlist (top → bottom) with one line of cited evidence per candidate. This is scored against ground truth via the rubric. |
|
|
| ### Adversarial Cohort & Curriculum |
|
|
| Fake candidates are generated with tier-specific fraud signals of escalating subtlety: |
|
|
| | Tier | Fraud signals | Difficulty | |
| |------|--------------|------------| |
| | 1 | Impossible dates, obvious location mismatch | Easy | |
| | 2 | Non-existent employer, skills not in work history | Medium | |
| | 3 | GitHub burst activity, suspicious short tenures | Hard | |
| | 4 | Real references at wrong companies, subtle location fraud | Very hard | |
|
|
| Difficulty advances automatically when rolling-window nDCG@5 > 0.8 over the last 20 episodes — the environment gets harder as the agent gets better. |
|
|
| ### Hiring Manager Personas |
|
|
| Each episode is paired with one of 6 hiring manager personas (conservative, balanced, growth-focused, risk-averse, technical, culture-fit) that shift the ground-truth hireability scores. The agent sees the persona tag in its observation and must adapt its ranking criterion accordingly. |
|
|
| --- |
|
|
| ## Reward Engineering and Hacking Checks |
|
|
| Reward design is the hardest part of this environment. The naive reward — binary correct/incorrect ranking — is too sparse and easy to exploit. |
|
|
| ### Reward Function |
|
|
| ``` |
| Episode return = nDCG@5 × difficulty_mult × 5.0 |
| + per-step info-gain shaping (+0.1 per new fake signal revealed) |
| − 3.0 × fakes_in_top_5 |
| + 0.5 × feedback_quality (keyword-match on cited evidence) |
| + 0.3 × budget_efficiency_bonus (if 1–10 cost-units remain) |
| ``` |
|
|
| - **nDCG@5** gives a continuous, graded ranking signal — not just "right or wrong" |
| - **Fake penalty (−3.0 per fake in top 5)** is strong enough to dominate the signal when the agent guesses randomly |
| - **Per-step shaping (+0.1)** provides a training signal in Phase A, not just at the terminal step |
| - **Feedback bonus** rewards the agent for *citing the right evidence*, not just ranking correctly — prevents memorising orderings without understanding |
|
|
| ### Hacking Checks |
|
|
| The rubric is designed to resist three common exploit patterns: |
|
|
| 1. **Always rank real candidates first** — fake candidates are randomly positioned in the cohort; simple positional heuristics don't generalise |
| 2. **Use all budget to appear thorough** — the efficiency bonus rewards leaving budget on the table; budget drain without signal gain is not rewarded |
| 3. **Submit feedback keywords without tool use** — the feedback bonus only awards keywords that correspond to signals the agent actually had the opportunity to observe via tools |
|
|
| Training runs a dedicated `test_reward_hacking.py` suite that stress-tests these edge cases after each curriculum promotion. |
|
|
| --- |
|
|
| ## Training Pipeline |
|
|
| **Base model:** Qwen3-1.7B-Instruct, 4-bit quantised via Unsloth, LoRA (r=16, α=32) |
|
|
| **Two-stage training:** |
|
|
| 1. **SFT Warmup** — 76 hand-written expert trajectories teach the model JSON action format, tool selection patterns, and recruiter voice before any RL signal. This avoids the cold-start problem where early GRPO updates are dominated by malformed-action penalties. |
|
|
| 2. **GRPO** — Manual policy-gradient loop (not TRL GRPOTrainer, which doesn't support multi-turn rollouts). group_size=4 rollouts per update; only the terminal ranking step carries a non-zero reward. Per-step info-gain shaping provides Phase A signal. |
| |
| **Training cohort:** 5 candidates (3 real + 2 fake) per episode for speed. Evaluation and demo always use the full 10-candidate cohort. |
| |
| **Curriculum:** `CurriculumController` promotes difficulty automatically when nDCG@5 > 0.8 on a rolling 20-episode window. State is persisted to disk so training can resume across sessions. |
| |
| ```bash |
| # Dry run (CPU, no GPU needed, ~2 min) |
| python -m recruiter.training.train_grpo --dry-run |
|
|
| # Full training (A100/L4, ~2-4 hrs) |
| python -m recruiter.training.train_grpo --model Qwen/Qwen3-1.7B --episodes 500 |
| ``` |
| |
| The full training pipeline is available as a Colab notebook: [`training/train_grpo.ipynb`](recruiter/training/train_grpo.ipynb) |
| |
| --- |
| |
| ## Training Results |
| |
| > *Fill after training run completes — pull values from `baseline_random.json` and `trained_eval.json`.* |
| |
| ### Before Training (Random Baseline) |
| |
| | Metric | Tier 1 | |
| |--------|--------| |
| | nDCG@5 | — | |
| | Fakes in Top-5 | — | |
| | Mean Episode Reward | — | |
| |
| ### After Training (GRPO, N episodes) |
| |
| | Metric | Tier 1 | |
| |--------|--------| |
| | nDCG@5 | — | |
| | Fakes in Top-5 | — | |
| | Mean Episode Reward | — | |
| |
|  |
| |
| *The key behaviour change: the agent goes from spray-and-pray tool use to surgical selection — reading the job description first, budgeting aggressively on suspicious candidates, and emitting a clean ranked shortlist with cited evidence. That's what recursive skill amplification looks like in a hiring context.* |
| |
| --- |
| |
| ## Demo |
| |
| **Live environment:** [https://huggingface.co/spaces/dipsha/recruiter](https://huggingface.co/spaces/dipsha/recruiter) |
| |
| The Space exposes the full OpenEnv HTTP API: |
| - `POST /reset` — start a new episode with a fresh cohort |
| - `POST /step` — execute a tool or submit a ranking |
| - `GET /state` — inspect current episode state |
| - `GET /curriculum` — check current difficulty and rolling nDCG@5 |
| |
| A Gradio interactive demo is also bundled (`recruiter/demo/gradio_app.py`) and supports: |
| - **Full cohort mode** — 10-candidate episode with a mock or trained policy (~1-3 min) |
| - **Single candidate Q&A** — quick profile inspection (~15s) |
|
|
| --- |
|
|
| ## Conclusion and Further Work |
|
|
| Open Recruiter demonstrates that a non-trivial professional judgment task — adversarial candidate screening under budget — can be turned into a trainable OpenEnv environment with a rich, hacking-resistant reward signal and measurable improvement curves. |
|
|
| The environment teaches the agent three things it currently does poorly: |
| - **When to stop investigating** (budget efficiency) |
| - **Which tool to use for which fraud signal** (tool-signal alignment) |
| - **How to rank relative quality, not just flag individuals** (nDCG-driven ranking) |
|
|
| **What's next:** |
|
|
| - **Tier 5 (recursive amplification):** The adversary generates new fake candidates by few-shot prompting with the agent's recent false negatives — the environment literally adapts to what the agent currently misses |
| - **Multi-domain generalisation:** Swap the job description for a grant proposal or vendor RFP — the Phase A/B structure and reward function transfer directly |
| - **Longer horizons:** Extend Phase A across multiple rounds of information gathering with inter-candidate reasoning via the scratchpad |
| - **Persona-conditioned policy:** Train separate LoRA adapters per hiring persona, then blend at inference time based on the episode tag |
|
|
| --- |
|
|
| *Code: [github.com/sdipanshu/open-recruiter](https://github.com/sdipanshu/open-recruiter) | Environment: [huggingface.co/spaces/dipsha/recruiter](https://huggingface.co/spaces/dipsha/recruiter)* |
|
|