Candidate Canonical Data Model
A structured candidate profile: experience, normalized skills with proficiency, education, work authorization, preferences, and AI enrichment — embeddings, seniority, generated summaries.
schema.json →One canonical shape for candidates, jobs, matches, and sync — so every résumé parser, ATS, job board, and LLM agent can finally speak the same language.
npm install @agent-resume/schemas
A résumé leaves a parser as one shape, lands in an ATS as another, gets re-shaped for a job board, and is flattened again before it ever reaches a model. Every integration is a bespoke mapping, every matching engine reinvents "what is a skill," and every LLM agent is handed a slightly different blob of JSON.
There's a good standard for the human résumé —
JSON Resume — but nothing canonical for the parts
machines now care about: normalized skills, requirement levels, knock-out logic,
match scores, model evaluations, and the events that keep two systems in sync.
agent-resume is that missing layer.
Strict draft-07 JSON Schema, additionalProperties: false, semver-versioned $ids — with mirror TypeScript types and Ajv validators.
A structured candidate profile: experience, normalized skills with proficiency, education, work authorization, preferences, and AI enrichment — embeddings, seniority, generated summaries.
schema.json →A structured posting: company, comp, responsibilities, and requirements tagged by level — Knock-Out / Required / Preferred / Optional.
schema.json →A deterministic algorithmic score (always present) plus an optional LLM evaluation — recommendation, rationale, and requirement-by-requirement analysis.
schema.json →An HMAC-authenticated webhook envelope for cross-system sync, covering 18 event types across candidates, jobs, applications, matches, evaluations, and scrapes.
schema.json →JD-CDM tags every requirement with one of four levels. This is what lets a matcher reason instead of keyword-count.
| Level | Meaning | Effect on matching |
|---|---|---|
| Knock-Out | Hard gate (work authorization, an active clearance). | Failing one sets knock_out_passed: false — the candidate does not advance, regardless of score. |
| Required | Must-have to be competitive. | Heavily weighted; gaps surface as critical. |
| Preferred | Strong plus. | Moderately weighted; raises the ceiling. |
| Optional | Nice to have. | Lightly weighted; tie-breaker only. |
Validate, convert, and sign — in a few lines.
import {
validateCCDM,
ccdmToJsonResume,
signPayload,
verifyPayload,
type CCDM,
} from "@agent-resume/schemas";
// 1. Validate a parsed candidate against the canonical model.
const candidate = validateCCDM(parsedResume) as CCDM;
// 2. Export it to JSON Resume for any downstream renderer.
const resume = ccdmToJsonResume(candidate);
// 3. Ship a sync event with a tamper-proof signature.
const { header } = signPayload(body, process.env.WEBHOOK_SECRET);
// ...and verify on the receiving end:
const ok = verifyPayload(rawBody, signatureHeader, secret);
JSON Resume is the standard for the human-facing résumé. CCDM is a superset built for machines and the rest of the pipeline. Adopting it is additive, and ccdmToJsonResume() exports back anytime.
| JSON Resume | agent-resume (CCDM) | |
|---|---|---|
| Primary audience | Humans rendering a résumé | Parsers, ATS, matchers, LLM agents |
| Scope | The résumé document | Candidate + job + match + sync |
| Skills | Free-text name + keywords | Normalized skill, proficiency, years |
| Requirement levels | — | Knock-Out / Required / Preferred / Optional |
| Matching & evaluation | — | First-class MatchObject |
| AI enrichment | — | Embeddings, seniority, semantic keywords |
| Interop | — | ccdmToJsonResume() |
It's a community standard — proposals, adapters, and new language bindings are all welcome.