Repository navigation
.NET: fix(dotnet): refresh reused workflow executor state - #9394
Conversation
Co-authored-by: Copilot <[email protected]> Copilot-Session: 892f90aa-ef94-4e11-87a3-88a8cb755405
There was a problem hiding this comment.
🟡 Changes recommended
OutputMessagesExecutor bypasses the new base reset, allowing interrupted-run messages to leak across sessions.
1 open finding
What changed in this PR
Refreshes cached .NET workflow executor state between hosted runs so reused executors restore session-specific persisted state.
Changes:
- Adds cache initialization tracking and reset lifecycle support.
- Adds regression coverage for value-state, session reuse, streaming, and interrupted turns.
| File | Description |
|---|---|
StatefulExecutor.cs |
Invalidates cached state during executor reset. |
WorkflowExecutorStateTests.cs |
Tests state restoration across reset and hosted sessions. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (1 commit(s)): 58e47cc33322
Model: gpt-5.6-sol
Overview
The change correctly invalidates the base state cache at workflow release, explicitly tracks value-type cache initialization, and adds focused checkpoint, hosted-session, and interrupted-turn coverage. The cache bypass for concurrent runs and virtual reset dispatch are strong guardrails. However, making the public base class implement IResettableExecutor also marks every existing derived executor as fully resettable even though the base reset cannot clear derived per-run fields, allowing mixed workflows that previously rejected reuse to carry those fields into another session.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 medium) across 1 file. Details are attached to the affected lines below.
Affected areas: dotnet/src/Microsoft.Agents.AI.Workflows/StatefulExecutor.cs
Code coverage overviewLanguages: C# C# / code-coverage/dotnet
View coverage of the 4 most impacted files.
ℹ️ Calculations represent line coverage. Results may change as calculations are updated. Updated |
Co-authored-by: Copilot <[email protected]> Copilot-Session: 892f90aa-ef94-4e11-87a3-88a8cb755405
Co-authored-by: Copilot <[email protected]> Copilot-Session: 892f90aa-ef94-4e11-87a3-88a8cb755405
Co-authored-by: Copilot <[email protected]> Copilot-Session: 892f90aa-ef94-4e11-87a3-88a8cb755405
Co-authored-by: Copilot <[email protected]> Copilot-Session: 892f90aa-ef94-4e11-87a3-88a8cb755405
Co-authored-by: Copilot <[email protected]> Copilot-Session: 892f90aa-ef94-4e11-87a3-88a8cb755405
There was a problem hiding this comment.
MAF Automated Review — Iteration 2
Result: No findings
Scope: 5 net-new commit(s): 690672937893, 4c6f0cb5b38c, 2af20ad1050e, ecdea14801e0, 9af8f0b55948
Model: gpt-5.6-sol
Overview
This increment removes executor-local workflow-state caching and delegates reads and updates to the current runner-local context while preserving explicit reset opt-in for other executor instance fields. Initialization now occurs only when state is absent and queues the same value returned to callers, with regressions covering repeated and nested reads, hosted reuse, and interrupted output. The workflow ownership guards, context read-your-writes contract, and publish-before-checkpoint lifecycle prevent a publishable cross-session, persistence, compatibility, or security concern.
Reviewed the supplied incremental change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.


Motivation & Context
Read executor state from the current workflow context when a hosted workflow reuses an executor instance. Each run should load its persisted workflow state rather than retain an earlier run's cached value.
Description & Review Guide
skipCachefor API compatibility, and add hosted-session, interrupted-output, value-state, nested-read, repeated-initialization, and mixed-workflow reuse regressions. Make the test runner context's read-or-initialize implementation use its existing state manager rather than always returning new initial state.ChatProtocolExecutoruses the same context-scoped state for interrupted turns. Reset does not clear persisted workflow state. The executor-local cache optimization is removed.Commands executed from
dotnet:dotnet test --project tests\Microsoft.Agents.AI.Workflows.UnitTests -f net10.0 --no-restore --filter-class '*WorkflowExecutorStateTests' --no-progress: six original regression cases failed for the intended behavior before the fix; all fourteen final cases passed after the fix.dotnet test --project tests\Microsoft.Agents.AI.Workflows.UnitTests -f net472 --no-restore --filter-class '*WorkflowExecutorStateTests' --no-progress: passed, all fourteen cases. CI previously found two unsupportedValueTaskfactory calls in test helpers; these now wrap compatible canceled and faulted tasks without changing the assertions.dotnet build tests\Microsoft.Agents.AI.Workflows.UnitTests\Microsoft.Agents.AI.Workflows.UnitTests.csproj --no-restore --tl:off -v:quiet: passed across all target frameworks, zero warnings and errors.dotnet test --project tests\Microsoft.Agents.AI.Workflows.UnitTests -f net10.0 --no-restore --filter-method '*OutputExecutor_ResetClearsMessagesAfterInterruptedTurnAsync' --no-progress: two additional regression cases failed before the output executor reset repair; both passed afterward.dotnet test --project tests\Microsoft.Agents.AI.Workflows.UnitTests -f net10.0 --no-restore --filter-method '*MixedWorkflow_RequiresExplicitResetSupportForReuseAsync' --no-progress: failed before preserving explicit reset opt-in; passed after the revision.dotnet test --project tests\Microsoft.Agents.AI.Workflows.UnitTests -f net10.0 --no-restore --filter-method '*StatefulExecutor_PreservesNestedReadUpdatesDuringInitializationAsync' --no-progress: failed before the initialization repair because the nested update was lost; passed afterward.dotnet test --project tests\Microsoft.Agents.AI.Workflows.UnitTests -f net10.0 --no-restore --filter-method '*StatefulExecutor_InitializesOnlyWhenStateIsMissingAsync' --no-progress: both pending and committed state cases failed before deferring factory execution until initialization; both passed afterward.dotnet test --project tests\Microsoft.Agents.AI.Workflows.UnitTests -f net10.0 --no-restore --no-progress: passed, 858 tests. Seven existing tests initially failed after cache removal because the test runner context reinitialized state on every read; all passed after aligning that fixture with the state manager, with assertions unchanged.dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests -f net10.0 --no-restore --no-progress: passed, 1,028 tests.dotnet build src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj --no-restore --tl:off -v:quiet: passed across all target frameworks, zero warnings and errors.dotnet format src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj --no-restore: passed.dotnet format tests\Microsoft.Agents.AI.Workflows.UnitTests\Microsoft.Agents.AI.Workflows.UnitTests.csproj --no-restore: passed.dotnet build agent-framework-dotnet.slnx --tl:off -v:quiet: blocked by unrelated package restore errors (NU1102); the configured feed does not containA2AorA2A.AspNetCoreversion1.0.0-preview3. The full-solution unit suite was not run.Related Issue
N/A - maintainer-requested bugfix tracked internally; no public issue was opened. No matching open PR was found.
AI Assistance
AI assistance details: GitHub Copilot assisted with implementation, regression tests, XML documentation, and this PR description.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.