|
| 1 | +# Memory Client Migration Status |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +We've migrated from a custom wrapper (`redis_context_course.memory_client.MemoryClient`) to using the official `agent_memory_client.MemoryAPIClient` directly. |
| 6 | + |
| 7 | +## Completed ✅ |
| 8 | + |
| 9 | +### 1. Infrastructure |
| 10 | +- ✅ Removed custom `memory_client.py` wrapper |
| 11 | +- ✅ Updated `__init__.py` to export `MemoryAPIClient` as `MemoryClient` |
| 12 | +- ✅ Updated `docker-compose.yml` with correct `LOG_LEVEL=INFO` |
| 13 | +- ✅ Updated CI workflow with correct `LOG_LEVEL=INFO` |
| 14 | + |
| 15 | +### 2. Core Code |
| 16 | +- ✅ **agent.py**: Fully migrated to use `MemoryAPIClient` |
| 17 | + - Uses `get_or_create_working_memory()` with tuple unpacking |
| 18 | + - Uses `put_working_memory()` with `WorkingMemory` objects |
| 19 | + - Uses `create_long_term_memory()` with `ClientMemoryRecord` list |
| 20 | + - Uses `search_long_term_memory()` with proper parameters |
| 21 | + |
| 22 | +- ✅ **tools.py**: Fully migrated to use `MemoryAPIClient` |
| 23 | + - Uses `create_long_term_memory()` with `ClientMemoryRecord` |
| 24 | + - Uses `search_long_term_memory()` returning `MemoryRecordResults` |
| 25 | + |
| 26 | +### 3. Tests |
| 27 | +- ✅ Updated `test_package.py` to import from `agent_memory_client` |
| 28 | + |
| 29 | +## In Progress 🚧 |
| 30 | + |
| 31 | +### Notebooks |
| 32 | +- ✅ Updated imports to use `agent_memory_client` |
| 33 | +- ✅ Fixed `get_or_create_working_memory()` tuple unpacking |
| 34 | +- ✅ Fixed `search_long_term_memory()` parameter names (`text=` instead of `query=`) |
| 35 | +- ❌ **Still TODO**: Fix `save_working_memory()` calls |
| 36 | + |
| 37 | +## API Differences |
| 38 | + |
| 39 | +### Old Wrapper API (Removed) |
| 40 | +```python |
| 41 | +# Initialization |
| 42 | +memory_client = MemoryClient( |
| 43 | + user_id="user123", |
| 44 | + namespace="my_namespace" |
| 45 | +) |
| 46 | + |
| 47 | +# Get/create working memory |
| 48 | +working_memory = await memory_client.get_or_create_working_memory( |
| 49 | + session_id="session_001", |
| 50 | + model_name="gpt-4o" |
| 51 | +) |
| 52 | + |
| 53 | +# Save working memory |
| 54 | +await memory_client.save_working_memory( |
| 55 | + session_id="session_001", |
| 56 | + messages=[{"role": "user", "content": "Hello"}] |
| 57 | +) |
| 58 | + |
| 59 | +# Create long-term memory |
| 60 | +await memory_client.create_memory( |
| 61 | + text="User prefers dark mode", |
| 62 | + memory_type="semantic", |
| 63 | + topics=["preferences"] |
| 64 | +) |
| 65 | + |
| 66 | +# Search memories |
| 67 | +memories = await memory_client.search_memories( |
| 68 | + query="preferences", |
| 69 | + limit=10 |
| 70 | +) |
| 71 | +``` |
| 72 | + |
| 73 | +### New MemoryAPIClient API (Current) |
| 74 | +```python |
| 75 | +# Initialization |
| 76 | +from agent_memory_client import MemoryAPIClient, MemoryClientConfig |
| 77 | + |
| 78 | +config = MemoryClientConfig( |
| 79 | + base_url="http://localhost:8000", |
| 80 | + default_namespace="my_namespace" |
| 81 | +) |
| 82 | +memory_client = MemoryAPIClient(config=config) |
| 83 | + |
| 84 | +# Get/create working memory (returns tuple!) |
| 85 | +created, working_memory = await memory_client.get_or_create_working_memory( |
| 86 | + session_id="session_001", |
| 87 | + user_id="user123", |
| 88 | + model_name="gpt-4o" |
| 89 | +) |
| 90 | + |
| 91 | +# Save working memory (requires WorkingMemory object) |
| 92 | +from agent_memory_client import WorkingMemory, MemoryMessage |
| 93 | + |
| 94 | +messages = [MemoryMessage(role="user", content="Hello")] |
| 95 | +working_memory = WorkingMemory( |
| 96 | + session_id="session_001", |
| 97 | + user_id="user123", |
| 98 | + messages=messages, |
| 99 | + memories=[], |
| 100 | + data={} |
| 101 | +) |
| 102 | + |
| 103 | +await memory_client.put_working_memory( |
| 104 | + session_id="session_001", |
| 105 | + memory=working_memory, |
| 106 | + user_id="user123", |
| 107 | + model_name="gpt-4o" |
| 108 | +) |
| 109 | + |
| 110 | +# Create long-term memory (requires list of ClientMemoryRecord) |
| 111 | +from agent_memory_client import ClientMemoryRecord |
| 112 | + |
| 113 | +memory = ClientMemoryRecord( |
| 114 | + text="User prefers dark mode", |
| 115 | + user_id="user123", |
| 116 | + memory_type="semantic", |
| 117 | + topics=["preferences"] |
| 118 | +) |
| 119 | + |
| 120 | +await memory_client.create_long_term_memory([memory]) |
| 121 | + |
| 122 | +# Search memories (returns MemoryRecordResults) |
| 123 | +from agent_memory_client import UserId |
| 124 | + |
| 125 | +results = await memory_client.search_long_term_memory( |
| 126 | + text="preferences", # Note: 'text' not 'query' |
| 127 | + user_id=UserId(eq="user123"), |
| 128 | + limit=10 |
| 129 | +) |
| 130 | + |
| 131 | +# Access memories via results.memories |
| 132 | +for memory in results.memories: |
| 133 | + print(memory.text) |
| 134 | +``` |
| 135 | + |
| 136 | +## Key Changes |
| 137 | + |
| 138 | +1. **Initialization**: Requires `MemoryClientConfig` object |
| 139 | +2. **get_or_create_working_memory**: Returns `tuple[bool, WorkingMemory]` - must unpack! |
| 140 | +3. **save_working_memory → put_working_memory**: Requires `WorkingMemory` object |
| 141 | +4. **create_memory → create_long_term_memory**: Takes list of `ClientMemoryRecord` |
| 142 | +5. **search_memories → search_long_term_memory**: |
| 143 | + - Parameter is `text=` not `query=` |
| 144 | + - Returns `MemoryRecordResults` not list |
| 145 | + - Access memories via `results.memories` |
| 146 | +6. **user_id**: Must be passed to most methods (not stored in client) |
| 147 | + |
| 148 | +## Remaining Work |
| 149 | + |
| 150 | +### Notebooks to Fix |
| 151 | + |
| 152 | +All notebooks in `section-3-memory/` and some in `section-4-optimizations/` need manual fixes for `save_working_memory()` calls. |
| 153 | + |
| 154 | +**Pattern to find:** |
| 155 | +```bash |
| 156 | +grep -r "save_working_memory" notebooks/ |
| 157 | +``` |
| 158 | + |
| 159 | +**Fix required:** |
| 160 | +Replace: |
| 161 | +```python |
| 162 | +await memory_client.save_working_memory( |
| 163 | + session_id=session_id, |
| 164 | + messages=messages |
| 165 | +) |
| 166 | +``` |
| 167 | + |
| 168 | +With: |
| 169 | +```python |
| 170 | +from agent_memory_client import WorkingMemory, MemoryMessage |
| 171 | + |
| 172 | +memory_messages = [MemoryMessage(**msg) for msg in messages] |
| 173 | +working_memory = WorkingMemory( |
| 174 | + session_id=session_id, |
| 175 | + user_id=user_id, # Need to add user_id! |
| 176 | + messages=memory_messages, |
| 177 | + memories=[], |
| 178 | + data={} |
| 179 | +) |
| 180 | + |
| 181 | +await memory_client.put_working_memory( |
| 182 | + session_id=session_id, |
| 183 | + memory=working_memory, |
| 184 | + user_id=user_id, |
| 185 | + model_name="gpt-4o" |
| 186 | +) |
| 187 | +``` |
| 188 | + |
| 189 | +## Testing |
| 190 | + |
| 191 | +After fixing notebooks, run: |
| 192 | +```bash |
| 193 | +cd python-recipes/context-engineering |
| 194 | +source venv/bin/activate |
| 195 | +pytest --nbval-lax --disable-warnings notebooks/section-3-memory/ |
| 196 | +pytest --nbval-lax --disable-warnings notebooks/section-4-optimizations/ |
| 197 | +``` |
| 198 | + |
| 199 | +## CI Status |
| 200 | + |
| 201 | +Current status: **9/15 notebooks passing (60%)** |
| 202 | + |
| 203 | +Expected after notebook fixes: **12-13/15 notebooks passing (80-87%)** |
| 204 | + |
| 205 | +The remaining failures will likely be due to: |
| 206 | +- OpenAI API rate limits |
| 207 | +- Agent Memory Server extraction timing |
| 208 | +- Network issues in CI |
| 209 | + |
| 210 | +## References |
| 211 | + |
| 212 | +- [Agent Memory Server GitHub](https://github.com/redis/agent-memory-server) |
| 213 | +- [Agent Memory Client Source](https://github.com/redis/agent-memory-server/tree/main/agent-memory-client) |
| 214 | +- [Agent Memory Server Docs](https://redis.github.io/agent-memory-server/) |
| 215 | + |
0 commit comments