Aggregate ChatMessages from AgentRunUpdates before forwarding (#515)

The current implementation of AIAgentHostExecutor unwraps every incoming AgentRunResponseUpdate into a separate ChatMessage, amplifying the number of ChatMessages are actually generated, and yielding multiple messages with the same MessageId.

The fix is to aggregate by MesageId, with the expectation that agents do not interleave messages with differing ids, thus every new MessageId indicates a new ChatMessage and never an old one.
This commit is contained in:
Jacob Alber
2025-08-27 18:32:27 -04:00
committed by GitHub
Unverified
parent 8e14dfc522
commit 738866f4fe
@@ -95,6 +95,8 @@ internal class AIAgentHostExecutor : Executor
IAsyncEnumerable<AgentRunResponseUpdate> agentStream = this._agent.RunStreamingAsync(this._pendingMessages, this.EnsureThread(context));
List<AgentRunResponseUpdate> updates = new();
ChatMessage? currentStreamingMessage = null;
await foreach (AgentRunResponseUpdate update in agentStream.ConfigureAwait(false))
{
if (emitEvents)
@@ -108,18 +110,32 @@ internal class AIAgentHostExecutor : Executor
// workflow.
updates.Add(update);
ChatMessage message = new(update.Role ?? ChatRole.Assistant, update.Contents)
{
AuthorName = update.AuthorName,
CreatedAt = update.CreatedAt,
MessageId = update.MessageId,
RawRepresentation = update.RawRepresentation,
AdditionalProperties = update.AdditionalProperties
};
await context.SendMessageAsync(message).ConfigureAwait(false);
if (currentStreamingMessage == null || currentStreamingMessage.MessageId != update.MessageId)
{
await PublishCurrentMessageAsync().ConfigureAwait(false);
currentStreamingMessage = new(update.Role ?? ChatRole.Assistant, update.Contents)
{
AuthorName = update.AuthorName,
CreatedAt = update.CreatedAt,
MessageId = update.MessageId,
RawRepresentation = update.RawRepresentation,
AdditionalProperties = update.AdditionalProperties
};
}
}
await PublishCurrentMessageAsync().ConfigureAwait(false);
await context.SendMessageAsync(token).ConfigureAwait(false);
async ValueTask PublishCurrentMessageAsync()
{
if (currentStreamingMessage != null)
{
await context.SendMessageAsync(currentStreamingMessage).ConfigureAwait(false);
}
currentStreamingMessage = null;
}
}
}