Repository navigation
Labels
.NETUsage: [Issues, PRs], Target: .NetUsage: [Issues, PRs], Target: .Netag-uiUsage: [Issues, PRs], Target: AG-UI protocol integrationUsage: [Issues, PRs], Target: AG-UI protocol integrationhostingUsage: [Issues, PRs], Target: all hosting related solutionsUsage: [Issues, PRs], Target: all hosting related solutionsreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
Description
Description
MapAGUIServer writes a stream that the official AG-UI TypeScript client (@ag-ui/client 1.0.1, used by CopilotKit 1.76) rejects. Separately, any interrupt makes the run end in RUN_ERROR. Both defects come from ConfigureAGUIJsonOptions in Microsoft.Agents.AI.Hosting.AGUI.AspNetCore, which AddAGUIServer() registers:
// Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.ConfigureAGUIJsonOptions (1.23.0-preview.260928.1, decompiled)
public void Configure(JsonOptions options)
{
var chain = options.SerializerOptions.TypeInfoResolverChain;
chain.Add(AgentAbstractionsJsonUtilities.DefaultOptions.TypeInfoResolver);
chain.Add(((JsonSerializerContext)AGUIJsonSerializerContext.Default).Options.TypeInfoResolver);
}1. Optional event fields are written as null, and the official client rejects them.
- Cause: the method appends the raw
AGUIJsonSerializerContextresolver.AGUI.AbstractionsdocumentsAGUIJsonUtilities.DefaultTypeInfoResolver(that context plusOmitPropertiesWithoutAValue) as the resolver to use instead. - What happens:
RUN_STARTEDgoes out with"parentRunId": nulland"input": null, and interrupts carry"subagentRunId": null.@ag-ui/client's schema validation fails on the first event, so no run can be followed from a browser. - Expected: optional fields without a value are omitted, as
AGUIJsonUtilities.DefaultTypeInfoResolverdoes.
2. Interrupts cannot be serialized.
- Cause: the method never calls
AGUIJsonUtilities.RegisterInterruptContentTypes. - What happens: an agent that yields
InterruptRequestContentmakes the server fail the run. The same happens when the response update containing one is serialized, for example forrawEvent. The client receivesRUN_ERROR("An error occurred while streaming the agent response.") instead of aRUN_FINISHEDwhose outcome is an interrupt. - Expected:
AddAGUIServer()registers the interrupt content types, so the protocol's own interrupt/resume works out of the box.
Steps to reproduce
- Use
builder.Services.AddAGUIServer();andapp.MapAGUIServer("/agui", agent);with anyChatClientAgent. - POST a run and read the stream with
@ag-ui/client'sHttpAgent. You get a ZodError onRUN_STARTED(defect 1). - Have the agent's chat client yield
new ChatResponseUpdate(ChatRole.Assistant, [new InterruptRequestContent("ask-1") { Reason = "input_required", Message = "?" }]). The run ends inRUN_ERROR(defect 2).
Code Sample
```csharp
// Workaround we use today; with it, both cases work end to end with @ag-ui/client and CopilotKit.
builder.Services.AddAGUIServer();
builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(o =>
AGUIJsonUtilities.RegisterInterruptContentTypes(o.SerializerOptions));
builder.Services.PostConfigure<Microsoft.AspNetCore.Http.Json.JsonOptions>(o =>
o.SerializerOptions.TypeInfoResolverChain.Insert(0, AGUIJsonUtilities.DefaultTypeInfoResolver));
```Error Messages / Stack Traces
```
// 1 — @ag-ui/client 1.0.1 on RUN_STARTED:
ZodError: parentRunId: expected string, received null; input: expected object, received null
// 2 — server, when an InterruptRequestContent is serialized:
System.NotSupportedException: Runtime type 'AGUI.Abstractions.InterruptRequestContent' is not supported by polymorphic type 'Microsoft.Extensions.AI.AIContent'.
```Package Versions
Microsoft.Agents.AI.Hosting.AGUI.AspNetCore: 1.23.0-preview.260928.1, Microsoft.Agents.AI: 1.23.0, Microsoft.Agents.AI.Hosting: 1.23.0-preview.260928.1, AGUI.Abstractions: 1.0.0, AGUI.Server: 1.0.0, Microsoft.Extensions.AI.Abstractions: 10.10.1
.NET Version
.NET 10 (SDK 10.0.401)
Additional Context
- Version scope: 1.22.0-preview.260918.1 has the same
ConfigureAGUIJsonOptions, and it also targetsAGUI.*0.0.6. - Suggested fix: in
ConfigureAGUIJsonOptions.Configure, insertAGUIJsonUtilities.DefaultTypeInfoResolver(rather than adding the raw context) and callAGUIJsonUtilities.RegisterInterruptContentTypes(options.SerializerOptions).
Reacted by Mario Grabinsky
Metadata
Metadata
Assignees
Labels
.NETUsage: [Issues, PRs], Target: .NetUsage: [Issues, PRs], Target: .Netag-uiUsage: [Issues, PRs], Target: AG-UI protocol integrationUsage: [Issues, PRs], Target: AG-UI protocol integrationhostingUsage: [Issues, PRs], Target: all hosting related solutionsUsage: [Issues, PRs], Target: all hosting related solutionsreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
Type
Projects
- StatusShow more project fieldsDone
Activity
petarnenov commentedon Oct 2, 2026
Update after more searching: defect 1 (null optional fields) is the same as #7919, and it is still present in 1.23.0-preview.260928.1 with
AGUI.*1.0.0. Defect 2 is not covered there:AGUIJsonUtilities.RegisterInterruptContentTypesis never called, soInterruptRequestContentcannot be serialized and interrupts end inRUN_ERROR. The AG-UI SDK side of defect 1 is tracked in ag-ui-protocol/ag-ui#2816.github-actions commentedon Oct 2, 2026
🤖 Automated triage reproduction notes (agent-authored — trust but verify)
Agent analysis
Repro:
dotnet/src/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore/ConfigureAGUIJsonOptions.cs::Configurelines 15-25 produces both failures through the options registered byAddAGUIServer(). Serializing an unsetRunStartedEventasBaseEventemitsparentRunIdandinputas null; serializingInterruptRequestContentasAIContentthrowsNotSupportedException. Minimal repro: resolve ASP.NET CoreJsonOptionsafter callingAddAGUIServer()and perform those twoJsonSerializer.Serializecalls.dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests/ConfigureAGUIJsonOptionsTests.cs1.23.0-preview.260928.11.23.0-preview.260928.1aetherxeg-source commentedon Oct 2, 2026
This exposes a useful interoperability invariant:
"serialized event != protocol-valid event"
Producing JSON successfully is not sufficient evidence that the emitted object satisfies the protocol contract consumed by another implementation.
For AG-UI I would bind each outgoing event to:
"event schema version + serializer semantics + registered polymorphic types"
and validate at that boundary.
A strong conformance suite should round-trip every event family through the official client schema, including:
The failure mode to prevent is especially important:
"serializer fallback -> syntactically valid JSON -> semantically invalid protocol event"
That state should be impossible to classify as successful emission.
This also suggests treating interrupt registration as part of the effective serialization contract, not optional initialization detail.
Related reference implementation / design work: AETHER X GLOBAL ExecSurface — https://github.com/AETHERXGLOBAL/execsurface
1aifanatic commentedon Oct 3, 2026
PR #7920 already addresses the null-field/resolver defect. I will address the separate missing interrupt-content registration here with serialization regression tests, keeping the change complementary to #7920.