Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ protected override async Task<AgentResponse> RunCoreAsync(
// so let's update it and set the conversation id for the service session case.
var forceEndOfRunPersistence = chatOptions?.ContinuationToken is not null || chatOptions?.AllowBackgroundResponses is true;
this.UpdateSessionConversationIdAtEndOfRun(safeSession, chatResponse.ConversationId, cancellationToken, forceUpdate: forceEndOfRunPersistence);
chatOptions = SetResponseConversationId(chatOptions, chatResponse.ConversationId);

// Ensure that the author name is set for each message in the response.
foreach (ChatMessage chatResponseMessage in chatResponse.Messages)
Expand Down Expand Up @@ -387,6 +388,7 @@ protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingA
// We can derive the type of supported session from whether we have a conversation id,
// so let's update it and set the conversation id for the service session case.
this.UpdateSessionConversationIdAtEndOfRun(safeSession, chatResponse.ConversationId, cancellationToken, forceUpdate: forceEndOfRunPersistence);
chatOptions = SetResponseConversationId(chatOptions, chatResponse.ConversationId);

// Notify providers of all new messages unless persistence is handled per-service-call by the decorator.
// When resuming from a continuation token or using background responses, force notification
Expand Down Expand Up @@ -1006,6 +1008,18 @@ private void WarnOnMissingPerServiceCallChatHistoryPersistingChatClient()
return provider;
}

private static ChatOptions? SetResponseConversationId(ChatOptions? chatOptions, string? responseConversationId)
{
if (string.IsNullOrWhiteSpace(responseConversationId))
{
return chatOptions;
}

chatOptions ??= new();
chatOptions.ConversationId ??= responseConversationId;
return chatOptions;
}
Comment on lines +1011 to +1021
Comment on lines +1011 to +1021

/// <summary>
/// Loads chat history from the resolved <see cref="ChatHistoryProvider"/> and prepends it to the given messages.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ public async Task RunAsync_Throws_WhenThrowEnabledRegardlessOfClearSettingAsync(
}

/// <summary>
/// Verify that RunAsync does not throw when no ChatHistoryProvider is configured on options,
/// even if the service returns a conversation id (default InMemoryChatHistoryProvider is used but not from options).
/// Verify that RunAsync does not throw or persist local history when no ChatHistoryProvider is configured on options,
/// even if the service returns a conversation id.
/// </summary>
[Fact]
public async Task RunAsync_DoesNotThrow_WhenNoChatHistoryProviderInOptionsAndConversationIdReturnedAsync()
Expand All @@ -407,8 +407,11 @@ public async Task RunAsync_DoesNotThrow_WhenNoChatHistoryProviderInOptionsAndCon
ChatClientAgentSession? session = await agent.CreateSessionAsync() as ChatClientAgentSession;
await agent.RunAsync([new(ChatRole.User, "test")], session);

// Assert - no exception, session gets the conversation id
// Assert - no exception, session gets the conversation id, and local history is not also persisted.
Assert.Equal("ConvId", session!.ConversationId);
var inMemoryProvider = agent.ChatHistoryProvider as InMemoryChatHistoryProvider;
Assert.NotNull(inMemoryProvider);
Assert.Empty(inMemoryProvider.GetMessages(session));
Comment on lines +412 to +414
}

#endregion
Expand Down