diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowChatHistoryProvider.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowChatHistoryProvider.cs index 2815ed99f0..3f6656b994 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowChatHistoryProvider.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowChatHistoryProvider.cs @@ -62,6 +62,12 @@ internal sealed class WorkflowChatHistoryProvider : ChatHistoryProvider } } + public IEnumerable GetAllMessages(AgentSession session) + { + var state = this._sessionState.GetOrInitializeState(session); + return state.Messages; + } + public void UpdateBookmark(AgentSession session) { var state = this._sessionState.GetOrInitializeState(session); diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowHostAgent.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowHostAgent.cs index 7679123970..295c08ceeb 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowHostAgent.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows/WorkflowHostAgent.cs @@ -119,13 +119,17 @@ internal sealed class WorkflowHostAgent : AIAgent MessageMerger merger = new(); await foreach (AgentResponseUpdate update in workflowSession.InvokeStageAsync(cancellationToken) - .ConfigureAwait(false) - .WithCancellation(cancellationToken)) + .ConfigureAwait(false) + .WithCancellation(cancellationToken)) { merger.AddUpdate(update); } - return merger.ComputeMerged(workflowSession.LastResponseId!, this.Id, this.Name); + AgentResponse response = merger.ComputeMerged(workflowSession.LastResponseId!, this.Id, this.Name); + workflowSession.ChatHistoryProvider.AddMessages(workflowSession, response.Messages); + workflowSession.ChatHistoryProvider.UpdateBookmark(workflowSession); + + return response; } protected override async @@ -138,11 +142,18 @@ internal sealed class WorkflowHostAgent : AIAgent await this.ValidateWorkflowAsync().ConfigureAwait(false); WorkflowSession workflowSession = await this.UpdateSessionAsync(messages, session, cancellationToken).ConfigureAwait(false); + MessageMerger merger = new(); + await foreach (AgentResponseUpdate update in workflowSession.InvokeStageAsync(cancellationToken) .ConfigureAwait(false) .WithCancellation(cancellationToken)) { + merger.AddUpdate(update); yield return update; } + + AgentResponse response = merger.ComputeMerged(workflowSession.LastResponseId!, this.Id, this.Name); + workflowSession.ChatHistoryProvider.AddMessages(workflowSession, response.Messages); + workflowSession.ChatHistoryProvider.UpdateBookmark(workflowSession); } } diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/WorkflowHostSmokeTests.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/WorkflowHostSmokeTests.cs index 1920a57cb1..e61f4efe07 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/WorkflowHostSmokeTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/WorkflowHostSmokeTests.cs @@ -206,7 +206,7 @@ internal sealed class TurnTrackingStartExecutor : ChatProtocolExecutor } } -public class WorkflowHostSmokeTests +public class WorkflowHostSmokeTests : AIAgentHostingExecutorTestsBase { private sealed class AlwaysFailsAIAgent(bool failByThrowing) : AIAgent { @@ -731,4 +731,26 @@ public class WorkflowHostSmokeTests .Should() .BeEmpty(); } + + [Fact] + public async Task Test_AsAgent_OutgoingMessagesInHistoryAsync() + { + // Arrange + TestReplayAgent agent = new(TestMessages, TestAgentId, TestAgentName); + Workflow handoffWorkflow = new HandoffsWorkflowBuilder(agent).Build(); + AIAgent workflowAgent = handoffWorkflow.AsAIAgent(); + + // Act + AgentSession session = await workflowAgent.CreateSessionAsync(); + AgentResponse response = await workflowAgent.RunAsync(session); + + // Assert + WorkflowSession workflowSession = session.Should().BeOfType().Subject; + + ChatMessage[] responseMessages = response.Messages.ToArray(); + ChatMessage[] sessionMessages = workflowSession.ChatHistoryProvider.GetAllMessages(workflowSession).ToArray(); + + // Since we never sent an incoming message, the expectation is that there should be nothing in the session + responseMessages.Should().BeEquivalentTo(sessionMessages); + } }