Skip to content

.NET: fall back when a restored agent mode is no longer configured - #9873

Open
NingLin Liu (ninglinLiu) wants to merge 14 commits into
microsoft:mainfrom
ninglinLiu:fix/9829-mode-restore-fallback
Open

NingLin Liu (ninglinLiu) wants to merge 14 commits into
microsoft:mainfrom
ninglinLiu:fix/9829-mode-restore-fallback

Conversation

@ninglinLiu

Copy link
Copy Markdown
Contributor

Motivation & Context

AgentModeProvider validates the default mode and every SetModeAsync / mode_set call against the configured modes, but a mode restored from persisted session state is not validated. After an app removes or renames a mode, sessions saved before that change keep the old mode: GetModeAsync returns it, instructions mention it, and SetModeAsync would reject setting it again.

Description & Review Guide

  • What are the major changes? GetModeAsync, ProvideAIContextAsync, and mode_get now run restored modes through EnsureConfiguredMode, which falls back to the configured default and persists the correction — matching Python get_agent_mode.
  • What is the impact of these changes? Stale mode names from older configurations no longer stick after restore.
  • What do you want reviewers to focus on? Parity with Python fallback and the new restore regression test.

Related Issue

Fixes #9829

AI Assistance

  • No material AI assistance was used.
  • This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.

AI assistance details: Assisted with implementation and the restore regression test; I reviewed the change against Python get_agent_mode and the issue repro, and accept responsibility for the change.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

GetModeAsync / ProvideAIContextAsync / mode_get now reset to the
configured default when session state holds a mode that was removed,
matching Python get_agent_mode.

Fixes microsoft#9829

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Restoring the fallback mode leaves a pending notification marker intact, causing a spurious draft-to-draft mode-change notification on the next invocation; the marker must be cleared and the restore-and-invoke case tested.

1 open issue
What changed in this PR

This PR addresses #9829 by making .NET AgentModeProvider fall back to the configured default when a restored session references a removed mode, matching Python behavior.

Changes:

  • Validate restored modes in GetModeAsync, AI context generation, and mode_get.
  • Persist the fallback mode in session state.
  • Add a regression test for restoring a session after its mode is removed.
File Description
dotnet/​tests/​Microsoft.Agents.AI.UnitTests/​Harness/​AgentMode/​AgentModeProviderTests.cs Tests fallback after restoring an obsolete mode.
dotnet/​src/​Microsoft.Agents.AI/​Harness/​AgentMode/​AgentModeProvider.cs Centralizes restored-mode validation and persists corrections.

Review effort: Balanced

Comment on lines +808 to +812
string mode = await v2.GetModeAsync(restored);

// Assert
Assert.Equal("draft", mode);
Assert.Equal("draft", await v2.GetModeAsync(restored));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why call GetModeAsync twice and check it's output twice?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — the second GetModeAsync is intentional: the first call is what performs the fallback and persists draft into session state, and the second call asserts that the rewritten mode sticks (so a later restore/read does not re-trigger fallback or flip back to the removed "review" id). Happy to collapse it to a single read + a StateBag assertion if you prefer that shape.

@kartikmadan11

Copy link
Copy Markdown
Contributor

this fixed my repro

This branch was previously deployed

1 inactive deployment
github-app-auth — 08f85a72 Deployed Oct 30, 2026 by ninglinLiu via add_label #26748
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

.NET Usage: [Issues, PRs], Target: .Net

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: AgentModeProvider keeps a restored mode that is no longer configured

4 participants