Skip to content

.NET: Python: [Bug]: Declarative SetValue with variable: builds fine but never writes the value #9427

Closed

Description

Observed Behavior

A SetValue action that uses variable: instead of path: passes build() validation, then does nothing at run time. The target variable stays unset and there is no error or warning.

The builder accepts variable on purpose. ACTION_ALTERNATE_FIELDS has "SetValue.path": ["variable"] (_declarative_builder.py:99) and test_setvalue_accepts_alternate_variable_field checks that this builds. But SetValueExecutor only reads path (_executors_basic.py:56), so the write is skipped.

Expected Behavior

SetValue with variable: Local.b (or variable: {path: Local.b}) sets Local.b, same as path: Local.b does. SetVariable already reads both shapes through _get_variable_path.

Steps to Reproduce

  1. Build a workflow with kind: SetValue, variable: Local.b, value: from variable.
  2. Run it.
  3. Read Local.b. It is None.

Minimal Reproduction

No API keys or PowerFx needed. It reads the state from the last checkpoint.

"""Repro: declarative SetValue with `variable:` builds fine but writes nothing.

Runs the real workflow (no PowerFx, no API keys) and reads the declarative
state from the last checkpoint.
"""

import asyncio

import agent_framework_declarative
from agent_framework import InMemoryCheckpointStorage
from agent_framework_declarative._workflows._declarative_base import DECLARATIVE_STATE_KEY
from agent_framework_declarative._workflows._factory import WorkflowFactory

print("agent_framework_declarative from:", agent_framework_declarative.__file__)

YAML = """
kind: Workflow
name: setvalue_variable
actions:
  - kind: SetValue
    id: with_path
    path: Local.a
    value: from path
  - kind: SetValue
    id: with_variable
    variable: Local.b
    value: from variable
  - kind: SetValue
    id: with_nested_variable
    variable:
      path: Local.c
    value: from nested variable
"""


async def main() -> None:
    storage = InMemoryCheckpointStorage()
    workflow = WorkflowFactory(checkpoint_storage=storage).create_workflow_from_yaml(YAML)
    await workflow.run({})
    checkpoints = await storage.list_checkpoints(workflow_name=workflow.name)
    last = max(checkpoints, key=lambda c: c.timestamp)
    local = last.state[DECLARATIVE_STATE_KEY]["Local"]
    print("Local.a =", repr(local.get("a")))
    print("Local.b =", repr(local.get("b")))
    print("Local.c =", repr(local.get("c")))


asyncio.run(main())

Output on main (cae4955):

agent_framework_declarative from: python/packages/declarative/agent_framework_declarative/__init__.py
Local.a = 'from path'
Local.b = None
Local.c = None

Local.a uses path: and works. Local.b and Local.c use variable: and are never set.

Error Messages and Stack Traces

None. That's the problem, it fails silently.

Package Versions

agent-framework-core 1.22.0, agent-framework-declarative 1.3.0 (main at cae4955)

Python Version

3.12.13

Operating System

macOS 26.6.2

Regression

No. The alias and the executor have been out of sync since the declarative runtime landed in #2815.

Additional Context

Root cause: python/packages/declarative/agent_framework_declarative/_workflows/_executors_basic.py:56

path = self._action_def.get("path")

Proposed fix, one line: path = self._action_def.get("path") or _get_variable_path(self._action_def). path still wins when both are set. I have it ready with a test and can open the PR.

The other choice would be to drop the variable alternate from the builder so this fails at build time. I went with honoring it, since the builder and its test already treat variable as valid, and .NET authors write variable: on SetVariable.

AI assistance: I used an AI assistant to help find and analyze this bug. I ran the repro and checked the output myself.

Acknowledgements

  • I searched existing issues and did not find a duplicate.
  • I personally verified this behavior and the reproduction details are authentic.
  • I will wait for explicit maintainer agreement before starting implementation of a non-trivial change.

Activity

  1. added
    .NETUsage: [Issues, PRs], Target: .Net
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 15, 2026
  2. changed the title [-]Python: [Bug]: Declarative SetValue with `variable:` builds fine but never writes the value[/-] [+].NET: Python: [Bug]: Declarative SetValue with `variable:` builds fine but never writes the value[/+] on Oct 15, 2026
  3. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 15, 2026
  4. github-actions commented on Oct 15, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    Repro: python/packages/declarative/agent_framework_declarative/_workflows/_executors_basic.py::SetValueExecutor.handle_action at line 56 skips writes when SetValue supplies variable as either a string or {path: ...}. The builder accepts both shapes, but the executor observes no path. Minimal repro: execute SetValueExecutor with either variable shape and assert the target state value; it remains None.

    • Failing test: python/packages/declarative/tests/test_graph_coverage.py::TestBasicExecutorsCoverage::test_set_value_executor_with_variable
    • Files examined: python/packages/declarative/agent_framework_declarative/_workflows/_executors_basic.py, python/packages/declarative/agent_framework_declarative/_workflows/_declarative_builder.py, python/packages/declarative/tests/test_graph_coverage.py, python/packages/declarative/pyproject.toml
    • Tests run: test_set_value_executor_with_variable, test_setvalue_accepts_alternate_variable_field
    • Reported version: 1.3.0
    • Current version: 1.3.0
  5. added
    declarativeUsage: [Issues, PRs], Target: declarative agents and workflows
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

.NETUsage: [Issues, PRs], Target: .NetdeclarativeUsage: [Issues, PRs], Target: declarative agents and workflowspythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions