Skip to content

.NET: fix: preserve AG-UI event metadata#5816

Open
he-yufeng wants to merge 4 commits into
microsoft:mainfrom
he-yufeng:fix/agui-text-additional-properties
Open

.NET: fix: preserve AG-UI event metadata#5816
he-yufeng wants to merge 4 commits into
microsoft:mainfrom
he-yufeng:fix/agui-text-additional-properties

Conversation

@he-yufeng
Copy link
Copy Markdown
Contributor

Summary

  • preserve TextContent.AdditionalProperties as AG-UI passthrough fields on text start/content events
  • preserve event passthrough fields when converting AG-UI text events back to TextContent
  • carry DataContent.AdditionalProperties through state snapshot/delta events as the same passthrough metadata path
  • filter event-owned fields like type, messageId, delta, and snapshot so metadata cannot shadow AG-UI protocol fields

Fixes #4923

Validation

  • dotnet run --project dotnet\tests\Microsoft.Agents.AI.AGUI.UnitTests\Microsoft.Agents.AI.AGUI.UnitTests.csproj --framework net10.0 -- --filter-class Microsoft.Agents.AI.AGUI.UnitTests.ChatResponseUpdateAGUIExtensionsTests
  • dotnet run --project dotnet\tests\Microsoft.Agents.AI.AGUI.UnitTests\Microsoft.Agents.AI.AGUI.UnitTests.csproj --framework net10.0
  • dotnet format dotnet\agent-framework-dotnet.slnx --verify-no-changes --include dotnet\src\Microsoft.Agents.AI.AGUI\Shared\BaseEvent.cs dotnet\src\Microsoft.Agents.AI.AGUI\Shared\ChatResponseUpdateAGUIExtensions.cs dotnet\tests\Microsoft.Agents.AI.AGUI.UnitTests\ChatResponseUpdateAGUIExtensionsTests.cs
  • git diff --check

Copilot AI review requested due to automatic review settings May 13, 2026 16:11
@moonbox3 moonbox3 added the .NET label May 13, 2026
@github-actions github-actions Bot changed the title fix: preserve AG-UI event metadata .NET: fix: preserve AG-UI event metadata May 13, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 updates the .NET AG-UI adapter layer to preserve AIContent.AdditionalProperties as AG-UI “passthrough” JSON fields when converting between ChatResponseUpdate streams and AG-UI event streams, while filtering reserved protocol-owned field names so they can’t be shadowed by metadata.

Changes:

  • Add JsonExtensionData support to AG-UI events (BaseEvent) to carry arbitrary passthrough fields.
  • Preserve passthrough metadata across conversions (TextContentTEXT_MESSAGE_* events, DataContentSTATE_* events) with reserved-field filtering.
  • Add unit tests validating passthrough emission, filtering of reserved fields, and round-tripping back into AIContent.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
dotnet/src/Microsoft.Agents.AI.AGUI/Shared/BaseEvent.cs Adds JsonExtensionData-backed AdditionalProperties for AG-UI passthrough fields on all events.
dotnet/src/Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs Copies AdditionalProperties between AIContent and events and filters reserved protocol fields during event emission.
dotnet/tests/Microsoft.Agents.AI.AGUI.UnitTests/ChatResponseUpdateAGUIExtensionsTests.cs Adds coverage for preserving passthrough metadata and ensuring reserved fields aren’t shadowed in serialized output.

Comment on lines 238 to +254
public void AddTextStart(TextMessageStartEvent textStart)
{
if (this._currentRole != default || this._currentMessageId != null)
{
throw new InvalidOperationException("Received TextMessageStartEvent while another message is being processed.");
}

this._currentRole = AGUIChatMessageExtensions.MapChatRole(textStart.Role);
this._currentMessageId = textStart.MessageId;
}

internal ChatResponseUpdate EmitTextUpdate(TextMessageContentEvent textContent)
{
TextContent content = new(textContent.Delta)
{
AdditionalProperties = CopyAdditionalProperties(textContent)
};
Comment on lines 712 to 728
@@ -660,12 +718,13 @@
#if !NET
Delta = (JsonElement?)JsonSerializer.Deserialize(
dataContent.Data.ToArray(),
jsonSerializerOptions.GetTypeInfo(typeof(JsonElement)))
jsonSerializerOptions.GetTypeInfo(typeof(JsonElement))),
#else
Delta = (JsonElement?)JsonSerializer.Deserialize(
dataContent.Data.Span,
jsonSerializerOptions.GetTypeInfo(typeof(JsonElement)))
jsonSerializerOptions.GetTypeInfo(typeof(JsonElement))),
#endif
AdditionalProperties = CopyAdditionalProperties(dataContent, "type", "delta")
};
@he-yufeng
Copy link
Copy Markdown
Contributor Author

Addressed both review comments in a follow-up commit.

Changes:

  • TextMessageBuilder now captures passthrough metadata from TextMessageStartEvent and merges it into emitted TextContent.AdditionalProperties.
  • When the same key exists on START and CONTENT, the CONTENT value wins.
  • BaseEventJsonConverter.Read now maps STATE_DELTA to StateDeltaEvent, matching the existing write path.
  • Added tests for START metadata merging and STATE_DELTA BaseEvent deserialization.

Local validation:

dotnet build dotnet\tests\Microsoft.Agents.AI.AGUI.UnitTests\Microsoft.Agents.AI.AGUI.UnitTests.csproj --no-restore
dotnet dotnet\tests\Microsoft.Agents.AI.AGUI.UnitTests\bin\Debug\net10.0\Microsoft.Agents.AI.AGUI.UnitTests.dll --filter-method '*AsChatResponseUpdatesAsync_WithTextStartAdditionalProperties_PreservesAndMergesMetadataAsync' --filter-method '*BaseEventJsonConverter_WithStateDeltaEvent_DeserializesStateDeltaEvent' --filter-method '*AsAGUIEventStreamAsync_ConvertsDataContentWithJsonPatch_ToStateDeltaEventAsync' --filter-method '*AsChatResponseUpdatesAsync_WithTextEventAdditionalProperties_PreservesTextContentMetadataAsync' --no-progress
dotnet format dotnet\agent-framework-dotnet.slnx --verify-no-changes --no-restore --include dotnet\src\Microsoft.Agents.AI.AGUI\Shared\ChatResponseUpdateAGUIExtensions.cs dotnet\src\Microsoft.Agents.AI.AGUI\Shared\BaseEventJsonConverter.cs dotnet\tests\Microsoft.Agents.AI.AGUI.UnitTests\ChatResponseUpdateAGUIExtensionsTests.cs
git diff --check

Result: build succeeded with 0 warnings/errors; 4 targeted tests passed; format and diff checks passed.

Note: dotnet test with this .NET 10 SDK hits the Microsoft.Testing.Platform/VSTest transition error, so I used the built MTP test assembly directly for the targeted run.

@he-yufeng he-yufeng force-pushed the fix/agui-text-additional-properties branch from 3c5586b to b04daf6 Compare May 14, 2026 14:33
@he-yufeng
Copy link
Copy Markdown
Contributor Author

Rebased this branch onto current main and force-pushed with lease. Re-ran the focused AG-UI validation after the rebase: AGUI unit-test project build passed with 0 warnings/errors; the text START metadata test, StateDelta BaseEvent converter test, JSON Patch StateDelta emission test, and existing text-event metadata test all passed; dotnet format --verify-no-changes passed for the touched files; git diff --check passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.NET: [Bug]: TextContent.AdditionalProperties dropped by AsAGUIEventStreamAsync for TEXT_MESSAGE_START/TEXT_MESSAGE_CONTENT events

3 participants