Description
AddAGUIServer() registers the AG-UI wire types through AGUIJsonSerializerContext.Default.Options.TypeInfoResolver. AGUI 0.0.6 moved the "omit a property that has no value" rule off that resolver. In 0.0.5 the rule came from DefaultIgnoreCondition on the context's own options; in 0.0.6 it lives on the new AGUIJsonUtilities.DefaultTypeInfoResolver, which applies it per property with a type-info modifier so it travels with the resolver into other JsonSerializerOptions.
The consequence, for an app on hosting 1.17–1.19 with AGUI.Server / AGUI.Abstractions raised to 0.0.6, is that every SSE event goes out with explicit nulls for its optional fields:
data: {"type":"RUN_STARTED","threadId":"…","runId":"…","parentRunId":null,"input":null,"timestamp":null,"rawEvent":null,"metadata":null}
The AG-UI TypeScript client (@ag-ui/client 0.0.59) declares those fields optional, not nullable, so it rejects the first event and the whole run fails client-side:
ZodError: [
{ "code": "invalid_type", "expected": "string", "received": "null", "path": ["parentRunId"] },
{ "code": "invalid_type", "expected": "object", "received": "null", "path": ["input"] },
…
]
AGUIJsonUtilities' own doc comment names this exact failure — "would start writing "parentMessageId": null and similar — the exact wire divergence that receiving SDKs have had to be patched to tolerate" — and tells integrators to compose AGUIJsonUtilities.DefaultTypeInfoResolver rather than the context directly.
This is not visible in this repo's own CI today because dotnet/Directory.Packages.props pins the AGUI packages at 0.0.5. It becomes the default behavior the moment that pin moves to 0.0.6.
Suggested fix — in ConfigureAGUIJsonOptions.Configure:
chain.Add(AgentAbstractionsJsonUtilities.DefaultOptions.TypeInfoResolver!);
-chain.Add(AGUIJsonSerializerContext.Default.Options.TypeInfoResolver!);
+chain.Add(AGUIJsonUtilities.DefaultTypeInfoResolver);
AGUIJsonUtilities.DefaultTypeInfoResolver is AGUIJsonSerializerContext.Default with the omit-empty modifier attached, so it resolves the same types and only changes what is written for properties with no value. It is new in 0.0.6, so this line and the package bump have to land together.
Code Sample
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAGUIServer();
builder.AddAIAgent("agent", (sp, name) => new ChatClientAgent(chatClient, new ChatClientAgentOptions { Name = name }));
var app = builder.Build();
app.MapAGUIServer("/ag-ui", app.Services.GetRequiredKeyedService<AIAgent>("agent"));
app.Run();
With AGUI.Server / AGUI.Abstractions raised to 0.0.6, curl -N -H 'Accept: text/event-stream' … on that endpoint shows "timestamp": null, "metadata": null, "parentRunId": null and "input": null on the events. With 0.0.5 the same fields are omitted.
Workaround for anyone hitting this before the fix lands — put the modified resolver first in the chain, after AddAGUIServer():
builder.Services.Configure<JsonOptions>(options =>
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AGUIJsonUtilities.DefaultTypeInfoResolver));
Error Messages / Stack Traces
Agent execution failed: ZodError: [
{ "code": "invalid_type", "expected": "number", "received": "null", "path": ["timestamp"], "message": "Expected number, received null" },
{ "code": "invalid_type", "expected": "object", "received": "null", "path": ["metadata"], "message": "Expected object, received null" },
{ "code": "invalid_type", "expected": "string", "received": "null", "path": ["parentRunId"], "message": "Expected string, received null" },
{ "code": "invalid_type", "expected": "object", "received": "null", "path": ["input"], "message": "Expected object, received null" }
]
Package Versions
Microsoft.Agents.AI.Hosting.AGUI.AspNetCore 1.17.0-preview.260804.1 (the same code is in 1.19.0-preview.260822.1 and on main)
AGUI.Server / AGUI.Abstractions 0.0.6
Microsoft.Extensions.AI 10.8.3
- Client:
@ag-ui/client 0.0.59
.NET Version
net10.0
Additional Context
Both current hosting previews (1.17, 1.19) declare AGUI 0.0.5, so ConfigureAGUIJsonOptions and the AGUI package version have to move together for the wire format to stay unchanged.
Description
AddAGUIServer()registers the AG-UI wire types throughAGUIJsonSerializerContext.Default.Options.TypeInfoResolver. AGUI 0.0.6 moved the "omit a property that has no value" rule off that resolver. In 0.0.5 the rule came fromDefaultIgnoreConditionon the context's own options; in 0.0.6 it lives on the newAGUIJsonUtilities.DefaultTypeInfoResolver, which applies it per property with a type-info modifier so it travels with the resolver into otherJsonSerializerOptions.The consequence, for an app on hosting 1.17–1.19 with AGUI.Server / AGUI.Abstractions raised to 0.0.6, is that every SSE event goes out with explicit nulls for its optional fields:
The AG-UI TypeScript client (
@ag-ui/client0.0.59) declares those fields optional, not nullable, so it rejects the first event and the whole run fails client-side:AGUIJsonUtilities' own doc comment names this exact failure — "would start writing"parentMessageId": nulland similar — the exact wire divergence that receiving SDKs have had to be patched to tolerate" — and tells integrators to composeAGUIJsonUtilities.DefaultTypeInfoResolverrather than the context directly.This is not visible in this repo's own CI today because
dotnet/Directory.Packages.propspins the AGUI packages at 0.0.5. It becomes the default behavior the moment that pin moves to 0.0.6.Suggested fix — in
ConfigureAGUIJsonOptions.Configure:AGUIJsonUtilities.DefaultTypeInfoResolverisAGUIJsonSerializerContext.Defaultwith the omit-empty modifier attached, so it resolves the same types and only changes what is written for properties with no value. It is new in 0.0.6, so this line and the package bump have to land together.Code Sample
With
AGUI.Server/AGUI.Abstractionsraised to 0.0.6,curl -N -H 'Accept: text/event-stream' …on that endpoint shows"timestamp": null,"metadata": null,"parentRunId": nulland"input": nullon the events. With 0.0.5 the same fields are omitted.Workaround for anyone hitting this before the fix lands — put the modified resolver first in the chain, after
AddAGUIServer():Error Messages / Stack Traces
Agent execution failed: ZodError: [ { "code": "invalid_type", "expected": "number", "received": "null", "path": ["timestamp"], "message": "Expected number, received null" }, { "code": "invalid_type", "expected": "object", "received": "null", "path": ["metadata"], "message": "Expected object, received null" }, { "code": "invalid_type", "expected": "string", "received": "null", "path": ["parentRunId"], "message": "Expected string, received null" }, { "code": "invalid_type", "expected": "object", "received": "null", "path": ["input"], "message": "Expected object, received null" } ]Package Versions
Microsoft.Agents.AI.Hosting.AGUI.AspNetCore1.17.0-preview.260804.1 (the same code is in 1.19.0-preview.260822.1 and onmain)AGUI.Server/AGUI.Abstractions0.0.6Microsoft.Extensions.AI10.8.3@ag-ui/client0.0.59.NET Version
net10.0
Additional Context
Both current hosting previews (1.17, 1.19) declare AGUI 0.0.5, so
ConfigureAGUIJsonOptionsand the AGUI package version have to move together for the wire format to stay unchanged.