# How the Jinja Templating Engine Parses Different Resume Sections in Hiring-Agent

> Learn how the Jinja templating engine parses resume sections effectively. Discover how it transforms raw markdown into structured LLM prompts.

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

---

**The Jinja templating engine generates section-specific LLM prompts by injecting raw resume markdown into pre-defined template files, creating structured extraction instructions for each resume section without performing any textual parsing itself.**

The interviewstreet/hiring-agent repository leverages **Jinja2** to transform raw resume markdown into structured LLM-ready prompts. Rather than parsing resume content directly, the engine uses a template composition approach where each logical section—such as work experience, education, or skills—receives its own specialized extraction instructions. This architecture centralizes prompt management in [`prompts/template_manager.py`](https://github.com/interviewstreet/hiring-agent/blob/main/prompts/template_manager.py) while maintaining flexibility through modular `.jinja` template files.

## Template Discovery and Environment Setup

The `TemplateManager` class serves as the central orchestrator for all Jinja operations. Located in [`prompts/template_manager.py`](https://github.com/interviewstreet/hiring-agent/blob/main/prompts/template_manager.py), this manager initializes a **Jinja2 Environment** with a `FileSystemLoader` pointing to the `prompts/templates` directory (lines 30-31).

During instantiation, the manager builds an internal `template_files` map that associates logical section names with their corresponding template filenames (lines 38-48). For example, the key `"work"` maps to `"work.jinja"`, while `"education"` maps to `"education.jinja"`. This mapping enables the system to resolve section requests to specific template files without hardcoding filenames throughout the codebase.

## Anatomy of Section-Specific Templates

Every `.jinja` file in the templates directory follows a uniform structural pattern designed to standardize LLM interactions:

- **Instruction header**: A concise directive specifying what to extract (e.g., "Extract ONLY the work experience from this resume")
- **Content markers**: Delimiters sandwiching the resume text (`--- The input markdown starts here ---` and `--- The input markdown ends here ---`)
- **JSON skeleton**: A schema definition that dictates the exact shape of the expected LLM response
- **Validation rules**: Inline constraints regarding date formats, profile extraction, and field requirements

For instance, the work experience template (`prompts/templates/work.jinja`) contains specific date-parsing rules and field validations embedded within the prompt instructions. The template receives content through the `{{ text_content }}` variable, which the engine replaces with the full resume markdown during rendering.

## Rendering Pipeline for Resume Sections

The `render_template(section_name, **kwargs)` method (lines 69-88) executes the actual prompt generation. This method:

1. Retrieves the pre-loaded `Template` object from the Jinja environment using the section name
2. Invokes `template.render(**kwargs)` with the `text_content` parameter containing the raw resume markdown
3. Returns a fully-formed prompt string ready for LLM consumption

Higher-level orchestration code—typically residing in [`prompt.py`](https://github.com/interviewstreet/hiring-agent/blob/main/prompt.py) or similar modules—coordinates the section-by-section extraction workflow. The process iterates over sections returned by `get_available_sections()`, rendering each template individually:

```python
from prompts.template_manager import TemplateManager

# Initialize template manager with default prompts/templates directory

tm = TemplateManager()

# Raw resume markdown (typically from file or user input)

resume_md = """
John Doe
john@example.com | +1-555-123-4567

## Work Experience

**Acme Corp** – Software Engineer (Jan 2020 – Present)
- Built microservices platform

## Education

B.Sc. Computer Science, 2019
"""

# Render section-specific prompts

for section in tm.get_available_sections():
    prompt = tm.render_template(section, text_content=resume_md)
    # Send prompt to LLM and parse JSON response

    print(f"Generated prompt for {section}: {prompt[:100]}...")

```

This modular approach allows the system to process **basics**, **work**, **education**, **skills**, **projects**, and **awards** sections independently, generating targeted extraction prompts for each domain.

## Separation of Concerns: Templating vs. Parsing

**Jinja does not perform textual parsing of resume content.** Its sole responsibility is **template composition**: injecting the raw markdown into deterministic instruction sets that remain identical across execution runs.

All resume-parsing intelligence—including entity recognition, date normalization, and relationship extraction—lives within the LLM prompts themselves and the downstream validation code that processes the JSON responses. This architectural boundary ensures that the templating engine remains a lightweight, predictable component while the complex extraction logic resides in the prompts and validation layers.

## Summary

- **TemplateManager** in [`prompts/template_manager.py`](https://github.com/interviewstreet/hiring-agent/blob/main/prompts/template_manager.py) initializes the Jinja environment and manages template discovery through the `template_files` mapping
- Each resume section uses a dedicated `.jinja` file containing LLM instructions, content markers, and JSON output schemas
- The `render_template()` method injects resume markdown via the `text_content` variable to generate section-specific prompts
- New sections require only a new template file and map entry—no rendering engine modifications needed
- Jinja handles prompt composition exclusively, while actual resume parsing occurs within the LLM and validation pipeline

## Frequently Asked Questions

### Does the Jinja templating engine actually parse resume text to extract data?

No. Jinja performs only variable substitution, specifically replacing `{{ text_content }}` with the raw resume markdown. All extraction and parsing logic resides in the LLM prompts and subsequent validation code that processes the returned JSON structures.

### How can I add support for a new resume section using the existing Jinja setup?

Create a new `.jinja` file in the `prompts/templates` directory following the standard pattern of instructions, content markers, and JSON schema. Add the section name and filename to the `template_files` dictionary in `TemplateManager`. The existing `render_template()` method will automatically handle the new section without requiring code changes to the rendering logic.

### What parameters are passed to the Jinja templates during rendering?

The only variable supplied to templates is `text_content`, which contains the complete resume markdown string. Templates reference this variable using standard Jinja syntax (`{{ text_content }}`) to position the raw input within the structured LLM instructions.

### Where is the JSON schema for each resume section defined?

Each `.jinja` template file contains an inline JSON skeleton that specifies the expected output structure, field types, and validation constraints. The LLM generates responses conforming to this schema, which downstream code then validates and processes into the final structured data format.