diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 3ba3f3b13b..ac7eb21424 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -38,7 +38,7 @@
-
+
@@ -104,6 +104,7 @@
+
diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index 9442f98cb1..40c791159b 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -187,6 +187,7 @@
+
diff --git a/dotnet/eng/verify-samples/AgentsSamples.cs b/dotnet/eng/verify-samples/AgentsSamples.cs
index b19217230a..f629bdf600 100644
--- a/dotnet/eng/verify-samples/AgentsSamples.cs
+++ b/dotnet/eng/verify-samples/AgentsSamples.cs
@@ -532,6 +532,26 @@ internal static class AgentsSamples
],
},
+ new SampleDefinition
+ {
+ Name = "AgentWithMemory_Step08_MemoryUsingCosmosNoSql",
+ ProjectPath = "samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql",
+ RequiredEnvironmentVariables = ["FOUNDRY_PROJECT_ENDPOINT", "COSMOS_ENDPOINT"],
+ OptionalEnvironmentVariables = ["FOUNDRY_MODEL", "FOUNDRY_EMBEDDING_MODEL", "COSMOS_DATABASE_NAME"],
+ MustContain =
+ [
+ "First session:",
+ "Second session (recalling prior chat history from Cosmos DB):",
+ ],
+ ExpectedOutputDescription =
+ [
+ "The output should contain two joke responses.",
+ "The first joke should be about a pirate (as explicitly requested).",
+ "The second joke should also be pirate-themed or similar to what the user likes, since chat history from the first session should be recalled from Cosmos DB.",
+ "The output should not contain error messages or stack traces.",
+ ],
+ },
+
// ── AgentWithRAG ────────────────────────────────────────────────────
new SampleDefinition
diff --git a/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/AgentWithMemory_Step08_MemoryUsingCosmosNoSql.csproj b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/AgentWithMemory_Step08_MemoryUsingCosmosNoSql.csproj
new file mode 100644
index 0000000000..6aacaa5662
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/AgentWithMemory_Step08_MemoryUsingCosmosNoSql.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/Program.cs b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/Program.cs
new file mode 100644
index 0000000000..4552d04653
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/Program.cs
@@ -0,0 +1,92 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// This sample shows how to persist chat history in Azure Cosmos DB for NoSQL using the ChatHistoryMemoryProvider.
+// The agent can then use chat history from prior conversations to inform responses in new conversations.
+
+using System.Text.Json;
+using Azure.AI.Projects;
+using Azure.Identity;
+using CommunityToolkit.VectorData.CosmosNoSql;
+using Microsoft.Agents.AI;
+using Microsoft.Azure.Cosmos;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.VectorData;
+
+var endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
+var deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL") ?? "gpt-5.4-mini";
+var embeddingDeploymentName = Environment.GetEnvironmentVariable("FOUNDRY_EMBEDDING_MODEL") ?? "text-embedding-3-large";
+var embeddingDimensions = 3072;
+if (Environment.GetEnvironmentVariable("FOUNDRY_EMBEDDING_DIMENSIONS") is string embeddingDimensionsValue &&
+ (!int.TryParse(embeddingDimensionsValue, out embeddingDimensions) || embeddingDimensions <= 0))
+{
+ throw new InvalidOperationException("FOUNDRY_EMBEDDING_DIMENSIONS must be a positive integer.");
+}
+var cosmosEndpoint = Environment.GetEnvironmentVariable("COSMOS_ENDPOINT") ?? throw new InvalidOperationException("COSMOS_ENDPOINT is not set.");
+var cosmosDatabaseName = Environment.GetEnvironmentVariable("COSMOS_DATABASE_NAME") ?? "agent-memory";
+
+// 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.
+DefaultAzureCredential credential = new();
+AIProjectClient aiProjectClient = new(new Uri(endpoint), credential);
+
+using CosmosClient cosmosClient = new(
+ cosmosEndpoint,
+ credential,
+ new CosmosClientOptions
+ {
+ UseSystemTextJsonSerializerWithOptions = JsonSerializerOptions.Default,
+ });
+
+DatabaseResponse databaseResponse = await cosmosClient.CreateDatabaseIfNotExistsAsync(cosmosDatabaseName);
+
+VectorStore vectorStore = new CosmosNoSqlVectorStore(
+ databaseResponse.Database,
+ new CosmosNoSqlVectorStoreOptions
+ {
+ JsonSerializerOptions = JsonSerializerOptions.Default,
+ EmbeddingGenerator = aiProjectClient
+ .GetProjectOpenAIClient()
+ .GetEmbeddingClient(embeddingDeploymentName)
+ .AsIEmbeddingGenerator(),
+ });
+
+var userId = $"sample-{Guid.NewGuid():N}";
+
+// Create the agent and add the ChatHistoryMemoryProvider to store chat messages in Cosmos DB.
+AIAgent agent = aiProjectClient
+ .AsAIAgent(new ChatClientAgentOptions
+ {
+ ChatOptions = new() { ModelId = deploymentName, Instructions = "You are good at telling jokes." },
+ Name = "Joker",
+ AIContextProviders = [new ChatHistoryMemoryProvider(
+ vectorStore,
+ collectionName: "chathistory",
+ vectorDimensions: embeddingDimensions,
+ // Callback to configure the initial state of the ChatHistoryMemoryProvider.
+ // The ChatHistoryMemoryProvider stores its state in the AgentSession and this callback
+ // will be called whenever the ChatHistoryMemoryProvider cannot find existing state in the session,
+ // typically the first time it is used with a new session.
+ _ => new ChatHistoryMemoryProvider.State(
+ // Configure the scope values under which chat messages will be stored.
+ // In this case, we are using a per-run user ID and a unique session ID for each new session.
+ storageScope: new() { UserId = userId, SessionId = Guid.NewGuid().ToString("N") },
+ // Configure the scope which would be used to search for relevant prior messages.
+ // In this case, we are searching for any messages for the user across all sessions.
+ searchScope: new() { UserId = userId }))]
+ });
+
+// Start a new session for the agent conversation.
+AgentSession session = await agent.CreateSessionAsync();
+
+// Run the agent with the session that stores conversation history in Cosmos DB.
+Console.WriteLine("First session:");
+Console.WriteLine(await agent.RunAsync("I like jokes about Pirates. Tell me a joke about a pirate.", session));
+
+// Start a second session. Since we configured the search scope to be across all sessions for the user,
+// the agent should remember that the user likes pirate jokes.
+AgentSession session2 = await agent.CreateSessionAsync();
+
+// Run the agent with the second session.
+Console.WriteLine("Second session (recalling prior chat history from Cosmos DB):");
+Console.WriteLine(await agent.RunAsync("Tell me a joke that I might like.", session2));
diff --git a/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/README.md b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/README.md
new file mode 100644
index 0000000000..16775abcd8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step08_MemoryUsingCosmosNoSql/README.md
@@ -0,0 +1,41 @@
+# Agent with Memory Using Azure Cosmos DB for NoSQL
+
+This sample uses `ChatHistoryMemoryProvider` with `CosmosNoSqlVectorStore` to persist chat history in Azure Cosmos DB for NoSQL and recall relevant messages in a new agent session.
+
+## Features Demonstrated
+
+- Authenticating to Microsoft Foundry and Azure Cosmos DB with `DefaultAzureCredential`
+- Storing chat messages in an Azure Cosmos DB vector store
+- Creating the configured database and chat-history container when they do not exist
+- Recalling relevant chat history across agent sessions
+
+## Prerequisites
+
+1. [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0)
+2. A Microsoft Foundry project with:
+ - A chat model deployment (the default is `gpt-5.4-mini`)
+ - A `text-embedding-3-large` deployment with 3,072 dimensions
+3. An Azure Cosmos DB for NoSQL account with [vector search enabled](https://learn.microsoft.com/azure/cosmos-db/nosql/vector-search)
+4. An Azure identity that can create the configured database and container and read and write items
+5. Azure CLI authentication (`az login`)
+
+## Configuration
+
+Set the following environment variables:
+
+| Variable | Description | Default |
+|---|---|---|
+| `FOUNDRY_PROJECT_ENDPOINT` | Microsoft Foundry project endpoint | *(required)* |
+| `COSMOS_ENDPOINT` | Azure Cosmos DB account endpoint | *(required)* |
+| `FOUNDRY_MODEL` | Chat model deployment name | `gpt-5.4-mini` |
+| `FOUNDRY_EMBEDDING_MODEL` | Embedding model deployment name | `text-embedding-3-large` |
+| `FOUNDRY_EMBEDDING_DIMENSIONS` | Number of dimensions produced by the embedding deployment | `3072` |
+| `COSMOS_DATABASE_NAME` | Database used to store agent memory | `agent-memory` |
+
+## Run the Sample
+
+```bash
+dotnet run
+```
+
+The first session stores the user's preference for pirate jokes. The second session uses a different `AgentSession` but the same per-run user search scope, allowing the agent to retrieve that preference from Azure Cosmos DB without recalling data from earlier sample runs.
\ No newline at end of file
diff --git a/dotnet/samples/02-agents/AgentWithMemory/README.md b/dotnet/samples/02-agents/AgentWithMemory/README.md
index f1dc4064a5..16096f44fa 100644
--- a/dotnet/samples/02-agents/AgentWithMemory/README.md
+++ b/dotnet/samples/02-agents/AgentWithMemory/README.md
@@ -11,6 +11,7 @@ These samples show how to create an agent with the Agent Framework that uses Mem
|[Bounded Chat History with Overflow](./AgentWithMemory_Step05_BoundedChatHistory/)|This sample demonstrates how to create a bounded chat history provider that overflows older messages to a vector store and recalls them as memories.|
|[Memory Using AgentMemory](./AgentWithMemory_Step06_MemoryUsingAgentMemory/)|This sample demonstrates a retail shopping assistant built with [`AgentMemory`](https://www.nuget.org/packages/AgentMemory), an unofficial .NET port of the Neo4j Labs graph-memory provider, to learn customer preferences and recommend products via graph traversal.|
|[File Based Memory](./AgentWithMemory_Step07_FileMemoryProvider/)|This sample demonstrates how to use the `FileMemoryProvider` to give an agent tools for storing and recalling memories as files, and how to configure the folder that those memory files are written to.|
+|[Memory with Azure Cosmos DB for NoSQL](./AgentWithMemory_Step08_MemoryUsingCosmosNoSql/)|This sample demonstrates how to persist and retrieve chat history across sessions with Azure Cosmos DB for NoSQL.|
> **See also**: [Memory Search with Foundry Agents](../AgentProviders/foundry/Agent_Step22_MemorySearch/) - demonstrates using the built-in Memory Search tool with Microsoft Foundry agents.