# How Prompt Templates Are Structured in the Hiring-Agent Project

> Discover how prompt templates are structured in the hiring-agent project using Jinja files and the TemplateManager class for efficient loading and rendering.

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

---

**The hiring-agent project stores Jinja-style prompt templates as separate .jinja files under `prompts/templates/` and uses a `TemplateManager` class to load, index, and render them with runtime variables.**

The interviewstreet/hiring-agent repository separates prompt logic from application code by organizing LLM prompts as external template files. This architecture allows prompt engineers to modify instructions without touching Python source code, while the `TemplateManager` class handles the heavy lifting of template loading and variable substitution.

## Template File Organization

All raw prompt texts live in the `prompts/templates/` directory as individual `.jinja` files. Each file contains the exact prompt that will be sent to the LLM for a specific resume-section extraction task, using placeholders such as `{{ text_content }}` that are substituted at runtime.

The repository includes distinct templates for different resume sections:

- `basics.jinja` – Extracts basic personal information
- `work.jinja` – Parses work experience entries
- `education.jinja` – Handles education details
- `skills.jinja` – Extracts skill lists
- `projects.jinja` – Processes project information
- `awards.jinja` – Identifies awards and recognitions

## The TemplateManager Class

Located in [`prompts/template_manager.py`](https://github.com/interviewstreet/hiring-agent/blob/main/prompts/template_manager.py), the `TemplateManager` class abstracts the loading, indexing, and rendering of Jinja templates. It creates a Jinja `Environment` pointing at the template directory and maintains a private dictionary `self._templates` to store compiled `Template` objects.

### Loading Mechanism

During initialization, the manager iterates over a hard-coded mapping of logical section names (e.g., `basics`, `work`, `skills`) to their corresponding filenames. It loads each file into the Jinja environment and stores the compiled templates in `self._templates`, making them available for rapid lookup by section name.

### Rendering Interface

The `render_template(section_name, **kwargs)` method serves as the primary interface for consumers. It looks up the requested section in the internal dictionary, passes the supplied keyword arguments to Jinja's `render` method, and returns the final prompt string. If the template cannot be found, the method prints an error and returns `None`, allowing calling code to implement fallback behavior.

## Practical Usage Examples

Instantiate the manager and list available sections:

```python
from prompts.template_manager import TemplateManager

tm = TemplateManager()                 # defaults to "prompts/templates"

print(tm.get_available_sections())    # → ['basics', 'work', 'education', …]

```

Render the "basics" prompt with resume markdown content:

```python
resume_md = "... (raw markdown) ..."
prompt_text = tm.render_template("basics", text_content=resume_md)

# `prompt_text` now holds the full Jinja-expanded prompt ready for the LLM.

```

Handle missing templates gracefully:

```python
missing = tm.render_template("nonexistent")

# prints an error and returns None; you can fall back to a default behavior.

```

Use the rendered prompt in downstream LLM calls:

```python
from llm_utils import call_llm   # hypothetical helper

response = call_llm(prompt_text)   # returns JSON with extracted basics

```

## Summary

- **Template storage**: Prompts are stored as `.jinja` files in `prompts/templates/` with placeholders like `{{ text_content }}` for dynamic content.
- **Manager implementation**: `TemplateManager` in [`prompts/template_manager.py`](https://github.com/interviewstreet/hiring-agent/blob/main/prompts/template_manager.py) initializes a Jinja `Environment` and indexes templates by section name in `self._templates`.
- **Rendering API**: The `render_template(section_name, **kwargs)` method handles variable substitution and returns the final prompt string, or `None` if the section is not found.
- **Architectural benefit**: This three-layer design (filesystem → manager → consumer) keeps prompt content decoupled from core application logic, enabling independent prompt iteration.

## Frequently Asked Questions

### Where are the prompt template files located in the hiring-agent repository?

All Jinja template files reside in the `prompts/templates/` directory. Individual files such as `basics.jinja`, `work.jinja`, and `skills.jinja` contain the raw prompt texts for different resume sections, each describing specific extraction instructions for the LLM.

### How does TemplateManager handle missing template files?

If you call `render_template()` with a section name that does not exist in the hard-coded mapping, the method prints an error message and returns `None`. This allows consumer code in modules like [`prompt.py`](https://github.com/interviewstreet/hiring-agent/blob/main/prompt.py) to detect the failure and implement appropriate fallback behavior.

### What variables can be passed to render_template?

You can pass any keyword arguments that match the Jinja placeholders defined in the template files. The most commonly used variable is `text_content`, which typically contains the raw resume markdown to be processed, though additional context-specific variables may be defined per template.

### Why does the project use Jinja templates instead of hard-coded strings?

Separating prompts into external Jinja files allows non-developers to modify LLM instructions without changing Python code, enables version control of prompts independently from application logic, and maintains a clean separation of concerns between prompt engineering and software implementation.