# How Drafter-Reviewer Separation Improves AI Job Application Drafts

> Improve AI job application drafts with drafter-reviewer separation. Two Claude Code agents enhance keyword coverage, tailor applications, and cut costs for error-free PDFs.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: internals
- Published: 2026-08-31

---

**The drafter-reviewer separation improves application drafts by splitting content generation and critique between two distinct Claude Code agents, enabling ATS-optimized keyword coverage, company-specific tailoring, and reduced token costs while ensuring error-free PDF output.**

The **MadsLorentzen/ai-job-search** repository implements a sophisticated multi-agent architecture that elevates automated job application generation beyond simple template filling. This **drafter-reviewer separation** pattern orchestrates two specialized Claude Code agents—one to create initial drafts and another to critique them with fresh context—resulting in higher-quality, tailored CVs and cover letters that outperform single-pass generation approaches.

## The Two-Agent Architecture

The core pattern divides responsibilities between distinct cognitive roles to prevent the compromises typical of monolithic AI systems.

### The Drafter Agent

The **drafter** generates initial **LaTeX** drafts for both CV and cover letter documents. It consumes the candidate profile defined in [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) and follows the template rules specified in [`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md) and [`06-cover-letter-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/06-cover-letter-templates.md). This agent handles the initial transformation of raw profile data into structured application documents based on the target job posting.

### The Reviewer Agent

The **reviewer** is spawned by the `/apply` workflow with a **fresh context** that contains no prior conversation history. According to the orchestration logic in [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md), the reviewer receives the drafts **inline** within its prompt rather than reading them from disk. It conducts external research on the target company, identifies missing keywords, critiques weak framing, and flags generic language that could trigger applicant tracking system (ATS) filters.

## Quality Improvements Through Separation

This architectural split delivers four measurable improvements to final application quality.

### Enhanced Keyword Coverage for ATS Optimization

The reviewer spots critical keywords the drafter initially missed. Because the reviewer focuses exclusively on critique rather than generation, it detects subtle terminology gaps that would otherwise cause rejection by automated ATS filters. The drafter then incorporates these terms during the revision phase, ensuring keyword-dense content without sacrificing readability.

### Company-Specific Tailoring

While the drafter works from static templates, the reviewer actively researches the target organization. This allows the drafter to rewrite opening paragraphs with concrete references to company values, recent projects, or industry position during the second pass. The separation ensures research-informed customization without contaminating the initial drafting context.

### Token Efficiency and Context Management

Only the reviewer receives the full drafts inline; it does not re-read the template files. This design reduces token consumption significantly compared to a monolithic agent that would need to maintain the entire template library, conversation history, and draft content simultaneously. The pattern minimizes API costs while maintaining high output quality.

### PDF Verification and Error Handling

The reviewer's critique triggers a second LaTeX compile pass that catches layout problems before final PDF generation. The [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) script executes a verification loop that confirms contact details appear as literal text in the PDF layer, preventing rendering errors that could disqualify otherwise qualified candidates.

## Implementing the Drafter-Reviewer Workflow

The complete pipeline executes through the `/apply` command documented in the repository's [`README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/README.md). Trigger the workflow by passing a job posting URL:

```bash

# Apply to a Danish Jobindex posting

/apply https://jobindex.dk/job/1234567

```

Internally, [`apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/apply.md) orchestrates the handoff using the **Agent tool** to spawn a `general-purpose` reviewer. The reviewer receives structured drafts inline:

```markdown
Use the **Agent tool** to spawn a `general-purpose` reviewer agent.
Pass the drafts inline in the prompt (no file reads needed):

```

After critique, the drafter applies changes using JSON-encoded edits without re-reading source files:

```json
[
  {
    "file": "cv/main_example.tex",
    "old_string": "Experienced data scientist",
    "new_string": "Senior data scientist with 5 years of experience"
  },
  {
    "file": "cover_letters/cover_example.tex",
    "old_string": "I am excited about the role",
    "new_string": "I am excited about the role at {{CompanyName}} because ..."
  }
]

```

Finally, the drafter executes PDF verification to ensure text renders correctly:

```bash
pdftotext output_cv.pdf - | grep -i "email@example.com"

# Ensures contact details appear as literal text in the PDF layer

```

## Summary

- **Drafter-reviewer separation** splits generation and critique between two Claude Code agents with isolated contexts.
- The **drafter** creates initial LaTeX drafts using [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) and template files ([`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md), [`06-cover-letter-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/06-cover-letter-templates.md)).
- The **reviewer** receives drafts inline with fresh context, researches companies, and provides structured feedback without token-heavy file re-reads.
- This pattern improves **ATS keyword coverage**, enables **company-specific tailoring**, reduces **token costs**, and ensures **error-free PDF output** through verification loops in [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py).
- The workflow is language-agnostic and executes via the `/apply` command defined in [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md).

## Frequently Asked Questions

### How does the drafter-reviewer separation reduce API costs?

The separation eliminates redundant context loading. Only the reviewer receives the draft content inline, while the drafter maintains template context separately. This prevents a single monolithic agent from holding the entire template library, conversation history, and draft content simultaneously, significantly reducing token consumption during the critique and revision phases.

### Why does the reviewer need a fresh context instead of sharing history with the drafter?

A fresh context prevents cognitive contamination. According to the implementation in [`.claude/commands/apply.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/apply.md), spawning the reviewer without prior conversation history enables objective critique unburdened by the drafter's initial assumptions or template constraints. This isolation ensures the reviewer evaluates the drafts as a hiring manager would, spotting gaps that the original author might overlook due to confirmation bias.

### What files does the reviewer read compared to the drafter?

The drafter actively reads [`CLAUDE.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CLAUDE.md) for candidate profiles and both [`05-cv-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/05-cv-templates.md) and [`06-cover-letter-templates.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/06-cover-letter-templates.md) for LaTeX formatting rules. The reviewer receives drafts inline in its prompt and does not re-read these template files. It focuses instead on external company research and critique, making the workflow more efficient by avoiding redundant file I/O operations.

### How does the workflow ensure PDFs render correctly?

The reviewer's feedback triggers a second LaTeX compilation pass before final output. Additionally, [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) executes verification commands like `pdftotext` to confirm that contact details and critical text appear as literal strings in the PDF text layer rather than as images or corrupted encodings, preventing ATS parsing failures.