Uh oh!
There was an error while loading. Please reload this page.
feat(utils): add opt-in Jinja2 instruction templating via use_jinja2 flag - #6186
feat(utils): add opt-in Jinja2 instruction templating via use_jinja2 flag#6186vaibhav-patel wants to merge 14 commits into
Conversation
…flag
Add a `use_jinja2: bool = False` flag to `inject_session_state` that, when
enabled, renders the instruction template with a sandboxed Jinja2 environment
instead of the existing regex-based `{var}` substitution. This unlocks control
flow (conditionals, loops) and filters in agent instructions while keeping the
default behavior fully backward compatible.
The regex rendering logic is extracted unchanged into `_render_with_regex`, and
a new `_render_with_jinja2` coroutine handles the Jinja2 path. It exposes the
session `state` mapping and an async `artifact(name)` accessor to templates;
the environment runs with `enable_async=True` so the artifact coroutine is
awaited automatically, and missing artifacts render as empty strings.
jinja2 is imported lazily inside the Jinja2 path so the base install is not
forced to depend on it, and a dedicated `jinja` optional extra documents the
install path (`pip install google-adk[jinja]`). A
`jinja2.sandbox.SandboxedEnvironment` is used because instruction templates may
carry user/session data.
Adds unit tests for variable substitution, conditionals, loops, filters,
artifact loading, the uninitialized-artifact-service error, the sandbox
blocking unsafe attribute access, and confirmation that the default path is
unchanged.
Fixesgoogle#2942.Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
vaibhav-patel
commented
Jun 22, 2026
@googlebot I signed it! |
- Annotate the inner _artifact helper with a -> str return type to satisfy mypy --strict (no-untyped-def). - Assign render_async() result to a str-typed variable before returning so mypy does not flag returning Any from a str-typed function (no-any-return). - Collapse the Jinja2 conditional test template onto a single line to match pyink formatting.
vaibhav-patel
commented
Jun 26, 2026
HI @rohityan |
rohityan
commented
Jul 1, 2026
Hi @vaibhav-patel , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Your PR has been received by the team and is currently under review. We will provide feedback as soon as we have an update to share. |
rohityan
commented
Jul 1, 2026
Hi @Jacksunwei , can you please review this. |
Summary
Adds an opt-in
use_jinja2flag toinject_session_state(src/google/adk/utils/instructions_utils.py). When enabled, instruction templates are rendered with a sandboxed Jinja2 environment, unlocking control flow ({% if %},{% for %}) and filters in addition to the existing{var}substitution. The default (use_jinja2=False) is fully backward compatible.Changes
_render_with_regex._render_with_jinja2, which renders viajinja2.sandbox.SandboxedEnvironment(enable_async=True)and exposes:state— the session state mapping ({{ state['var'] }}).artifact— an async accessor ({{ artifact('file') }}), auto-awaited by the async environment; missing artifacts render as empty string.jinja2lazily so the base install isn't forced to depend on it; add ajinjaoptional extra (pip install google-adk[jinja]).Notes for reviewers
jinja2is not a core dependency today (only in theeval/testextras). I added a dedicatedjinjaoptional extra rather than touching core deps. Happy to fold it into core deps or another extra if you prefer.{{ await artifact(...) }}; that syntax is invalid in Jinja2. Withenable_async=Truethe coroutine is awaited automatically, so the supported syntax is{{ artifact('file') }}.Testing
Added unit tests for variable substitution, conditionals, loops, filters, artifact loading, the uninitialized-artifact-service error, sandbox rejection of unsafe attribute access, and an explicit check that the default path is unchanged. All
tests/unittests/utils/test_instructions_utils.pypass (24).Fixes#2942.