From efb5b902bd71c9f624d6d3ecf8ffbeb27badb268 Mon Sep 17 00:00:00 2001 From: gmtorres Date: Thu, 9 Apr 2026 12:47:38 +0200 Subject: [PATCH 1/3] Propagate FunctionResult Metadata to Tool ChatMessageContent --- .../connectors/AI/FunctionCalling/FunctionCallsProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs b/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs index ddca98c7c053..b1659df31f1e 100644 --- a/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs +++ b/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs @@ -388,7 +388,7 @@ await this.OnAutoFunctionInvocationAsync( /// The function result context. private void AddFunctionCallResultToChatHistory(ChatHistory chatHistory, FunctionResultContext resultContext) { - var message = new ChatMessageContent(role: AuthorRole.Tool, content: resultContext.Result); + var message = new ChatMessageContent(role: AuthorRole.Tool, content: resultContext.Result, metadata: resultContext.Context.Result.Metadata); message.Items.Add(this.GenerateResultContent(resultContext)); chatHistory.Add(message); } From 48757b66b52b868a23d9f8b1c05780d6d58c3dd4 Mon Sep 17 00:00:00 2001 From: gmtorres Date: Thu, 9 Apr 2026 13:41:41 +0200 Subject: [PATCH 2/3] Add test --- .../FunctionCallsProcessorTests.cs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/dotnet/src/SemanticKernel.UnitTests/Utilities/AIConnectors/FunctionCallsProcessorTests.cs b/dotnet/src/SemanticKernel.UnitTests/Utilities/AIConnectors/FunctionCallsProcessorTests.cs index e1258d124c6a..6119ca7d9684 100644 --- a/dotnet/src/SemanticKernel.UnitTests/Utilities/AIConnectors/FunctionCallsProcessorTests.cs +++ b/dotnet/src/SemanticKernel.UnitTests/Utilities/AIConnectors/FunctionCallsProcessorTests.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading; @@ -855,6 +856,54 @@ public void ItShouldSerializeFunctionResultsWithStringProperties() Assert.Equal("{\"Text\":\"テスト\"}", result); } + [Fact] + public async Task ItShouldPropagateFunctionResultMetadataToChatHistoryAsync() + { + // Arrange + var expectedMetadata = new Dictionary + { + ["key1"] = "value1", + ["key2"] = 42 + }; + + var function1 = KernelFunctionFactory.CreateFromMethod((string parameter) => parameter, "Function1"); + var plugin = KernelPluginFactory.CreateFromFunctions("MyPlugin", [function1]); + + var kernel = CreateKernel(plugin, async (context, next) => + { + await next(context); + + // Filter sets metadata on the FunctionResult + context.Result = new FunctionResult(context.Function, context.Result.GetValue(), context.Result.Culture, expectedMetadata); + }); + + var chatMessageContent = new ChatMessageContent(); + chatMessageContent.Items.Add(new FunctionCallContent("Function1", "MyPlugin", arguments: new KernelArguments() { ["parameter"] = "function1-result" })); + + var chatHistory = new ChatHistory(); + + // Act + await this._sut.ProcessFunctionCallsAsync( + chatMessageContent: chatMessageContent, + executionSettings: this._promptExecutionSettings, + chatHistory: chatHistory, + requestIndex: 0, + checkIfFunctionAdvertised: (_) => true, + options: this._functionChoiceBehaviorOptions, + kernel: kernel!, + isStreaming: false, + cancellationToken: CancellationToken.None); + + // Assert + Assert.Equal(2, chatHistory.Count); + + var toolMessage = chatHistory[1]; // First is the assistant message, second is the tool result + Assert.Equal(AuthorRole.Tool, toolMessage.Role); + Assert.NotNull(toolMessage.Metadata); + Assert.Equal("value1", toolMessage.Metadata["key1"]); + Assert.Equal(42, toolMessage.Metadata["key2"]); + } + [Fact] public async Task ItShouldPassPromptExecutionSettingsToAutoFunctionInvocationFilterAsync() { From c6e397a7d20651823dbe927a88e6322035d3492a Mon Sep 17 00:00:00 2001 From: gmtorres Date: Thu, 9 Apr 2026 13:55:10 +0200 Subject: [PATCH 3/3] Address comment --- .../connectors/AI/FunctionCalling/FunctionCallsProcessor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs b/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs index b1659df31f1e..f54d0e3784bb 100644 --- a/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs +++ b/dotnet/src/InternalUtilities/connectors/AI/FunctionCalling/FunctionCallsProcessor.cs @@ -388,7 +388,8 @@ await this.OnAutoFunctionInvocationAsync( /// The function result context. private void AddFunctionCallResultToChatHistory(ChatHistory chatHistory, FunctionResultContext resultContext) { - var message = new ChatMessageContent(role: AuthorRole.Tool, content: resultContext.Result, metadata: resultContext.Context.Result.Metadata); + var message = new ChatMessageContent(role: AuthorRole.Tool, content: resultContext.Result); + message.Metadata = resultContext.Context.Result.Metadata; message.Items.Add(this.GenerateResultContent(resultContext)); chatHistory.Add(message); }