1. Sixty postings → a ranked shortlist, then a tailored application (map-reduce, 3 agents)
One CV, unchanged, went out to sixty postings. Each application took twenty minutes of scrolling and copy-paste, so the tailoring stopped after the first four and the rest went out generic. Nobody ever read back which sixty they were, or which ones actually matched what the person can genuinely do.
Trigger: Webhook (saved-search digest from a job board) / Email (job alerts)
How the workflow runs
- Trigger
The day's postings arrive. Job-board alert emails hit an Email trigger, or a saved-search digest posts to a Webhook. Job boards and ATS career portals have no first-party connector — postings come in via Webhook and/or are fetched by a Tool (MCP) node.
- Knowledge
Your own record, once. A Knowledge node holds the person's real material: current CV, past project write-ups, certificates, transcripts, reference letters. This is the ONLY source of fact about them — everything downstream is grounded in it.
- Loop
Map: one cheap pass per posting. A Loop node fans a cheap screener agent across every posting — one focused pass each, isolated context — so sixty postings cost the same per item as six.
- Agent
Screener scores the fit honestly. The screener returns strict JSON per posting: must-have requirements found vs. missing, evidence quoted from the person's own Knowledge, and a verdict. A missing must-have is reported as missing, never smoothed over.
- Tool (MCP)
Your must-haves, encoded once. A user-defined tool turns the screener's counts into a single verdict using YOUR thresholds, not a model's mood — the same rule applied identically to all sixty.
- Agent
Reduce: the shortlist. A reducer agent ranks the STRONG and STRETCH postings into one shortlist with the reason for each, and lists the SKIPs with the specific must-have that was missing — that list is the honest map of the person's real gaps.
- Agent
Premium tailoring, shortlist only. Only for shortlisted roles does a premium-tier writer draft the tailored CV summary and cover letter — re-ordering and re-framing what is already true in Knowledge, adding nothing that isn't.
- Approval
You read it before it exists anywhere. An Approval node holds every draft. The person reads the claims, checks each one is theirs, edits, and only then releases. Nothing is submitted by the workflow — applications are filed by the human on the employer's own portal.
Channels & connectors
- Webhook (job-board digest)
- Tool (MCP → job board / ATS career portal)
- Knowledge base
- Approval / HITL
- Telegram
Outcome
Every posting in the day's batch is screened against the person's actual must-haves, the shortlist arrives ranked with reasons, and only shortlisted roles get a hand-checked tailored draft.
Why it helps
The mechanism is cost asymmetry plus grounding: the expensive work (tailoring) is spent only where a cheap, rule-checked screen says it's warranted, and every claim in the draft traces back to a document the person already owns — so tailoring scales without the CV drifting away from the truth.
Build spec
3 agents — 1 screener (runs once per posting via the Loop node) + 1 reducer (once) + 1 tailoring writer (only for shortlisted roles). The Loop, the user-defined verdict tool and the Approval are workflow nodes. · Pattern: Map-reduce with a premium tail: Loop (cheap map) → reducer (rank) → premium writer on the shortlist only → human approves
System prompt (paste-ready)
(Screener) Assess ONE job posting against the candidate's own record in Knowledge. Return strict JSON {title, employer, mustHaveTotal, mustHaveMatches, matched[{requirement, evidence, source_doc}], missing[{requirement, why}], niceToHaveMatches, notes}. EVERY item in matched[] MUST quote real evidence from the candidate's own documents and name the source document — if you cannot find evidence, the requirement goes in missing[], never in matched[]. Do NOT infer a skill from a job title, do NOT round up years of experience, do NOT assume a degree or certificate that isn't in Knowledge. You are scoring fit, not selling the candidate. If the posting is unreadable or a duplicate, return {skip: true, reason}.Agent roles & model tiers
Screener (per posting) — Economy tier — fast and cheap; it runs once per posting, so this single choice dominates the total cost of the whole run. Configure a fallback model so one flaky call doesn't drop a posting from the batch.
Score ONE posting against the candidate's Knowledge into schema-valid JSON. Quote evidence and name its source document for every match; anything without evidence is 'missing'. No inferred skills, no rounded-up years, no assumed credentials.
Reducer (once per batch) — Standard tier — reasoning over the whole batch
Rank the screened postings into one shortlist (STRONG first, then STRETCH) with a one-line reason each, and list the SKIPs grouped by the must-have that was missing. Use only the provided results — never re-score a posting yourself. Finish with the two or three requirements that blocked the most roles; that is the candidate's real gap list, state it plainly.
Tailoring writer (shortlist only) — Premium tier — this is the one place the quality is worth paying for, and it runs on a handful of roles, not on sixty
Draft a tailored CV summary and a cover letter for ONE shortlisted role, using ONLY facts present in the candidate's Knowledge. You may re-order, re-frame, re-word and choose which true things to lead with. You may NOT add a skill, tool, employer, responsibility, qualification or date that is not in the source documents, and you may NOT change any date or duration. Where the role asks for something the candidate genuinely lacks, either omit it or address it honestly as a gap they are working on — never imply it is held. Mark every draft as a draft for the candidate to check.
MCP connectors
- Job board / saved search — inbound via Webhook; posting bodies fetched by a Tool (MCP) node (no first-party connector)
- ATS career portal — read-only via Tool (MCP) where the employer exposes one; applications are filed by the human, never by the workflow
- Email / Telegram — where the shortlist and the drafts are delivered
Built-in tools
- knowledge_search (the candidate's own CV, project write-ups, certificates, references)
- web_search (employer background for the cover letter — public information only)
- http_request (fetch posting bodies from the board)
- user-defined tool `role_fit` (SpEL): input.mustHaveMatches >= input.mustHaveTotal ? 'STRONG' : (input.mustHaveMatches >= input.mustHaveTotal - 1 ? 'STRETCH' : 'SKIP') — a tenant-authored SpEL expression over the tool's JSON input. It is a data-transform/formula tool, not a scripting engine: sandboxed by construction, because the grammar allows no method calls, no constructors, no bean or type references and no loop. The benefit is that the person encodes THEIR OWN must-have threshold once — 'one gap is a stretch, two is a no' — and it is applied identically to all sixty postings, deterministically, without a developer and without asking a model to be consistent about arithmetic.
Guardrails
- HONESTY, absolute: the agent never fabricates experience, skills, qualifications, employers or dates. It only reframes and highlights what is genuinely true in the candidate's own Knowledge, and it flags missing requirements as missing — a CV that lies is unethical and is the candidate's legal risk to carry
- Every 'matched' requirement must quote evidence and name the source document; anything unevidenced is forced into the missing[] list, so the shortlist can't be inflated by a confident model
- No draft leaves as an application: the Approval node holds every CV summary and cover letter for the person to read line by line, and the submission itself is done by the human on the employer's portal — the workflow never auto-applies
- The screener's verdict comes from the deterministic `role_fit` SpEL rule, not from model discretion, so the same posting scores the same way on every run
- Schema validation on each screener output — a malformed posting is skipped with a reason and surfaced, never silently ranked
Cost strategy
The whole design is a cost shape: N × economy-tier screener + ONE standard-tier reduce + K × premium-tier tailoring where K is the shortlist, not the batch. Screening sixty postings on the premium tier would cost roughly an order of magnitude more than screening them on the economy tier and paying premium for four cover letters — the Loop is exactly where cost routing earns its keep. Cap the screener per-call, give it a fallback model so a single failure doesn't cost a re-run of the batch, and run the map in Parallel batches for wall-clock speed at unchanged per-item cost.
Output & delivery
The Loop maps the economy screener over every posting → `role_fit` turns counts into STRONG/STRETCH/SKIP deterministically → the reducer emits one ranked shortlist plus an honest gap list → the premium writer drafts only for shortlisted roles → the Approval node puts every claim in front of the person before anything is used, and they file the application themselves.