Skip to content

.Net: Change ChatCompletionAgent to notify intermediate messages as soon as they are available. #12575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

westey-m
Copy link
Contributor

Motivation and Context

Addresses #12521

Contribution Checklist

@westey-m westey-m requested a review from a team as a code owner June 24, 2025 15:53
@markwallace-microsoft markwallace-microsoft added the .NET Issue or Pull requests regarding .NET code label Jun 24, 2025
@github-actions github-actions bot changed the title Change ChatCompletionAgent to notify intermediate messages as soon as they are available. .Net: Change ChatCompletionAgent to notify intermediate messages as soon as they are available. Jun 24, 2025
@rogerbarreto
Copy link
Member

Suggest adding a UT ensuring this behavior

@westey-m westey-m added this pull request to the merge queue Jun 25, 2025
@westey-m
Copy link
Contributor Author

Suggest adding a UT ensuring this behavior

Sure, will look at this separately.

@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jun 25, 2025
@westey-m westey-m added this pull request to the merge queue Jun 25, 2025
Merged via the queue into microsoft:main with commit 3d21f17 Jun 25, 2025
21 checks passed
@westey-m westey-m deleted the ccagent-intermediatemessage-timing-fix branch June 25, 2025 09:57
@GrillPhil
Copy link

GrillPhil commented Jul 23, 2025

@westey-m I still have this issue with the current version 1.60.0-preview of Microsoft.SemanticKernel.Agents.AzureAI
IntermediateMessages e.g. tool calls are arriving AFTER responses.

public async IAsyncEnumerable<AgentStreamingContent> Prompt(
        string prompt)
    {
        AzureAIAgent agent = await CreateAzureAIAgentWithTools().ConfigureAwait(false);
        Channel<AgentStreamingContent> channel = Channel.CreateUnbounded<AgentStreamingContent>();

        AzureAIAgentThread agentThread = new(agent.Client);
        AgentInvokeOptions agentInvokeOptions = new()
        {
            AdditionalInstructions = toolOptionsText,
            OnIntermediateMessage = (message) =>
            {
                foreach (KernelContent content in message.Items)
                {
                    if (content is Microsoft.SemanticKernel.FunctionCallContent functionCallContent)
                    {
                        Console.WriteLine($"FunctionCallContent Plugin {functionCallContent.PluginName}, Function {functionCallContent.FunctionName}");
                    }
                    else if (content is Microsoft.SemanticKernel.FunctionResultContent functionResultContent)
                    {
                        Console.WriteLine($"FunctionCallContent Plugin {functionResultContent.PluginName}, Function {functionResultContent.FunctionName}");
                    }
                    else
                    {
                        // Handle other content types if necessary
                    }
                }
                return Task.CompletedTask;
            }
        };

        async Task InvokeStreaming()
        {
            Microsoft.SemanticKernel.ChatMessageContent message = new(AuthorRole.User, prompt);
            await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsync(message, agentThread, options: agentInvokeOptions).ConfigureAwait(false))
            {
                if (!string.IsNullOrEmpty(response.Content))
                {
                    Console.WriteLine($"StreamingChatMessageContent {response.Content}");
                }
            }
        }

        Console.WriteLine($"Invoking streaming");
        Task.Run(async () => await InvokeStreaming());
    }

@westey-m
Copy link
Contributor Author

@GrillPhil, this fix was on the ChatCompletionAgent, but it looks like you are using an AzureAIAgent here right?

@GrillPhil
Copy link

@GrillPhil, this fix was on the ChatCompletionAgent, but it looks like you are using an AzureAIAgent here right?

Yes exactly. The events come in the right order on AzureAIAgent when I user InvokeAsync but at the end when using the streaming API.

@westey-m
Copy link
Contributor Author

Thanks @GrillPhil, I've opened a new bug to address this across all agent types.
See #12789

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
.NET Issue or Pull requests regarding .NET code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants