Skip to content

.NET: coalesce AG-UI text completions#6048

Open
he-yufeng wants to merge 3 commits into
microsoft:mainfrom
he-yufeng:fix/agui-coalesce-text-completions
Open

.NET: coalesce AG-UI text completions#6048
he-yufeng wants to merge 3 commits into
microsoft:mainfrom
he-yufeng:fix/agui-coalesce-text-completions

Conversation

@he-yufeng

Copy link
Copy Markdown
Contributor

Fixes #6010.

Summary

  • Keep one AG-UI text message open across consecutive assistant text completions, even when the provider assigns a new ChatResponseUpdate.MessageId per completion.
  • Continue to split text messages when the chat role changes.
  • Add a regression test covering assistant text around tool-call/tool-result events with different completion IDs.

Validation

  • dotnet build dotnet\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj --no-restore --tl:off
  • dotnet dotnet\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\bin\Debug\net10.0\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.dll --filter-class Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.ChatResponseUpdateAGUIExtensionsTests --timeout 2m
  • dotnet format dotnet\agent-framework-dotnet.slnx --verify-no-changes --include dotnet\src\Microsoft.Agents.AI.AGUI\Shared\ChatResponseUpdateAGUIExtensions.cs dotnet\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\ChatResponseUpdateAGUIExtensionsTests.cs --no-restore --verbosity minimal
  • git diff --check

Copilot AI review requested due to automatic review settings May 22, 2026 22:15
@moonbox3 moonbox3 added the .NET Usage: [Issues, PRs], Target: .Net label May 22, 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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@he-yufeng he-yufeng force-pushed the fix/agui-coalesce-text-completions branch from 63cf392 to 36d9494 Compare June 2, 2026 19:50
@he-yufeng

Copy link
Copy Markdown
Contributor Author

Rebased on current upstream/main and resolved the AGUI text-stream conflict by keeping both fixes: the upstream empty-message-id fallback stays local to text events, and this PR still coalesces assistant text completions across adjacent text chunks.

Validated locally:

dotnet build .\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj -f net10.0 -c Debug --tl:off
dotnet test --project .\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj -f net10.0 -c Debug --no-build -v Normal --report-xunit-trx --ignore-exit-code 8 -- --filter-class Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.ChatResponseUpdateAGUIExtensionsTests
git diff --check upstream/main...HEAD

Result: the targeted test class passed after the conflict resolution.

@he-yufeng

Copy link
Copy Markdown
Contributor Author

Rebased onto current upstream/main and reran the targeted AG-UI validation.

Validation on Windows:

dotnet build .\dotnet\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj -f net10.0 -c Debug --tl:off
# build succeeded, 0 warnings, 0 errors

cd dotnet
dotnet test --project .\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj -f net10.0 -c Debug --no-build -v Normal -- --filter-class Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.ChatResponseUpdateAGUIExtensionsTests
# 11 passed

git diff --check upstream/main...HEAD

Note: because this repo's global.json with the Microsoft.Testing.Platform runner lives under dotnet/, the targeted dotnet test command has to be run from that directory.

@he-yufeng he-yufeng force-pushed the fix/agui-coalesce-text-completions branch from 36d9494 to 099d57a Compare June 4, 2026 04:02
@he-yufeng he-yufeng force-pushed the fix/agui-coalesce-text-completions branch from 099d57a to 06bf735 Compare June 4, 2026 05:00
@he-yufeng

Copy link
Copy Markdown
Contributor Author

Updated this to avoid keeping a text message open across tool events.

The converter now closes the current TextMessage* bracket before emitting ToolCall* or ToolCallResult*, then starts a new text message if text continues afterward. That keeps the .NET AG-UI producer aligned with the Python producer shape instead of nesting tool events inside an open text message.

I also changed the regression test to assert the wire order directly:

TEXT_MESSAGE_START completion-1
TEXT_MESSAGE_CONTENT completion-1
TEXT_MESSAGE_END completion-1
TOOL_CALL_*
TOOL_RESULT
TEXT_MESSAGE_START completion-2
TEXT_MESSAGE_CONTENT completion-2
TEXT_MESSAGE_END completion-2

Validation on Windows:

dotnet build .\dotnet\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj -f net10.0 -c Debug --tl:off
# build succeeded, 0 warnings, 0 errors

dotnet .\dotnet\tests\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests\bin\Debug\net10.0\Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.dll --filter-class Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.ChatResponseUpdateAGUIExtensionsTests --no-progress
# 11 passed

git diff --check

@moonbox3 moonbox3 requested a review from westey-m June 4, 2026 05:39
@moonbox3 moonbox3 enabled auto-merge June 4, 2026 05:39
@moonbox3 moonbox3 requested a review from rogerbarreto June 4, 2026 08:58
@moonbox3 moonbox3 added this pull request to the merge queue Jun 4, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 4, 2026
@moonbox3 moonbox3 added this pull request to the merge queue Jun 4, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 4, 2026
@moonbox3 moonbox3 added this pull request to the merge queue Jun 9, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 9, 2026
@moonbox3 moonbox3 added this pull request to the merge queue Jun 9, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 9, 2026
@he-yufeng

