Back to portfolio
SERVICE · port 8004 · live

Resume Builder

Paste a job description, click Tailor, get a polished PDF in under a minute. Behind the curtain: a single-stage Opus call constrained by a strict JSON schema, a Redis-backed job queue, Memory Archive context lookup for past-job detail, and a non-negotiable rule that the JSON pipeline is never overwritten with markdown.

Generation pipeline

One Opus call, four boundaries. Each boundary fails loud.

Why single-stage Opus

Earlier iterations chained: Sonnet draft → Opus polish → Sonnet shrink. Cheaper per call, more retries, more drift, more places for the JSON contract to slip into markdown. The single-stage Opus version trades dollars for determinism — one prompt, one schema, one pass, one PDF.

The cost ledger says it's worth it: median spend per resume is well below the value of getting a clean output every time.

Components

Web form
paste JD · select base · go
Authenticated form. Accepts a job description and a base-résumé identifier; everything else is server-side. Optimistic UI with progress polling.
Flask progress polling
Redis job queue
RQ · single worker
One job per resume. Worker picks it up, hits MA for past-job detail, calls Opus, validates, renders. Queue depth + age are exposed for monitoring.
Redis RQ single worker
Memory Archive context
past-job detail · recall
Pulls indexed memories for prior roles, projects, and metrics so Opus tailors with real specifics — not invented numbers. If the memory isn't there, the line isn't generated.
MCP hybrid_search
Opus + JSON schema
single-stage · structured
One call, one schema. Tool-use forces a JSON object: summary, experience[], skills[], education[]. No prose escapes. If the response doesn't validate, retry — never silently coerce.
Claude Opus tool use JSON schema
Validator
no-markdown rule
Strict no-markdown sentinel: validator rejects backticks, bold markers, list dashes anywhere in the JSON values. Past incident: a single stray **bold** meant a dozen broken PDFs in production. Now it's an explicit guardrail.
jsonschema post-validate
PDF renderer
WeasyPrint · LaTeX-ish CSS
Renders the validated JSON through a hand-tuned HTML/CSS template. Letter and A4 paths. Embedded fonts. ATS-readable; no clever tricks that break parsers.
WeasyPrint ATS-safe
Cost row + audit trail
PostgreSQL · per-resume
Each generation writes a row: input/output tokens, model, latency, dollars, success bool, and the JSON itself. Lets the FinOps Agent flag cost regressions and lets me regenerate any past resume from its exact inputs.
FinOps audit re-runnable

Hard-won rules

JSON pipeline never gets overwritten with markdown
Listed in the standing-corrections file. Every layer enforces it; the validator is the last line. Saved hours of debugging on the day a prompt-tweak introduced a single backtick.
Don't invent specifics
If a memory isn't there, the bullet isn't generated. False precision is the worst kind of failure for a tailored resume.
Single worker on the queue
Anthropic rate limits + cost predictability beat throughput. One resume at a time, every time.
Re-runnable from history
Every input is in the cost ledger. If a template changes, regenerating a past resume is one query away. Audit trail = recovery tool.

More of the system

Resume Builder is one of 11 services. Memory Archive holds the past-job memories it depends on; the agentic-framework provides the Opus client; the deployment pipeline ships changes safely.