diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index 1ab73c2b8b..7c1d0d48eb 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -56,6 +56,7 @@
+
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Agent_Step18_CompactionPipeline.csproj b/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Agent_Step18_CompactionPipeline.csproj
new file mode 100644
index 0000000000..0f9de7c359
--- /dev/null
+++ b/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Agent_Step18_CompactionPipeline.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Program.cs
new file mode 100644
index 0000000000..7849cb4656
--- /dev/null
+++ b/dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/Program.cs
@@ -0,0 +1,97 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// This sample demonstrates how to use a ChatHistoryCompactionPipeline as the ChatReducer for an agent's
+// in-memory chat history. The pipeline chains multiple compaction strategies from gentle to aggressive:
+// 1. ToolResultCompactionStrategy - Collapses old tool-call groups into concise summaries
+// 2. SummarizationCompactionStrategy - LLM-compresses older conversation spans
+// 3. SlidingWindowCompactionStrategy - Keeps only the most recent N user turns
+// 4. TruncationCompactionStrategy - Emergency token-budget backstop
+
+using System.ComponentModel;
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.Compaction;
+using Microsoft.Extensions.AI;
+
+var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
+var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
+
+// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
+// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
+// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
+AzureOpenAIClient openAIClient = new(new Uri(endpoint), new DefaultAzureCredential());
+
+// Create a chat client for the agent and a separate one for the summarization strategy.
+// Using the same model for simplicity; in production, use a smaller/cheaper model for summarization.
+IChatClient agentChatClient = openAIClient.GetChatClient(deploymentName).AsIChatClient();
+IChatClient summarizerChatClient = openAIClient.GetChatClient(deploymentName).AsIChatClient();
+
+// Define a tool the agent can use, so we can see tool-result compaction in action.
+[Description("Look up the current price of a product by name.")]
+static string LookupPrice([Description("The product name to look up.")] string productName) =>
+ productName.ToUpperInvariant() switch
+ {
+ "LAPTOP" => "The laptop costs $999.99.",
+ "KEYBOARD" => "The keyboard costs $79.99.",
+ "MOUSE" => "The mouse costs $29.99.",
+ _ => $"Sorry, I don't have pricing for '{productName}'."
+ };
+
+// Configure the compaction pipeline with one of each strategy, ordered least to most aggressive.
+const int MaxTokens = 512;
+const int MaxTurns = 4;
+
+ChatHistoryCompactionPipeline compactionPipeline =
+ new(// 1. Gentle: collapse old tool-call groups into short summaries like "[Tool calls: LookupPrice]"
+ new ToolResultCompactionStrategy(MaxTokens, preserveRecentGroups: 2),
+
+ // 2. Moderate: use an LLM to summarize older conversation spans into a concise message
+ new SummarizationCompactionStrategy(summarizerChatClient, MaxTokens, preserveRecentGroups: 2),
+
+ // 3. Aggressive: keep only the last N user turns and their responses
+ new SlidingWindowCompactionStrategy(MaxTurns),
+
+ // 4. Emergency: drop oldest groups until under the token budget
+ new TruncationCompactionStrategy(MaxTokens, preserveRecentGroups: 1));
+
+// Create the agent with an in-memory chat history provider whose reducer is the compaction pipeline.
+AIAgent agent = agentChatClient.AsAIAgent(new ChatClientAgentOptions
+{
+ Name = "ShoppingAssistant",
+ ChatOptions = new()
+ {
+ Instructions = "You are a helpful shopping assistant. Help the user look up prices and compare products.",
+ Tools = [AIFunctionFactory.Create(LookupPrice)],
+ },
+ ChatHistoryProvider = new InMemoryChatHistoryProvider(new() { ChatReducer = compactionPipeline }),
+});
+
+AgentSession session = await agent.CreateSessionAsync();
+
+// Helper to print chat history size
+void PrintChatHistory()
+{
+ if (session.TryGetInMemoryChatHistory(out var history))
+ {
+ Console.WriteLine($" [Chat history: {history.Count} messages]\n");
+ }
+}
+
+// Run a multi-turn conversation with tool calls to exercise the pipeline.
+string[] prompts =
+[
+ "What's the price of a laptop?",
+ "How about a keyboard?",
+ "And a mouse?",
+ "Which product is the cheapest?",
+ "Can you compare the laptop and the keyboard for me?",
+ "What was the first product I asked about?",
+];
+
+foreach (string prompt in prompts)
+{
+ Console.WriteLine($"User: {prompt}");
+ Console.WriteLine($"Agent: {await agent.RunAsync(prompt, session)}");
+ PrintChatHistory();
+}
diff --git a/dotnet/src/Microsoft.Agents.AI.Abstractions/Compaction/ChatHistoryCompactionPipeline.cs b/dotnet/src/Microsoft.Agents.AI.Abstractions/Compaction/ChatHistoryCompactionPipeline.cs
index 451a171226..8b678602a1 100644
--- a/dotnet/src/Microsoft.Agents.AI.Abstractions/Compaction/ChatHistoryCompactionPipeline.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Abstractions/Compaction/ChatHistoryCompactionPipeline.cs
@@ -37,7 +37,7 @@ public class ChatHistoryCompactionPipeline : IChatReducer
/// By default, is used.
///
public ChatHistoryCompactionPipeline(
- IEnumerable strategies)
+ params IEnumerable strategies)
: this(metricsCalculator: null, strategies) { }
///