Copy link
Copy Markdown
Contributor Author

Friendly ping: this has two approvals and the latest CI/merge-gatekeeper run is green. Please let me know if there is any remaining AG-UI concern before merge.

@moonbox3 moonbox3 added this pull request to the merge queue Jun 12, 2026
@moonbox3

Copy link
Copy Markdown
Contributor

Friendly ping: this has two approvals and the latest CI/merge-gatekeeper run is green. Please let me know if there is any remaining AG-UI concern before merge.

There was another test failing during merge, which I think was unrelated. Trying the merge again.

@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 12, 2026
@moonbox3 moonbox3 added this pull request to the merge queue Jun 12, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 12, 2026
@he-yufeng

Copy link
Copy Markdown
Contributor Author

This one has been green and approved for a few weeks now. Anything still blocking the merge, or is it just waiting in the queue?

@he-yufeng

Copy link
Copy Markdown
Contributor Author

This has two approvals (@moonbox3, @westey-m) and is mergeable with green CI — could someone merge it when convenient? Happy to rebase if it goes stale. Thanks!

@moonbox3 moonbox3 added this pull request to the merge queue Jun 17, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 17, 2026
@moonbox3

Copy link
Copy Markdown
Contributor

@he-yufeng there is an integration test failing:

failed Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests.BasicStreamingTests.AgentSendsMultipleMessagesInOneTurnAsync (677ms)
  Expected collection to contain more than 1 item(s) because agent should send multiple messages, but found 1: {"8e920ac81a5349919f4481ba0d5236a6"}.
  from /home/runner/work/agent-framework/agent-framework/dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests/bin/Release/net10.0/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests.dll (net10.0|x64)
  Expected collection to contain more than 1 item(s) because agent should send multiple messages, but found 1: {"8e920ac81a5349919f4481ba0d5236a6"}.
    at FluentAssertions.Execution.LateBoundTestFramework.Throw(String message)
    at FluentAssertions.Execution.DefaultAssertionStrategy.HandleFailure(String message)
    at FluentAssertions.Execution.AssertionScope.AddPreFormattedFailure(String formattedFailureMessage)
    at FluentAssertions.Execution.AssertionChain.FailWith(Func`1 getFailureReason)
    at FluentAssertions.Execution.AssertionChain.FailWith(Func`1 getFailureReason)
    at FluentAssertions.Execution.AssertionChain.FailWith(String message, Object[] args)
    at FluentAssertions.Execution.GivenSelector`1.FailWith(String message, Object[] args)
    at FluentAssertions.Execution.GivenSelector`1.FailWith(String message, Func`2[] args)
    at FluentAssertions.Collections.GenericCollectionAssertions`3.<>c__DisplayClass48_0.<HaveCountGreaterThan>b__0(AssertionChain chain)
    at FluentAssertions.Execution.AssertionChain.WithExpectation(String message, Action`1 chain, Object[] args)
    at FluentAssertions.Execution.AssertionChain.WithExpectation(String message, Object arg1, Action`1 chain)
    at FluentAssertions.Collections.GenericCollectionAssertions`3.HaveCountGreaterThan(Int32 expected, String because, Object[] becauseArgs)
    at Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests.BasicStreamingTests.AgentSendsMultipleMessagesInOneTurnAsync() in /home/runner/work/agent-framework/agent-framework/dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests/BasicStreamingTests.cs:189
    --- End of stack trace from previous location ---
/home/runner/work/agent-framework/agent-framework/dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests/bin/Release/net10.0/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests.dll (net10.0|x64) failed with 1 error(s) (5s 868ms)
Exit code: 2

@he-yufeng

Copy link
Copy Markdown
Contributor Author

Thanks @moonbox3, good catch. I looked into it and the failure is a real consequence of this PR, not flaky.

AgentSendsMultipleMessagesInOneTurnAsync feeds three assistant text completions, each with its own MessageId and nothing between them (no tool call, no role change), then asserts the AG-UI round-trip yields more than one message. This PR coalesces consecutive same-role text across MessageId changes, so those three collapse into one text message and the assertion trips.

The wrinkle is that this is the exact shape #6010 wants coalesced. The issue's own repro (TwoCompletionsWithDifferentMessageIds_ProducesTwoTextMessages) treats "two consecutive text completions, different MessageIds, nothing between them" as the bug, while this integration test treats the same shape as the desired result. Both can't hold: at the update level a fragmented single completion and two deliberately distinct messages are indistinguishable (same role, distinct non-null MessageIds, no separator).

My read is that the integration test encodes the pre-#6010 behavior and should move to the coalesced contract: one text message, content preserved in order, still split whenever the role changes or a tool call/result lands between (the unit test in this PR already covers those boundaries). I'm happy to rebase onto main and push that test update now.

If you'd rather keep multi-message turns distinct on the AG-UI surface, then #6010 needs a narrower fix, probably where the provider hands out a fresh MessageId per completion above AG-UI, and I'll close this in favor of that. Tell me which way you'd like to go and I'll turn it around.

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: [Bug]: AG-UI host generates as many text messages as completions

4 participants