Description
On Microsoft.Agents.AI.Hosting.AGUI.AspNetCore version 1.0.0-preview.260311.1, our copilot kit front end would display each tool call made by the remote agent, as expected.
Once we update to version 1.3.0-preview.260423.1, those are not shown anymore.
I can't give a lot of information about the code or screenshots unfortunately but here is an AI analysis (unverified)
● I found the root cause. It's a regression introduced in commit ca02146 ("BugFix #3433 ChatClientAgent streaming responses missing messageid") in agent-framework, which shipped in 1.3.0-preview.260423.1 but not in 1.0.0-preview.260311.1.
What changed
In Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs, AsAGUIEventStreamAsync got this new block (lines 343–353):
string? streamingMessageId = null;
await foreach (var chatResponse in updates.WithCancellation(cancellationToken).ConfigureAwait(false))
{
if (string.IsNullOrWhiteSpace(chatResponse.MessageId))
{
streamingMessageId ??= Guid.NewGuid().ToString("N");
chatResponse.MessageId = streamingMessageId;
}
...
Note the ??=. A single fallback streamingMessageId is generated once per stream and applied to every chunk whose provider didn't supply a MessageId.
Why it breaks tool-call rendering
The same chatResponse.MessageId is used for two semantically different events further down in that method:
- ToolCallStartEvent.ParentMessageId = chatResponse.MessageId — the assistant message the tool call belongs to (correct usage)
- ToolCallResultEvent.MessageId = chatResponse.MessageId — the id of the tool-role result message itself, which must be distinct from the assistant message (ToolCallResultEvent.cs:18-19)
When the provider (Azure OpenAI with FunctionInvokingChatClient round-trips) doesn't set MessageId on the tool-result chunk, both the assistant text message and the tool result message now share the same id. CopilotKit deduplicates by messageId, so the tool result event
collides with the assistant message and the FE never renders a separate tool-call row. The fix author's own unit test (AGUIStreamingMessageIdTests.cs) explicitly asserts "All events should share the same generated MessageId" — they didn't catch that this includes tool result
events.
In 1.0.0-preview.260311.1 the MessageId stayed null, so CopilotKit assigned each event its own id and the rows rendered correctly.
Options
- Stay on 1.0.0-preview.260311.1 (current committed state) — keeps tool-call rendering. Trade-off: the bug the new version was trying to fix (text content silently dropped when LLM provider returns null MessageId) is back. For Azure OpenAI in Warlock we've never observed that
in practice, since Azure OpenAI does set MessageIds.
- File an upstream bug on agent-framework — the fix should generate a distinct fallback id per logical message boundary (e.g. flip to a new id when the chunk contains FunctionResultContent, or use the FunctionResultContent.CallId).
- Workaround at our IChatClient layer — inject a decorator that assigns distinct MessageIds before chunks reach the AGUI converter. Adds complexity for an upstream bug.
My recommendation: drop the working-tree bump back to 1.0.0 (option 1) and file an upstream issue. The bug ca02146 was fixing doesn't affect us (Azure OpenAI populates MessageId), and the regression is real. Want me to draft the upstream issue?
Code Sample
Error Messages / Stack Traces
Package Versions
Microsoft.Agents.AI.Hosting.AGUI.AspNetCore 1.3.0-preview.260423.1
.NET Version
NET 10
Additional Context
No response
Description
On Microsoft.Agents.AI.Hosting.AGUI.AspNetCore version 1.0.0-preview.260311.1, our copilot kit front end would display each tool call made by the remote agent, as expected.
Once we update to version 1.3.0-preview.260423.1, those are not shown anymore.
I can't give a lot of information about the code or screenshots unfortunately but here is an AI analysis (unverified)
● I found the root cause. It's a regression introduced in commit ca02146 ("BugFix #3433 ChatClientAgent streaming responses missing messageid") in agent-framework, which shipped in 1.3.0-preview.260423.1 but not in 1.0.0-preview.260311.1.
What changed
In Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs, AsAGUIEventStreamAsync got this new block (lines 343–353):
string? streamingMessageId = null;
await foreach (var chatResponse in updates.WithCancellation(cancellationToken).ConfigureAwait(false))
{
if (string.IsNullOrWhiteSpace(chatResponse.MessageId))
{
streamingMessageId ??= Guid.NewGuid().ToString("N");
chatResponse.MessageId = streamingMessageId;
}
...
Note the ??=. A single fallback streamingMessageId is generated once per stream and applied to every chunk whose provider didn't supply a MessageId.
Why it breaks tool-call rendering
The same chatResponse.MessageId is used for two semantically different events further down in that method:
When the provider (Azure OpenAI with FunctionInvokingChatClient round-trips) doesn't set MessageId on the tool-result chunk, both the assistant text message and the tool result message now share the same id. CopilotKit deduplicates by messageId, so the tool result event
collides with the assistant message and the FE never renders a separate tool-call row. The fix author's own unit test (AGUIStreamingMessageIdTests.cs) explicitly asserts "All events should share the same generated MessageId" — they didn't catch that this includes tool result
events.
In 1.0.0-preview.260311.1 the MessageId stayed null, so CopilotKit assigned each event its own id and the rows rendered correctly.
Options
in practice, since Azure OpenAI does set MessageIds.
My recommendation: drop the working-tree bump back to 1.0.0 (option 1) and file an upstream issue. The bug ca02146 was fixing doesn't affect us (Azure OpenAI populates MessageId), and the regression is real. Want me to draft the upstream issue?
Code Sample
Error Messages / Stack Traces
Package Versions
Microsoft.Agents.AI.Hosting.AGUI.AspNetCore 1.3.0-preview.260423.1
.NET Version
NET 10
Additional Context
No response