Jev Case Study: Resume Fit Scoring vs a JD (Full Code)
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
| Field | Value | Why it matters |
|---|---|---|
model | typesafe/jev-1.13 | Pin 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 shape | A fixed rubric (1-10) plus fixed output shape keeps scores sortable. |
messages[1] (user) | JD then resume, labeled | Label both blocks explicitly; unlabeled text invites the model to guess which is which. |
answer (response) | 8 | The 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 sentence | The auditable first-pass note. |
| Price | $0.0462 per 1M input tokens | One call per application; verify current pricing on OpenRouter before budgeting. |
Notes
- Responses are example fixtures; verify field names against official docs before relying on them. Official API details live at typesafe.ai — see the System One announcement post.
- Confirm the exact model slug (
typesafe/jev-1.13) on the OpenRouter model page before shipping. - HR data is sensitive: send only what the score needs, follow your data-processing rules, and check where your OpenRouter requests are processed.
- Audit for bias before trusting the ordering: run a fixture set through the scorer and read the rationales for anything demographic leaking into scoring.
- Applies to Jev 1.13 (released September 2026) via the OpenRouter demonstration channel.