Skip to content

.NET: Refactor Workflows MessageMerger to preserve message order and structure#6826

Open
marcominerva wants to merge 9 commits into
microsoft:mainfrom
marcominerva:workflws-as-agent-message-order-fix
Open

.NET: Refactor Workflows MessageMerger to preserve message order and structure#6826
marcominerva wants to merge 9 commits into
microsoft:mainfrom
marcominerva:workflws-as-agent-message-order-fix

Conversation

@marcominerva

Copy link
Copy Markdown
Contributor

Summary

Refactored MessageMerger to delegate update grouping and merging to M.E.AI, preserving the correct order and structure of assistant messages, especially for reasoning content without message IDs. Removed per-message bucketing and CreatedAt-based sorting. Added tests to verify message order and correct merging of reasoning and text updates.

Refactoring and Simplification:

  • The ResponseMergeState class now maintains a single ordered list of updates (_updates) instead of bucketing updates by message ID and separately tracking dangling updates. Grouping and coalescing of updates into messages is now handled by M.E.AI's ToAgentResponse method, ensuring correct merging of reasoning and text, as well as preserving message order.
  • The custom merge logic for responses and the manual ordering by CreatedAt timestamp have been removed, eliminating previous issues where reasoning content without a timestamp could be reordered incorrectly. [1] [2] [3]

Bug Fixes and Behavioral Improvements:

  • The merger now preserves the order of reasoning and text messages, even when reasoning messages lack a CreatedAt timestamp, and correctly merges id-less reasoning updates with subsequent text into a single message when appropriate.

Testing:

  • Added two new unit tests to verify that (1) message order is preserved when reasoning lacks a CreatedAt timestamp, and (2) reasoning and text are merged into a single message when reasoning updates lack a message ID, matching the behavior of directly-invoked agents.

Closes #6329

Refactored MessageMerger to delegate update grouping and merging to M.E.AI, preserving the correct order and structure of assistant messages, especially for reasoning content without message IDs. Removed per-message bucketing and CreatedAt-based sorting. Added tests to verify message order and correct merging of reasoning and text updates.
Copilot AI review requested due to automatic review settings June 30, 2026 12:44
@moonbox3 moonbox3 added .NET Usage: [Issues, PRs], Target: .Net workflows Usage: [Issues, PRs], Target: Workflows labels Jun 30, 2026
@github-actions github-actions Bot changed the title Refactor Workflows MessageMerger to preserve message order and structure .NET: Refactor Workflows MessageMerger to preserve message order and structure Jun 30, 2026

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.

Pull request overview

This PR refactors the .NET MessageMerger in Microsoft.Agents.AI.Workflows to preserve assistant message order/structure by delegating update grouping and coalescing to Microsoft.Extensions.AI’s ToAgentResponse, addressing the reasoning-vs-text ordering/structure discrepancy reported in #6329.

Changes:

  • Refactored MessageMerger to maintain a single ordered update list per response and rely on ToAgentResponse for message reconstruction (removing per-message bucketing and CreatedAt-based sorting).
  • Simplified response merging logic and handling of id-less (“dangling”) updates.
  • Added unit tests to validate ordering when reasoning lacks CreatedAt, and merging reasoning + text into a single assistant message when reasoning updates lack MessageId.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
dotnet/src/Microsoft.Agents.AI.Workflows/MessageMerger.cs Refactors merge state to preserve streaming/arrival order and delegate message grouping to ToAgentResponse.
dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/MessageMergerTests.cs Adds tests covering ordering and reasoning/text merge behavior for id-less reasoning updates.

Comment thread dotnet/src/Microsoft.Agents.AI.Workflows/MessageMerger.cs Outdated
Removed logic for tracking unique creation times and now always assign DateTimeOffset.UtcNow to the merged response's CreatedAt property. This simplifies timestamp handling during message merging.
@marcominerva

Copy link
Copy Markdown
Contributor Author

Hi @rogerbarreto!

I'm just asking to understand the situation, I definitely don't want to rush you. Is there anything I need to do on the branch so you can continue with the review?

I noticed there's one failing test, but it seems to be related to an XunitException in OpenTelemetryAgentTests.Ctor_NullOrWhitespaceSourceName_AutoWiredChatClientUsesDefaultSource_Async:
https://github.com/microsoft/agent-framework/actions/runs/28799163307/job/85397632168#step:9:230

@peibekwe

Copy link
Copy Markdown
Contributor

@marcominerva could you please resolve the conflict with main? We recently made changes to MessageMerger as well to address #5720.

Refactored MessageMerger to fold identifierless reasoning segments into the following id'd message at the flattened-message level, ensuring correct merging across response buckets (fixes microsoft#6329). Updated ComputeMerged to merge id-less messages with the next message of the same role. Removed redundant per-bucket folding logic. Added unit tests to verify correct folding behavior and role matching.
@marcominerva

Copy link
Copy Markdown
Contributor Author

@peibekwe MessageMerger.cs has had several changes. I believe I've reconciled everything, but please let me know if I missed anything.

Comment thread dotnet/src/Microsoft.Agents.AI.Workflows/MessageMerger.cs Outdated
Comment thread dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/MessageMergerTests.cs Outdated
Comment thread dotnet/src/Microsoft.Agents.AI.Workflows/MessageMerger.cs Outdated
@peibekwe

Copy link
Copy Markdown
Contributor

@marcominerva - Thanks for the quick update to the PR branch! Please take a look at the few comments and we can get the review finalized.

 Removed the unused Role property from MessageMergeState for code cleanliness.
Changed MessageMerger to iterate messages in reverse order, ensuring all consecutive messages without IDs preceding a message with an ID are merged correctly. Updated merging logic, index handling, and comments to reflect this new approach.
@marcominerva

Copy link
Copy Markdown
Contributor Author

@peibekwe done 😉

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 workflows Usage: [Issues, PRs], Target: Workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: [Bug]: Inconsistent session message structure between Agent and Workflow-as-Agent

5 participants