Building a Dual‑Stack Memory Agent: Situational + Semantic Memory for Long‑Term AI Understanding

This tutorial walks through designing and implementing a dual‑stack memory architecture for AI agents—combining episodic vector‑based situational memory with graph‑based semantic memory—using LangChain, FAISS, and Neo4j, and demonstrates a complete end‑to‑end workflow with code examples.

Data STUDIO
Data STUDIO
Data STUDIO
Building a Dual‑Stack Memory Agent: Situational + Semantic Memory for Long‑Term AI Understanding

What Is "Double‑Stack Memory"?

Two complementary memory systems are introduced:

Situational Memory : Stores raw conversation snippets in a vector database (FAISS) to answer "what happened?" by similarity search.

Semantic Memory : Extracts structured knowledge cards (e.g., user preferences) and stores them in a graph database (Neo4j) to answer "what do I know?".

Combined, they enable an agent to recall past dialogues and reason over extracted facts.

Architecture Workflow: From Forgetting to Remembering

The agent processes each turn in three stages:

Recall : Query both the vector store and the graph for relevant episodic and semantic memories.

Generate : Append the retrieved memories to a prompt and let a large language model produce a context‑aware response.

Encode : After the response, summarize the interaction for situational memory and extract entities/relations for semantic memory, storing them back into the respective databases.

This loop allows unlimited accumulation of user knowledge beyond the LLM context window.

Step‑by‑Step Implementation

Stage 0 – Setup

Install required libraries and load environment variables.

# !pip install -q -U langchain-nebius langchain langgraph rich python-dotenv langchain_community langchain-openai neo4j faiss-cpu tiktoken

Import modules, configure API keys, and verify that Neo4j credentials are available.

Stage 1 – Build Memory Components

Initialize the FAISS vector store and the Neo4j graph, then define Pydantic models for nodes, relationships, and the knowledge graph.

class Node(BaseModel):
    id: str = Field(description="Unique identifier, e.g., person name or concept.")
    type: str = Field(description="Node type, e.g., 'User', 'Company'.")
    properties: Dict[str, Any] = Field(description="Attribute dictionary.")

class Relationship(BaseModel):
    source: Node = Field(description="Source node.")
    target: Node = Field(description="Target node.")
    type: str = Field(description="Relationship type, e.g., 'INTERESTED_IN'.")
    properties: Dict[str, Any] = Field(description="Attribute dictionary.")

class KnowledgeGraph(BaseModel):
    """Structured knowledge extracted from a dialogue."""
    relationships: List[Relationship] = Field(description="List of relationships to add to the graph.")

Define create_memories that generates a concise episodic summary using a summarization prompt and extracts semantic triples with a structured‑output LLM, storing results in FAISS and Neo4j respectively.

Stage 2 – Assemble the Memory‑Enhanced Agent

Using LangGraph, define the agent state and three nodes: retrieve_memory, generate_response, and update_memory. The workflow connects them as Retrieve → Generate → Update → END.

class AgentState(TypedDict):
    user_input: str
    retrieved_memories: Optional[str]
    generation: str

workflow = StateGraph(AgentState)
workflow.add_node("retrieve", retrieve_memory)
workflow.add_node("generate", generate_response)
workflow.add_node("update", update_memory)
workflow.set_entry_point("retrieve")
workflow.add_edge("retrieve", "generate")
workflow.add_edge("generate", "update")
workflow.add_edge("update", END)
memory_agent = workflow.compile()

Stage 3 – Demonstration

Run a three‑turn conversation:

# Turn 1 – Seed memory
run_interaction("Hi, I'm Alex. I'm a conservative investor interested in mature tech stocks.")
# Turn 2 – Ask about a specific stock
run_interaction("What do you think about Apple (AAPL)?")
# Turn 3 – Memory test
run_interaction("Based on my goals, what are good alternative stocks?")

The third response references Alex's conservative profile and the earlier Apple discussion, suggesting Microsoft and Google as more suitable alternatives.

Inspecting Stored Memories

Query the FAISS store and Neo4j graph to verify that episodic summaries and semantic triples have been persisted, e.g.,

(User {id: "Alex"})-[:HAS_GOAL]->(Goal {value: "conservative"})
(User)-[:INTERESTED_IN]->(Company {name: "Apple"})

These structures illustrate how the agent can "remember" user preferences over time.

Key Takeaways Two memory types: situational (vector store) and semantic (graph) provide comprehensive knowledge capture. Workflow: Recall → Generate → Update creates a continuous learning loop. Practical tips: implement summarization, entity extraction, and periodic pruning to prevent memory bloat.

Building agents with long‑term memory is a crucial step toward truly personalized AI assistants, though scaling introduces challenges such as consistency and privacy that must be addressed in production.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonPrompt EngineeringLangChainFAISSNeo4jknowledge graphAgent Memory
Data STUDIO
Written by

Data STUDIO

Click to receive the "Python Study Handbook"; reply "benefit" in the chat to get it. Data STUDIO focuses on original data science articles, centered on Python, covering machine learning, data analysis, visualization, MySQL and other practical knowledge and project case studies.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.