Skip to content

feat: Jinja2 support for system_prompt of the Agent#10718

Merged
anakin87 merged 15 commits intomainfrom
agent-jinja2-system-prompt
Mar 6, 2026
Merged

feat: Jinja2 support for system_prompt of the Agent#10718
anakin87 merged 15 commits intomainfrom
agent-jinja2-system-prompt

Conversation

@anakin87
Copy link
Member

@anakin87 anakin87 commented Mar 3, 2026

Related Issues

Proposed Changes:

How did you test it?

  • CI
  • Refactored tests: removed duplicate tests, marked some heavy tests as integration tests, ...

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes.
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test: and added ! in case the PR includes breaking changes.
  • I have documented my code.
  • I have added a release note file, following the contributors guidelines.
  • I have run pre-commit hooks and fixed any issue.

@vercel
Copy link

vercel bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
haystack-docs Ignored Ignored Preview Mar 6, 2026 3:58pm

Request Review

@github-actions github-actions bot added topic:tests type:documentation Improvements on the docs labels Mar 3, 2026
@anakin87 anakin87 changed the title feat: Jinja2 support for system_prompt of the Agent - draft feat: Jinja2 support for system_prompt of the Agent Mar 3, 2026
@anakin87 anakin87 marked this pull request as ready for review March 3, 2026 17:55
@anakin87 anakin87 requested a review from a team as a code owner March 3, 2026 17:55
@anakin87 anakin87 requested review from bogdankostic and removed request for a team March 3, 2026 17:55
@coveralls
Copy link
Collaborator

coveralls commented Mar 5, 2026

Pull Request Test Coverage Report for Build 22771120562

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 12 unchanged lines in 1 file lost coverage.
  • Overall coverage increased (+0.02%) to 92.787%

Files with Coverage Reduction New Missed Lines %
components/agents/agent.py 12 96.88%
Totals Coverage Status
Change from base Build 22770452027: 0.02%
Covered Lines: 15629
Relevant Lines: 16844

💛 - Coveralls

Copy link
Contributor

@bogdankostic bogdankostic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good in principle, I'm just wondering why we don't allow users to provide a system prompt template with variables at runtime if they didn't do so when initializing the agent.

Comment on lines +249 to +255
:param system_prompt: System prompt for the agent. Can be a plain string or a Jinja2 string template.
For details on the supported template syntax, refer to the
[documentation](https://docs.haystack.deepset.ai/docs/chatpromptbuilder#string-templates).
:param user_prompt: User prompt for the agent, defined as a Jinja2 string template. If provided, this is
appended to the messages provided at runtime.
For details on the supported template syntax, refer to the
[documentation](https://docs.haystack.deepset.ai/docs/chatpromptbuilder#string-templates).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we allow for system_prompt both string and Jinja2 string template but for user_prompt only Jinja2 string template?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user_prompt was originally introduced in #10638 for Platform needs. Here, I just expanded the docstring to make it clear that we expect Jinja2 templates.

In system_prompt, we accept both because the request was to allow Jinja2 templates, but keeping compatibility with the existing plain string behavior.


self._chat_prompt_builder: ChatPromptBuilder | None = self._initialize_chat_prompt_builder(
user_prompt, required_variables
self._user_chat_prompt_builder = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add a comment here saying that required variables will be set in _register_prompt_variables?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Added in 2b37ac7

Comment on lines +553 to +558
if self._system_chat_prompt_builder is None:
raise ValueError(
"system_prompt contains Jinja2 template syntax but no system prompt builder is initialized. "
"Please make sure a system_prompt with Jinja2 template syntax is provided at initialization "
"time."
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To allow passing a system prompt with variables at run time, the user also needs to pass a system prompt with variables when initializing the agent? Why?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mostly mirrors the choices made in #10638 for user_prompt

It is also worth noting that, similarly to the ChatPromptBuilder, a user_prompt can be provided at both init and run time, with one caveat: providing a user_prompt at run time, and not init would raise an error as the necessary ChatPromptBuilder instance wouldn't have been initiated prior.
That behavior could be disputed, there is the possibility of instantiating the necessary ChatPromptBuilder ad-hoc at run-time as well, and handle it gracefully. But my understand of that API is that it is already quite 'hacky' and most likely not going to be used. Happy to be told otherwise!

In general, I agree with this view, also because now the failure is clear and explicit.
(I'd even be in favor of restricting the API further to avoid footguns).

Allowing dynamic system prompts:

  • we would need to build Chat Prompt Builders at runtime, adding complexity and a performance penalty
  • the Agent's inputs would become much more dynamic vs having components' inputs and required variables set at init
  • in addition,system_prompt can accept both a plain string and a Jinja2 template. If we allow any template at run, this would also enable switching from a static prompt to a dynamic one at runtime, which would complicate things.

Happy to revisit if we see a concrete use case.

Comment on lines +547 to +548
if len(user_messages) != 1 or not user_messages[0].is_from(ChatRole.USER):
raise ValueError("user_prompt must render to exactly one user message.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can give raise here different error based on whether there are too many messages or the message has the wrong role?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 9f4c272

Comment on lines +566 to +567
if len(system_messages) != 1 or not system_messages[0].is_from(ChatRole.SYSTEM):
raise ValueError("system_prompt must render to exactly one system message.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can give raise here different error based on whether there are too many messages or the message has the wrong role?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 9f4c272

@anakin87 anakin87 requested a review from bogdankostic March 6, 2026 15:58
Copy link
Contributor

@bogdankostic bogdankostic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, thanks for answering my questions 🙏

@anakin87 anakin87 enabled auto-merge (squash) March 6, 2026 16:05
@anakin87 anakin87 merged commit 79adf06 into main Mar 6, 2026
22 checks passed
@anakin87 anakin87 deleted the agent-jinja2-system-prompt branch March 6, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants