# Rules for Generating Key Strengths and Areas for Improvement in Hiring-Agent

> Discover the rules for generating key strengths and areas for improvement in Hiring-Agent. Learn how Pydantic validation and automatic trimming ensure data integrity.

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

---

**The Hiring-Agent repository enforces strict 1-to-5 item limits on both `key_strengths` and `areas_for_improvement` using Pydantic validation in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py), with [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py) handling automatic trimming of excess LLM output.**

In the **interviewstreet/hiring-agent** repository, candidate evaluations rely on structured extraction of feedback into two critical fields: `key_strengths` and `areas_for_improvement`. These fields are strictly governed by validation rules defined in the `EvaluationData` model to ensure consistent, consumable output across CSV exports and UI rendering. The constraints ensure that every evaluation contains actionable feedback while preventing unbounded list sizes that could overwhelm downstream systems.

## Pydantic Validation Constraints in models.py

The data model definition in [`main/models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/models.py) (lines 48-49) specifies both fields as `List[str]` with explicit boundaries using Pydantic's `Field` parameters:

- **Minimum items:** 1 (prevents empty feedback)
- **Maximum items:** 5 (caps the output for readability)

If instantiation attempts violate these bounds, Pydantic raises a `ValidationError` immediately, preventing invalid data from propagating to export or display functions.

## Extraction and Trimming Logic in transform.py

When the LLM (Ollama or Gemini) returns textual evaluations, [`main/transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/transform.py) handles the parsing. Around line 730, the extraction routine implements defensive trimming to enforce the generation rules:

1. **Parsing:** Bullet-point lists are extracted from the LLM response text
2. **Truncation:** If more than five items are detected, only the first five are retained
3. **Validation:** The trimmed list is passed to the `EvaluationData` constructor

This ensures the 1-to-5 constraint is satisfied even when LLMs generate excessive content, while guaranteeing at least one item is present to avoid validation failures.

## Practical Implementation Example

The following example demonstrates a valid `EvaluationData` instantiation that complies with the constraints:

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

# Example of a correctly‑shaped EvaluationData instance

evaluation = EvaluationData(
    scores=Scores(
        open_source=CategoryScore(score=8.5, max=10, evidence="Contributed to 3 OSS projects"),
        self_projects=CategoryScore(score=7.0, max=10, evidence="Built a personal web app"),
        production=CategoryScore(score=6.5, max=10, evidence="2 years in a SaaS company"),
        technical_skills=CategoryScore(score=9.0, max=10, evidence="Strong Python/ML background")
    ),
    bonus_points=BonusPoints(total=4.0, breakdown="Fast learner, good communication"),
    deductions=Deductions(total=1.5, reasons="Minor gaps in CI/CD knowledge"),
    # **Rules enforced here** – between 1 and 5 items each

    key_strengths=[
        "Excellent problem‑solving ability",
        "Strong grasp of data structures",
        "Effective collaboration in remote teams"
    ],
    areas_for_improvement=[
        "Gain deeper experience with cloud deployments",
        "Increase familiarity with testing frameworks"
    ]
)

print(evaluation.json(indent=2))

```

Running this snippet yields a JSON payload that conforms to the model’s validation rules. Supplying an empty list or more than five items triggers a Pydantic `ValidationError`, preventing the evaluation from being stored or exported.

## Key Files in the Evaluation Pipeline

Three files implement the full lifecycle of generating and constraining these fields:

- **[`main/models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/models.py)** — Defines `EvaluationData` with constrained `key_strengths` and `areas_for_improvement` fields using Pydantic validation
- **[`main/transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/transform.py)** — Parses LLM output, extracts bullet-point lists, and enforces the 1-to-5 item rule before model instantiation (around line 730)
- **[`main/score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/score.py)** — Prints the collected key strengths and improvement areas when displaying the final candidate score report

## Summary

- Both fields require **1 to 5 items** enforced at the model level in [`main/models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/models.py)
- Validation uses Pydantic `Field(min_items=1, max_items=5)` at lines 48-49
- [`main/transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/transform.py) automatically trims excess items before instantiation to prevent validation failures
- Empty lists trigger `ValidationError`, preventing incomplete evaluations from entering the system
- Downstream consumers receive predictable, bounded lists suitable for CSV export and UI rendering

## Frequently Asked Questions

### What happens if the LLM returns more than five key strengths?

The extraction logic in [`main/transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/transform.py) (around line 730) automatically trims the list to the first five items before creating the `EvaluationData` instance. This ensures compliance with the Pydantic model constraints defined in [`main/models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/models.py) while preserving the most important feedback.

### Can an evaluation be created with empty strengths or improvement areas?

No. The `EvaluationData` model requires a minimum of one item in both lists. Attempting to instantiate the model with empty lists triggers a Pydantic `ValidationError`, preventing the storage or export of incomplete candidate evaluations.

### Where are the constraints for generating these fields actually defined?

The constraints are defined in [`main/models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/models.py) at lines 48-49, where both `key_strengths` and `areas_for_improvement` are declared as `List[str]` with `Field(min_items=1, max_items=5)`. These constraints apply regardless of whether the input comes from Ollama, Gemini, or manual instantiation.

### How does the system display these fields after validation?

Once validated, the fields are rendered through [`main/score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/main/score.py), which accesses the `EvaluationData` object to print the collected key strengths and areas for improvement when generating the final candidate score report. The bounded list size guarantees consistent formatting in the output.