33
44This demo shows a memory-augmented Agent built with Haystack components instead of using the prebuilt Agent tools:
55
6- 1. Pre-seeded memories are written to Mem0 before the conversation starts.
6+ 1. Pre-seeded memories are written to Mem0 before the first conversation starts.
772. Before each turn, Mem0MemoryRetriever fetches memories relevant to the user message.
883. OutputAdapter prepends retrieved memories to live chat history and the current user message.
994. Agent answers with the combined context.
10105. Mem0MemoryWriter stores the Agent's full message trace with inference enabled, giving Mem0 the
1111 user message, any tool-call context, and the final assistant response when extracting memories.
12+ 6. A second conversation starts with empty chat history and recalls facts introduced in the first conversation.
1213
1314Pipeline structure per turn:
1415
2728 OPENAI_API_KEY - Your OpenAI API key
2829"""
2930
31+ import time
32+
3033from haystack import Pipeline
3134from haystack .components .agents import Agent
3235from haystack .components .converters import OutputAdapter
3740from haystack_integrations .components .writers .mem0 import Mem0MemoryWriter
3841from haystack_integrations .memory_stores .mem0 import Mem0MemoryStore
3942
40- USER_ID = "mem0-agent-pipeline-demo-user"
41- AGENT_ID = "mem0-agent-pipeline-demo-agent"
43+ USER_ID = "mem0-agent-pipeline-demo-user-5 "
44+ MEMORY_INFERENCE_WAIT_SECONDS = 15
4245
4346SEEDED_MEMORIES = [
4447 "My name is Alice. I am a senior data scientist at Acme Corp specializing in NLP." ,
4750 "I prefer concise answers with Python code examples over long prose explanations." ,
4851]
4952
53+ FIRST_CONVERSATION_TURNS = [
54+ "Hi! Can you remind me what project I am currently working on?" ,
55+ (
56+ "Quick update for memory: I switched the prototype vector database to Qdrant Cloud, "
57+ "and the main blocker is extracting tables cleanly from PDFs."
58+ ),
59+ (
60+ "Also remember that Dana joined the team to own evaluation, and I want future code examples "
61+ "to be fully documented with api doc strings."
62+ ),
63+ ]
64+
65+ SECOND_CONVERSATION_TURNS = [
66+ "What vector database did I switch the prototype to, and what is the current blocker?" ,
67+ "Who owns evaluation now, and how should you tailor code examples for me?" ,
68+ ]
69+
5070SYSTEM_PROMPT = (
5171 "You are a helpful assistant with access to persistent memory from past conversations. "
5272 "System messages at the start of the conversation contain relevant memories retrieved from Mem0. "
@@ -93,20 +113,20 @@ def build_memory_agent_pipeline(store: Mem0MemoryStore) -> Pipeline:
93113def seed_memories (store : Mem0MemoryStore ) -> None :
94114 """Seed facts that simulate memories from a previous session."""
95115 messages = [ChatMessage .from_user (fact ) for fact in SEEDED_MEMORIES ]
96- store .add_memories (messages = messages , user_id = USER_ID , agent_id = AGENT_ID , infer = False )
116+ store .add_memories (messages = messages , user_id = USER_ID , infer = False )
97117
98118
99119def run_turn (pipeline : Pipeline , user_text : str , history : list [ChatMessage ]) -> str :
100120 """Run one conversation turn, update clean user/assistant history, and return the reply."""
101121 user_message = ChatMessage .from_user (user_text )
102122 result = pipeline .run (
103123 {
104- "retriever" : {"query" : user_text , "user_id" : USER_ID , "agent_id" : AGENT_ID },
124+ "retriever" : {"query" : user_text , "user_id" : USER_ID },
105125 "memory_injector" : {
106126 "history" : history ,
107127 "user_messages" : [user_message ],
108128 },
109- "writer" : {"user_id" : USER_ID , "agent_id" : AGENT_ID },
129+ "writer" : {"user_id" : USER_ID },
110130 }
111131 )
112132
@@ -119,6 +139,15 @@ def run_turn(pipeline: Pipeline, user_text: str, history: list[ChatMessage]) ->
119139 return reply
120140
121141
142+ def wait_for_memory_processing (seconds : int ) -> None :
143+ """Print a countdown while Mem0 processes inferred memories."""
144+ print ("Waiting for Mem0 to process inferred memories:" ) # noqa: T201
145+ for remaining in range (seconds , 0 , - 1 ):
146+ print (f" { remaining } second(s) remaining..." , end = "\r " , flush = True ) # noqa: T201
147+ time .sleep (1 )
148+ print (" done.\n " ) # noqa: T201
149+
150+
122151def main () -> None :
123152 """Run the Mem0 memory Agent pipeline demo."""
124153 print ("=== Mem0 Memory Agent Pipeline Demo ===\n " ) # noqa: T201
@@ -127,23 +156,25 @@ def main() -> None:
127156 seed_memories (store )
128157 print (f"Seeded { len (SEEDED_MEMORIES )} memories for { USER_ID } .\n " ) # noqa: T201
129158 print ("Seeded memories:" ) # noqa: T201
130- for memory in store .search_memories (query = "" , top_k = 10 , user_id = USER_ID , agent_id = AGENT_ID ):
159+ for memory in store .search_memories (query = "" , top_k = 10 , user_id = USER_ID ):
131160 print (f"- { memory .text } " ) # noqa: T201
132161
133162 pipeline = build_memory_agent_pipeline (store )
134- history : list [ChatMessage ] = []
163+ first_history : list [ChatMessage ] = []
164+
165+ print ("\n ==Starting first conversation...==\n " ) # noqa: T201
166+ for user_text in FIRST_CONVERSATION_TURNS :
167+ print (f"User: { user_text } " ) # noqa: T201
168+ reply = run_turn (pipeline , user_text , first_history )
169+ print (f"Agent: { reply } \n " ) # noqa: T201
135170
136- turns = [
137- "Hi! Can you remind me what project I am currently working on?" ,
138- "What is the tech stack we are using for it?" ,
139- "Who else is on my team, and what are their roles?" ,
140- "Based on what you know about me, give me a quick tip for structuring a new Haystack pipeline component." ,
141- ]
171+ wait_for_memory_processing (MEMORY_INFERENCE_WAIT_SECONDS )
142172
143- print ("\n Starting conversation...\n " ) # noqa: T201
144- for user_text in turns :
173+ second_history : list [ChatMessage ] = []
174+ print ("==Starting second conversation with empty local history...==\n " ) # noqa: T201
175+ for user_text in SECOND_CONVERSATION_TURNS :
145176 print (f"User: { user_text } " ) # noqa: T201
146- reply = run_turn (pipeline , user_text , history )
177+ reply = run_turn (pipeline , user_text , second_history )
147178 print (f"Agent: { reply } \n " ) # noqa: T201
148179
149180 print ("=== Done ===" ) # noqa: T201
0 commit comments