How Bonus Points and Deductions Work in the Hiring Agent Scoring System

Bonus points add up to 20 points to a candidate’s final score, while deductions subtract penalties from the cumulative total, with both values hard-capped between -20 and 120 according to the evaluator constraints.

The Hiring Agent scoring system evaluates candidates by combining LLM-generated assessments with structured bonus points and deductions mechanisms. According to the interviewstreet/hiring-agent source code, the ResumeEvaluator processes resumes through a strict schema that defines how extra credit and demerits modify the final numeric outcome. This article explains the exact calculation logic, constraints, and file locations governing these score adjustments.

LLM-Generated Evaluation Schema

The ResumeEvaluator class prompts the LLM with specific scoring criteria that must return a structured JSON response. This response must contain two dedicated objects: bonus_points and deductions.

The bonus_points object requires a total field and a breakdown field, while the deductions object requires a total field and a reasons list. These schemas are strictly enforced through Pydantic models to ensure data integrity before score calculation begins.

Data Model Constraints in models.py

The schema definitions and validation rules reside in models.py, where Pydantic constraints enforce hard limits on both values.

BonusPoints Structure

The BonusPoints model is defined in models.py between lines 31 and 34. It enforces the following constraints:

  • total: Integer bounded between 0 and 20 (ge=0, le=20)
  • breakdown: Textual explanation of why points were awarded

This 20-point ceiling represents the maximum additive boost available to any candidate.

Deductions Structure

The Deductions model is defined in models.py between lines 36 and 41. It specifies:

  • total: Non-negative integer (ge=0) that will be subtracted from the final score
  • reasons: List of textual explanations for each penalty

Note that deductions are stored as positive values but are always subtracted during aggregation.

Score Aggregation Logic in score.py

After the LLM returns an EvaluationData instance, the score calculation logic in score.py applies the adjustments. The specific handling occurs at lines 57-60 for bonuses and lines 62-64 for deductions.


# Add category scores → total_score

# ...

# Add bonus points

if hasattr(evaluation, "bonus_points") and evaluation.bonus_points:
    total_score += evaluation.bonus_points.total

# Subtract deductions

if hasattr(evaluation, "deductions") and evaluation.deductions:
    total_score -= evaluation.deductions.total

Adding Bonus Points

The code checks for the existence of bonus_points on the evaluation object. If present, it adds the total value directly to the cumulative score derived from category assessments.

Subtracting Deductions

Similarly, the logic validates the presence of deductions and subtracts the total value from the running total. This occurs after all category scores and bonuses have been summed.

Final Score Constraints and Capping

After adding bonuses and subtracting deductions, the system applies hard limits to prevent extreme values. The maximum possible score equals the sum of all category maximums plus the full 20-point bonus ceiling. The minimum final score is -20.

These boundaries are defined as constants in evaluator.py between lines 9 and 12. The final score is clamped to ensure it never exceeds 120 points and never drops below -20, regardless of the LLM’s output.

Report Output Format

The user-visible evaluation report displays these adjustments transparently. The raw bonus total appears alongside its textual breakdown, showing exactly which criteria earned extra credit. Deductions render as negative amounts with a bulleted list of reasons, providing full auditability for the final score.

Summary

  • Bonus points are capped at 20 points and added to the cumulative category scores during final calculation.
  • Deductions are positive values stored in the Deductions model that are subtracted from the total score in score.py.
  • Final scores are clamped between -20 and 120 as defined in evaluator.py to maintain evaluation consistency.
  • Both adjustments are stored in the EvaluationData model with full breakdowns and reasons for complete transparency.

Frequently Asked Questions

What is the maximum number of bonus points a candidate can receive?

The BonusPoints.total field in models.py enforces a hard ceiling of 20 points using Pydantic constraints (ge=0, le=20). The LLM cannot assign more than this value, and any attempt to exceed it fails validation at the schema level.

How are deductions applied to the final score in Hiring Agent?

Deductions are stored as positive integers in the Deductions.total field. During the aggregation phase in score.py (lines 62-64), the system subtracts this value from the cumulative score. The reasons list accompanies each deduction to explain why the penalty was applied.

Where are the score limits defined in the Hiring Agent codebase?

The minimum final score of -20 and maximum of 120 are defined as constants in evaluator.py between lines 9 and 12. These values act as absolute floors and ceilings after all bonuses and deductions have been calculated.

What happens if the LLM returns a bonus or deduction outside the allowed range?

The Pydantic models in models.py validate inputs at ingestion time. Any bonus_points.total exceeding 20 or any negative deductions.total value triggers a validation error before the data reaches the calculation logic in score.py, ensuring only compliant values enter the scoring pipeline.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →