Semantic Kernel
Use this integration to add Agent Memory to Semantic Kernel through IKernelBuilder plugin functions or IChatCompletionService middleware.
Before configuring this integration, prepare the Agent Memory prerequisites.
Installation
Install the Semantic Kernel Memory integration:
dotnet add package Progress.Memory.SemanticKernel
dotnet add package Microsoft.SemanticKernel.Connectors.OpenAI --version 1.76.0
The Memory package includes Progress.Memory and Semantic Kernel core as transitive dependencies. The OpenAI connector package provides the Azure OpenAI chat completion methods used in these examples.
The following examples use Azure OpenAI. Replace the backend URL, SDK API key, Azure deployment name, endpoint, and API key with your own values. The fixed user and agent identifiers are for a single-user example.
Integration Modes
| Mode | How it works | When to use |
|---|---|---|
| Plugin | Exposes remember, recall, and forget as kernel functions. The LLM decides when to invoke them. | Agent workflows that use Semantic Kernel planning or function calling. |
| Middleware | Wraps IChatCompletionService to inject recalled memories before every completion and optionally save exchanges automatically. | Chat loops that require automatic recall and unchanged PromptExecutionSettings. |
Recall Options
The following option applies to AddProgressMemoryPlugin() and UseProgressMemory() overloads that accept a memory client. It is also available on the ProgressMemoryPlugin and ProgressMemoryInjectingChatCompletionService constructors.
| Parameter | Type | Default | Purpose |
|---|---|---|---|
includeOutdatedByDefault | bool | false | Optional. If omitted, recalls only active memories. Set to true to also recall outdated memories. See memory status. |
Plugin Mode
Register the memory plugin with AddProgressMemoryPlugin(). Set FunctionChoiceBehavior.Auto() so the model can discover and invoke the memory functions. Without this setting, the model may answer without calling them.
The following console example creates the memory client, registers the plugin, and sends a chat request:
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Progress.Memory;
using Progress.Memory.SemanticKernel;
var memoryClient = ProgressMemoryClient.Create(new ProgressMemoryConfig(
BackendBaseUrl: "https://memory-api.observability.progress.com",
SdkApiKey: "pmem_d_..."));
var deploymentName = "your-deployment";
var endpoint = "https://your-endpoint.openai.azure.com";
var apiKey = "your-azure-openai-key";
var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey)
.AddProgressMemoryPlugin(
memoryClient, userId: "user-123", agentId: "support-bot",
includeOutdatedByDefault: false) // Optional; omit for active-only retrieval.
.Build();
var chat = kernel.GetRequiredService<IChatCompletionService>();
var history = new ChatHistory();
history.AddUserMessage("What do you know about my preferences?");
var executionSettings = new OpenAIPromptExecutionSettings
{
// Required in plugin mode so the model can discover and invoke memory plugin functions.
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
var result = await chat.GetChatMessageContentAsync(history, executionSettings, kernel);
Console.WriteLine(result.Content);
Middleware Mode
Wrap the chat service with UseProgressMemory() and send requests through the returned service. The wrapper recalls relevant memories before each completion and forwards PromptExecutionSettings to the underlying service without serialization.
The autoRemember parameter controls whether the wrapper saves the exchange:
false(default)—Recall memories without saving the exchange. CallAddMemoryAsync()yourself when you need to store information.true—After the model responds, send the latest user message and the assistant response to memory.
The following console example enables automatic saving and sends a chat request:
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Progress.Memory;
using Progress.Memory.SemanticKernel;
var memoryClient = ProgressMemoryClient.Create(new ProgressMemoryConfig(
BackendBaseUrl: "https://memory-api.observability.progress.com",
SdkApiKey: "pmem_d_..."));
var deploymentName = "your-deployment";
var endpoint = "https://your-endpoint.openai.azure.com";
var apiKey = "your-azure-openai-key";
var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey)
.Build();
var baseService = kernel.GetRequiredService<IChatCompletionService>();
IChatCompletionService chat = baseService.UseProgressMemory(
serviceProvider: kernel.Services,
memory: memoryClient,
userId: "user-123",
agentId: "support-bot",
includeOutdatedByDefault: false, // Optional; omit for active-only retrieval.
topK: 5,
autoRemember: true);
var history = new ChatHistory();
history.AddUserMessage("I prefer dark mode and metric units.");
var response = await chat.GetChatMessageContentAsync(history, kernel: kernel);
Console.WriteLine(response.Content);
Using Dependency Injection
The following examples use a ServiceCollection to resolve the Memory client through a service provider.
For plugin mode, register the memory client with DI and add the memory plugin:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Progress.Memory.Extensions;
using Progress.Memory.SemanticKernel;
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var deploymentName = "your-deployment";
var endpoint = "https://your-endpoint.openai.azure.com";
var apiKey = "your-azure-openai-key";
services.AddProgressMemory(configuration);
var sp = services.BuildServiceProvider();
var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey)
.AddProgressMemoryPlugin(sp, userId: "user-123", agentId: "support-bot")
.Build();
var chat = kernel.GetRequiredService<IChatCompletionService>();
var history = new ChatHistory();
history.AddUserMessage("What do you know about my preferences?");
var executionSettings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
var response = await chat.GetChatMessageContentAsync(history, executionSettings, kernel);
Console.WriteLine(response.Content);
For middleware mode, register the memory client with DI and wrap the chat service:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Progress.Memory.Extensions;
using Progress.Memory.SemanticKernel;
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var deploymentName = "your-deployment";
var endpoint = "https://your-endpoint.openai.azure.com";
var apiKey = "your-azure-openai-key";
services.AddProgressMemory(configuration);
var sp = services.BuildServiceProvider();
var kernel = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey)
.Build();
var baseService = kernel.GetRequiredService<IChatCompletionService>();
IChatCompletionService chat = baseService.UseProgressMemory(
serviceProvider: sp,
userId: "user-123",
agentId: "support-bot",
autoRemember: true);
var history = new ChatHistory();
history.AddUserMessage("I prefer dark mode and metric units.");
var response = await chat.GetChatMessageContentAsync(history, kernel: kernel);
Console.WriteLine(response.Content);