# Hiring Agent Scoring Weights and Calculation Methods: Open Source, Self-Projects, Production & Technical Skills

> Discover Hiring Agent scoring weights and calculation methods for open source, self projects, production, and technical skills. Learn how the 100-point system works.

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

---

**The Hiring-Agent uses a 100-point core scoring system with fixed category weights (Open Source 35, Self-Projects 30, Production 25, Technical Skills 10), caps raw scores at these maximums in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py), and allows up to 20 bonus points for a maximum possible total of 120.**

The **interviewstreet/hiring-agent** repository implements a résumé evaluation engine that quantifies candidate quality across four distinct dimensions. Understanding these scoring weights and the precise calculation methods used to aggregate them is essential for interpreting evaluation results or extending the system. The scoring logic resides primarily in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py), with data structures defined in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py).

## Category Weights and Maximum Points

The system assigns fixed maximum values to each of the four core evaluation categories. These weights are hardcoded in the `category_maxes` dictionary inside [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) (lines 85-93):

```python

# score.py – category maximums

category_maxes = {
    "open_source": 35,
    "self_projects": 30,
    "production": 25,
    "technical_skills": 10,
}

```

This configuration yields a **total core maximum of 100 points**, distributed as follows:

- **Open Source**: 35 points (35% of core score)
- **Self-Projects**: 30 points (30% of core score)
- **Production Experience**: 25 points (25% of core score)
- **Technical Skills**: 10 points (10% of core score)

## Calculation Methods and Scoring Flow

The calculation process involves four distinct stages: capping raw LLM-generated scores, summing the core total, applying bonuses and deductions, and enforcing a final ceiling.

### Raw Score Capping

The `ResumeEvaluator` produces raw scores for each category, but the system enforces hard caps during aggregation. For every category, the logic takes the minimum of the raw score and the configured weight:

```python
capped_score = min(category_score.score, category_maxes[category_name])

```

This ensures that no single category can exceed its allocated weight, even if the LLM evaluator assigns a higher raw value.

### Bonus and Deduction Handling

After capping, the system incorporates optional adjustments:

- **Bonus points**: Added from `evaluation.bonus_points.total` (maximum 20 points)
- **Deductions**: Subtracted from `evaluation.deductions.total` (stored as positive numbers and subtracted from the total)

### Final Total Calculation

The `print_evaluation_results` function in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) (lines 48-77) implements the complete aggregation logic:

```python

# score.py – overall calculation (excerpt)

total_score = 0
max_score = 0
for category_name, category_data in evaluation.scores.model_dump().items():
    category_score = min(category_data["score"], category_data["max"])
    total_score += category_score
    max_score += category_data["max"]

# add bonus

if evaluation.bonus_points:
    total_score += evaluation.bonus_points.total

# subtract deductions

if evaluation.deductions:
    total_score -= evaluation.deductions.total

# cap to max possible (core max + 20 bonus)

max_possible_score = max_score + 20
total_score = min(total_score, max_possible_score)

```

The final result is clamped to **120 points** (100 core + 20 bonus maximum), preventing runaway scores from exceptional bonus claims.

## Data Models and Implementation

The scoring system relies on Pydantic models defined in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py). The `Scores` class encapsulates the four categories, each containing a raw score, maximum value, and evidence text:

```python

# models.py – Scores definition

class Scores(BaseModel):
    open_source: CategoryScore
    self_projects: CategoryScore
    production: CategoryScore
    technical_skills: CategoryScore

```

While the `CategoryScore` objects carry their own `max` fields from the LLM response, the `print_evaluation_results` function overrides these with the hardcoded `category_maxes` values to ensure consistency.

## Practical Code Examples

### Manual Total Score Calculation

You can replicate the library's capping and aggregation logic manually:

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

# Example raw evaluation (normally produced by the LLM)

raw = EvaluationData(
    scores=Scores(
        open_source=CategoryScore(score=40, max=35, evidence="10+ PRs"),
        self_projects=CategoryScore(score=28, max=30, evidence="2 personal apps"),
        production=CategoryScore(score=22, max=25, evidence="3 years at Acme"),
        technical_skills=CategoryScore(score=12, max=10, evidence="Node, React")
    ),
    bonus_points=BonusPoints(total=15, breakdown="Outstanding teamwork"),
    deductions=Deductions(total=5, reasons="Resume formatting issues"),
    key_strengths=["Leadership", "Problem solving"],
    areas_for_improvement=["Public speaking"]
)

# Apply the same capping logic as the library

category_maxes = {"open_source": 35, "self_projects": 30,
                 "production": 25, "technical_skills": 10}

core_total = sum(
    min(getattr(raw.scores, cat).score, category_maxes[cat])
    for cat in category_maxes
)

total = core_total + raw.bonus_points.total - raw.deductions.total
max_possible = sum(category_maxes.values()) + 20   # 120

total = min(total, max_possible)

print(f"Final score: {total}/{max_possible}")

# → Final score: 115/120

```

### Using the Library's Helper Function

For production use, invoke the built-in formatter which automatically applies all weights and caps:

```python
from score import print_evaluation_results

print_evaluation_results(raw, candidate_name="Alice Example")

```

This function enforces the category maximums, handles bonus/deduction arithmetic, and generates the formatted report used by the CLI.

## Summary

- **Fixed weights**: Open Source (35), Self-Projects (30), Production (25), and Technical Skills (10) are defined in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) as `category_maxes`.
- **Capping mechanism**: Raw LLM scores are capped at their category maximums using `min()` before aggregation.
- **Bonus ceiling**: The system supports up to 20 bonus points, creating a theoretical maximum of 120 points.
- **Core logic**: The `print_evaluation_results` function in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) orchestrates the calculation, handling deductions and final ceiling enforcement.
- **Data structure**: The `Scores` model in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) carries the raw evaluation data, but the hardcoded weights always take precedence during calculation.

## Frequently Asked Questions

### What is the maximum possible score in the Hiring Agent?

The maximum possible score is **120 points**: 100 points from the four core categories (Open Source 35 + Self-Projects 30 + Production 25 + Technical Skills 10) plus up to 20 bonus points. The final total is explicitly capped at this value in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) to prevent overflow from excessive bonus claims.

### How does the system prevent category scores from exceeding their weights?

The system applies a hard cap during the aggregation phase in `print_evaluation_results`. For each category, it calculates `min(category_data["score"], category_maxes[category_name])`, ensuring that even if the LLM evaluator assigns 50 points to Open Source, only 35 points contribute to the final total.

### Where are the scoring weights defined in the codebase?

The weights are defined as a dictionary named `category_maxes` in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) at lines 85-93. This central configuration maps category names to their integer maximums and serves as the single source of truth for all scoring calculations in the repository.

### Can the category weights be customized or configured?

Currently, the weights are hardcoded as constants in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py). To modify them, you must edit the `category_maxes` dictionary in the source code and adjust the bonus ceiling constant (20) if desired. There is no external configuration file or environment variable override implemented in the current version of the repository.