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);
+ }
}
///