Description
A declarative SendActivity template can rewrite a substituted value and leave an authored placeholder unresolved when the value contains another placeholder from the template.
For example, with Local.first = "{Local.second}" and Local.second = "B", the authored template {Local.first}|{Local.second} produces B|{Local.second}. The expected output is {Local.second}|B: resolve the two authored placeholders and preserve the substituted text.
interpolate_string finds matches in the original template but applies each replacement to the already-modified string. A later replacement can therefore consume a placeholder introduced by an earlier value instead of the original occurrence. Repeated placeholders have the same problem when their value contains a reference to itself.
Code Sample
import asyncio
from agent_framework_declarative import WorkflowFactory
async def main():
workflow = WorkflowFactory().create_workflow_from_definition({
"kind": "Workflow",
"actions": [
{"kind": "SetVariable", "variable": "Local.first", "value": "{Local.second}"},
{"kind": "SetVariable", "variable": "Local.second", "value": "B"},
{"kind": "SendActivity", "activity": "{Local.first}|{Local.second}"},
],
})
result = await workflow.run({})
print(result.get_outputs())
asyncio.run(main())
Expected: ['{Local.second}|B'].
Actual: ['B|{Local.second}'].
The behavior also reproduces with streaming execution and an activity mapping's text field. A template containing only {Local.first} already preserves its value as {Local.second}.
Error Messages / Stack Traces
No exception is raised; the output text is incorrect.
Package Versions
Source checkout at b9d24c8fb484c8330abe8bb9e7500ca3c3bbf46c; declarative package version 1.2.0, core version 1.20.0.
Python Version
Python 3.12.14 on Windows.
Additional Context
This reproducer uses local workflow execution without an external service or model. It concerns directly authored templates; the expression-result behavior addressed by #8509 is a separate path. I have a local fix that substitutes matches at their original template positions while retaining the existing matcher and state-path resolution, and will submit it with regression tests.
Description
A declarative SendActivity template can rewrite a substituted value and leave an authored placeholder unresolved when the value contains another placeholder from the template.
For example, with Local.first = "{Local.second}" and Local.second = "B", the authored template {Local.first}|{Local.second} produces B|{Local.second}. The expected output is {Local.second}|B: resolve the two authored placeholders and preserve the substituted text.
interpolate_string finds matches in the original template but applies each replacement to the already-modified string. A later replacement can therefore consume a placeholder introduced by an earlier value instead of the original occurrence. Repeated placeholders have the same problem when their value contains a reference to itself.
Code Sample
Expected: ['{Local.second}|B'].
Actual: ['B|{Local.second}'].
The behavior also reproduces with streaming execution and an activity mapping's text field. A template containing only {Local.first} already preserves its value as {Local.second}.
Error Messages / Stack Traces
No exception is raised; the output text is incorrect.
Package Versions
Source checkout at b9d24c8fb484c8330abe8bb9e7500ca3c3bbf46c; declarative package version 1.2.0, core version 1.20.0.
Python Version
Python 3.12.14 on Windows.
Additional Context
This reproducer uses local workflow execution without an external service or model. It concerns directly authored templates; the expression-result behavior addressed by #8509 is a separate path. I have a local fix that substitutes matches at their original template positions while retaining the existing matcher and state-path resolution, and will submit it with regression tests.