11"""
22Mem0 toolkit demo using SpoonReactAI.
3- This demo requires spoon-toolkit to be installed
3+ This demo requires spoon-toolkit to be installed (pip install spoon-toolkit or local install).
44"""
55
66import asyncio
7- from typing import Any , Dict , List
7+ from typing import Dict , List , Optional
88
99from pydantic import Field
1010
1111from spoon_ai .agents .spoon_react import SpoonReactAI
1212from spoon_ai .chat import ChatBot
13+ from spoon_ai .llm .manager import get_llm_manager
14+ from spoon_ai .memory .utils import extract_memories , extract_first_memory_id
1315from spoon_ai .tools .tool_manager import ToolManager
1416from spoon_ai .tools .base import ToolResult
15- from spoon_toolkits .memory import AddMemoryTool , SearchMemoryTool , GetAllMemoryTool
17+ from spoon_toolkits .memory import (
18+ AddMemoryTool ,
19+ SearchMemoryTool ,
20+ GetAllMemoryTool ,
21+ UpdateMemoryTool ,
22+ DeleteMemoryTool ,
23+ )
1624
1725
18- USER_ID = "defi_user_002 "
26+ USER_ID = "defi_user_005 "
1927
2028
2129class DeFiMemoryAgent (SpoonReactAI ):
@@ -26,14 +34,14 @@ class DeFiMemoryAgent(SpoonReactAI):
2634
2735 def model_post_init (self , __context : Any = None ) -> None :
2836 super ().model_post_init (__context )
29- # Rebuild tools with the injected mem0_config for this agent
3037 memory_tools = [
3138 AddMemoryTool (mem0_config = self .mem0_config ),
3239 SearchMemoryTool (mem0_config = self .mem0_config ),
3340 GetAllMemoryTool (mem0_config = self .mem0_config ),
41+ UpdateMemoryTool (mem0_config = self .mem0_config ),
42+ DeleteMemoryTool (mem0_config = self .mem0_config ),
3443 ]
3544 self .available_tools = ToolManager (memory_tools )
36- # Refresh prompts so SpoonReactAI lists the newly provided tools
3745 if hasattr (self , "_refresh_prompts" ):
3846 self ._refresh_prompts ()
3947
@@ -55,11 +63,10 @@ def build_agent(mem0_cfg: Dict[str, Any]) -> DeFiMemoryAgent:
5563
5664
5765def print_memories (result : ToolResult , label : str ) -> None :
58- if not isinstance (result , ToolResult ):
59- print (f"[Mem0] { label } : error -> { result } " )
60- return
61- memories : List [str ] = result .output .get ("memories" , []) if result and result .output else []
66+ memories = extract_memories (result )
6267 print (f"[Mem0] { label } :" )
68+ if not memories :
69+ print (" (none)" )
6370 for m in memories :
6471 print (f" - { m } " )
6572
@@ -77,12 +84,26 @@ async def phase_capture(agent: DeFiMemoryAgent) -> None:
7784 "and dislike Ethereum gas fees."
7885 ),
7986 }
80- ]
87+ ],
88+ "user_id" : USER_ID ,
89+ "async_mode" : False ,
8190 },
8291 )
92+ # Verify storage immediately after add to avoid read-after-write surprises
93+ verified : ToolResult = ToolResult ()
94+ for attempt in range (3 ):
95+ verified = await agent .available_tools .execute (
96+ name = "get_all_memory" ,
97+ tool_input = {"user_id" : USER_ID , "limit" : 5 },
98+ )
99+ if extract_memories (verified ):
100+ break
101+ await asyncio .sleep (0.5 )
102+ print_memories (verified , "Verification after Phase 1 store" )
103+
83104 memories = await agent .available_tools .execute (
84105 name = "search_memory" ,
85- tool_input = {"query" : "Solana meme coins high risk" },
106+ tool_input = {"query" : "Solana meme coins high risk" , "user_id" : USER_ID },
86107 )
87108 print_memories (memories , "After Phase 1 store" )
88109
@@ -92,12 +113,12 @@ async def phase_recall(mem0_cfg: Dict[str, Any]) -> None:
92113 agent = build_agent (mem0_cfg )
93114 memories = await agent .available_tools .execute (
94115 name = "search_memory" ,
95- tool_input = {"query" : "trading strategy solana meme" },
116+ tool_input = {"query" : "trading strategy solana meme" , "user_id" : USER_ID },
96117 )
97118 print_memories (memories , "Retrieved for Phase 2" )
98119
99120
100- async def phase_update (agent : DeFiMemoryAgent ) -> None :
121+ async def phase_update (agent : DeFiMemoryAgent , memory_id : Optional [ str ] ) -> None :
101122 print ("\n === Phase 3: Update preferences to safer Arbitrum yield ===" )
102123 await agent .available_tools .execute (
103124 name = "add_memory" ,
@@ -109,27 +130,63 @@ async def phase_update(agent: DeFiMemoryAgent) -> None:
109130 "I lost too much money. I want to pivot to safe stablecoin yield farming on Arbitrum now."
110131 ),
111132 }
112- ]
133+ ],
134+ "user_id" : USER_ID ,
135+ "async_mode" : False ,
113136 },
114137 )
138+ update_result = await agent .available_tools .execute (
139+ name = "update_memory" ,
140+ tool_input = {
141+ "memory_id" : memory_id ,
142+ "text" : "User pivoted to safer Arbitrum stablecoin yield farming with low risk." ,
143+ "user_id" : USER_ID ,
144+ },
145+ )
146+ print (f"[Mem0] Update result: { update_result } " )
115147 memories = await agent .available_tools .execute (
116148 name = "search_memory" ,
117- tool_input = {"query" : "stablecoin yield chain choice" },
149+ tool_input = {"query" : "stablecoin yield chain choice" , "user_id" : USER_ID },
118150 )
119151 print_memories (memories , "Retrieved after update (Phase 3)" )
120152
121153
154+ async def phase_cleanup (agent : DeFiMemoryAgent , memory_id : Optional [str ]) -> None :
155+ print ("\n === Phase 4: Clean up a memory entry ===" )
156+ delete_result = await agent .available_tools .execute (
157+ name = "delete_memory" ,
158+ tool_input = {"memory_id" : memory_id , "user_id" : USER_ID },
159+ )
160+ print (f"[Mem0] Delete result: { delete_result } " )
161+ remaining = await agent .available_tools .execute (
162+ name = "get_all_memory" ,
163+ tool_input = {"limit" : 5 , "user_id" : USER_ID },
164+ )
165+ print_memories (remaining , "Remaining memories after delete" )
166+
167+
122168async def main () -> None :
123169 mem0_cfg = {
124170 "user_id" : USER_ID ,
125171 "metadata" : {"project" : "defi-investment-advisor" },
126172 "async_mode" : False , # synchronous writes so the next search sees new data
127173 }
128- agent = build_agent (mem0_cfg )
129- await phase_capture (agent )
130- await phase_recall (mem0_cfg )
131- await phase_update (agent )
132-
174+
175+ try :
176+ agent = build_agent (mem0_cfg )
177+ await phase_capture (agent )
178+ await phase_recall (mem0_cfg )
179+
180+ all_memories = await agent .available_tools .execute (
181+ name = "get_all_memory" , tool_input = {"limit" : 5 , "user_id" : USER_ID }
182+ )
183+ print_memories (all_memories , "All memories before update/delete" )
184+ first_id = extract_first_memory_id (all_memories )
185+
186+ await phase_update (agent , first_id )
187+ await phase_cleanup (agent , first_id )
188+ finally :
189+ await get_llm_manager ().cleanup ()
133190
134191
135192if __name__ == "__main__" :
0 commit comments