How to Contribute to the Prompt Management System in Hiring-Agent
To contribute to the prompt management system in hiring-agent, you create Jinja template files in prompts/templates/, register them in the TemplateManager class, and invoke them through the render_template() method in your LLM caller modules.
The hiring-agent repository by InterviewStreet powers LLM-driven resume evaluation and candidate screening through a modular prompt architecture. Understanding how to contribute to the prompt management system in hiring-agent allows you to add new evaluation criteria, refine existing prompts, or extend capabilities to new data sources like GitHub projects or cover letters. The system uses a centralized TemplateManager that ensures every prompt is reusable, version-controlled, and instantly available across all LLM-driven features.
Understanding the Core Architecture
TemplateManager
The TemplateManager class serves as the central loader and rendering engine for all prompts. Located in prompts/template_manager.py, it builds a Jinja Environment pointing at the prompts/templates directory and eagerly loads every known template via the _load_templates method starting at line 35. The manager caches templates and exposes the render_template() method to supply structured prompts to any caller in the system.
Jinja Template Files
Jinja template files contain the raw prompt text stored in prompts/templates/*.jinja. Each file corresponds to a logical section—such as basics, work, or resume_evaluation_criteria—and defines the actual prompt strings sent to the LLM. These files use Jinja placeholder syntax ({{ variable }}) to inject dynamic data at runtime.
LLM-Aware Callers
LLM-aware callers are modules that request prompts from TemplateManager and subsequently call the LLM. Key examples include pdf.py, evaluator.py, and github.py. These callers combine the rendered user prompt with a system message and forward the complete payload to the LLM provider.
Model Configuration
The prompt.py file stores model-specific defaults, including the default model, provider settings, and per-model parameters. Callers import these defaults to ensure consistent LLM behavior across different components of the hiring-agent system.
How the Prompt System Works
-
Initialization: When a caller such as
PDFHandleris instantiated, it creates aTemplateManager()instance (see line 40 inpdf.py). -
Template loading:
TemplateManager.__init__builds a JinjaEnvironmentand eagerly loads all templates via_load_templates(starting at line 35). Missing files are reported but do not crash the system. -
Rendering: The caller requests a specific section by invoking
self.template_manager.render_template("section_name", variable=value). -
Prompt composition: The rendered user prompt is combined with a system message (typically from
system_message.jinja) and passed to the LLM via the provider obtained frominitialize_llm_provider. -
Result handling: The raw LLM response is cleaned using
extract_json_from_response, parsed as JSON, transformed, and returned to the caller.
Because every component routes through TemplateManager, adding a new prompt once makes it instantly available everywhere.
Adding or Modifying Prompts
| Step | Action | Location |
|---|---|---|
| Create template | Create a .jinja file with placeholders ({{ variable }}) for dynamic data. |
prompts/templates/new_section.jinja |
| Register template | Add the mapping section_name: "new_section.jinja" to the template_files dictionary inside _load_templates (lines 38-44). |
prompts/template_manager.py |
| Implement caller | Call self.template_manager.render_template("new_section", your_key=your_value) in the module that needs the prompt. |
pdf.py, evaluator.py, github.py, or new modules |
| Add tests | Verify the template renders without errors and that required variables are present. | tests/ directory |
| Document | Update README.md or create a dedicated "Prompt Templates" section linking to the new file. |
README.md or docs |
Code Examples
Creating a New Template File
Create prompts/templates/cover_letter.jinja:
You are an AI assistant helping a candidate draft a concise cover letter.
Use the following resume details:
{{ resume_json }}
Write a 250-word cover letter tailored to the role: {{ job_title }}.
Registering the Template
Update template_files in prompts/template_manager.py (around line 38):
template_files = {
# … existing entries …
"cover_letter": "cover_letter.jinja",
}
Implementing the Caller
Create a new module that utilizes the template:
from prompts.template_manager import TemplateManager
from llm_utils import initialize_llm_provider, extract_json_from_response
DEFAULT_MODEL = "llama3.1"
class CoverLetterGenerator:
def __init__(self):
self.tm = TemplateManager()
self.provider = initialize_llm_provider(DEFAULT_MODEL)
def generate(self, resume_json: str, job_title: str) -> str:
prompt = self.tm.render_template(
"cover_letter",
resume_json=resume_json,
job_title=job_title,
)
if not prompt:
raise RuntimeError("Failed to render cover-letter prompt")
chat = {
"model": DEFAULT_MODEL,
"messages": [
{"role": "system", "content": "You are a helpful AI assistant."},
{"role": "user", "content": prompt},
],
"options": {"temperature": 0.7, "top_p": 0.9},
}
response = self.provider.chat(**chat)
return response["message"]["content"]
Rendering an Existing Template
from prompts.template_manager import TemplateManager
tm = TemplateManager()
resume_text = open("sample_resume.txt").read()
work_prompt = tm.render_template("work", text_content=resume_text)
print(work_prompt) # Fully-filled Jinja prompt ready for the LLM
Best Practices for Prompt Contributions
- Keep prompts declarative: Avoid embedding Python logic inside Jinja templates; perform data preparation in the caller and pass simple variables.
- Validate rendering:
TemplateManager.render_templatereturnsNoneon failure; callers should check the return value and log meaningful errors. - Version-control templates: Since prompts are part of the model's behavior, treat them like code by reviewing changes via pull requests and running the full test suite.
- Use consistent naming: Employ snake_case for section names (matching the key in
template_files) and keep the filename identical (e.g.,work.jinjafor theworksection).
Summary
- The TemplateManager in
prompts/template_manager.pyis the central hub for loading and rendering all Jinja templates. - New prompts require three actions: creating a
.jinjafile inprompts/templates/, registering it in thetemplate_filesdictionary, and invoking it viarender_template(). - LLM callers in
pdf.py,evaluator.py, andgithub.pydemonstrate how to integrate rendered prompts with system messages and LLM providers. - Always validate that
render_template()does not returnNonebefore passing to the LLM. - Treat prompt changes as code changes: add tests, run
pytest, and document updates inREADME.md.
Frequently Asked Questions
What is the TemplateManager responsible for?
The TemplateManager loads Jinja templates from the prompts/templates/ directory, caches them in memory, and renders them with supplied variables via the render_template() method. It serves as the single source of truth for all LLM prompts in the hiring-agent system, ensuring consistency across PDF parsing, resume evaluation, and GitHub project analysis.
How do I test a new template before submitting a PR?
Add a unit test in the tests/ directory that verifies the template renders without errors and that all required variables are present. Run pytest to ensure your changes do not break existing functionality. The test should instantiate TemplateManager, call render_template() with mock data, and assert the output contains expected content.
Can I use Python logic inside Jinja templates?
While Jinja supports Python-like logic, the best practice is to keep templates declarative and perform data preparation in the caller module. Pass simple, pre-formatted variables to the template rather than embedding complex logic, making prompts easier to maintain and review by non-developers.
Where should I document new prompt changes?
Update README.md with a description of the new template and its purpose, or create a dedicated "Prompt Templates" section in the documentation that links to the new file. Since prompts directly influence model behavior, they require the same level of documentation and review as code changes.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →