From 07a9ce1e81dc412716e10f2bf28e3d6f60200cae Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 17:48:00 -0400 Subject: [PATCH 1/9] docs: add hybrid and keyword search references across all documentation Update documentation and tool schemas that previously only mentioned semantic search to also reference keyword and hybrid search modes. Documentation updates: - README.md: features list and architecture diagram - docs/index.md: feature descriptions and context finding - docs/long-term-memory.md: overview, feature table, search capabilities - docs/mcp.md: search_long_term_memory tool description - docs/quick-start.md: search step, summary table, checklist - docs/use-cases.md: search optimization best practices - docs/README.md: feature cross-reference table - docs/agent-examples.md: long-term memory description - docs/java-sdk.md: keyword and hybrid search examples - docs/typescript-sdk.md: keyword and hybrid search examples - examples/README.md: long-term memory description - agent-memory-client/README.md: search mode examples - agent-memory-client/agent-memory-client-js/README.md: search mode examples Tool schema updates (shown to LLMs): - agent-memory-client/agent_memory_client/client.py: search_memory tool description - agent-memory-client/agent_memory_client/integrations/langchain.py: LangChain tool description --- README.md | 4 +-- agent-memory-client/README.md | 15 ++++++++++ .../agent-memory-client-js/README.md | 17 ++++++++++- .../agent_memory_client/client.py | 2 +- .../integrations/langchain.py | 2 +- docs/README.md | 2 +- docs/agent-examples.md | 2 +- docs/index.md | 6 ++-- docs/java-sdk.md | 15 ++++++++++ docs/long-term-memory.md | 29 ++++++++++++++++--- docs/mcp.md | 4 +-- docs/quick-start.md | 6 ++-- docs/typescript-sdk.md | 17 ++++++++++- docs/use-cases.md | 2 +- examples/README.md | 2 +- 15 files changed, 103 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index c4e99ced..df2e0748 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ A memory layer for AI agents. - **Dual Interface**: REST API and Model Context Protocol (MCP) server - **Two-Tier Memory**: Working memory (session-scoped) and long-term memory (persistent) - **Configurable Memory Strategies**: Customize how memories are extracted (discrete, summary, preferences, custom) -- **Semantic Search**: Vector-based similarity search with metadata filtering +- **Semantic, Keyword & Hybrid Search**: Vector-based similarity, full-text keyword, and combined hybrid search with metadata filtering - **Flexible Backends**: Pluggable memory vector database factory system - **Multi-Provider LLM Support**: OpenAI, Anthropic, AWS Bedrock, Ollama, Azure, Gemini via [LiteLLM](https://docs.litellm.ai/) - **AI Integration**: Automatic topic extraction, entity recognition, and conversation summarization @@ -268,7 +268,7 @@ See **[LLM Providers](https://redis.github.io/agent-memory-server/llm-providers/ ``` Working Memory (Session-scoped) → Long-term Memory (Persistent) ↓ ↓ -- Messages - Semantic search +- Messages - Semantic, keyword & hybrid search - Structured memories - Topic modeling - Summary of past messages - Entity recognition - Metadata - Deduplication diff --git a/agent-memory-client/README.md b/agent-memory-client/README.md index 75a29a45..9e58947f 100644 --- a/agent-memory-client/README.md +++ b/agent-memory-client/README.md @@ -201,6 +201,21 @@ results = await client.search_long_term_memory( user_id=UserId(eq="user-123"), limit=20 ) + +# Keyword search - exact term matching +results = await client.search_long_term_memory( + text="science fiction", + search_mode="keyword", + limit=20 +) + +# Hybrid search - combines semantic and keyword matching +results = await client.search_long_term_memory( + text="science fiction", + search_mode="hybrid", + hybrid_alpha=0.7, # 0.0=keyword, 1.0=semantic + limit=20 +) ``` ## Enhanced Features diff --git a/agent-memory-client/agent-memory-client-js/README.md b/agent-memory-client/agent-memory-client-js/README.md index 0ed434c8..841e3288 100644 --- a/agent-memory-client/agent-memory-client-js/README.md +++ b/agent-memory-client/agent-memory-client-js/README.md @@ -90,7 +90,7 @@ await client.createLongTermMemory([ }, ]); -// Search with filters +// Search with filters (default: semantic search) const results = await client.searchLongTermMemory({ text: "science fiction", topics: new Topics({ any: ["books", "entertainment"] }), @@ -98,6 +98,21 @@ const results = await client.searchLongTermMemory({ limit: 20, }); +// Keyword search - exact term matching +const keywordResults = await client.searchLongTermMemory({ + text: "science fiction", + searchMode: "keyword", + limit: 20, +}); + +// Hybrid search - combines semantic and keyword matching +const hybridResults = await client.searchLongTermMemory({ + text: "science fiction", + searchMode: "hybrid", + hybridAlpha: 0.7, // 0.0=keyword, 1.0=semantic + limit: 20, +}); + // Get by ID const memory = await client.getLongTermMemory("memory-id"); diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index 9bd521c4..15429197 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -1386,7 +1386,7 @@ async def handle_tool_calls(client, tool_calls): "type": "function", "function": { "name": "search_memory", - "description": "Search long-term memory for relevant information using semantic vector search. Use this when you need to find previously stored information about the user, such as their preferences, past conversations, or important facts. Examples: 'Find information about user food preferences', 'What did they say about their job?', 'Look for travel preferences'. This searches only long-term memory, not current working memory - use get_working_memory for current session info. IMPORTANT: The result includes 'memories' with an 'id' field; use these IDs when calling edit_long_term_memory or delete_long_term_memories.", + "description": "Search long-term memory for relevant information using semantic, keyword, or hybrid search. Use this when you need to find previously stored information about the user, such as their preferences, past conversations, or important facts. Examples: 'Find information about user food preferences', 'What did they say about their job?', 'Look for travel preferences'. This searches only long-term memory, not current working memory - use get_working_memory for current session info. IMPORTANT: The result includes 'memories' with an 'id' field; use these IDs when calling edit_long_term_memory or delete_long_term_memories.", "parameters": { "type": "object", "properties": { diff --git a/agent-memory-client/agent_memory_client/integrations/langchain.py b/agent-memory-client/agent_memory_client/integrations/langchain.py index 255f1572..7e6b2e6b 100644 --- a/agent-memory-client/agent_memory_client/integrations/langchain.py +++ b/agent-memory-client/agent_memory_client/integrations/langchain.py @@ -127,7 +127,7 @@ def get_memory_tools( tool_configs = { "search_memory": { "name": "search_memory", - "description": "Search long-term memory for relevant information using semantic search. Use this to recall past conversations, user preferences, or stored facts. Returns memories ranked by relevance with scores.", + "description": "Search long-term memory for relevant information using semantic, keyword, or hybrid search. Use this to recall past conversations, user preferences, or stored facts. Returns memories ranked by relevance with scores.", "func": _create_search_memory_func(memory_client), }, "get_or_create_working_memory": { diff --git a/docs/README.md b/docs/README.md index 5daf38ef..a5cfaded 100644 --- a/docs/README.md +++ b/docs/README.md @@ -75,7 +75,7 @@ For contributors and advanced users: | Feature | REST API | MCP Server | CLI | Documentation | |---------|----------|------------|-----|---------------| -| **Memory Search** | ✅ `/v1/long-term-memory/search` | ✅ `search_long_term_memory` | ❌ | [REST API](api.md), [MCP](mcp.md) | +| **Memory Search** (semantic, keyword, hybrid) | ✅ `/v1/long-term-memory/search` | ✅ `search_long_term_memory` | ❌ | [REST API](api.md), [MCP](mcp.md) | | **Memory Editing** | ✅ `PATCH /v1/long-term-memory/{id}` | ✅ `edit_long_term_memory` | ❌ | [Memory Editing](memory-lifecycle.md#memory-editing) | | **Query Optimization** | ✅ `optimize_query` param | ✅ `optimize_query` param | ❌ | [Query Optimization](query-optimization.md) | | **Recency Boost** | ✅ Default enabled | ✅ Available | ❌ | [Recency Boost](recency-boost.md) | diff --git a/docs/agent-examples.md b/docs/agent-examples.md index a9167f19..be1fedfe 100644 --- a/docs/agent-examples.md +++ b/docs/agent-examples.md @@ -93,7 +93,7 @@ A comprehensive travel assistant that demonstrates the most complete integration - **Automatic Tool Discovery**: Uses `MemoryAPIClient.get_all_memory_tool_schemas()` to automatically discover and integrate all available memory tools - **Unified Tool Resolution**: Leverages `client.resolve_tool_call()` to handle all memory tool calls uniformly across different LLM providers - **Working Memory Management**: Session-based conversation state and structured memory storage -- **Long-term Memory**: Persistent memory storage and semantic search capabilities +- **Long-term Memory**: Persistent memory storage with semantic, keyword, and hybrid search capabilities - **Optional Web Search**: Cached web search using Tavily API with Redis caching ### Available Tools diff --git a/docs/index.md b/docs/index.md index 865fe6df..7cb8b0e5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -38,7 +38,7 @@ Transform your AI agents from goldfish 🐠 into elephants 🐘 with Redis-power Redis Agent Memory Server is a production-ready memory system for AI agents and applications that: - **🧠 Remembers everything**: Stores conversation history, user preferences, and important facts across sessions -- **🔍 Finds relevant context**: Uses semantic search to surface the right information at the right time +- **🔍 Finds relevant context**: Uses semantic, keyword, and hybrid search to surface the right information at the right time - **📈 Gets smarter over time**: Automatically extracts, organizes, and deduplicates memories from interactions - **🔌 Works with any AI model**: REST API and MCP interfaces compatible with OpenAI, Anthropic, and others - **🌐 Multi-provider support**: Use [100+ LLM providers](llm-providers.md) via LiteLLM (OpenAI, Anthropic, AWS Bedrock, Ollama, Azure, Gemini, and more) @@ -95,11 +95,11 @@ print(f"Found: {results.memories[0].text}") !!! success "Long-Term Memory (Persistent)" - User preferences, facts, and important information - - Semantic search with vector embeddings + - Semantic, keyword, and hybrid search with vector embeddings - Advanced filtering by time, topics, entities, users ### 🔍 Intelligent Search -- **Semantic similarity**: Find memories by meaning, not just keywords +- **Multiple search modes**: Semantic (vector similarity), keyword (full-text), and hybrid (combined) search - **Advanced filters**: Search by user, session, time, topics, entities - **Query optimization**: AI-powered query refinement for better results - **Recency boost**: Time-aware ranking that surfaces relevant recent information diff --git a/docs/java-sdk.md b/docs/java-sdk.md index cf4f65bc..da15ec91 100644 --- a/docs/java-sdk.md +++ b/docs/java-sdk.md @@ -144,6 +144,21 @@ MemoryRecordResults results = client.longTermMemory().searchLongTermMemories(req // Simple text search MemoryRecordResults simpleResults = client.longTermMemory() .searchLongTermMemories("user preferences"); + +// Keyword search - exact term matching +SearchRequest keywordRequest = SearchRequest.builder() + .text("TechCorp engineer") + .searchMode("keyword") + .limit(10) + .build(); + +// Hybrid search - combines semantic and keyword matching +SearchRequest hybridRequest = SearchRequest.builder() + .text("user preferences") + .searchMode("hybrid") + .hybridAlpha(0.7) // 0.0=keyword, 1.0=semantic + .limit(10) + .build(); ``` ### Get, Edit, and Delete diff --git a/docs/long-term-memory.md b/docs/long-term-memory.md index 9ae06206..601013ee 100644 --- a/docs/long-term-memory.md +++ b/docs/long-term-memory.md @@ -4,14 +4,14 @@ Long-term memory is **persistent**, **cross-session** storage designed for knowl ## Overview -Long-term memory provides persistent storage that survives server restarts and session expiration. It's optimized for semantic search, deduplication, and rich metadata to enable intelligent retrieval of relevant information. +Long-term memory provides persistent storage that survives server restarts and session expiration. It's optimized for semantic, keyword, and hybrid search, deduplication, and rich metadata to enable intelligent retrieval of relevant information. | Feature | Details | |---------|---------| | **Scope** | Cross-session, persistent | | **Lifespan** | Permanent until manually deleted | | **Storage** | Redis with vector indexing | -| **Search** | Semantic vector search | +| **Search** | Semantic, keyword, and hybrid search | | **Capacity** | Unlimited (with compaction) | | **Use Case** | Knowledge base, user preferences | | **Indexing** | Vector embeddings + metadata | @@ -126,17 +126,38 @@ POST /v1/long-term-memory/search ## Search Capabilities -Long-term memory provides powerful search features: +Long-term memory supports three search modes: **semantic** (vector similarity), **keyword** (full-text matching), and **hybrid** (combined). -### Semantic Vector Search +### Semantic Search (Default) ```json { "text": "python programming help", + "search_mode": "semantic", "limit": 10, "distance_threshold": 0.8 } ``` +### Keyword Search +```json +{ + "text": "TechCorp engineer", + "search_mode": "keyword", + "limit": 10 +} +``` + +### Hybrid Search +Combines vector similarity with full-text keyword matching. Use `hybrid_alpha` to control the balance (0.0 = pure keyword, 1.0 = pure semantic, default 0.7). +```json +{ + "text": "python programming help", + "search_mode": "hybrid", + "hybrid_alpha": 0.7, + "limit": 10 +} +``` + ### Advanced Filtering ```json { diff --git a/docs/mcp.md b/docs/mcp.md index eb71b9c8..b31b9a6c 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -4,7 +4,7 @@ Agent Memory Server offers an MCP (Model Context Protocol) server interface powe - **set_working_memory**: Set working memory for a session (like `PUT /v1/working-memory/{session_id}` in the REST API). Stores structured memory records and JSON data in working memory with automatic promotion to long-term storage. - **create_long_term_memories**: Create long-term memories directly, bypassing working memory. Useful for bulk memory creation. -- **search_long_term_memory**: Perform semantic search across long-term memories with advanced filtering options. +- **search_long_term_memory**: Search across long-term memories using semantic, keyword, or hybrid search modes with advanced filtering options. - **edit_long_term_memory**: Update existing long-term memories with new or corrected information. Allows partial updates to specific fields while preserving other data. - **delete_long_term_memories**: Remove specific long-term memories by ID. Useful for cleaning up outdated or incorrect information. - **get_long_term_memory**: Retrieve specific memories by ID for detailed inspection or verification before editing. @@ -17,7 +17,7 @@ The MCP server provides the following tools that AI agents can use to manage mem ### Memory Search and Retrieval **search_long_term_memory** -- Search for memories using semantic similarity +- Search for memories using semantic (vector), keyword (full-text), or hybrid (combined) search - Supports advanced filtering by user, session, namespace, topics, entities, and timestamps - Configurable query optimization and recency boost - Returns ranked results with relevance scores diff --git a/docs/quick-start.md b/docs/quick-start.md index a7530f4f..d4490c01 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -178,7 +178,7 @@ await memory_client.create_long_term_memory([ ## Step 7: Search Your Memories -Search across all stored memories with semantic similarity: +Search across all stored memories using semantic similarity, keyword matching, or hybrid search: ```python # Search for work-related information @@ -331,7 +331,7 @@ You've just worked with both types of memory: - **Scope**: Cross-session, persistent - **Lifetime**: Permanent until deleted - **Use case**: User preferences, facts, knowledge -- **Search**: Semantic vector search with advanced filtering +- **Search**: Semantic, keyword, and hybrid search with advanced filtering ## Next Steps @@ -537,7 +537,7 @@ redis-cli -h localhost -p 6379 You now have a working AI agent memory system! Your memories will: - ✅ Persist across sessions -- ✅ Be searchable with semantic similarity +- ✅ Be searchable with semantic, keyword, or hybrid search - ✅ Automatically extract context from conversations - ✅ Provide relevant context to AI responses diff --git a/docs/typescript-sdk.md b/docs/typescript-sdk.md index dc0fe629..0793d815 100644 --- a/docs/typescript-sdk.md +++ b/docs/typescript-sdk.md @@ -106,12 +106,27 @@ import { MemoryType, } from "agent-memory-client"; -// Basic search +// Basic semantic search (default) const results = await client.searchLongTermMemory({ text: "user preferences", limit: 10, }); +// Keyword search - exact term matching +const keywordResults = await client.searchLongTermMemory({ + text: "TechCorp engineer", + searchMode: "keyword", + limit: 10, +}); + +// Hybrid search - combines semantic and keyword matching +const hybridResults = await client.searchLongTermMemory({ + text: "user preferences", + searchMode: "hybrid", + hybridAlpha: 0.7, // 0.0=keyword, 1.0=semantic + limit: 10, +}); + // With filters const filtered = await client.searchLongTermMemory({ text: "programming languages", diff --git a/docs/use-cases.md b/docs/use-cases.md index d3860390..80d430e0 100644 --- a/docs/use-cases.md +++ b/docs/use-cases.md @@ -701,7 +701,7 @@ guidance = await health.get_contextual_health_guidance( ### Search Optimization - **Enable recency boost**: For time-sensitive domains like support or health - **Use query optimization**: For natural language queries from end users -- **Filter strategically**: Combine semantic search with metadata filters +- **Filter strategically**: Combine semantic, keyword, or hybrid search with metadata filters ### Privacy and Security - **User isolation**: Always filter by user_id for personal data diff --git a/examples/README.md b/examples/README.md index bc3cb1d8..f03f764a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -51,7 +51,7 @@ A comprehensive travel assistant that demonstrates: - **Automatic Tool Discovery**: Uses `MemoryAPIClient.get_all_memory_tool_schemas()` to automatically discover and integrate all available memory tools - **Unified Tool Resolution**: Leverages `client.resolve_tool_call()` to handle all memory tool calls uniformly across different LLM providers - **Working Memory Management**: Session-based conversation state and structured memory storage -- **Long-term Memory**: Persistent memory storage and semantic search capabilities +- **Long-term Memory**: Persistent memory storage with semantic, keyword, and hybrid search capabilities - **Optional Web Search**: Cached web search using Tavily API with Redis caching ### Available Tools From 9178c57f17b9878f759c36138c4d780d5f328315 Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 18:18:39 -0400 Subject: [PATCH 2/9] fix: update deprecated function references in tool descriptions, docstrings, and docs - langchain.py: fix search_memory description to mention semantic/keyword/hybrid search; add search_mode, hybrid_alpha, text_scorer params to _create_search_memory_func - client.py: update tool schema descriptions to use non-deprecated names (get_or_create_working_memory, lazily_create_long_term_memory, eagerly_create_long_term_memory); fix docstrings for deprecated resolvers - agent-memory-client/README.md: use get_or_create_working_memory in examples - docs/agent-examples.md: use get_or_create_working_memory in code example --- agent-memory-client/README.md | 4 ++-- agent-memory-client/agent_memory_client/client.py | 14 +++++++------- .../agent_memory_client/integrations/langchain.py | 6 ++++++ docs/agent-examples.md | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/agent-memory-client/README.md b/agent-memory-client/README.md index 9e58947f..4421790b 100644 --- a/agent-memory-client/README.md +++ b/agent-memory-client/README.md @@ -165,7 +165,7 @@ working_memory = WorkingMemory( response = await client.put_working_memory("user-session-123", working_memory) # Retrieve working memory -memory = await client.get_working_memory("user-session-123") +memory, created = await client.get_or_create_working_memory("user-session-123") # Convenience method for data storage await client.set_working_memory_data( @@ -348,7 +348,7 @@ from agent_memory_client.exceptions import ( ) try: - memory = await client.get_working_memory("nonexistent-session") + memory, created = await client.get_or_create_working_memory("nonexistent-session") except MemoryNotFoundError: print("Session not found") except MemoryServerError as e: diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index 15429197..33d6c514 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -1386,7 +1386,7 @@ async def handle_tool_calls(client, tool_calls): "type": "function", "function": { "name": "search_memory", - "description": "Search long-term memory for relevant information using semantic, keyword, or hybrid search. Use this when you need to find previously stored information about the user, such as their preferences, past conversations, or important facts. Examples: 'Find information about user food preferences', 'What did they say about their job?', 'Look for travel preferences'. This searches only long-term memory, not current working memory - use get_working_memory for current session info. IMPORTANT: The result includes 'memories' with an 'id' field; use these IDs when calling edit_long_term_memory or delete_long_term_memories.", + "description": "Search long-term memory for relevant information using semantic, keyword, or hybrid search. Use this when you need to find previously stored information about the user, such as their preferences, past conversations, or important facts. Examples: 'Find information about user food preferences', 'What did they say about their job?', 'Look for travel preferences'. This searches only long-term memory, not current working memory - use get_or_create_working_memory for current session info. IMPORTANT: The result includes 'memories' with an 'id' field; use these IDs when calling edit_long_term_memory or delete_long_term_memories.", "parameters": { "type": "object", "properties": { @@ -1875,7 +1875,7 @@ def get_update_memory_data_tool_schema(cls) -> ToolSchema: "type": "function", "function": { "name": "update_working_memory_data", - "description": "Store or update structured session data (JSON objects) in working memory. Use this for complex session-specific information that needs to be accessed and modified during the conversation. Examples: Travel itinerary {'destination': 'Paris', 'dates': ['2024-03-15', '2024-03-20']}, project details {'name': 'Website Redesign', 'deadline': '2024-04-01', 'status': 'in_progress'}. Different from add_memory_to_working_memory which stores simple text facts.", + "description": "Store or update structured session data (JSON objects) in working memory. Use this for complex session-specific information that needs to be accessed and modified during the conversation. Examples: Travel itinerary {'destination': 'Paris', 'dates': ['2024-03-15', '2024-03-20']}, project details {'name': 'Website Redesign', 'deadline': '2024-04-01', 'status': 'in_progress'}. Different from lazily_create_long_term_memory which stores simple text facts for later promotion to long-term storage.", "parameters": { "type": "object", "properties": { @@ -2706,7 +2706,7 @@ async def _resolve_search_memory(self, args: dict[str, Any]) -> dict[str, Any]: async def _resolve_get_working_memory( self, session_id: str, namespace: str | None, user_id: str | None = None ) -> dict[str, Any]: - """Resolve get_working_memory function call.""" + """Resolve get_working_memory (deprecated) function call.""" return await self.get_working_memory_tool( session_id=session_id, namespace=namespace, @@ -2731,7 +2731,7 @@ async def _resolve_add_memory( namespace: str | None, user_id: str | None = None, ) -> dict[str, Any]: - """Resolve add_memory_to_working_memory function call.""" + """Resolve lazily_create_long_term_memory (formerly add_memory_to_working_memory) function call.""" text = args.get("text", "") if not text: raise ValueError("Text parameter is required for adding memory") @@ -2790,11 +2790,11 @@ async def _resolve_get_long_term_memory( async def _resolve_create_long_term_memory( self, args: dict[str, Any], namespace: str | None, user_id: str | None = None ) -> dict[str, Any]: - """Resolve create_long_term_memory function call.""" + """Resolve eagerly_create_long_term_memory (and deprecated create_long_term_memory alias) function call.""" memories_data = args.get("memories") if not memories_data: raise ValueError( - "memories parameter is required for create_long_term_memory" + "memories parameter is required for eagerly_create_long_term_memory" ) # Convert dict memories to ClientMemoryRecord objects @@ -2907,7 +2907,7 @@ async def resolve_function_calls( # Handle multiple function calls calls = [ {"name": "search_memory", "arguments": {"query": "user preferences"}}, - {"name": "get_working_memory", "arguments": {}}, + {"name": "get_or_create_working_memory", "arguments": {}}, ] results = await client.resolve_function_calls(calls, "session123") diff --git a/agent-memory-client/agent_memory_client/integrations/langchain.py b/agent-memory-client/agent_memory_client/integrations/langchain.py index 7e6b2e6b..3808d589 100644 --- a/agent-memory-client/agent_memory_client/integrations/langchain.py +++ b/agent-memory-client/agent_memory_client/integrations/langchain.py @@ -224,6 +224,9 @@ def _create_search_memory_func(client: MemoryAPIClient) -> Any: async def search_memory( query: str, + search_mode: str = "semantic", + hybrid_alpha: float | None = None, + text_scorer: str | None = None, topics: list[str] | None = None, entities: list[str] | None = None, memory_type: str | None = None, @@ -234,6 +237,9 @@ async def search_memory( """Search long-term memory for relevant information.""" result = await client.search_memory_tool( query=query, + search_mode=search_mode, + hybrid_alpha=hybrid_alpha, + text_scorer=text_scorer, topics=topics, entities=entities, memory_type=memory_type, diff --git a/docs/agent-examples.md b/docs/agent-examples.md index be1fedfe..ecac3866 100644 --- a/docs/agent-examples.md +++ b/docs/agent-examples.md @@ -402,7 +402,7 @@ from agent_memory_client import create_memory_client client = await create_memory_client(base_url="http://localhost:8000") # Get only the 3 most recent messages -memory = await client.get_working_memory( +created, memory = await client.get_or_create_working_memory( session_id="my-session", namespace="demo", context_window_max=3 From 67ae70306d07bdd3e321becde6e49e199b71b67d Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 21:17:38 -0400 Subject: [PATCH 3/9] fix: correct tuple unpacking order and error handling examples - agent-memory-client/README.md: fix (memory, created) -> (created, memory) to match get_or_create_working_memory() return type; remove impossible MemoryNotFoundError catch (get_or_create never raises it); fix duplicate except block - docs/index.md: clarify that keyword search is full-text, not vector-based --- agent-memory-client/README.md | 8 ++++---- docs/index.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/agent-memory-client/README.md b/agent-memory-client/README.md index 4421790b..bfe486b1 100644 --- a/agent-memory-client/README.md +++ b/agent-memory-client/README.md @@ -165,7 +165,7 @@ working_memory = WorkingMemory( response = await client.put_working_memory("user-session-123", working_memory) # Retrieve working memory -memory, created = await client.get_or_create_working_memory("user-session-123") +created, memory = await client.get_or_create_working_memory("user-session-123") # Convenience method for data storage await client.set_working_memory_data( @@ -348,9 +348,9 @@ from agent_memory_client.exceptions import ( ) try: - memory, created = await client.get_or_create_working_memory("nonexistent-session") -except MemoryNotFoundError: - print("Session not found") + created, memory = await client.get_or_create_working_memory("nonexistent-session") + if created: + print("New session created") except MemoryServerError as e: print(f"Server error {e.status_code}: {e}") except MemoryClientError as e: diff --git a/docs/index.md b/docs/index.md index 7cb8b0e5..f46e5266 100644 --- a/docs/index.md +++ b/docs/index.md @@ -95,7 +95,7 @@ print(f"Found: {results.memories[0].text}") !!! success "Long-Term Memory (Persistent)" - User preferences, facts, and important information - - Semantic, keyword, and hybrid search with vector embeddings + - Flexible search: semantic (vector embeddings), keyword (full-text), and hybrid (combined) - Advanced filtering by time, topics, entities, users ### 🔍 Intelligent Search From e47412fb0950359bd30b02083a20d14855a3503d Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 21:46:29 -0400 Subject: [PATCH 4/9] fix: forward hybrid search params in resolve_tool_call and fix inaccurate comments Bug fix: - client.py _resolve_search_memory: forward search_mode, hybrid_alpha, text_scorer to search_memory_tool (previously silently dropped) Accuracy fixes: - client.py: query param description 'vector search' -> 'search query' - langchain.py: use Literal type for search_mode parameter - 4 files: 'exact term matching' -> 'full-text matching' for keyword search (agent-memory-client/README.md, agent-memory-client-js/README.md, typescript-sdk.md, java-sdk.md) --- agent-memory-client/README.md | 2 +- agent-memory-client/agent-memory-client-js/README.md | 2 +- agent-memory-client/agent_memory_client/client.py | 8 +++++++- .../agent_memory_client/integrations/langchain.py | 2 +- docs/java-sdk.md | 2 +- docs/typescript-sdk.md | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/agent-memory-client/README.md b/agent-memory-client/README.md index bfe486b1..755c97b6 100644 --- a/agent-memory-client/README.md +++ b/agent-memory-client/README.md @@ -202,7 +202,7 @@ results = await client.search_long_term_memory( limit=20 ) -# Keyword search - exact term matching +# Keyword search - full-text matching results = await client.search_long_term_memory( text="science fiction", search_mode="keyword", diff --git a/agent-memory-client/agent-memory-client-js/README.md b/agent-memory-client/agent-memory-client-js/README.md index 841e3288..78cee72d 100644 --- a/agent-memory-client/agent-memory-client-js/README.md +++ b/agent-memory-client/agent-memory-client-js/README.md @@ -98,7 +98,7 @@ const results = await client.searchLongTermMemory({ limit: 20, }); -// Keyword search - exact term matching +// Keyword search - full-text matching const keywordResults = await client.searchLongTermMemory({ text: "science fiction", searchMode: "keyword", diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index 33d6c514..ba64fb4d 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -1392,7 +1392,7 @@ async def handle_tool_calls(client, tool_calls): "properties": { "query": { "type": "string", - "description": "The query for vector search describing what information you're looking for", + "description": "The search query describing what information you're looking for", }, "search_mode": { "type": "string", @@ -2692,9 +2692,15 @@ async def _resolve_search_memory(self, args: dict[str, Any]) -> dict[str, Any]: max_results = args.get("max_results", 5) min_relevance = args.get("min_relevance") user_id = args.get("user_id") + search_mode = args.get("search_mode", "semantic") + hybrid_alpha = args.get("hybrid_alpha") + text_scorer = args.get("text_scorer") return await self.search_memory_tool( query=query, + search_mode=search_mode, + hybrid_alpha=hybrid_alpha, + text_scorer=text_scorer, topics=topics, entities=entities, memory_type=memory_type, diff --git a/agent-memory-client/agent_memory_client/integrations/langchain.py b/agent-memory-client/agent_memory_client/integrations/langchain.py index 3808d589..3961e6eb 100644 --- a/agent-memory-client/agent_memory_client/integrations/langchain.py +++ b/agent-memory-client/agent_memory_client/integrations/langchain.py @@ -224,7 +224,7 @@ def _create_search_memory_func(client: MemoryAPIClient) -> Any: async def search_memory( query: str, - search_mode: str = "semantic", + search_mode: Literal["semantic", "keyword", "hybrid"] = "semantic", hybrid_alpha: float | None = None, text_scorer: str | None = None, topics: list[str] | None = None, diff --git a/docs/java-sdk.md b/docs/java-sdk.md index da15ec91..336b2160 100644 --- a/docs/java-sdk.md +++ b/docs/java-sdk.md @@ -145,7 +145,7 @@ MemoryRecordResults results = client.longTermMemory().searchLongTermMemories(req MemoryRecordResults simpleResults = client.longTermMemory() .searchLongTermMemories("user preferences"); -// Keyword search - exact term matching +// Keyword search - full-text matching SearchRequest keywordRequest = SearchRequest.builder() .text("TechCorp engineer") .searchMode("keyword") diff --git a/docs/typescript-sdk.md b/docs/typescript-sdk.md index 0793d815..d1fa7416 100644 --- a/docs/typescript-sdk.md +++ b/docs/typescript-sdk.md @@ -112,7 +112,7 @@ const results = await client.searchLongTermMemory({ limit: 10, }); -// Keyword search - exact term matching +// Keyword search - full-text matching const keywordResults = await client.searchLongTermMemory({ text: "TechCorp engineer", searchMode: "keyword", From 4ac1b79f6e66770f0a197de580f941bc5566cd33 Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 21:52:06 -0400 Subject: [PATCH 5/9] fix: add hybrid search params to MCP memory_prompt and client hydrate_memory_prompt Both functions were missing search_mode, hybrid_alpha, and text_scorer parameters, forcing all searches through these paths to default to semantic-only search. - mcp.py memory_prompt: accept and forward all 3 params to SearchRequest - client.py hydrate_memory_prompt: accept and forward all 3 params to long_term_search dict --- .../agent_memory_client/client.py | 18 +++++++++++++++++- agent_memory_server/mcp.py | 15 ++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index ba64fb4d..cf4d429c 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -3398,6 +3398,9 @@ async def hydrate_memory_prompt( user_id: dict[str, Any] | None = None, distance_threshold: float | None = None, memory_type: dict[str, Any] | None = None, + search_mode: SearchModeEnum | str = SearchModeEnum.SEMANTIC, + hybrid_alpha: float | None = None, + text_scorer: str | None = None, limit: int = 10, offset: int = 0, optimize_query: bool = False, @@ -3409,7 +3412,7 @@ async def hydrate_memory_prompt( long-term memory search with the specified filters. Args: - query: The query for vector search to find relevant context for + query: The search query to find relevant context for session_id: Optional session ID filter (as dict) namespace: Optional namespace filter (as dict) topics: Optional topics filter (as dict) @@ -3419,6 +3422,9 @@ async def hydrate_memory_prompt( user_id: Optional user ID filter (as dict) distance_threshold: Optional distance threshold memory_type: Optional memory type filter (as dict) + search_mode: Search strategy to use ("semantic", "keyword", or "hybrid") + hybrid_alpha: Optional weight for vector similarity in hybrid search (0.0-1.0) + text_scorer: Optional Redis full-text scoring algorithm for keyword and hybrid search limit: Maximum number of long-term memories to include offset: Offset for pagination (default: 0) optimize_query: Whether to optimize the query for vector search using a fast model (default: True) @@ -3449,6 +3455,16 @@ async def hydrate_memory_prompt( long_term_search["distance_threshold"] = distance_threshold if memory_type is not None: long_term_search["memory_type"] = memory_type + normalized_search_mode = ( + search_mode.value + if isinstance(search_mode, SearchModeEnum) + else str(search_mode) + ) + long_term_search["search_mode"] = normalized_search_mode + if hybrid_alpha is not None: + long_term_search["hybrid_alpha"] = hybrid_alpha + if text_scorer is not None: + long_term_search["text_scorer"] = text_scorer return await self.memory_prompt( query=query, diff --git a/agent_memory_server/mcp.py b/agent_memory_server/mcp.py index 58139997..a9336cae 100644 --- a/agent_memory_server/mcp.py +++ b/agent_memory_server/mcp.py @@ -643,12 +643,15 @@ async def memory_prompt( user_id: UserId | None = None, memory_type: MemoryType | None = None, distance_threshold: float | None = None, + search_mode: SearchModeEnum = SearchModeEnum.SEMANTIC, + hybrid_alpha: float = 0.7, + text_scorer: str = "BM25STD", limit: int = 10, offset: int = 0, optimize_query: bool = False, ) -> dict[str, Any]: """ - Hydrate a query for vector search with relevant session history and long-term memories. + Hydrate a query with relevant session history and long-term memories. This tool enriches the query by retrieving: 1. Context from the current conversation session @@ -657,7 +660,7 @@ async def memory_prompt( The tool returns both the relevant memories AND the user's query in a format ready for generating comprehensive responses. - The function uses the query field as the query for vector search, + The function uses the query field for searching (semantic, keyword, or hybrid), and any filters to retrieve relevant memories. DATETIME INPUT FORMAT: @@ -722,7 +725,7 @@ async def memory_prompt( ``` Args: - - query: The query for vector search + - query: The search query text - session_id: Add conversation history from a working memory session - namespace: Filter session and long-term memory namespace - topics: Search for long-term memories matching topics @@ -731,6 +734,9 @@ async def memory_prompt( - last_accessed: Search for long-term memories matching last access date - user_id: Search for long-term memories matching user ID - distance_threshold: Distance threshold for semantic search + - search_mode: Search strategy to use (semantic, keyword, or hybrid) + - hybrid_alpha: Weight assigned to vector similarity in hybrid search (0.0-1.0) + - text_scorer: Redis full-text scoring algorithm for keyword and hybrid search - limit: Maximum number of long-term memory results - offset: Offset for pagination of long-term memory results - optimize_query: Whether to optimize the query for vector search (default: False - LLMs typically provide already optimized queries) @@ -768,6 +774,9 @@ async def memory_prompt( user_id=user_id, distance_threshold=distance_threshold, memory_type=memory_type, + search_mode=search_mode, + hybrid_alpha=hybrid_alpha, + text_scorer=text_scorer, limit=limit, offset=offset, ) From 6d175bf86760e40892a766ee888ef1c5bdda09d3 Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 22:06:00 -0400 Subject: [PATCH 6/9] fix: correct optimize_query docstrings and add distance_threshold validation - Fix optimize_query docs: clarify it only applies to semantic search, ignored for keyword/hybrid modes - Fix default value docs: 3 occurrences said 'default: True' but signature is False - Add distance_threshold + search_mode validation to MCP memory_prompt (matches existing validation in search_long_term_memory) --- agent-memory-client/agent_memory_client/client.py | 10 +++++----- agent_memory_server/api.py | 4 ++-- agent_memory_server/mcp.py | 9 +++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index cf4d429c..e9ad49d6 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -1070,7 +1070,7 @@ async def search_long_term_memory( memory_type: Optional memory type filter limit: Maximum number of results to return (default: 10) offset: Offset for pagination (default: 0) - optimize_query: Whether to optimize the query for vector search using a fast model (default: True) + optimize_query: Whether to optimize the query for semantic (vector) search using a fast model; ignored for keyword and hybrid modes (default: False) Returns: MemoryRecordResults with matching memories and metadata @@ -1233,7 +1233,7 @@ async def search_memory_tool( offset: Offset for pagination (default: 0) min_relevance: Optional minimum relevance score (0.0-1.0) user_id: Optional user ID to filter memories by - optimize_query: Whether to optimize the query for vector search (default: False - LLMs typically provide already optimized queries) + optimize_query: Whether to optimize the query for semantic (vector) search; ignored for keyword and hybrid modes (default: False) Returns: Dict with 'memories' list and 'summary' for LLM consumption @@ -1451,7 +1451,7 @@ async def handle_tool_calls(client, tool_calls): "optimize_query": { "type": "boolean", "default": False, - "description": "Whether to optimize the query for vector search (default: False - LLMs typically provide already optimized queries)", + "description": "Whether to optimize the query for semantic (vector) search; ignored for keyword and hybrid modes (default: False)", }, }, "required": ["query"], @@ -3312,7 +3312,7 @@ async def memory_prompt( context_window_max: Optional direct specification of context window tokens long_term_search: Optional search parameters for long-term memory user_id: Optional user ID for the session - optimize_query: Whether to optimize the query for vector search using a fast model (default: True) + optimize_query: Whether to optimize the query for semantic (vector) search using a fast model; ignored for keyword and hybrid modes (default: False) Returns: Dict with messages hydrated with relevant memory context @@ -3427,7 +3427,7 @@ async def hydrate_memory_prompt( text_scorer: Optional Redis full-text scoring algorithm for keyword and hybrid search limit: Maximum number of long-term memories to include offset: Offset for pagination (default: 0) - optimize_query: Whether to optimize the query for vector search using a fast model (default: True) + optimize_query: Whether to optimize the query for semantic (vector) search using a fast model; ignored for keyword and hybrid modes (default: False) Returns: Dict with messages hydrated with relevant long-term memories diff --git a/agent_memory_server/api.py b/agent_memory_server/api.py index b5be13dc..52901f4e 100644 --- a/agent_memory_server/api.py +++ b/agent_memory_server/api.py @@ -654,7 +654,7 @@ async def search_long_term_memory( Args: payload: Search payload with filter objects for precise queries - optimize_query: Whether to optimize the query for vector search using a fast model (default: False) + optimize_query: Whether to optimize the query for semantic (vector) search using a fast model; ignored for keyword and hybrid modes (default: False) Returns: List of search results @@ -926,7 +926,7 @@ async def memory_prompt( Args: params: MemoryPromptRequest - optimize_query: Whether to optimize the query for vector search using a fast model (default: False) + optimize_query: Whether to optimize the query for semantic (vector) search using a fast model; ignored for keyword and hybrid modes (default: False) Returns: List of messages to send to an LLM, hydrated with relevant memory context diff --git a/agent_memory_server/mcp.py b/agent_memory_server/mcp.py index a9336cae..6a36ca79 100644 --- a/agent_memory_server/mcp.py +++ b/agent_memory_server/mcp.py @@ -575,7 +575,7 @@ async def search_long_term_memory( distance_threshold: Distance threshold for semantic search limit: Maximum number of results offset: Offset for pagination - optimize_query: Whether to optimize the query for vector search (default: False - LLMs typically provide already optimized queries) + optimize_query: Whether to optimize the query for semantic (vector) search only; ignored for keyword and hybrid modes (default: False - LLMs typically provide already optimized queries) Returns: MemoryRecordResults containing matched memories sorted by relevance @@ -739,11 +739,16 @@ async def memory_prompt( - text_scorer: Redis full-text scoring algorithm for keyword and hybrid search - limit: Maximum number of long-term memory results - offset: Offset for pagination of long-term memory results - - optimize_query: Whether to optimize the query for vector search (default: False - LLMs typically provide already optimized queries) + - optimize_query: Whether to optimize the query for semantic (vector) search only; ignored for keyword and hybrid modes (default: False - LLMs typically provide already optimized queries) Returns: JSON-serializable memory prompt payload including memory context and the user's query """ + if distance_threshold is not None and search_mode != SearchModeEnum.SEMANTIC: + raise ValueError( + "distance_threshold is only supported for semantic search mode" + ) + _session_id = session_id.eq if session_id and session_id.eq else None session = None From eb2e92e2a6ec835b41ab99a785341ee0fb183c13 Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 22:24:24 -0400 Subject: [PATCH 7/9] fix: align _resolve_search_memory max_results default with tool schema (5 -> 10) Bug fix: - _resolve_search_memory defaulted max_results to 5, but the OpenAI tool schema and search_memory_tool signature both default to 10 Test: - Extend test_memory_prompt_parameter_passing to assert search_mode, hybrid_alpha, and text_scorer are forwarded through MCP memory_prompt --- agent-memory-client/agent_memory_client/client.py | 2 +- tests/test_mcp.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index e9ad49d6..4833dfd7 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -2689,7 +2689,7 @@ async def _resolve_search_memory(self, args: dict[str, Any]) -> dict[str, Any]: topics = args.get("topics") entities = args.get("entities") memory_type = args.get("memory_type") - max_results = args.get("max_results", 5) + max_results = args.get("max_results", 10) min_relevance = args.get("min_relevance") user_id = args.get("user_id") search_mode = args.get("search_mode", "semantic") diff --git a/tests/test_mcp.py b/tests/test_mcp.py index 86a5312a..f1c299f9 100644 --- a/tests/test_mcp.py +++ b/tests/test_mcp.py @@ -15,6 +15,7 @@ MemoryRecord, MemoryRecordResult, MemoryRecordResults, + SearchModeEnum, SystemMessage, WorkingMemoryResponse, ) @@ -263,6 +264,9 @@ async def mock_core_memory_prompt( "namespace": {"eq": "test-namespace"}, "topics": {"any": ["test-topic"]}, "entities": {"any": ["test-entity"]}, + "search_mode": "hybrid", + "hybrid_alpha": 0.5, + "text_scorer": "TFIDF", "limit": 5, }, ) @@ -285,6 +289,13 @@ async def mock_core_memory_prompt( assert captured_params["long_term_search"].topics is not None assert captured_params["long_term_search"].entities is not None + # Verify hybrid search parameters were forwarded + assert ( + captured_params["long_term_search"].search_mode == SearchModeEnum.HYBRID + ) + assert captured_params["long_term_search"].hybrid_alpha == 0.5 + assert captured_params["long_term_search"].text_scorer == "TFIDF" + @pytest.mark.asyncio async def test_set_working_memory_tool(self, mcp_test_setup): """Test the set_working_memory tool function""" From 436b4429a0893063588cd547037fcda9aadf0c1c Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Thu, 26 Mar 2026 22:30:52 -0400 Subject: [PATCH 8/9] fix: forward offset and optimize_query in _resolve_search_memory Both params are in the tool schema but were not extracted or passed to search_memory_tool(), so LLM-provided values were silently ignored. --- agent-memory-client/agent_memory_client/client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index 4833dfd7..8ac8909f 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -2695,6 +2695,8 @@ async def _resolve_search_memory(self, args: dict[str, Any]) -> dict[str, Any]: search_mode = args.get("search_mode", "semantic") hybrid_alpha = args.get("hybrid_alpha") text_scorer = args.get("text_scorer") + offset = args.get("offset", 0) + optimize_query = args.get("optimize_query", False) return await self.search_memory_tool( query=query, @@ -2705,8 +2707,10 @@ async def _resolve_search_memory(self, args: dict[str, Any]) -> dict[str, Any]: entities=entities, memory_type=memory_type, max_results=max_results, + offset=offset, min_relevance=min_relevance, user_id=user_id, + optimize_query=optimize_query, ) async def _resolve_get_working_memory( From 49008ec381b080741dcacadd2e8f8fb81451ea13 Mon Sep 17 00:00:00 2001 From: Nitin Kanukolanu Date: Fri, 27 Mar 2026 10:48:47 -0400 Subject: [PATCH 9/9] fix: make error message name-agnostic and update docs table for full-text indexing - _resolve_create_long_term_memory error message now says 'memories parameter is required' instead of naming a specific tool (handles both eagerly_create and deprecated create aliases) - docs/long-term-memory.md Storage and Indexing rows now mention full-text indexing alongside vector indexing --- agent-memory-client/agent_memory_client/client.py | 4 +--- docs/long-term-memory.md | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/agent-memory-client/agent_memory_client/client.py b/agent-memory-client/agent_memory_client/client.py index 8ac8909f..2e423c0f 100644 --- a/agent-memory-client/agent_memory_client/client.py +++ b/agent-memory-client/agent_memory_client/client.py @@ -2803,9 +2803,7 @@ async def _resolve_create_long_term_memory( """Resolve eagerly_create_long_term_memory (and deprecated create_long_term_memory alias) function call.""" memories_data = args.get("memories") if not memories_data: - raise ValueError( - "memories parameter is required for eagerly_create_long_term_memory" - ) + raise ValueError("memories parameter is required") # Convert dict memories to ClientMemoryRecord objects from .models import ClientMemoryRecord, MemoryTypeEnum diff --git a/docs/long-term-memory.md b/docs/long-term-memory.md index 601013ee..81885f57 100644 --- a/docs/long-term-memory.md +++ b/docs/long-term-memory.md @@ -10,11 +10,11 @@ Long-term memory provides persistent storage that survives server restarts and s |---------|---------| | **Scope** | Cross-session, persistent | | **Lifespan** | Permanent until manually deleted | -| **Storage** | Redis with vector indexing | +| **Storage** | Redis with vector and full-text indexing | | **Search** | Semantic, keyword, and hybrid search | | **Capacity** | Unlimited (with compaction) | | **Use Case** | Knowledge base, user preferences | -| **Indexing** | Vector embeddings + metadata | +| **Indexing** | Vector embeddings + full-text index + metadata | | **Deduplication** | Hash-based and semantic | ## Characteristics