-
Notifications
You must be signed in to change notification settings - Fork 1.2k
.NET: Add Foundry Agents Tool Sample - Memory Search #3700
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
rogerbarreto
merged 5 commits into
microsoft:main
from
rogerbarreto:feature/3674-memory-search
Feb 23, 2026
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
99cad3a
.NET: Add Memory Search sample #3674
rogerbarreto 0cecee6
Apply format fixes
rogerbarreto 72ddef0
Add MemorySearch sample to solution, FoundryAgents and AgentWithMemor…
rogerbarreto b05ff59
Merge branch 'main' into feature/3674-memory-search
rogerbarreto 1d968bc
Merge branch 'main' into feature/3674-memory-search
rogerbarreto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
.../FoundryAgents/FoundryAgents_Step26_MemorySearch/FoundryAgents_Step26_MemorySearch.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFrameworks>net10.0</TargetFrameworks> | ||
|
|
||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <NoWarn>$(NoWarn);CA1812</NoWarn> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Extensions.Logging.Console" /> | ||
| <PackageReference Include="Azure.Identity" /> | ||
| <PackageReference Include="Azure.AI.Projects" /> | ||
| <PackageReference Include="Azure.AI.Projects.OpenAI" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> | ||
124 changes: 124 additions & 0 deletions
124
dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step26_MemorySearch/Program.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| // This sample demonstrates how to use the Memory Search Tool with AI Agents. | ||
| // The Memory Search Tool enables agents to recall information from previous conversations, | ||
| // supporting user profile persistence and chat summaries across sessions. | ||
|
|
||
| using Azure.AI.Projects; | ||
| using Azure.AI.Projects.OpenAI; | ||
| using Azure.Identity; | ||
| using Microsoft.Agents.AI; | ||
| using OpenAI.Responses; | ||
|
|
||
| string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set."); | ||
| string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; | ||
|
|
||
| // Memory store configuration | ||
| // NOTE: Memory stores must be created beforehand via Azure Portal or Python SDK. | ||
| // The .NET SDK currently only supports using existing memory stores with agents. | ||
| string memoryStoreName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_MEMORY_STORE_NAME") ?? throw new InvalidOperationException("AZURE_FOUNDRY_MEMORY_STORE_NAME is not set."); | ||
|
|
||
| const string AgentInstructions = """ | ||
| You are a helpful assistant that remembers past conversations. | ||
| Use the memory search tool to recall relevant information from previous interactions. | ||
| When a user shares personal details or preferences, remember them for future conversations. | ||
| """; | ||
|
|
||
| const string AgentNameMEAI = "MemorySearchAgent-MEAI"; | ||
| const string AgentNameNative = "MemorySearchAgent-NATIVE"; | ||
|
|
||
| // Scope identifies the user or context for memory isolation. | ||
| // Using a unique user identifier ensures memories are private to that user. | ||
| string userScope = $"user_{Environment.MachineName}"; | ||
|
|
||
| // Get a client to create/retrieve/delete server side agents with Azure Foundry Agents. | ||
| AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); | ||
|
|
||
| // Create the Memory Search tool configuration | ||
| MemorySearchTool memorySearchTool = new(memoryStoreName, userScope) | ||
| { | ||
| // Optional: Configure how quickly new memories are indexed (in seconds) | ||
| UpdateDelay = 1, | ||
|
|
||
| // Optional: Configure search behavior | ||
| SearchOptions = new MemorySearchToolOptions | ||
| { | ||
| // Additional search options can be configured here if needed | ||
| } | ||
| }; | ||
|
|
||
| // Create agent using Option 1 (MEAI) or Option 2 (Native SDK) | ||
| AIAgent agent = await CreateAgentWithMEAI(); | ||
| // AIAgent agent = await CreateAgentWithNativeSDK(); | ||
|
|
||
| Console.WriteLine("Agent created with Memory Search tool. Starting conversation...\n"); | ||
|
|
||
| // Conversation 1: Share some personal information | ||
| Console.WriteLine("User: My name is Alice and I love programming in C#."); | ||
| AgentResponse response1 = await agent.RunAsync("My name is Alice and I love programming in C#."); | ||
| Console.WriteLine($"Agent: {response1.Messages.LastOrDefault()?.Text}\n"); | ||
|
|
||
| // Allow time for memory to be indexed | ||
| await Task.Delay(2000); | ||
|
|
||
| // Conversation 2: Test if the agent remembers | ||
| Console.WriteLine("User: What's my name and what programming language do I prefer?"); | ||
| AgentResponse response2 = await agent.RunAsync("What's my name and what programming language do I prefer?"); | ||
| Console.WriteLine($"Agent: {response2.Messages.LastOrDefault()?.Text}\n"); | ||
|
|
||
| // Inspect memory search results if available in raw response items | ||
| // Note: Memory search tool call results appear as AgentResponseItem types | ||
| foreach (var message in response2.Messages) | ||
| { | ||
| if (message.RawRepresentation is AgentResponseItem agentResponseItem && | ||
| agentResponseItem is MemorySearchToolCallResponseItem memorySearchResult) | ||
| { | ||
| Console.WriteLine($"Memory Search Status: {memorySearchResult.Status}"); | ||
| Console.WriteLine($"Memory Search Results Count: {memorySearchResult.Results.Count}"); | ||
|
|
||
| foreach (var result in memorySearchResult.Results) | ||
| { | ||
| var memoryItem = result.MemoryItem; | ||
| Console.WriteLine($" - Memory ID: {memoryItem.MemoryId}"); | ||
| Console.WriteLine($" Scope: {memoryItem.Scope}"); | ||
| Console.WriteLine($" Content: {memoryItem.Content}"); | ||
| Console.WriteLine($" Updated: {memoryItem.UpdatedAt}"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Cleanup: Delete the agent (memory store persists and should be cleaned up separately if needed) | ||
| Console.WriteLine("\nCleaning up agent..."); | ||
| await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); | ||
| Console.WriteLine("Agent deleted successfully."); | ||
|
|
||
| // NOTE: Memory stores are long-lived resources and are NOT deleted with the agent. | ||
| // To delete a memory store, use the Azure Portal or Python SDK: | ||
| // await project_client.memory_stores.delete(memory_store.name) | ||
|
|
||
| // --- Agent Creation Options --- | ||
| #pragma warning disable CS8321 // Local function is declared but never used | ||
|
|
||
| // Option 1 - Using MemorySearchTool wrapped as MEAI AITool | ||
| async Task<AIAgent> CreateAgentWithMEAI() | ||
| { | ||
| return await aiProjectClient.CreateAIAgentAsync( | ||
| model: deploymentName, | ||
| name: AgentNameMEAI, | ||
| instructions: AgentInstructions, | ||
| tools: [((ResponseTool)memorySearchTool).AsAITool()]); | ||
| } | ||
|
|
||
| // Option 2 - Using PromptAgentDefinition with MemorySearchTool (Native SDK) | ||
| async Task<AIAgent> CreateAgentWithNativeSDK() | ||
| { | ||
| return await aiProjectClient.CreateAIAgentAsync( | ||
| name: AgentNameNative, | ||
| creationOptions: new AgentVersionCreationOptions( | ||
| new PromptAgentDefinition(model: deploymentName) | ||
| { | ||
| Instructions = AgentInstructions, | ||
| Tools = { memorySearchTool } | ||
| }) | ||
| ); | ||
| } |
92 changes: 92 additions & 0 deletions
92
...amples/GettingStarted/FoundryAgents/FoundryAgents_Step26_MemorySearch/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| # Using Memory Search with AI Agents | ||
|
|
||
| This sample demonstrates how to use the Memory Search tool with AI agents. The Memory Search tool enables agents to recall information from previous conversations, supporting user profile persistence and chat summaries across sessions. | ||
|
|
||
| ## What this sample demonstrates | ||
|
|
||
| - Creating an agent with Memory Search tool capabilities | ||
| - Configuring memory scope for user isolation | ||
| - Having conversations where the agent remembers past information | ||
| - Inspecting memory search results from agent responses | ||
| - Managing agent lifecycle (creation and deletion) | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| Before you begin, ensure you have the following prerequisites: | ||
|
|
||
| - .NET 10 SDK or later | ||
| - Azure Foundry service endpoint and deployment configured | ||
| - Azure CLI installed and authenticated (for Azure credential authentication) | ||
| - **A pre-created Memory Store** (see below) | ||
|
|
||
| **Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively). | ||
|
|
||
| ### Creating a Memory Store | ||
|
|
||
| Memory stores must be created before running this sample. The .NET SDK currently only supports **using** existing memory stores with agents. To create a memory store, use one of these methods: | ||
|
|
||
| **Option 1: Azure Portal** | ||
| 1. Navigate to your Azure AI Foundry project | ||
| 2. Go to the Memory section | ||
| 3. Create a new memory store with your desired settings | ||
|
|
||
| **Option 2: Python SDK** | ||
| ```python | ||
| from azure.ai.projects import AIProjectClient | ||
| from azure.ai.projects.models import MemoryStoreDefaultDefinition, MemoryStoreDefaultOptions | ||
| from azure.identity import DefaultAzureCredential | ||
|
|
||
| project_client = AIProjectClient( | ||
| endpoint="https://your-endpoint.openai.azure.com/", | ||
| credential=DefaultAzureCredential() | ||
| ) | ||
|
|
||
| memory_store = await project_client.memory_stores.create( | ||
| name="my-memory-store", | ||
| description="Memory store for Agent Framework conversations", | ||
| definition=MemoryStoreDefaultDefinition( | ||
| chat_model=os.environ["AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME"], | ||
| embedding_model=os.environ["AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME"], | ||
| options=MemoryStoreDefaultOptions( | ||
| user_profile_enabled=True, | ||
| chat_summary_enabled=True | ||
| ) | ||
| ) | ||
| ) | ||
| ``` | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| Set the following environment variables: | ||
|
|
||
| ```powershell | ||
| $env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" | ||
| $env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini | ||
| $env:AZURE_AI_MEMORY_STORE_NAME="your-memory-store-name" # Required - name of pre-created memory store | ||
| ``` | ||
|
|
||
| ## Run the sample | ||
|
|
||
| Navigate to the FoundryAgents sample directory and run: | ||
|
|
||
| ```powershell | ||
| cd dotnet/samples/GettingStarted/FoundryAgents | ||
| dotnet run --project .\FoundryAgents_Step26_MemorySearch | ||
| ``` | ||
|
|
||
| ## Expected behavior | ||
|
|
||
| The sample will: | ||
|
|
||
| 1. Create an agent with Memory Search tool configured | ||
| 2. Send a message with personal information ("My name is Alice and I love programming in C#") | ||
| 3. Wait for memory indexing | ||
| 4. Ask the agent to recall the previously shared information | ||
| 5. Display memory search results if available in the response | ||
| 6. Clean up by deleting the agent (note: memory store persists) | ||
|
|
||
| ## Important notes | ||
|
|
||
| - **Memory Store Lifecycle**: Memory stores are long-lived resources and are NOT deleted when the agent is deleted. Clean them up separately via Azure Portal or Python SDK. | ||
| - **Scope**: The `scope` parameter isolates memories per user/context. Use unique identifiers for different users. | ||
| - **Update Delay**: The `UpdateDelay` parameter controls how quickly new memories are indexed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.