3939 RecencyConfig ,
4040 SessionListResponse ,
4141 WorkingMemory ,
42+ WorkingMemoryGetOrCreateResponse ,
4243 WorkingMemoryResponse ,
4344)
4445
@@ -216,6 +217,11 @@ async def get_working_memory(
216217 """
217218 Get working memory for a session, including messages and context.
218219
220+ .. deprecated:: next_version
221+ This method is deprecated because it doesn't inform you whether
222+ a session was created or found existing. Use `get_or_create_working_memory`
223+ instead, which returns a tuple of (memory, created) for better session management.
224+
219225 Args:
220226 session_id: The session ID to retrieve working memory for
221227 user_id: The user ID to retrieve working memory for
@@ -230,6 +236,15 @@ async def get_working_memory(
230236 MemoryNotFoundError: If the session is not found
231237 MemoryServerError: For other server errors
232238 """
239+ import warnings
240+
241+ warnings .warn (
242+ "get_working_memory is deprecated and will be removed in a future version. "
243+ "Use get_or_create_working_memory instead, which returns both the memory and "
244+ "whether the session was created or found existing." ,
245+ DeprecationWarning ,
246+ stacklevel = 2 ,
247+ )
233248 params = {}
234249
235250 if user_id is not None :
@@ -267,6 +282,82 @@ async def get_working_memory(
267282 self ._handle_http_error (e .response )
268283 raise
269284
285+ async def get_or_create_working_memory (
286+ self ,
287+ session_id : str ,
288+ user_id : str | None = None ,
289+ namespace : str | None = None ,
290+ model_name : ModelNameLiteral | None = None ,
291+ context_window_max : int | None = None ,
292+ ) -> WorkingMemoryGetOrCreateResponse :
293+ """
294+ Get working memory for a session, creating it if it doesn't exist.
295+
296+ This method returns both the working memory and whether it was created or found.
297+ This is important for applications that need to know if they're working with
298+ a new session or an existing one.
299+
300+ Args:
301+ session_id: The session ID to retrieve or create working memory for
302+ user_id: The user ID to retrieve working memory for
303+ namespace: Optional namespace for the session
304+ model_name: Optional model name to determine context window size
305+ context_window_max: Optional direct specification of context window tokens
306+
307+ Returns:
308+ WorkingMemoryGetOrCreateResponse containing the memory and creation status
309+
310+ Example:
311+ ```python
312+ # Get or create session memory
313+ result = await client.get_or_create_working_memory(
314+ session_id="chat_session_123",
315+ user_id="user_456"
316+ )
317+
318+ if result.created:
319+ print("Created new session")
320+ else:
321+ print("Found existing session")
322+
323+ # Access the memory
324+ memory = result.memory
325+ print(f"Session has {len(memory.messages)} messages")
326+ ```
327+ """
328+ try :
329+ # Try to get existing working memory first
330+ existing_memory = await self .get_working_memory (
331+ session_id = session_id ,
332+ user_id = user_id ,
333+ namespace = namespace ,
334+ model_name = model_name ,
335+ context_window_max = context_window_max ,
336+ )
337+ return WorkingMemoryGetOrCreateResponse (
338+ memory = existing_memory , created = False
339+ )
340+ except Exception :
341+ # Session doesn't exist, create it
342+ empty_memory = WorkingMemory (
343+ session_id = session_id ,
344+ namespace = namespace or self .config .default_namespace ,
345+ messages = [],
346+ memories = [],
347+ data = {},
348+ user_id = user_id ,
349+ )
350+
351+ created_memory = await self .put_working_memory (
352+ session_id = session_id ,
353+ memory = empty_memory ,
354+ user_id = user_id ,
355+ model_name = model_name ,
356+ context_window_max = context_window_max ,
357+ )
358+
359+ return WorkingMemoryGetOrCreateResponse (memory = created_memory , created = True )
360+
270361 async def put_working_memory (
271362 self ,
272363 session_id : str ,
@@ -392,10 +483,14 @@ async def set_working_memory_data(
392483 # Get existing memory if preserving
393484 existing_memory = None
394485 if preserve_existing :
395- existing_memory = await self .get_working_memory (
396- session_id = session_id ,
397- namespace = namespace ,
398- )
486+ try :
487+ result_obj = await self .get_or_create_working_memory (
488+ session_id = session_id ,
489+ namespace = namespace ,
490+ )
491+ existing_memory = result_obj .memory
492+ except Exception :
493+ existing_memory = None
399494
400495 # Create new working memory with the data
401496 working_memory = WorkingMemory (
@@ -449,10 +544,11 @@ async def add_memories_to_working_memory(
449544 ```
450545 """
451546 # Get existing memory
452- existing_memory = await self .get_working_memory (
547+ result_obj = await self .get_or_create_working_memory (
453548 session_id = session_id ,
454549 namespace = namespace ,
455550 )
551+ existing_memory = result_obj .memory
456552
457553 # Determine final memories list
458554 if replace or not existing_memory :
@@ -1029,11 +1125,12 @@ async def get_working_memory_tool(
10291125 ```
10301126 """
10311127 try :
1032- result = await self .get_working_memory (
1128+ result_obj = await self .get_or_create_working_memory (
10331129 session_id = session_id ,
10341130 namespace = namespace or self .config .default_namespace ,
10351131 user_id = user_id ,
10361132 )
1133+ result = result_obj .memory
10371134
10381135 # Format for LLM consumption
10391136 message_count = len (result .messages ) if result .messages else 0
@@ -1074,6 +1171,95 @@ async def get_working_memory_tool(
10741171 "summary" : f"Error retrieving working memory: { str (e )} " ,
10751172 }
10761173
1174+ async def get_or_create_working_memory_tool (
1175+ self ,
1176+ session_id : str ,
1177+ namespace : str | None = None ,
1178+ user_id : str | None = None ,
1179+ ) -> dict [str , Any ]:
1180+ """
1181+ Get or create working memory state formatted for LLM consumption.
1182+
1183+ This method provides a summary of the current working memory state
1184+ that's easy for LLMs to understand and work with. If the session
1185+ doesn't exist, it creates a new one.
1186+
1187+ Args:
1188+ session_id: The session ID to get or create memory for
1189+ namespace: Optional namespace for the session
1190+ user_id: Optional user ID for the session
1191+
1192+ Returns:
1193+ Dict with formatted working memory information and creation status
1194+
1195+ Example:
1196+ ```python
1197+ # Get or create working memory state for LLM
1198+ memory_state = await client.get_or_create_working_memory_tool(
1199+ session_id="current_session"
1200+ )
1201+
1202+ if memory_state["created"]:
1203+ print("Created new session")
1204+ else:
1205+ print("Found existing session")
1206+
1207+ print(memory_state["summary"]) # Human-readable summary
1208+ print(f"Messages: {memory_state['message_count']}")
1209+ print(f"Memories: {len(memory_state['memories'])}")
1210+ ```
1211+ """
1212+ try :
1213+ result_obj = await self .get_or_create_working_memory (
1214+ session_id = session_id ,
1215+ namespace = namespace or self .config .default_namespace ,
1216+ user_id = user_id ,
1217+ )
1218+
1219+ # Format for LLM consumption
1220+ result = result_obj .memory
1221+ message_count = len (result .messages ) if result .messages else 0
1222+ memory_count = len (result .memories ) if result .memories else 0
1223+ data_keys = list (result .data .keys ()) if result .data else []
1224+
1225+ # Create formatted memories list
1226+ formatted_memories = []
1227+ if result .memories :
1228+ for memory in result .memories :
1229+ formatted_memories .append (
1230+ {
1231+ "text" : memory .text ,
1232+ "memory_type" : memory .memory_type ,
1233+ "topics" : memory .topics or [],
1234+ "entities" : memory .entities or [],
1235+ "created_at" : memory .created_at .isoformat ()
1236+ if memory .created_at
1237+ else None ,
1238+ }
1239+ )
1240+
1241+ status_text = "new session" if result_obj .created else "existing session"
1242+
1243+ return {
1244+ "session_id" : session_id ,
1245+ "created" : result_obj .created ,
1246+ "message_count" : message_count ,
1247+ "memory_count" : memory_count ,
1248+ "memories" : formatted_memories ,
1249+ "data_keys" : data_keys ,
1250+ "data" : result .data or {},
1251+ "context" : result .context ,
1252+ "summary" : f"Retrieved { status_text } with { message_count } messages, { memory_count } stored memories, and { len (data_keys )} data entries" ,
1253+ }
1254+
1255+ except Exception as e :
1256+ return {
1257+ "session_id" : session_id ,
1258+ "created" : False ,
1259+ "error" : str (e ),
1260+ "summary" : f"Error retrieving or creating working memory: { str (e )} " ,
1261+ }
1262+
10771263 async def add_memory_tool (
10781264 self ,
10791265 session_id : str ,
@@ -1227,8 +1413,8 @@ def get_working_memory_tool_schema(cls) -> dict[str, Any]:
12271413 return {
12281414 "type" : "function" ,
12291415 "function" : {
1230- "name" : "get_working_memory " ,
1231- "description" : "Get the current working memory state including recent messages, temporarily stored memories, and session-specific data. Use this to check what's already in the current conversation context before deciding whether to search long-term memory or add new information. Examples: Check if user preferences are already loaded in this session, review recent conversation context, see what structured data has been stored for this session." ,
1416+ "name" : "get_or_create_working_memory " ,
1417+ "description" : "Get the current working memory state including recent messages, temporarily stored memories, and session-specific data. Creates a new session if one doesn't exist. Returns information about whether the session was created or found existing. Use this to check what's already in the current conversation context before deciding whether to search long-term memory or add new information. Examples: Check if user preferences are already loaded in this session, review recent conversation context, see what structured data has been stored for this session." ,
12321418 "parameters" : {
12331419 "type" : "object" ,
12341420 "properties" : {},
@@ -1907,10 +2093,16 @@ async def resolve_function_call(
19072093 result = await self ._resolve_search_memory (args )
19082094
19092095 elif function_name == "get_working_memory" :
2096+ # Keep backward compatibility for deprecated method
19102097 result = await self ._resolve_get_working_memory (
19112098 session_id , effective_namespace , user_id
19122099 )
19132100
2101+ elif function_name == "get_or_create_working_memory" :
2102+ result = await self ._resolve_get_or_create_working_memory (
2103+ session_id , effective_namespace , user_id
2104+ )
2105+
19142106 elif function_name == "add_memory_to_working_memory" :
19152107 result = await self ._resolve_add_memory (
19162108 args , session_id , effective_namespace , user_id
@@ -1994,6 +2186,17 @@ async def _resolve_get_working_memory(
19942186 user_id = user_id ,
19952187 )
19962188
2189+ async def _resolve_get_or_create_working_memory (
2190+ self , session_id : str , namespace : str | None , user_id : str | None = None
2191+ ) -> dict [str , Any ]:
2192+ """Resolve get_or_create_working_memory function call."""
2193+ result = await self .get_or_create_working_memory_tool (
2194+ session_id = session_id ,
2195+ namespace = namespace ,
2196+ user_id = user_id ,
2197+ )
2198+ return result
2199+
19972200 async def _resolve_add_memory (
19982201 self ,
19992202 args : dict [str , Any ],
@@ -2192,9 +2395,10 @@ async def promote_working_memories_to_long_term(
21922395 Acknowledgement of promotion operation
21932396 """
21942397 # Get current working memory
2195- working_memory = await self .get_working_memory (
2398+ result_obj = await self .get_or_create_working_memory (
21962399 session_id = session_id , namespace = namespace
21972400 )
2401+ working_memory = result_obj .memory
21982402
21992403 # Filter memories if specific IDs are requested
22002404 memories_to_promote = working_memory .memories
@@ -2407,9 +2611,10 @@ async def update_working_memory_data(
24072611 WorkingMemoryResponse with updated memory
24082612 """
24092613 # Get existing memory
2410- existing_memory = await self .get_working_memory (
2614+ result_obj = await self .get_or_create_working_memory (
24112615 session_id = session_id , namespace = namespace , user_id = user_id
24122616 )
2617+ existing_memory = result_obj .memory
24132618
24142619 # Determine final data based on merge strategy
24152620 if existing_memory and existing_memory .data :
@@ -2462,9 +2667,10 @@ async def append_messages_to_working_memory(
24622667 WorkingMemoryResponse with updated memory (potentially summarized if token limit exceeded)
24632668 """
24642669 # Get existing memory
2465- existing_memory = await self .get_working_memory (
2670+ result_obj = await self .get_or_create_working_memory (
24662671 session_id = session_id , namespace = namespace , user_id = user_id
24672672 )
2673+ existing_memory = result_obj .memory
24682674
24692675 # Convert messages to MemoryMessage objects
24702676 converted_messages = []
0 commit comments