Fake candidates: the intake signals an agent can flag, and the call it must not make

A recruiter calls you about a placement that went wrong. The consultant who showed up on the first day of the assignment was not the person on the video screen in the interview, or the resume belonged to someone else, or the same phone number has now applied to four of your reqs under three names. If you place remote contractors in IT, this stopped being a curiosity somewhere around 2024 and is now a line item in your client's security review.

The temptation is to point a model at it and let it reject people. Do not. Identity-risk scoring is a selection decision if it removes anyone from consideration, which puts it squarely inside the AEDT rules your firm — not your vendor — answers for. The useful build is narrower and more boring: an agent that gathers signals at intake, writes them down with their source, and puts a short queue in front of a named recruiter.

This walkthrough covers the data model, the signals worth collecting, where to draw the line between flagging and deciding, and what to keep for the file.

Step one: decide what the agent is allowed to do

Write this down before any code, because it is the part a client's security questionnaire and a plaintiff's lawyer both ask about.

The agent mayThe agent may not
Compare an application against records you already holdReject, auto-archive or silently deprioritise a candidate
Flag duplicates, reused contact details and inconsistent historyScore candidates on accent, name, photo, country or video appearance
Ask for a verification step through your existing processRun face matching against an ID document on its own authority
Open a review task for a named recruiterTell the candidate they are suspected of fraud
Log every signal, its source and timestampShare the flag with the client before a human has looked

The asymmetry matters. Flagging costs a recruiter two minutes. Rejecting costs you a discrimination claim built out of your own log table, and the log will exist, because you are going to build it in step two.

Step two: the signal table

One row per signal, not one score per candidate. Scores are opinions; signals are facts you can show someone.

create table identity_signal (
  id              bigserial primary key,
  candidate_id    text        not null,
  application_id  text,
  signal_code     text        not null,
  detail          jsonb       not null,
  source_system   text        not null,   -- 'ats', 'email_headers', 'scheduler'
  observed_at     timestamptz not null default now(),
  surfaced_to     text,                   -- recruiter handle, null until queued
  reviewed_at     timestamptz,
  outcome         text                    -- 'cleared' | 'verification_requested' | 'withdrawn' | 'other'
);

create index on identity_signal (candidate_id, observed_at desc);

detail holds the evidence, not a sentence about it. For a duplicate-contact signal that is the other candidate ids and the matched value; for a resume-overlap signal the two placement rows and the dates. If a recruiter cannot see why a flag fired without opening a model trace, the flag is noise.

Step three: signals worth the trouble

Start with the ones computable from your own ATS, because they cost nothing and they are the ones that actually fire.

Contact reuse. Normalise phone numbers to E.164 and lowercase emails, strip Gmail dots and +tags, then look for the same value across distinct candidate records created in the last two years.

select lower(regexp_replace(split_part(email,'@',1),'[.]|\\+.*$','','g'))
         || '@' || lower(split_part(email,'@',2)) as norm_email,
       count(distinct candidate_id)               as candidates,
       array_agg(distinct candidate_id)           as ids
from candidate_contact
where created_at > now() - interval '24 months'
group by 1
having count(distinct candidate_id) > 1;

Most hits are benign: a duplicate record from a 2019 import, a spouse sharing a phone line, your own recruiter pasting their number into a test profile. That is fine. The agent is building a queue, not a verdict.

Overlapping assignments. Two concurrent full-time placements on the same person, or a claimed employment period that overlaps an assignment you yourself ran, is worth a question. Same query shape as a timesheet overlap check, and you probably already have one.

Resume-to-ATS drift. Dates, employer names and titles in the submitted document that contradict the record the candidate gave you six months ago. Store both, diff the fields, show the diff.

Scheduling pattern. A candidate who reschedules every camera-on interview, or whose invite is consistently opened from a different timezone than the one on their profile, is a soft signal. Keep it soft. Timezone data is noisy and people travel.

Banking change on an active contractor. Not an intake signal, but the same table and the same queue, and the one with the fastest payback. A pay-detail change arriving by email in the week before a pay run gets a hold and a call-back on the number already on file. No exceptions, including when the email is urgent and well written. Especially then.

What to leave out: anything inferred from a photo, a voice, a name's apparent origin, or the presence of an accent. Those are not fraud signals, they are proxies for protected characteristics, and an agent that collects them has created the evidence that convicts you.

Step four: the interview-stage evidence capture

The strongest control is not a model. It is making identity verification a normal, announced step in the process for everyone at the same stage, so it is consistent and provable.

The agent's job around it is clerical:

  1. When an interview is booked, attach the standard notice to the invite: camera on, government ID shown at the start, the same check for every candidate at this stage.
  2. After the interview, prompt the recruiter for three fields — ID shown yes/no, name matched yes/no, any concern free-text — and write them to the record. Thirty seconds, in the tool they are already in.
  3. On first day of assignment, reconcile the onboarding identity documents against the interview record and flag a mismatch to a human within the hour, before timesheets start accruing.
  4. If a client requires a verification vendor, let the agent open and track the case, and keep the vendor's reference id on the candidate record. The decision comes back to your recruiter.

Step three is where most impersonation gets caught, and it needs no model at all. Build it first.

Step five: the queue and the record

Surface signals as a short daily list, grouped by candidate, with a one-click outcome. Cap it. A queue that regularly exceeds a dozen items a day gets ignored, so tune thresholds down until a recruiter clears it in five minutes.

For every item, keep: the signals, their evidence, who reviewed it, when, which outcome they chose, and the free text they typed. Retain it under the same schedule as the rest of your candidate records — the retention and purge rules you already wrote for screening apply unchanged — and make sure a cleared flag actually disappears from view, rather than quietly following the candidate around your ATS for three years.

When a candidate asks why they were asked for extra verification, the answer should be a dated row, a named person and a policy that applied to everyone at that stage. If the honest answer is "the system flagged them", stop and redesign.

What this does not solve

It does not catch a competent fraud with clean contact details, a consistent story and a real document. It narrows the window and it gives you a record, which is what a client's security review is actually asking for.

It is also not worth building before the basics are in: if you are not reconciling onboarding documents against the interview on day one, start there and skip the signal table for a quarter.

If you want this scoped against your own ATS and onboarding stack, tell us what you run — the ATS, contractor headcount, and where the identity checks currently happen. We reply within one business day.