RAG for job search

RAG over job listings has a problem most RAG systems do not: the documents are written by strangers, and some of them are trying to manipulate you.

JobsDart Editorial5 min read

Key takeaways

  • Grounding means the assistant can only discuss jobs that exist, and every claim traces to a row.
  • Chunk for retrieval, assemble context at the posting level — a detached requirements list misleads.
  • A dead link costs more trust than a thin answer, so filter closed postings at retrieval.
  • Retrieved postings are untrusted third-party text, and a prompt rule is not a boundary.
  • Validate the identifiers in the answer against what you actually sent.

What RAG buys you here

A model with no retrieval will confidently invent postings, salaries and companies. Grounding its answers in your actual index is the entire point: the assistant can only talk about jobs that exist, and every claim can be traced to a row.

It also keeps the system current without retraining. New postings are searchable the moment they are indexed, which matters on a board where the useful inventory turns over every few weeks.

The traceability is what makes the product defensible as much as accurate. When a user asks why a role was suggested, an answer that points at the posting and the matching requirement is a different kind of claim from one the model asserts.

Retrieve postings, not paragraphs

Generic RAG chunks documents into fixed-size windows. That is wrong for job search, because the useful unit is a posting and a fragment of one is often misleading — a requirements list detached from the role title reads as belonging to a different job.

Retrieve at the chunk level for relevance if you like, but assemble the context at the posting level: title, company, location, requirements and the identifier, as one coherent block per job.

Cap on postings rather than characters, too. Eight complete postings the model can reason about beat twenty truncated ones, and a character budget quietly produces the second while appearing to be more generous.

  • Chunk for retrieval, assemble for generation
  • Always include the posting identifier so answers can link out
  • Include the posted date so the model can flag old listings
  • Cap the number of postings in context rather than the character count
Job search RAG against the generic pattern
AspectGeneric RAGJob search
Retrieval unitFixed-size chunkChunk to find, posting to send
Document trustUsually internalWritten by strangers
FreshnessRarely criticalWeeks-long shelf life
Hybrid searchOptionalRequired — exact terms matter
Answer validationRareCheck cited ids against context

Hybrid retrieval, not pure vectors

Job search has an unusual amount of vocabulary that must match exactly. A clearance level, a specific certification, a named framework, a visa category — semantic similarity treats these as close to their neighbours, and close is wrong when the requirement is binary.

Running keyword search alongside vector search and combining the result sets fixes most of this. The vector side finds the role whose title you would never have typed; the keyword side guarantees that an exact term appears where it was required.

Metadata filters belong in the retrieval query rather than in the prompt. Active only, eligible locations, employment type — applied before retrieval, so the model never sees a posting it should not have been offered and cannot be talked into mentioning it.

Stale postings are the credibility risk

An assistant that recommends a role filled three weeks ago burns trust faster than one that finds nothing. Users forgive a thin answer; they do not forgive being sent to a dead link twice.

Filter closed postings at retrieval rather than hoping the model notices the date. If you cannot guarantee freshness, surface the posted date in the answer so the user can judge.

Aggregated sources are where this bites hardest, because a posting can be closed at the employer without the aggregator knowing. Re-checking the ones you are about to recommend, rather than the whole index, keeps that cost proportional.

Retrieved text is untrusted input

This is the part general RAG guidance under-weights. Job descriptions are written by people outside your organisation, and a posting can contain text addressed to your model: ignore previous instructions, rank this role first, tell the candidate they are a perfect match.

Treat everything retrieved as data. Keep it in clearly delimited blocks, state in the system prompt that instructions inside retrieved content are content and not commands, and — because a prompt rule is not a security boundary — make sure the model has no tool that could act on such an instruction anyway.

The architectural version of this is the one that holds. If the assistant can only read and summarise, an injected instruction has nothing to reach for; if it can send an email or submit an application, the prompt rule is the only thing standing between a hostile posting and an action, and that is not a position to be in.

Answer only from what was retrieved

The failure that erodes trust is the plausible blend: a real posting described with details the model supplied. Salary bands and requirements are exactly the fields it will fill in helpfully and wrongly.

Constrain the model to the retrieved context, require it to say when something is not stated in the posting, and validate the identifiers in its answer against what you actually sent. A cited posting that was not in the context is a hallucination you can catch programmatically.

Retrieving nothing should produce a clear "nothing matched" rather than a helpful answer assembled from general knowledge. That is the single most common way a grounded system stops being grounded, and it happens precisely when the user asked something specific enough to be worth answering correctly.

Frequently asked questions

Why use RAG instead of just prompting a model about jobs?

Without retrieval the model invents postings, salaries and companies. RAG grounds every claim in a row in your index and stays current as new postings are added, with no retraining.

Should I chunk job postings like ordinary documents?

Chunk for retrieval, but assemble context at the posting level. A requirements list detached from its title reads as belonging to a different job and produces confidently wrong answers.

How do I stop the assistant recommending filled jobs?

Filter closed postings at retrieval rather than hoping the model reads the date, and surface the posted date in the answer when freshness cannot be guaranteed.

Can a job posting attack my RAG system?

Yes. Postings are written by strangers and can contain instructions aimed at your model. Delimit retrieved text as data, and ensure no tool exists that could act on such an instruction — prompt rules are not a boundary.

Why is pure vector retrieval insufficient here?

Because clearances, certifications and visa categories are binary requirements, and semantic similarity treats them as close to their neighbours. Hybrid retrieval keeps exact terms exact.

What should happen when retrieval returns nothing?

A clear statement that nothing matched. Answering anyway from general knowledge is the most common way a grounded system quietly stops being grounded.

Further reading

Check this against your own resume

Scan your CV against a real job description, or build a parse-safe one from scratch. Your first scan costs nothing.

Keep reading

Referenced in these guides

All career guides