Refactor client API based on OpenAPI spec and add mem0_delete tool

- Update client.py to use correct API endpoints from OpenAPI spec
- Add delete() method for memory deletion
- Add mem0_delete tool with schema and handler
- Simplify API calls to match actual Mem0 OSS server format
This commit is contained in:
2026-04-10 13:24:14 +02:00
parent fdd2a07ae5
commit 6e7c6dd3ce
3 changed files with 102 additions and 79 deletions
+54 -52
View File
@@ -1,4 +1,13 @@
"""Local Mem0 server HTTP client."""
"""Local Mem0 server HTTP client.
Based on OpenAPI spec from http://10.0.0.150:8889/openapi.json
Endpoints:
- POST /add - Add memory
- POST /search - Search memories
- GET /memories - Get all memories
- DELETE /delete/{memory_id} - Delete memory
"""
from __future__ import annotations
@@ -11,13 +20,7 @@ logger = logging.getLogger(__name__)
class LocalMem0Client:
"""HTTP client for self-hosted Mem0 server.
Expects Mem0 server at MEM0_BASE_URL with endpoints:
- POST /search
- GET /memories
- POST /add
"""
"""HTTP client for self-hosted Mem0 server."""
def __init__(self, base_url: str, timeout: float = 10.0):
self.base_url = base_url.rstrip("/")
@@ -60,60 +63,59 @@ class LocalMem0Client:
def search(
self,
query: str,
filters: Dict[str, Any],
rerank: bool = False,
top_k: int = 10,
user_id: Optional[str] = None,
limit: int = 5,
) -> List[Dict]:
"""Search memories by semantic similarity."""
payload = {
"query": query,
"user_id": filters.get("user_id"),
"agent_id": filters.get("agent_id"),
"top_k": top_k,
}
if rerank is not None:
payload["rerank"] = rerank
"""Search memories by semantic similarity.
API: POST /search
Request: {query, user_id, limit}
Response: {results: [{id, text, user_id, score, metadata}]}
"""
payload = {"query": query, "limit": limit}
if user_id:
payload["user_id"] = user_id
result = self._request("POST", "/search", json=payload)
return self._unwrap_results(result)
return result.get("results", [])
def get_all(self, filters: Dict[str, Any]) -> List[Dict]:
"""Get all memories matching filters."""
params = filters
def get_all(self, user_id: Optional[str] = None) -> List[Dict]:
"""Get all memories for a user.
API: GET /memories?user_id=...
Response: {memories: [{id, text, user_id, metadata}]}
"""
params = {}
if user_id:
params["user_id"] = user_id
result = self._request("GET", "/memories", params=params)
return self._unwrap_results(result)
return result.get("memories", [])
def add(
def add(
self,
messages: List[Dict[str, str]],
filters: Dict[str, Any],
infer: bool = True,
message: str,
user_id: Optional[str] = None,
metadata: Optional[Dict] = None,
) -> Dict:
"""Add conversation messages for fact extraction."""
# Extract message content from messages array
if messages and isinstance(messages[0], dict):
message_content = messages[0].get("content", "")
elif messages:
message_content = str(messages[0])
else:
message_content = ""
"""Add a new memory.
payload = {
"message": message_content,
"user_id": filters.get("user_id"),
"agent_id": filters.get("agent_id"),
}
if not infer:
payload["only_store_messages"] = True
API: POST /add
Request: {message, user_id, metadata}
Response: {success, memory_id, message}
"""
payload = {"message": message}
if user_id:
payload["user_id"] = user_id
if metadata:
payload["metadata"] = metadata
return self._request("POST", "/add", json=payload)
@staticmethod
def _unwrap_results(response: Any) -> List[Dict]:
"""Normalize Mem0 API response."""
if isinstance(response, dict):
return response.get("memories", response.get("results", []))
if isinstance(response, list):
return response
return []
def delete(self, memory_id: str) -> Dict:
"""Delete a memory by ID.
API: DELETE /delete/{memory_id}
Response: {success, memory_id, message}
"""
return self._request("DELETE", f"/delete/{memory_id}")
def health(self) -> bool:
"""Check if server is reachable."""