Architecture

Input Normalization

How Teamcast resolves semantic drift across job inputs, resumes, and transcripts to produce fair, evidence-backed evaluations.

Teamcast's product promise is trustworthy, evidence-backed evaluation. That requires the system to reason on the same vocabulary across every surface — job descriptions, candidate resumes, recruiter edits, and interview transcripts.

Without normalization, the same capability appears in many forms and the system implicitly rewards wording overlap rather than actual skill. A candidate who writes ReactJS and a job that requires React describe the same thing — but an unnormalized system treats them as different.

The Core Problem

Teamcast must distinguish between four different types of evidence for any given skill:

Evidence TypeWhat It MeansWhere It Comes From
What the job asks forRequired capabilities from the hiring intentJob description, skills array
What the candidate claimsSelf-declared skillsResume skills section, summary, qualifications
What the candidate has evidencedSkills with textual proof of useProject bullets, work experience, portfolio
What the candidate demonstrates liveSkills proven in the interview itselfTranscript turns, explanation depth, scenario responses

Without this distinction, the planner asks generic questions and the assessor scores based on wording overlap instead of capability evidence. With it, the planner probes precisely and the assessor scores defensibly.

Canonical Skills and Roles

Teamcast maintains a shared vocabulary of canonical skills and role families that all inputs are mapped to before reaching the planner or assessor.

Canonical Skills

Each canonical skill has a single authoritative name and a list of known aliases. When any input contains a raw term, it is mapped to its canonical form before being used for planning or evaluation.

Example — canonical skill
{
  "canonicalName": "React",
  "aliases": ["ReactJS", "react.js", "react js", "reactjs"],
  "category": "frontend_framework"
}

This means a job that requires React and a candidate who lists ReactJS are correctly treated as a match — no keyword luck required.

Canonical Roles

Job titles drift as much as skill names. Canonical roles map each position title to a role family and role category that drive competency selection. The role taxonomy is maintained by an AI enricher — when an unrecognized title is encountered, the system classifies it using the LLM and stores the result for all future interviews.

Raw TitleRole FamilyRole Category
SDR, BDR, Sales Development Repsdr_bdrsales_gtm
AE, Account Executive, Closing Repaccount_executivesales_gtm
Sales Engineer, Solutions Engineersales_engineersales_gtm
Frontend Dev, UI Engineerfrontend_engineeringengineering
ICU Nurse, Critical Care Nursecritical_care_nursing *healthcare *
Corporate Tax Attorneycorporate_tax_law *legal *

Entries marked * represent AI-enriched classifications. There are no hardcoded limits on which domains the system can interview for — any professional role is supported.

The role category feeds the planner's competency selection. A healthcare role selects appropriate behavioral competencies automatically — no manual configuration is required when expanding to new domains.

Capability Graph

Skills are connected in a capability graph that records which skills are commonly used alongside, prerequisite to, or build upon each other. During normalization, the system traverses this graph to find skills adjacent to those in the job requirements.

Adjacent skills are passed to the planner as context, enabling it to probe technically related areas even when they are not explicitly listed in the job description. The graph is seeded with known technology relationships and self-expands through AI enrichment as new skills are encountered.

Claimed vs Evidenced vs Demonstrated

Not every skill mention carries the same weight. Teamcast explicitly distinguishes three tiers of skill evidence, each stored as a separate artifact on the interview record.

TierMeaningExample Source
ClaimedThe candidate says they know itSkills section, self-declared qualifications, summary line
EvidencedThe candidate has textual proof of using itProject bullets, work experience, portfolio text
DemonstratedThe candidate proves it live in the interviewTranscript turns, explanation depth, scenario responses

These three tiers directly change how the planner behaves and how the assessor scores:

Candidate Status for a Required SkillPlanner Behavior
Evidenced matchAsk deeper, higher-signal technical questions
Claimed-only matchAsk validation questions to test the claim
Missing but adjacent roleProbe transferability
Missing and non-adjacentDeprioritize or flag as a gap
This is where normalization directly improves interview quality. The interviewer no longer asks the same generic questions for every candidate — it calibrates to what each candidate has actually demonstrated.

Interview Record Artifacts

Every interview record persists a set of normalization artifacts from the moment it is created. These are immutable once written and available on any GET /interviews/:id response.

FieldTypeDescription
rawPayloadJSONExact original input as received — never modified
canonicalPayloadJSONNormalized, structured form used by planner and assessor
diffReportJSONField-level delta showing what changed during normalization
candidateClaimedSkillsstring[]Skills the candidate self-declares (resume skills / qualifications section)
candidateEvidencedSkillsstring[]Skills with project / work-experience evidence in the resume text
candidateDemonstratedSkillsstring[]Skills proven live in the interview (written by assessor after completion)
Example — interview record (normalization fields)
{
  "id": "interview-uuid",
  "candidateClaimedSkills": ["React", "TypeScript", "Node.js"],
  "candidateEvidencedSkills": ["React", "TypeScript"],
  "canonicalPayload": {
    "position": "Senior Frontend Engineer",
    "skills": ["React", "TypeScript", "Node.js"],
    "level": "SENIOR"
  },
  "diffReport": {
    "skills[0]": { "before": "ReactJS", "after": "React" },
    "skills[1]": { "before": "TS", "after": "TypeScript" }
  },
  "rawPayload": {
    "position": "Sr Frontend Engineer",
    "skills": ["ReactJS", "TS", "NodeJS"]
  }
}
The diffReport is useful for recruiter transparency — it shows exactly what the system changed and why, without hiding the normalization behind a black box.

How This Affects the Assessor

After the interview, the assessor scores based on canonical skills linked to transcript evidence spans — not raw wording. Each skill in the assessment report maps to specific turns in the transcript where the candidate addressed it.

Example — evidence-backed assessment scoring
{
  "skill": "React",
  "evidence": [
    { "turn": 4, "quote": "I built the component library using React hooks..." },
    { "turn": 11, "quote": "We migrated from class components in that project..." }
  ],
  "score": 3,
  "maxScore": 4
}

This makes assessment results auditable. Recruiters can answer the question “why did this candidate score 3/4 on React?” by pointing to specific transcript evidence — not a generic summary.

Resume Parsing

Resumes submitted during interview creation are parsed to extract structured text before normalization is applied. This feeds both the claimed and evidenced skill extraction.

Input FormatSupported
PDFYes
DOCX / WordYes
Plain text (.txt)Yes

Use POST /api/v1/interviews/parse-resume to extract text from a resume file before creating an interview. See the Interviews API reference for the full endpoint details.

Normalization is applied symmetrically — the same canonical vocabulary and mapping rules apply to job inputs, candidate resumes, and interview transcripts. This prevents the system from creating false capability gaps when the job and candidate describe the same skill differently.
Was this page helpful?