Jev Case Study: Resume Fit Scoring vs a JD (Full Code)

Updated Applies to Jev 1.13 Example fixture

TL;DR: This Jev example scores resume-to-job-description fit with one scoring question on Jev 1.13: a 1-10 answer, a confidence value, and a one-sentence rationale a recruiter can audit. Full request, example-fixture response, and runnable Python below.

Scenario

A single opening at our company pulls in 200+ applications. A recruiter’s first pass — open resume, read against the JD, write a note — costs ten minutes per candidate, and the quality of that pass drifts by Friday afternoon. We did not want to automate the hiring decision; we wanted to automate the first-pass note: a fit score and a sentence explaining it, on every application, before a human looks.

The tool we reached for is Jev — TypeSafe AI’s System One judgment model, released September 2026 — used as a scoring question:

Score how well this resume fits this job description, on a scale of 1 to 10.

What comes back is typed JSON: answer (the score), scale, confidence, and a rationale. Compared with pointing a general chat model at the same task — the setup our Jev vs LLM-as-a-judge guide covers in depth — the difference is operational: the answer arrives in a fixed shape with a confidence value, so the fallback rule (“low confidence → second look by a human”) is a comparison, not a parsing exercise. We are not asking for a cover letter; we are asking for a number we can sort by, with evidence attached.

One policy note that matters more than any prompt: the score gates nobody automatically. It orders the queue and flags mismatches. Humans decide.

Request

{
  "model": "typesafe/jev-1.13",
  "messages": [
    {
      "role": "system",
      "content": "Scoring question. Score how well the resume fits the job description, on a scale of 1 to 10. Reply with JSON only: {\"answer\": <1-10>, \"scale\": [1, 10], \"confidence\": <0-1>, \"rationale\": <one sentence>}"
    },
    {
      "role": "user",
      "content": "Job description:\nSenior Backend Engineer: 5+ years of Python, PostgreSQL, Kubernetes. Owns payment services. Remote-friendly, EU time zones.\n\nResume:\n8 years backend, mostly Python and Go. Ran the billing platform at a fintech: PostgreSQL at 2TB, deployed on Kubernetes. Based in Berlin. Last role: Staff Engineer, payments."
    }
  ]
}

Response

Example fixture — illustrative output, not a live capture:

{
  "answer": 8,
  "scale": [1, 10],
  "confidence": 0.86,
  "rationale": "Exceeds the Python and payments-service requirements and matches the Kubernetes and EU-location criteria, with less evidence of day-to-day PostgreSQL ownership at scale."
}

The rationale is the part recruiters actually read. It names what pushed the score up and what held it back — which is what a good first-pass note looks like anyway.

Reproduce

Save as fit.py, set OPENROUTER_API_KEY, and run python3 fit.py:

import json, os, urllib.request

URL = "https://openrouter.ai/api/v1/chat/completions"
MODEL = "typesafe/jev-1.13"  # confirm exact slug on the OpenRouter model page

JD = """Senior Backend Engineer: 5+ years of Python, PostgreSQL,
Kubernetes. Owns payment services. Remote-friendly, EU time zones."""

RESUME = """8 years backend, mostly Python and Go. Ran the billing
platform at a fintech: PostgreSQL at 2TB, deployed on Kubernetes.
Based in Berlin. Last role: Staff Engineer, payments."""

SYSTEM = ('Scoring question. Score how well the resume fits the job '
          'description, on a scale of 1 to 10. Reply with JSON only: '
          '{"answer": <1-10>, "scale": [1, 10], "confidence": <0-1>, '
          '"rationale": <one sentence>}')

body = {"model": MODEL, "messages": [
    {"role": "system", "content": SYSTEM},
    {"role": "user", "content": "Job description:\n" + JD + "\n\nResume:\n" + RESUME}]}

req = urllib.request.Request(URL, data=json.dumps(body).encode(),
    headers={"Authorization": "Bearer " + os.environ["OPENROUTER_API_KEY"],
             "Content-Type": "application/json"})

with urllib.request.urlopen(req) as res:
    payload = json.load(res)

result = json.loads(payload["choices"][0]["message"]["content"])
print(result["answer"], result["confidence"])
print(result["rationale"])

Key parameters

FieldValueWhy it matters
modeltypesafe/jev-1.13Pin the version so scores are comparable across the whole applicant pool. Confirm the exact slug on the OpenRouter model page.
messages[0] (system)Scoring question + scale + JSON shapeA fixed rubric (1-10) plus fixed output shape keeps scores sortable.
messages[1] (user)JD then resume, labeledLabel both blocks explicitly; unlabeled text invites the model to guess which is which.
answer (response)8The sort key for the application queue.
scale (response)[1, 10]Echoes the rubric; a cheap sanity check per call.
confidence (response)0.86 (example fixture)Low-confidence scores go back to the top of the human pile, not the bottom.
rationale (response)One sentenceThe auditable first-pass note.
Price$0.0462 per 1M input tokensOne call per application; verify current pricing on OpenRouter before budgeting.

Notes

Keep reading