How Bonus Points and Deductions Are Handled in Hiring Agent’s Resume Evaluation

Bonus points are additive rewards capped at 20 points, while deductions are subtractive penalties, both processed in score.py after LLM evaluation and constrained within a -20 to 120 final score range.

The interviewstreet/hiring-agent repository implements a structured scoring pipeline where an LLM evaluates resumes against specific criteria and returns extra rewards or penalties. These adjustments are formally defined in the data models, aggregated during score calculation, and displayed in the final candidate report.

Evaluation Schema Definitions

The contract between the LLM evaluator and the scoring engine is defined in models.py, which mandates two specific objects in the JSON response: bonus_points and deductions.

BonusPoints Model

The BonusPoints schema requires a total integer bounded between 0 and 20 (ge=0, le=20) and a breakdown list explaining the awards. According to the source code in models.py (lines 31-34), this acts as a strictly limited additive boost to the candidate’s score.

Deductions Model

The Deductions schema defined in models.py (lines 36-41) contains a non-negative total (ge=0) and a reasons list. Unlike bonus points, this value represents a positive number that the scoring logic will later subtract from the cumulative score.

Score Aggregation Logic

After the ResumeEvaluator receives the LLM’s EvaluationData response, the calculation moves to score.py, where category scores are first summed, then modified by these adjustments.

Adding Bonus Points

The code checks for the presence of bonus points before applying them:


# Add category scores → total_score

# ...

# Add bonus points

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

This logic appears in score.py (lines 57-60), ensuring only valid bonus objects contribute to the total.

Subtracting Deductions

Deductions are processed immediately after bonuses in score.py (lines 62-64):


# Subtract deductions

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

This operation treats the deduction total as a penalty value to be removed from the running score.

Final Score Constraints

Once bonuses and deductions are applied, the aggregate is clamped to enforce business rules defined in evaluator.py (lines 9-12). The final score:

  • Cannot exceed 120 (the sum of category maximums plus the 20-point bonus ceiling)
  • Cannot fall below -20 (the defined minimum final score)

This prevents edge cases where excessive deductions or bonuses might distort the evaluation unfairly.

User-Visible Output

The final report renders these adjustments for human review:

  • Bonus points display as the raw total alongside the textual breakdown from the LLM
  • Deductions appear as a negative line item accompanied by the specific reasons provided by the evaluator

Summary

  • Bonus points are strictly bounded (0–20) and defined in models.py (lines 31-34)
  • Deductions are non-negative values stored in models.py (lines 36-41) and subtracted during calculation
  • score.py handles the arithmetic: lines 57-60 add bonuses, lines 62-64 subtract deductions
  • Final scores are capped between -20 and 120 according to constraints in evaluator.py (lines 9-12)
  • Both adjustments appear with detailed explanations in the evaluation report

Frequently Asked Questions

What is the maximum bonus points a candidate can receive?

The BonusPoints.total field is constrained to a maximum of 20 points with a minimum of 0, as enforced by the Pydantic model in models.py. This hard limit prevents over-inflation of scores regardless of the LLM’s assessment.

How are deduction values treated if the final score becomes negative?

The scoring logic in evaluator.py implements a floor of -20 for the final result. Even if cumulative deductions would mathematically push the score lower, the value is clamped to this minimum threshold before being recorded or displayed.

Why does the Deductions model use a non-negative constraint if it represents a penalty?

The schema enforces ge=0 (greater than or equal to zero) to ensure data integrity—the value stored is a positive magnitude of points lost. The sign conversion happens during aggregation in score.py, where the code explicitly subtracts this positive value from the running total.

Where can I modify the bonus point ceiling or deduction logic?

To adjust the 20-point bonus cap, edit the le=20 validator in models.py (lines 31-34). To change how deductions affect the total, modify the subtraction logic in score.py (lines 62-64). Always verify that corresponding constraints in evaluator.py are updated to reflect new score boundaries.

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 →