Pass globals context to env block template rendering#221
Conversation
swap_env and TmpEnv now accept an optional context dict so that
{{ globals.X }} references work in task env blocks, not just in
user_prompt templates. The runner passes globals through when
constructing TmpEnv.
Backward compatible: context defaults to None, existing env() calls
work unchanged.
There was a problem hiding this comment.
Pull request overview
Enables task env: block template rendering to access globals (in addition to env()), aligning env rendering capabilities with user_prompt templating.
Changes:
- Extended
swap_env()to accept an optional renderingcontextand pass it into Jinja rendering. - Updated
TmpEnvto accept/forward the optionalcontextwhen rendering environment variable templates. - Passed
{"globals": global_variables}from the runner when constructingTmpEnv.
Show a summary per file
| File | Description |
|---|---|
src/seclab_taskflow_agent/runner.py |
Passes globals into TmpEnv so task env: templates can reference globals.*. |
src/seclab_taskflow_agent/env_utils.py |
Adds optional template context support to swap_env()/TmpEnv and renders env values with that context. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 3
- Clarify docstring: globals only available when caller provides context - Filter reserved Jinja globals (e.g. env) from context to prevent callers from accidentally shadowing built-in template helpers - Add test_env_utils.py with 9 tests covering: globals rendering, missing context raises, reserved key protection, env() backward compat, TmpEnv context forwarding, env restoration
There was a problem hiding this comment.
Pull request overview
Enables Jinja template rendering inside task env: blocks to access globals (matching user_prompt behavior) by threading a caller-provided context through swap_env()/TmpEnv.
Changes:
- Add optional
contextparameter toswap_env()and forward it throughTmpEnv. - Pass
{"globals": global_variables}when constructingTmpEnvin the runner. - Add unit tests covering globals rendering and reserved-key behavior.
Show a summary per file
| File | Description |
|---|---|
| tests/test_env_utils.py | Adds coverage for swap_env/TmpEnv with globals context and reserved-key filtering. |
| src/seclab_taskflow_agent/runner.py | Ensures task env-block rendering receives globals via TmpEnv(..., context=...). |
| src/seclab_taskflow_agent/env_utils.py | Implements optional template context in swap_env and plumbs it through TmpEnv. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 3
ea07aa1 to
2c05b9c
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes Jinja template rendering in task env: blocks so they can reference global variables (e.g. {{ globals.X }}), matching the behavior already supported in user_prompt rendering.
Changes:
- Extend
swap_env()to accept an optional template context and pass it throughTmpEnv. - Update the runner to provide
{"globals": global_variables}when rendering task env blocks. - Add tests covering globals rendering, reserved key behavior, and TmpEnv rollback.
Show a summary per file
| File | Description |
|---|---|
src/seclab_taskflow_agent/env_utils.py |
Adds context-aware Jinja rendering for env strings and forwards context through TmpEnv; adds rollback behavior on failure. |
src/seclab_taskflow_agent/runner.py |
Passes taskflow globals into TmpEnv so task env: blocks can render {{ globals.* }}. |
tests/test_env_utils.py |
New tests for swap_env()/TmpEnv with globals context and rollback behavior. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 1
| except jinja2.UndefinedError as e: | ||
| # Convert Jinja undefined to LookupError for compatibility | ||
| raise LookupError(str(e)) | ||
| except jinja2.TemplateError: | ||
| # Not a template or failed to render, return as-is | ||
| return s | ||
| except jinja2.TemplateError as e: | ||
| raise LookupError(f"Template rendering failed for: {s!r}: {e}") |
There was a problem hiding this comment.
Catching jinja2.TemplateError and re-raising LookupError is a behavior change from the previous implementation (which returned the original string on template syntax/render errors). This can break existing configs that contain literal {{/{% sequences or other non-Jinja brace usage, and it also changes downstream behavior where callers treat LookupError as “missing env var” (e.g. some code deletes the entry on LookupError). If backward compatibility is required, consider preserving the old behavior for TemplateError (return s as-is) or introducing an explicit “strict” mode so invalid templates don’t get conflated with missing variables.
- TmpEnv.__enter__ rolls back already-set env vars if swap_env raises mid-loop, preventing leaked env state on enter failures - Remove silent TemplateError swallow: malformed templates now raise LookupError with the source string and error detail instead of silently passing through as literals - Convert tests to plain pytest classes (drop unittest.TestCase) - Add test_tmpenv_rollback_on_error for partial modification safety
2c05b9c to
a8fcc23
Compare
Problem
Task
env:blocks useswap_env()for template rendering, butswap_envonly has access to theenv()function -- notglobals. This means{{ globals.X }}references in env blocks raiseUndefinedError, even though they work fine inuser_promptblocks.This matters for taskflows that need to pass global variables into container configuration (e.g. using a GHSA ID as a container persist key).
Fix
swap_env()now accepts an optionalcontextdictTmpEnvaccepts and forwardscontexttoswap_env(){'globals': global_variables}when constructingTmpEnvBackward compatible:
contextdefaults toNone, all existingenv()calls work unchanged.