From f785079704db00c5da6c44a68ef07750ebab29be Mon Sep 17 00:00:00 2001 From: Jose Luis Latorre Millas Date: Tue, 14 Jul 2026 00:33:36 +0200 Subject: [PATCH 1/2] docs: add C# usage for the Neo4j Memory Provider Fills in the C# zone of the Neo4j Memory Provider page, previously just a "not yet available" placeholder, with Prerequisites/Installation/Usage/Key features/Resources sections mirroring the Python zone's structure. Documents the AgentMemory / AgentMemory.AgentFramework NuGet packages (a community .NET port of the Neo4j Labs memory provider, not an official Neo4j Labs package) and links to its source repo and the upcoming Agent Framework retail-assistant sample. Co-Authored-By: Claude Sonnet 5 --- agent-framework/integrations/neo4j-memory.md | 105 ++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/agent-framework/integrations/neo4j-memory.md b/agent-framework/integrations/neo4j-memory.md index f7e8947f..020faa6e 100644 --- a/agent-framework/integrations/neo4j-memory.md +++ b/agent-framework/integrations/neo4j-memory.md @@ -30,7 +30,110 @@ The provider manages three types of memory: ::: zone pivot="programming-language-csharp" -This provider is not yet available for C#. See the Python tab for usage examples. +> [!NOTE] +> The .NET package (`AgentMemory`) is an independent, community-maintained .NET port of the Neo4j Labs memory provider — it is not an official Neo4j Labs package. See the [AgentMemory (.NET) repository](https://github.com/joslat/agent-memory-dotnet) for source and details. + +## Prerequisites + +- A Neo4j instance (self-hosted or [Neo4j AuraDB](https://neo4j.com/cloud/aura/)) +- An Azure OpenAI or Microsoft Foundry deployment (a chat model + an embedding model) +- Environment variables set: `NEO4J_URI`, `NEO4J_USER`, `NEO4J_PASSWORD`, `AZURE_OPENAI_ENDPOINT` +- Azure CLI credentials configured (`az login`), or an API key +- .NET 9.0 or later + +## Installation + +```bash +dotnet add package AgentMemory +dotnet add package AgentMemory.AgentFramework +``` + +## Usage + +```csharp +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using AgentMemory.Abstractions.Services; +using AgentMemory.AgentFramework; +using AgentMemory.AgentFramework.Tools; +using AgentMemory.Core; +using AgentMemory.Core.Stubs; + +var builder = Host.CreateApplicationBuilder(args); + +// Reads NEO4J_URI / NEO4J_USER / NEO4J_PASSWORD (falls back to local-dev defaults) +builder.Services.AddNeo4jAgentMemory(options => +{ + options.Uri = Environment.GetEnvironmentVariable("NEO4J_URI") ?? "bolt://localhost:7687"; + options.Username = Environment.GetEnvironmentVariable("NEO4J_USER") ?? "neo4j"; + options.Password = Environment.GetEnvironmentVariable("NEO4J_PASSWORD") ?? "password"; +}); +builder.Services.AddAgentMemoryCore(_ => { }); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); + +// Any Microsoft.Extensions.AI-compatible chat + embedding client works +var azureClient = new AzureOpenAIClient( + new Uri(Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!), new DefaultAzureCredential()); +builder.Services.AddSingleton(azureClient.GetChatClient("gpt-4o-mini").AsIChatClient()); +builder.Services.AddSingleton(azureClient.GetEmbeddingClient("text-embedding-3-small").AsIEmbeddingGenerator()); + +// AutoExtractOnPersist builds the knowledge graph from every conversation turn +builder.Services.AddAgentMemoryFramework(options => +{ + options.AutoExtractOnPersist = true; + options.ContextFormat.IncludeEntities = true; + options.ContextFormat.IncludeFacts = true; + options.ContextFormat.IncludePreferences = true; +}); + +using var host = builder.Build(); +await using var scope = host.Services.CreateAsyncScope(); +var services = scope.ServiceProvider; + +// Bootstraps Neo4j schema/indexes on first run (idempotent) +await services.GetRequiredService().BootstrapAsync(); + +var memoryProvider = services.GetRequiredService(); +var memoryTools = services.GetRequiredService().CreateAIFunctions(); + +AIAgent agent = services.GetRequiredService().AsAIAgent(new ChatClientAgentOptions +{ + ChatOptions = new ChatOptions + { + Instructions = "You are a helpful assistant with persistent memory.", + Tools = [.. memoryTools], + }, + AIContextProviders = [memoryProvider], +}); + +var session = (await agent.CreateSessionAsync()) + .WithMemoryIdentity(userId: "user-123", sessionId: "session-1", applicationId: "my-app"); + +using (services.GetRequiredService().BeginOwnerScope("user-123")) +{ + var response = await agent.RunAsync("Remember that I prefer window seats on flights.", session); +} +``` + +## Key features + +- **Bidirectional**: `Neo4jMemoryContextProvider` recalls relevant memory before each run and persists new memory after — no manual wiring needed +- **Entity extraction**: builds a knowledge graph from conversations with a configurable extraction pipeline (`AutoExtractOnPersist`) +- **Preference learning**: infers and stores user preferences, facts, and entities, recalled automatically by a brand-new `AgentSession` for the same user +- **Memory tools**: `MemoryToolFactory` exposes `AIFunction`s so the model can explicitly search, remember, and recall +- **Dependency-injection first**: registers via `AddNeo4jAgentMemory` / `AddAgentMemoryCore` / `AddAgentMemoryFramework`, fitting naturally into Generic Host and ASP.NET Core apps +- **Beyond Agent Framework**: the same library also integrates with Semantic Kernel and MCP clients, and includes built-in OpenTelemetry observability + +## Resources + +- [AgentMemory (.NET) repository](https://github.com/joslat/agent-memory-dotnet) +- [NuGet package page](https://www.nuget.org/packages/AgentMemory) +- [Sample: Retail Assistant with AgentMemory](https://github.com/microsoft/agent-framework/tree/main/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step06_MemoryUsingAgentMemory) ::: zone-end From 9e20d2434f1be61b079a34f88b1e1e4e80988e16 Mon Sep 17 00:00:00 2001 From: Jose Luis Latorre Millas Date: Thu, 16 Jul 2026 16:28:02 +0200 Subject: [PATCH 2/2] Address PR review: fix C# sample and link Neo4j Memory in integrations index - List the Neo4j Memory Provider under the C# Memory AI Context Providers table in integrations/index.md (previously only linked from the Python pivot), per westey-m's review comment. - Update the C# usage sample to use AddNeo4jAgentMemory's configureMemory/ configureNeo4j overload (the prior single-arg call didn't resolve without an extra import), drop the now-redundant AddAgentMemoryCore/IClock/ IIdGenerator registrations AddNeo4jAgentMemory already wires up, and pass configureLlm so AutoExtractOnPersist isn't a silent no-op. - Wrap the agent in .WithMemoryOwnerScoping(services) instead of a manual BeginOwnerScope around RunAsync, matching the scoping fix from microsoft/agent-framework#7096 (BeginOwnerScope doesn't reliably cover the tool-calling loop). - Fix NEO4J_USER -> NEO4J_USERNAME and overstated .NET 9.0 -> 8.0 prerequisite to match the sibling Neo4j GraphRAG page and the library's actual multi-targeting. Co-Authored-By: Claude Sonnet 5 --- agent-framework/integrations/index.md | 1 + agent-framework/integrations/neo4j-memory.md | 43 ++++++++++---------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/agent-framework/integrations/index.md b/agent-framework/integrations/index.md index 657becd3..ebef640f 100644 --- a/agent-framework/integrations/index.md +++ b/agent-framework/integrations/index.md @@ -62,6 +62,7 @@ Here is a list of existing providers that can be used. | Memory AI Context Provider | Release Status | | ------------------------------------------------------------------ | --------------- | | [Chat History Memory Provider](./chat-history-memory-provider.md) | Released | +| [Neo4j Memory Provider](./neo4j-memory.md) | Preview | ::: zone-end diff --git a/agent-framework/integrations/neo4j-memory.md b/agent-framework/integrations/neo4j-memory.md index 020faa6e..a0c0b05f 100644 --- a/agent-framework/integrations/neo4j-memory.md +++ b/agent-framework/integrations/neo4j-memory.md @@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages author: retroryan ms.topic: article ms.author: westey -ms.date: 04/01/2026 +ms.date: 07/16/2026 ms.service: agent-framework --- @@ -37,9 +37,9 @@ The provider manages three types of memory: - A Neo4j instance (self-hosted or [Neo4j AuraDB](https://neo4j.com/cloud/aura/)) - An Azure OpenAI or Microsoft Foundry deployment (a chat model + an embedding model) -- Environment variables set: `NEO4J_URI`, `NEO4J_USER`, `NEO4J_PASSWORD`, `AZURE_OPENAI_ENDPOINT` +- Environment variables set: `NEO4J_URI`, `NEO4J_USERNAME`, `NEO4J_PASSWORD`, `AZURE_OPENAI_ENDPOINT` - Azure CLI credentials configured (`az login`), or an API key -- .NET 9.0 or later +- .NET 8.0 or later ## Installation @@ -57,24 +57,25 @@ using Microsoft.Agents.AI; using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using AgentMemory; using AgentMemory.Abstractions.Services; using AgentMemory.AgentFramework; using AgentMemory.AgentFramework.Tools; -using AgentMemory.Core; -using AgentMemory.Core.Stubs; var builder = Host.CreateApplicationBuilder(args); -// Reads NEO4J_URI / NEO4J_USER / NEO4J_PASSWORD (falls back to local-dev defaults) -builder.Services.AddNeo4jAgentMemory(options => -{ - options.Uri = Environment.GetEnvironmentVariable("NEO4J_URI") ?? "bolt://localhost:7687"; - options.Username = Environment.GetEnvironmentVariable("NEO4J_USER") ?? "neo4j"; - options.Password = Environment.GetEnvironmentVariable("NEO4J_PASSWORD") ?? "password"; -}); -builder.Services.AddAgentMemoryCore(_ => { }); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); +// Registers Core + Neo4j infrastructure in one call (reads NEO4J_URI / NEO4J_USERNAME / +// NEO4J_PASSWORD, falling back to local-dev defaults). Passing configureLlm opts in to +// LLM-backed entity/fact/preference extraction, using the IChatClient registered below. +builder.Services.AddNeo4jAgentMemory( + configureMemory: _ => { }, + configureNeo4j: neo4j => + { + neo4j.Uri = Environment.GetEnvironmentVariable("NEO4J_URI") ?? "bolt://localhost:7687"; + neo4j.Username = Environment.GetEnvironmentVariable("NEO4J_USERNAME") ?? "neo4j"; + neo4j.Password = Environment.GetEnvironmentVariable("NEO4J_PASSWORD") ?? "password"; + }, + configureLlm: _ => { }); // Any Microsoft.Extensions.AI-compatible chat + embedding client works var azureClient = new AzureOpenAIClient( @@ -101,6 +102,9 @@ await services.GetRequiredService().BootstrapAsync(); var memoryProvider = services.GetRequiredService(); var memoryTools = services.GetRequiredService().CreateAIFunctions(); +// WithMemoryOwnerScoping wraps the whole invocation — recall, the tool-calling loop, and +// persistence — in the owner scope set by WithMemoryIdentity below, so no manual +// BeginOwnerScope call is needed around RunAsync. AIAgent agent = services.GetRequiredService().AsAIAgent(new ChatClientAgentOptions { ChatOptions = new ChatOptions @@ -109,15 +113,12 @@ AIAgent agent = services.GetRequiredService().AsAIAgent(new ChatCli Tools = [.. memoryTools], }, AIContextProviders = [memoryProvider], -}); +}).WithMemoryOwnerScoping(services); var session = (await agent.CreateSessionAsync()) .WithMemoryIdentity(userId: "user-123", sessionId: "session-1", applicationId: "my-app"); -using (services.GetRequiredService().BeginOwnerScope("user-123")) -{ - var response = await agent.RunAsync("Remember that I prefer window seats on flights.", session); -} +var response = await agent.RunAsync("Remember that I prefer window seats on flights.", session); ``` ## Key features @@ -126,7 +127,7 @@ using (services.GetRequiredService().BeginOwnerScop - **Entity extraction**: builds a knowledge graph from conversations with a configurable extraction pipeline (`AutoExtractOnPersist`) - **Preference learning**: infers and stores user preferences, facts, and entities, recalled automatically by a brand-new `AgentSession` for the same user - **Memory tools**: `MemoryToolFactory` exposes `AIFunction`s so the model can explicitly search, remember, and recall -- **Dependency-injection first**: registers via `AddNeo4jAgentMemory` / `AddAgentMemoryCore` / `AddAgentMemoryFramework`, fitting naturally into Generic Host and ASP.NET Core apps +- **Dependency-injection first**: registers via `AddNeo4jAgentMemory` (wires up Core + Neo4j internally) and `AddAgentMemoryFramework`, fitting naturally into Generic Host and ASP.NET Core apps - **Beyond Agent Framework**: the same library also integrates with Semantic Kernel and MCP clients, and includes built-in OpenTelemetry observability ## Resources