fix(engine): template dict key collision and workflow.input for-each source#21
Merged
jrob5756 merged 3 commits intomicrosoft:mainfrom Mar 5, 2026
Merged
Conversation
Jinja2's default attribute resolution tries Python getattr() before dict key lookup. When a dict has a key named 'items' (or 'keys', 'values', etc.), getattr(d, 'items') returns the dict.items method instead of d['items'] (the stored value). Filters like '| length' then call len() on the method object, producing: Template rendering failed: object of type 'builtin_function_or_method' has no len() Fix: Subclass Jinja2 Environment with _DictSafeEnvironment that prefers dict key lookup over attribute access for dict objects. This resolves the collision for any field name that matches a dict method. Also rename the 'items' output field in for-each-simple.yaml to 'topics' to avoid the confusing collision in the example.
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. Thanks for integrating Codecov - We've got you covered ☂️ |
Add _resolve_workflow_input_array to handle workflow.input.* references in for-each source fields, with automatic JSON string parsing for CLI --input values. Update for-each-simple.yaml to accept optional --input items array with fallback to agent-generated topics when not provided. Add 9 tests covering workflow.input source resolution.
jrob5756
approved these changes
Mar 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related fixes for the workflow engine: a template rendering bug when dictionary keys shadow Python built-in methods, and missing support for
workflow.input.*references in for-each source fields.Changes
Fix template rendering error when dict keys shadow built-in methods
Dictionary outputs with keys like
"items","values", or"keys"causedAttributeErrorduring Jinja2 template rendering becauseTemplateRenderer._flatten_to_namespaceresolved these to the dict's built-in methods instead of the actual values.dict.__getitem__access in_flatten_to_namespaceto bypass method shadowingitems,values,keys,get, andupdateas dict keysSupport
workflow.input.*as for-each sourceThe docs and examples referenced
source: workflow.input.itemsfor for-each groups, but_resolve_array_referenceonly resolved paths fromagent_outputs, causing a runtime error._resolve_workflow_input_arrayhelper to resolveworkflow.input.*paths fromcontext.workflow_inputs--inputpasses arrays as strings like'["a","b"]')Update
for-each-simple.yamlexampleitemsas an optional input parameteritem_finderagent now conditionally passes through provided items or generates random topicsconductor run examples/for-each-simple.yaml --input items='["apple", "banana", "cherry"]' conductor run examples/for-each-simple.yaml