# Validation Rules Pydantic Models Enforce for Scores in Hiring-Agent

> Discover Pydantic validation rules for scores in the hiring-agent model. Learn how models enforce non-negative scores, bonus point limits, and feedback list constraints, preventing invalid data.

- Repository: [HackerRank/hiring-agent](https://github.com/interviewstreet/hiring-agent)
- Tags: deep-dive
- Published: 2026-07-07

---

**The hiring-agent repository uses Pydantic Field constraints in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) to enforce that scores are non-negative, bonus points never exceed 20, deductions remain positive, and feedback lists contain 1-5 items, automatically raising `ValidationError` on any violation.**

The interviewstreet/hiring-agent project relies on Pydantic models to maintain data integrity throughout its resume evaluation pipeline. Understanding the specific validation rules Pydantic models enforce for scores ensures that downstream scoring logic operates on clean, predictable data structures.

## Core Validation Rules in CategoryScore

The `CategoryScore` model defined in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) (lines 218-222) applies strict constraints to individual category evaluations.

### Non-Negative Score Floors

The `score` field uses `ge=0` to guarantee that no category receives a negative value. This constraint prevents the evaluator from assigning impossible point totals when assessing resume sections.

### Positive Maximum Boundaries

The `max` field enforces `gt=0`, ensuring every category defines a valid positive upper limit. This rule eliminates zero or negative maximums that would break percentage calculations later in the pipeline.

### Mandatory Evidence Strings

The `evidence` field requires `min_length=1`, forcing the evaluator to provide at least one character of supporting documentation. Empty strings trigger immediate validation failures.

## Bonus Points and Deductions Validation

The system caps adjustments to the final score through dedicated models.

### Capping Bonus Points

In `BonusPoints` (lines 32-34), the `total` field combines `ge=0` with `le=20` to restrict bonus contributions between 0 and 20 points inclusive. This hard limit prevents the bonus system from overwhelming the base category scores.

### Deductions Safety Checks

The `Deductions` model (lines 36-41) applies `ge=0` to the `total` field, ensuring deductions remain positive numbers. The system stores these as positive values and applies them negatively during final calculation, preventing accidental score inflation.

## List Size Constraints in EvaluationData

The top-level `EvaluationData` container enforces cardinality rules on feedback lists.

### Key Strengths Limits

The `key_strengths` field requires `min_items=1` and `max_items=5`, ensuring candidates receive at least one highlighted strength without overwhelming reviewers with excessive entries.

### Improvement Areas Limits

Similarly, `areas_for_improvement` uses identical bounds (1-5 items) to guarantee constructive feedback while maintaining review conciseness.

## Practical Implementation Examples

When consuming these models, validation occurs automatically during instantiation.

```python
from models import CategoryScore, BonusPoints, Deductions, EvaluationData

# Valid construction

category = CategoryScore(score=27.5, max=35, evidence="5 open-source projects")
bonus = BonusPoints(total=12.0, breakdown="Leadership +2, Community +10")
deductions = Deductions(total=3.0, reasons="Missing repository links")

evaluation = EvaluationData(
    scores={"technical": category},
    bonus_points=bonus,
    deductions=deductions,
    key_strengths=["Communication", "Architecture"],
    areas_for_improvement=["Documentation"]
)

# Invalid construction raises ValidationError

try:
    invalid = CategoryScore(score=-5, max=0, evidence="")
except Exception as e:
    print(e)  # Multiple constraint violations reported

```

## Summary

- **CategoryScore** enforces non-negative scores, positive maximums, and non-empty evidence in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) lines 218-222.
- **BonusPoints** limits total bonuses to 0-20 points (lines 32-34).
- **Deductions** ensures positive deduction values (lines 36-41).
- **EvaluationData** restricts feedback lists to 1-5 items each (lines 48-50).
- All rules trigger `ValidationError` immediately upon instantiation, protecting the [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) calculation logic from invalid inputs.

## Frequently Asked Questions

### What happens when a Pydantic validation rule is violated in the hiring-agent?

Pydantic raises a `ValidationError` exception immediately when constructing any model instance with invalid data. The surrounding application code in [`evaluator.py`](https://github.com/interviewstreet/hiring-agent/blob/main/evaluator.py) can catch this exception to handle malformed evaluator output before it reaches the scoring logic.

### Why is the bonus total capped at 20 points in the scoring system?

The `le=20` constraint on `BonusPoints.total` prevents excessive bonus inflation from dominating the final score calculation. This ensures that base category scores remain the primary evaluation factor while still rewarding exceptional candidates with up to 20 additional points.

### How does the CategoryScore model prevent negative scores?

The `score` field uses Pydantic's `ge=0` constraint (greater than or equal to 0), which rejects any negative float values during instantiation. This guarantees that all category contributions remain positive throughout the evaluation pipeline.

### Where are the validation rules defined in the repository?

All validation constraints reside in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) at the repository root. Specific line references include lines 218-222 for `CategoryScore`, lines 32-34 for `BonusPoints`, lines 36-41 for `Deductions`, and lines 48-50 for `EvaluationData` list constraints.