Skip to content

Python: [Bug]: State updates not propagated to the next activity with durable function and declarative workflow #4500

Closed

Description

@stepanradek

Description

Hello, we face and issue with durable function and declarative workflows.

We found that when an activity like "parse_code_1" updates a state value (e.g., Local.code), downstream activities never receive the updated value — it's always blank. This caused "evaluate_1" to always evaluate Not(IsBlank(Local.code)) as False.

- kind: ParseCode
  id: parse_code_1
  description: >
    Parses code and sets in workflow context.

- kind: If
  id: evaluate_1
  description: >
    Gate: only proceed if code parsed.
  condition: "=Not(IsBlank(Local.code))"

We traced this to _app.py in the agent framework, where the activity executor snapshots the workflow state before execution using dict(). Since dict() only creates a shallow copy, nested state objects are still shared references. When the activity mutates a nested value in place, the snapshot is silently modified too, making the before/after diff empty — so no changes are propagated forward.

about line 300...

# Deserialize shared state values to reconstruct dataclasses/Pydantic models
deserialized_state = {k: deserialize_value(v) for k, v in (shared_state_snapshot or {}).items()}
original_snapshot = dict(deserialized_state)

In our testing, replacing the shallow copy with copy.deepcopy() resolved the issue. However, we'd like the framework owners to review and determine the appropriate fix, as there may be broader implications we're not aware of.

# Deserialize shared state values to reconstruct dataclasses/Pydantic models
deserialized_state = {k: deserialize_value(v) for k, v in (shared_state_snapshot or {}).items()}
original_snapshot = copy.deepcopy(deserialized_state)

Thank you for having look into it!

Code Sample

Following code is working with fix described above.

ParseCodeExecutor(DeclarativeActionExecutor):
...
state.set("Local.code", "SOMECODEXXX")
code_check = state.get("Local.code")
logger.warning("[ParseCode] STATE-DEBUG: Local.code after set = %r", code_check)

CodeReaderExecutor(DeclarativeActionExecutor):
...
code_check = state.get("Local.code")
logger.warning("[CodeReader] STATE-DEBUG: Local.code after set = %r", code_check)

Error Messages / Stack Traces

Package Versions

agent-framework-azurefunctions>=1.0.0b260225; agent-framework-declarative>=1.0.0b260225;agent-framework-durabletask>=1.0.0b260225

Python Version

Python 3.12

Additional Context

No response

Activity

  1. added
    bugUsage: [Issues], Target: all issues (Legacy, prefer issue type: bug)
    on Mar 5, 2026
  2. added theissue type on Mar 5, 2026
  3. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Mar 5, 2026
  4. added
    durabletaskUsage: [Issues, PRs], Target: durable task
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugUsage: [Issues], Target: all issues (Legacy, prefer issue type: bug)durabletaskUsage: [Issues, PRs], Target: durable taskpythonUsage: [Issues, PRs], Target: Python

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions