Microsoft Agent Framework Integration
This guide explains how to use Neo4j Agent Memory with Microsoft Agent Framework to build agents with persistent memory, graph-enhanced context retrieval, and Graph Data Science (GDS) algorithms for advanced recommendations.
|
This integration targets Microsoft Agent Framework v1.0.0b260212 (preview). APIs may change before GA release (expected Q1 2026). See API Compatibility for version requirements and migration guidance. |
Overview
The Microsoft Agent Framework integration provides:
-
ContextProvider: Automatic memory injection before agent invocation
-
ChatMessageStore: Persistent conversation history in Neo4j
-
Memory tools: Search, preferences, knowledge graph queries
-
GDS integration: PageRank, community detection, shortest path with graceful fallback
-
Reasoning traces: Capture agent execution patterns for learning
Installation
Install with Microsoft Agent Framework support:
pip install neo4j-agent-memory[microsoft-agent]
This installs:
-
agent-framework>=1.0.0b- Microsoft Agent Framework -
Required Neo4j dependencies
Quick Start
Using Neo4jContextProvider
The Neo4jContextProvider automatically injects relevant memory context before each agent invocation:
from neo4j_agent_memory import MemoryClient, MemorySettings
from neo4j_agent_memory.integrations.microsoft_agent import Neo4jContextProvider
from agent_framework.azure import AzureOpenAIResponsesClient
settings = MemorySettings(
neo4j={"uri": "bolt://localhost:7687", "username": "neo4j", "password": "password"},
embedding={"provider": "openai", "api_key": "sk-..."},
)
async with MemoryClient(settings) as client:
# Create context provider
provider = Neo4jContextProvider(
memory_client=client,
session_id="user-123",
include_short_term=True, # Recent conversation
include_long_term=True, # Entities and preferences
include_reasoning=True, # Similar past traces
)
# Create agent with memory
chat_client = AzureOpenAIResponsesClient(model="gpt-4")
agent = chat_client.as_agent(
name="assistant",
instructions="You are a helpful assistant.",
context_providers=[provider],
)
# Use the agent - context is automatically injected
response = await agent.run("What did we discuss earlier?")
Using Neo4jChatMessageStore
Store conversation history with automatic entity extraction:
from neo4j_agent_memory.integrations.microsoft_agent import Neo4jChatMessageStore
async with MemoryClient(settings) as client:
store = Neo4jChatMessageStore(
memory_client=client,
session_id="user-123",
extract_entities=True, # Extract entities from messages
generate_embeddings=True, # Generate embeddings for search
)
# Add messages
await store.add_messages([
Message("user", ["I love Nike running shoes"]),
Message("assistant", ["Nike makes great running shoes!"]),
])
# List messages
messages = await store.list_messages()
# Serialize for persistence
state = store.serialize()
# Deserialize later
new_store = Neo4jChatMessageStore.deserialize(state, memory_client=client)
Using Neo4jMicrosoftMemory (Unified Interface)
For convenience, use the unified interface that combines both:
from neo4j_agent_memory.integrations.microsoft_agent import Neo4jMicrosoftMemory
async with MemoryClient(settings) as client:
memory = Neo4jMicrosoftMemory(
memory_client=client,
session_id="user-123",
user_id="user-456", # Optional for personalization
include_short_term=True,
include_long_term=True,
include_reasoning=True,
max_context_items=15,
extract_entities=True,
)
# Use context provider with agent
agent = chat_client.as_agent(
name="assistant",
context_providers=[memory.context_provider],
)
# Direct memory operations
await memory.save_message("user", "Hello!")
context = await memory.get_context("user query")
results = await memory.search_memory("search term")
Memory Tools
Create callable function tools for agent memory operations. The framework auto-invokes these tools during agent execution — no manual dispatch needed:
from neo4j_agent_memory.integrations.microsoft_agent import create_memory_tools
# Create all memory tools bound to a memory instance
tools = create_memory_tools(
memory, # Neo4jMicrosoftMemory instance (required)
include_gds_tools=True, # Include GDS algorithm tools (default: True)
)
# Use with agent — framework auto-invokes tools
agent = chat_client.as_agent(
name="assistant",
tools=tools,
context_providers=[memory.context_provider],
)
Available Tools
| Tool | Description |
|---|---|
|
Search conversation history, entities, and preferences |
|
Save a user preference (brand, style, budget, etc.) |
|
Retrieve preferences by category or search query |
|
Query the entity knowledge graph |
|
Save a factual SPO triple (subject-predicate-object) |
|
Find similar past reasoning traces |
|
Find shortest path between two entities (GDS) |
|
Find similar entities using graph similarity (GDS) |
|
Get most important entities by PageRank (GDS) |
Tool Execution
When using create_memory_tools(), tools are callable FunctionTool instances that the agent framework auto-invokes during agent.run(). No manual dispatch is needed — the framework calls the tool functions directly and feeds results back to the model.
|
The legacy |
GDS Integration
Neo4j Graph Data Science algorithms enhance recommendations:
from neo4j_agent_memory.integrations.microsoft_agent import (
GDSConfig,
GDSAlgorithm,
GDSIntegration,
)
# Configure GDS
gds_config = GDSConfig(
enabled=True,
use_pagerank_for_ranking=True, # Rank entities by importance
pagerank_weight=0.3, # Weight for PageRank scores
use_community_grouping=True, # Group related entities
expose_as_tools=[ # Make available as agent tools
GDSAlgorithm.SHORTEST_PATH,
GDSAlgorithm.NODE_SIMILARITY,
GDSAlgorithm.PAGERANK,
],
fallback_to_basic=True, # Use Cypher if GDS unavailable
warn_on_fallback=True, # Log warning when falling back
)
# Create memory with GDS
memory = Neo4jMicrosoftMemory(
memory_client=client,
session_id="user-123",
gds_config=gds_config,
)
# Use GDS directly
if memory.gds:
# Find path between entities
path = await memory.gds.find_shortest_path("Nike", "Running Shoes")
# Find similar entities
similar = await memory.gds.find_similar_entities("Nike Air Max", limit=5)
# Get important entities
important = await memory.gds.get_central_entities(limit=10)
GDS Fallback Behavior
When GDS library is not installed:
| Algorithm | Fallback Behavior |
|---|---|
PageRank |
Uses degree centrality (relationship count) |
Community Detection |
Uses connected components via Cypher |
Node Similarity |
Uses Jaccard similarity on shared relationships |
Shortest Path |
Uses native Cypher |
Reasoning Traces
Capture agent execution patterns:
from neo4j_agent_memory.integrations.microsoft_agent import (
record_agent_trace,
get_similar_traces,
format_traces_for_prompt,
)
# Record agent execution
await record_agent_trace(
memory=memory,
messages=[
{"role": "user", "content": "Find running shoes under $150"},
{"role": "assistant", "content": "Recommended Nike Pegasus 40 ($130)"},
],
task="Find running shoes under $150",
tool_calls=[
{"name": "search_products", "arguments": {"query": "running shoes"}, "result": "..."},
{"name": "recall_preferences", "arguments": {"category": "brand"}, "result": "Nike"},
],
outcome="success",
success=True,
)
# Find similar past tasks
traces = await get_similar_traces(
memory=memory,
task="Find shoes matching preferences",
limit=3,
)
# Format for system prompt
experience = format_traces_for_prompt(traces)
Context Composition
The before_run() hook composes context from all memory types:
## Recent Conversation
[Recent messages relevant to current query]
## Known Preferences
- Brand: Nike
- Budget: Under $150
- Style: Running shoes
## Relevant Entities
- Nike Air Max 90 (Product): Iconic style, $130
- Nike Pegasus 40 (Product): Running shoe, $130
## Past Experience
Similar task: "Find running shoes" - Successfully recommended Pegasus
Serialization
Context providers and message stores support serialization for persistence:
# Serialize state
provider_state = provider.serialize()
store_state = store.serialize()
# Save to Redis, database, etc.
await redis.set(f"provider:{thread_id}", json.dumps(provider_state))
await redis.set(f"store:{thread_id}", json.dumps(store_state))
# Later: restore state
provider_state = json.loads(await redis.get(f"provider:{thread_id}"))
store_state = json.loads(await redis.get(f"store:{thread_id}"))
# Deserialize (requires fresh MemoryClient)
provider = Neo4jContextProvider.deserialize(provider_state, memory_client=client)
store = Neo4jChatMessageStore.deserialize(store_state, memory_client=client)
Complete Example
Here’s a complete shopping assistant example. With callable FunctionTool instances, the framework auto-invokes tools during agent.run() — no manual dispatch needed:
import asyncio
from agent_framework import Message
from agent_framework.azure import AzureOpenAIResponsesClient
from neo4j_agent_memory import MemoryClient, MemorySettings
from neo4j_agent_memory.integrations.microsoft_agent import (
Neo4jMicrosoftMemory,
GDSConfig,
GDSAlgorithm,
create_memory_tools,
record_agent_trace,
)
async def main():
settings = MemorySettings(
neo4j={"uri": "bolt://localhost:7687", "username": "neo4j", "password": "password"},
embedding={"provider": "openai", "api_key": "sk-..."},
)
gds_config = GDSConfig(
enabled=True,
expose_as_tools=[GDSAlgorithm.SHORTEST_PATH, GDSAlgorithm.NODE_SIMILARITY],
fallback_to_basic=True,
)
async with MemoryClient(settings) as client:
# Create memory
memory = Neo4jMicrosoftMemory(
memory_client=client,
session_id="shopping-session-1",
user_id="user-123",
gds_config=gds_config,
)
# Create chat client
chat_client = AzureOpenAIResponsesClient(model="gpt-4")
# Create memory tools bound to the memory instance
tools = create_memory_tools(memory, include_gds_tools=True)
# Create agent — tools are callable, framework auto-invokes them
agent = chat_client.as_agent(
name="ShoppingAssistant",
instructions="""You are a helpful shopping assistant.
Use memory tools to remember preferences and provide personalized recommendations.""",
tools=tools,
context_providers=[memory.context_provider],
)
# Conversation loop
while True:
user_input = input("You: ")
if user_input.lower() in ("quit", "exit"):
break
# Save user message
await memory.save_message("user", user_input)
# Run agent — framework auto-invokes tools and returns final response
response = await agent.run(Message("user", [user_input]))
# Display response
if response.text:
await memory.save_message("assistant", response.text)
print(f"Assistant: {response.text}")
# Record trace for learning
await record_agent_trace(
memory=memory,
messages=[
{"role": "user", "content": user_input},
{"role": "assistant", "content": response.text[:200] if response.text else ""},
],
task=user_input,
outcome="success",
success=True,
)
if __name__ == "__main__":
asyncio.run(main())
API Compatibility
Target Version
This integration targets:
-
Package:
agent-framework -
Version:
1.0.0b260212 -
Status: Public Preview
-
GA Target: Q1 2026
Troubleshooting
ImportError: agent_framework not found
Install the Microsoft Agent Framework package:
pip install neo4j-agent-memory[microsoft-agent]
# or
pip install agent-framework>=1.0.0b
GDS Not Available Warning
If you see "GDS not available, using fallback":
-
Install Neo4j GDS plugin on your database
-
Or set
fallback_to_basic=True(default) to use Cypher alternatives -
To silence: set
warn_on_fallback=False
Empty Context
If get_context() returns empty:
-
Verify embeddings are configured and generated
-
Check that messages/entities exist in Neo4j
-
Lower
similarity_threshold(default: 0.7)
Serialization Errors
deserialize() requires a fresh MemoryClient:
# Wrong - connection not serializable
state = provider.serialize()
# ... save to file ...
provider = Neo4jContextProvider.deserialize(state) # Missing client!
# Correct
state = provider.serialize()
# ... save to file ...
async with MemoryClient(settings) as client: # Fresh client
provider = Neo4jContextProvider.deserialize(state, memory_client=client)
API Reference
Neo4jContextProvider
| Method | Description |
|---|---|
|
Called before agent invocation; injects memory context into |
|
Called after agent response; extracts and stores memories |
|
Serialize provider state |
|
Restore provider from state |
Neo4jChatMessageStore
| Method | Description |
|---|---|
|
Add messages to conversation history |
|
Get all messages for the session |
|
Clear session messages |
|
Serialize store state |
|
Restore store from state |
Neo4jMicrosoftMemory
| Property/Method | Description |
|---|---|
|
Get the underlying ContextProvider |
|
Get the underlying ChatMessageStore |
|
Get GDS integration (if enabled) |
|
Get combined context from all memory types |
|
Save a conversation message |
|
Search across all memory types |
|
Add a user preference |
|
Find path between entities |
|
Find similar entities |
|
Get entities ranked by importance |
Functions
| Function | Description |
|---|---|
|
Create callable |
|
Legacy manual tool dispatch. Use |
|
Record agent execution |
|
Find similar past traces |
|
Format traces for prompts |