diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/IdGenerator.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/IdGenerator.cs index bd35fa8308..4798f1b79a 100644 --- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/IdGenerator.cs +++ b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/IdGenerator.cs @@ -34,6 +34,7 @@ public IdGenerator(string? responseId, string? conversationId, int? randomSeed = this._random = randomSeed.HasValue ? new Random(randomSeed.Value) : null; this.ResponseId = responseId ?? NewId("resp", random: this._random); this.ConversationId = conversationId ?? NewId("conv", random: this._random); + this.IsNewConversation = conversationId is null; this._partitionId = GetPartitionIdOrDefault(this.ConversationId) ?? string.Empty; } @@ -59,6 +60,11 @@ public static IdGenerator From(CreateResponse request) /// public string ConversationId { get; } + /// + /// Gets a value indicating whether this is a new conversation. + /// + public bool IsNewConversation { get; } + /// /// Generates a new ID. /// diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentInvocationContext.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentInvocationContext.cs index f21c2e84e9..5f716ea3f2 100644 --- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentInvocationContext.cs +++ b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentInvocationContext.cs @@ -26,6 +26,11 @@ internal sealed class AgentInvocationContext(IdGenerator idGenerator, JsonSerial /// public string ConversationId => this.IdGenerator.ConversationId; + /// + /// Returns true, if conversation is new. + /// + public bool IsNewConversation => this.IdGenerator.IsNewConversation; + /// /// Gets the JSON serializer options. /// diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/HostedAgentResponseExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/HostedAgentResponseExecutor.cs index 01e7c60137..f520acb662 100644 --- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/HostedAgentResponseExecutor.cs +++ b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/HostedAgentResponseExecutor.cs @@ -81,10 +81,13 @@ public async IAsyncEnumerable ExecuteAsync( [EnumeratorCancellation] CancellationToken cancellationToken = default) { string agentName = GetAgentName(request)!; - AIAgent agent = this._serviceProvider.GetRequiredKeyedService(agentName); + string conversationId = context.ConversationId; + + var agent = this._serviceProvider.GetRequiredKeyedService(agentName); + var threadStore = this._serviceProvider.GetKeyedService(agent.Name); + var chatOptions = new ChatOptions { - ConversationId = request.Conversation?.Id, Temperature = (float?)request.Temperature, TopP = (float?)request.TopP, MaxOutputTokens = request.MaxOutputTokens, @@ -94,16 +97,25 @@ public async IAsyncEnumerable ExecuteAsync( var options = new ChatClientAgentRunOptions(chatOptions); var messages = new List(); + AgentThread thread = !context.IsNewConversation && threadStore is not null + ? await threadStore.GetThreadAsync(agent, conversationId, cancellationToken).ConfigureAwait(false) + : agent.GetNewThread(); + foreach (var inputMessage in request.Input.GetInputMessages()) { messages.Add(inputMessage.ToChatMessage()); } - await foreach (var streamingEvent in agent.RunStreamingAsync(messages, options: options, cancellationToken: cancellationToken) + await foreach (var streamingEvent in agent.RunStreamingAsync(messages, thread, options: options, cancellationToken: cancellationToken) .ToStreamingResponseAsync(request, context, cancellationToken).ConfigureAwait(false)) { yield return streamingEvent; } + + if (threadStore is not null && thread is not null) + { + await threadStore.SaveThreadAsync(agent, conversationId, thread, cancellationToken).ConfigureAwait(false); + } } ///