Progress.Memory.SemanticKernel
0.2.1
Prefix Reserved
dotnet add package Progress.Memory.SemanticKernel --version 0.2.1
NuGet\Install-Package Progress.Memory.SemanticKernel -Version 0.2.1
<PackageReference Include="Progress.Memory.SemanticKernel" Version="0.2.1" />
<PackageVersion Include="Progress.Memory.SemanticKernel" Version="0.2.1" />
<PackageReference Include="Progress.Memory.SemanticKernel" />
paket add Progress.Memory.SemanticKernel --version 0.2.1
#r "nuget: Progress.Memory.SemanticKernel, 0.2.1"
#:package Progress.Memory.SemanticKernel@0.2.1
#addin nuget:?package=Progress.Memory.SemanticKernel&version=0.2.1
#tool nuget:?package=Progress.Memory.SemanticKernel&version=0.2.1
Progress.Memory.SemanticKernel
Semantic Kernel integration for Progress Memory.
Adds long-term memory to Semantic Kernel agents via a KernelPlugin (remember / recall / forget) and an IChatCompletionService middleware wrapper that automatically injects memories into every SK chat request.
Not using Semantic Kernel?
For Microsoft.Extensions.AI pipelines, use Progress.Memory.Extensions.AI instead.
Requirements
- .NET 8, 9, or 10
- Progress.Memory (auto-included as a dependency)
Microsoft.SemanticKernel≥ 1.76.0
Installation
dotnet add package Progress.Memory.SemanticKernel
Integration modes
Choose one or combine both:
| Mode | When to use |
|---|---|
Plugin (AddProgressMemoryPlugin) |
LLM/planner-controlled — the model calls remember, recall, forget as kernel functions |
Middleware (UseProgressMemory) |
Silent auto-injection — memories are recalled before every SK chat call, without changing the prompt |
Mode 1 — Plugin (LLM-controlled)
Register a ProgressMemoryPlugin on the IKernelBuilder. The SK planner and the LLM can then autonomously invoke memory functions when they determine context is needed.
Minimal example
// Register the memory client
builder.Services.AddProgressMemory(new ProgressMemoryConfig(
BackendBaseUrl: "https://memory.example.com",
SdkApiKey: "pmem_p_..."));
// Add memory plugin to the kernel
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4o", apiKey)
.AddProgressMemoryPlugin(memoryClient, userId: "user-123", agentId: "my-agent")
.Build();
Dynamic identity (multi-tenant / per-request)
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4o", apiKey)
.AddProgressMemoryPlugin(
memoryClient,
getUserId: () => httpContextAccessor.HttpContext!.User.FindFirst("sub")!.Value,
getAgentId: () => "my-agent")
.Build();
Resolving from the service provider
services.AddProgressMemory(config);
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4o", apiKey)
.AddProgressMemoryPlugin(services.BuildServiceProvider(),
userId: "user-123", agentId: "my-agent")
.Build();
Plugin functions
| Function | Description |
|---|---|
memory.remember |
Save a durable memory. Pass the original utterance, not a summary. The backend extracts atomic facts automatically. |
memory.recall |
Retrieve relevant past memories with a short concrete query (e.g., "diet", "timezone"). Returns a JSON array. |
memory.forget |
Delete a stored memory by memoryId returned from recall. |
Mode 2 — Middleware (auto-inject)
Wrap an IChatCompletionService with the UseProgressMemory extension. On every SK chat call:
- The last user message is used to search for relevant past memories.
- Matching facts are prepended as a system message before the request reaches the underlying service.
- If
autoRemember: true, the completed exchange is saved to memory (awaited inline).
Why a separate
IChatCompletionServicewrapper?
Bridging viaAsChatClient()causes SK'sPromptExecutionSettingsto go through a JSON round-trip that breaksToolCallBehaviordeserialization. TheProgressMemoryInjectingChatCompletionServiceavoids this by operating directly at theIChatCompletionServicelayer.
Example
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4o", apiKey)
.Build();
// Wrap the registered chat completion service
var baseService = kernel.GetRequiredService<IChatCompletionService>();
var memoryService = baseService.UseProgressMemory(
kernel.Services,
memoryClient,
userId: "user-123",
agentId: "my-agent",
autoRemember: true);
// Use the wrapped service directly
var result = await memoryService.GetChatMessageContentsAsync(chatHistory);
Dynamic identity
var memoryService = baseService.UseProgressMemory(
memoryClient,
getUserId: () => httpContextAccessor.HttpContext!.User.FindFirst("sub")!.Value,
getAgentId: () => "my-agent",
autoRemember: false);
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
memory |
IProgressMemoryClient |
— | The memory client |
userId / getUserId |
string / Func<string> |
— | User identity for scoping |
agentId / getAgentId |
string / Func<string> |
— | Agent identity for scoping |
topK |
int |
10 |
Maximum memories injected per request |
autoRemember |
bool |
false |
Save each exchange automatically after the LLM responds |
conversationContext |
IConversationContext? |
null |
Threads turns into one conversation resource |
Combining both modes
Use the middleware for seamless silent recall and add the plugin for LLM-directed write/delete:
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4o", apiKey)
.AddProgressMemoryPlugin(memoryClient, userId: "user-123", agentId: "my-agent")
.Build();
var baseService = kernel.GetRequiredService<IChatCompletionService>();
var memoryService = baseService.UseProgressMemory(
memoryClient, userId: "user-123", agentId: "my-agent");
Conversation threading
Pass a shared ConversationContext instance to link all turns in a session into one conversation resource:
var context = new ConversationContext();
var memoryService = baseService.UseProgressMemory(
memoryClient,
userId: "user-123",
agentId: "my-agent",
conversationContext: context);
See also
- Progress.Memory — core client and DI registration
- Progress.Memory.Extensions.AI — Microsoft.Extensions.AI integration
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Microsoft.SemanticKernel (>= 1.76.0)
- Progress.Memory (>= 0.2.1)
-
net9.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Microsoft.SemanticKernel (>= 1.76.0)
- Progress.Memory (>= 0.2.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.