
A Two-Stage Chain-of-Thought Prompt Architecture for Resume Gap Analysis
Most people copy-paste their resume and a job description into an LLM and write: "Make my resume sound better for this job."
The model obliges. It adds stronger action verbs, tightens the language, and maybe cleans up a few bullets. What it doesn't do is identify that the job description uses the phrase "cross-functional stakeholder alignment" six times while your resume has it zero times. It doesn't tell you that you're missing a critical framework, or that your experience is framed as an executor rather than a leader. It polishes the surface without diagnosing the structural gaps.
If you don't enforce structured reasoning, the LLM jumps straight to generation. It anchors on your resume's existing vocabulary and fails to bridge the gap.
To fix this, we need a two-stage prompt architecture that enforces Chain-of-Thought (CoT) reasoning before a single edit is written.
Stage 1: The Gap Analyzer (No Rewriting Before Reasoning)
This prompt uses XML tags to enforce a mandatory thinking phase. By forcing the LLM to write out its reasoning inside <thinking> tags first, we shift the output distribution toward analytical mapping before it can generate suggestions.
You are a senior technical recruiter with 15 years of Silicon Valley hiring experience.
Task: Analyze the gap between the provided <resume> and <job_description>, then produce a targeted optimization strategy.
Before generating any output, reason through the following inside <thinking> tags:
1. Extract the core hard skills and soft skills stated or implied in the JD.
2. Map each requirement to evidence (or lack thereof) in the resume.
3. Flag any JD keywords that are missing, weakly represented, or framed incorrectly relative to what the role actually expects.
After your thinking is complete, output in this exact structure:
- **Missing or underrepresented keywords** (3–5, with context on why each matters)
- **Experience modules that need significant rewriting** (be specific: which job, which bullet)
- **Targeted optimization suggestions** (concrete, not generic — e.g., "In your 2023 Acme Corp role, reframe the data pipeline work to explicitly mention real-time throughput metrics, since the JD uses 'low-latency systems' three times")
<job_description>
{{job_description}}
</job_description>
<resume>
{{resume}}
</resume>
Why the order of the thinking steps matters: Starting with extracting skills from the job description (not the resume) prevents the model from anchoring on your resume's existing framing. It reads the requirements cold, then audits your resume against them.
Stage 2: The Targeted Rewrite
Once you review the gap analysis, you feed it into a second prompt to handle the actual rewriting. This keeps the model focused on execution, preventing it from rushing the diagnostic phase.
Using the gap analysis below, rewrite the specified experience bullets from my resume. For each rewrite:
- Incorporate the identified missing keywords naturally (not forced)
- Preserve all factual claims — do not invent metrics or responsibilities
- Match the technical register of the job description
Gap Analysis:
{{gap_analysis}}
Original Resume Sections to Rewrite:
{{resume_bullets}}
By decoupling analysis from generation, you avoid the hallucination/polishing trap and get highly targeted bullet points that map directly to what the hiring manager (and the ATS) is looking for.
Wrote up a deeper breakdown on the underlying research behind this, plus how to manage these templates locally using a privacy-first local manager if you're dealing with multiple roles: https://appliedaihub.org/blog/cot-prompting-job-hunt-resume/
How are you guys structuring prompts for subjective comparative tasks like this? Do you find XML tag scoping or other scratchpad techniques work better for keeping models in diagnostic mode?