Home

/

Build It in a Weekend. Run It for Years.

/

Use Case 2: CV Formatting & Redacting for Clients

Use Case 2: CV Formatting & Redacting for Clients

Chapter 6
Part II
4
min read

The job that isn't a job

Once screening tells you who's worth a phone call, the next job is turning a candidate's CV into something you can actually send a client. The part that catches people out is that it's two jobs wearing one coat.

The first is cosmetic. The CV arrives as a Word doc with three fonts, a header photo, and dates in two different formats. Your client wants it on your letterhead, in your house style, with your logo on it. So a recruiter spends ten to forty-five minutes retyping and reformatting, per CV, by hand. Across a week that's about four hours per recruiter on a task no client ever thanks you for. It's the most automatable work in the building.

The second job is the one most agencies do by reflex and never name: stripping out what shouldn't reach the client yet. The candidate's surname, their phone number, their home address, their date of birth, the current employer they haven't told. You redact it, or you should, because sending it is a problem with a fine attached.

Reformatting saves you hours. Redaction saves you a GDPR letter.

Before and after: a messy candidate CV becomes the agency-branded, PII-redacted client version.

Redaction is a security control, not a courtesy

Get precise about why this matters. It changes how you build it.

When you send a client an un-redacted CV, you've disclosed personal data about an identifiable person to a third party, often before that person has agreed to be put forward. Under UK and EU GDPR that's a processing-and-disclosure event you have to be able to justify, and the penalty ceiling for getting it wrong is up to 4% of global turnover, or about $22 million, whichever is higher. The date of birth that slips through isn't a typo. It's a breach.

So redaction belongs in the same mental category as a locked filing cabinet or a password. It's a control. And controls have a property that "being careful" does not: they're enforced, not hoped for. A recruiter reformatting by hand at 6pm on a Friday is "being careful." That's exactly the moment the phone number stays in.

This is the through-line of the whole approach. The agent does the tireless ninety per cent; a human owns the moment of consequence. For this use case, the moment of consequence is send to client, and the leash sits right there.

The trick: the model never sees the raw document

One design decision does most of the work here, and it's worth slowing down for. It's a teaser of the guardrail we build properly in the security and compliance work.

The naive approach is to hand the whole CV to the model and ask it nicely to "remove personal details and reformat this." That's hope, not a control. The model might miss a phone number in a footer. It might paraphrase the address instead of dropping it. And you've now sent the candidate's full personal data to a third-party API to ask it to protect that data, which is the opposite of what you wanted.

We invert it. First we extract the CV into a structured object, a known set of named fields. Then we decide, in our own code, which of those fields are allowed to leave the building. The model only ever works with the allowlisted fields. The raw document, and everything we chose to redact, never reaches it.

The safest data to leak is the data the model never received.

The shape of the extracted candidate looks like this. (Illustrative excerpt, not a full implementation.)

public sealed record CandidateProfile
{
    public string FullName { get; init; } = "";   // redacted from client copy
    public string Email { get; init; } = "";       // redacted
    public string Phone { get; init; } = "";       // redacted
    public DateOnly? DateOfBirth { get; init; }     // redacted — never sent
    public string CurrentEmployer { get; init; } = ""; // redacted by default

    public IReadOnlyList<RoleHistory> Experience { get; init; } = [];
    public IReadOnlyList<string> Skills { get; init; } = [];
    public string Summary { get; init; } = "";      // safe to send
}

Notice what's happening: redaction isn't a step we run after formatting and hope it caught everything. It's a property of the fields themselves. A field is either on the client allowlist or it isn't.

// The allowlist IS the redaction policy. One place. Auditable. Boring.
static readonly string[] ClientSafeFields =
    ["Summary", "Experience", "Skills", "Education", "Certifications"];

ClientCv BuildClientCopy(CandidateProfile p) => new()
{
    Reference  = AssignAnonRef(p),       // "Candidate A-2291", not a name
    Summary    = p.Summary,
    Experience = MaskEmployers(p.Experience), // "a FTSE-100 retailer"
    Skills     = p.Skills,
    // FullName, Email, Phone, DateOfBirth: simply never read here.
};

PII isn't removed. It's never selected. That's a much stronger guarantee: there's no regex chasing phone-number formats across a free-text blob, because the free-text blob never makes it this far.

the-math-no-recruiter-can-win-by-hand
what-an-ai-agent-actually-is
the-leash
the-toolkit
the-model-small-capable-swappable
talking-to-your-ats
use-case-1-resume-screening-against-a-job
the-shape-of-the-loop
running-it-thought-action-observation
use-case-2-cv-formatting-redacting-for-clients
reformatting-into-your-branded-template
resume-shortlisting
that-was-easy
security-compliance
keeping-pii-out-of-the-llm
exceptions-reliability
silent-api-drift-the-ats-changes-under-you
when-it-fails-anyway-dead-letter-and-the-leash
monitoring-observability
maintenance-the-lifecycle
the-scorecard-success-metrics-kpis
build-vs-buy-vs-managed
what-an-engineer-actually-costs
what-the-wider-data-says-happens-next
conclusion-how-this-gets-run-for-you
the-promises-behind-the-service
fuller-code-listings
one-full-screening-react-loop-semantic-kernel
env-deployment-reference
secrets-in-dev-vs-production
bullhorn-jobadder-endpoint-cheat-sheets
sources-further-reading
compliance-primary-law-sources

Download the full PDF for free?

Download full PDF
build-it-in-a-weekend.pdf
Oops! Something went wrong while submitting the form.
Related Chapters