0
# Persistent Storage
1
2
Cross-thread persistent memory system for storing and retrieving documents, configuration, and application data with namespacing, search capabilities, and flexible data organization.
3
4
## Capabilities
5
6
### Item Storage Operations
7
8
Store, retrieve, update, and delete items in the persistent storage system with flexible key-value organization.
9
10
```python { .api }
11
from collections.abc import Mapping, Sequence
12
from typing import Any, Literal
13
from langgraph_sdk.schema import Item, QueryParamTypes
14
15
# Via client.store
16
async def put_item(
17
namespace: Sequence[str],
18
/,
19
key: str,
20
value: Mapping[str, Any],
21
index: Literal[False] | list[str] | None = None,
22
ttl: int | None = None,
23
headers: Mapping[str, str] | None = None,
24
params: QueryParamTypes | None = None,
25
) -> None:
26
"""
27
Store an item.
28
29
Args:
30
namespace: The namespace to store the item in.
31
key: The unique identifier for the item.
32
value: The value to store.
33
index: Whether to index the item. If a list is provided, only the specified fields will be indexed.
34
ttl: Time-to-live for the item in seconds.
35
headers: Optional custom headers to include with the request.
36
params: Optional query parameters to include with the request.
37
"""
38
39
async def get_item(
40
namespace: Sequence[str],
41
/,
42
key: str,
43
*,
44
refresh_ttl: bool | None = None,
45
headers: Mapping[str, str] | None = None,
46
params: QueryParamTypes | None = None,
47
) -> Item:
48
"""
49
Retrieve a single item.
50
51
Args:
52
namespace: The namespace to retrieve the item from.
53
key: The unique identifier for the item.
54
refresh_ttl: Whether to refresh the item's TTL.
55
headers: Optional custom headers to include with the request.
56
params: Optional query parameters to include with the request.
57
58
Returns:
59
Item: The retrieved item.
60
"""
61
62
async def delete_item(
63
namespace: Sequence[str],
64
/,
65
key: str,
66
headers: Mapping[str, str] | None = None,
67
params: QueryParamTypes | None = None,
68
) -> None:
69
"""
70
Delete an item.
71
72
Args:
73
namespace: The namespace to delete the item from.
74
key: The unique identifier for the item.
75
headers: Optional custom headers to include with the request.
76
params: Optional query parameters to include with the request.
77
"""
78
```
79
80
### Search & Discovery
81
82
Search for items across namespaces with text queries, filtering, and pagination.
83
84
```python { .api }
85
from langgraph_sdk.schema import SearchItemsResponse, ListNamespaceResponse
86
87
async def search_items(
88
namespace_prefix: Sequence[str],
89
/,
90
filter: Mapping[str, Any] | None = None,
91
limit: int = 10,
92
offset: int = 0,
93
query: str | None = None,
94
refresh_ttl: bool | None = None,
95
headers: Mapping[str, str] | None = None,
96
params: QueryParamTypes | None = None,
97
) -> SearchItemsResponse:
98
"""
99
Search for items in the store.
100
101
Args:
102
namespace_prefix: The namespace prefix to search under.
103
filter: Filtering criteria for the search.
104
limit: Maximum number of items to return (default is 10).
105
offset: Number of items to skip before returning results (default is 0).
106
query: Optional query string for full-text search.
107
refresh_ttl: Whether to refresh the TTL of found items.
108
headers: Optional custom headers to include with the request.
109
params: Optional query parameters to include with the request.
110
111
Returns:
112
SearchItemsResponse: The search results.
113
"""
114
115
async def list_namespaces(
116
*,
117
prefix: Sequence[str] | None = None,
118
suffix: Sequence[str] | None = None,
119
max_depth: int | None = None,
120
limit: int = 100,
121
offset: int = 0,
122
headers: Mapping[str, str] | None = None,
123
params: QueryParamTypes | None = None,
124
) -> ListNamespaceResponse:
125
"""
126
List namespaces with optional match conditions.
127
128
Args:
129
prefix: Optional list of strings representing the prefix to filter namespaces.
130
suffix: Optional list of strings representing the suffix to filter namespaces.
131
max_depth: Optional integer specifying the maximum depth of namespaces to return.
132
limit: Maximum number of namespaces to return (default is 100).
133
offset: Number of namespaces to skip before returning results (default is 0).
134
headers: Optional custom headers to include with the request.
135
params: Optional query parameters to include with the request.
136
137
Returns:
138
ListNamespaceResponse: The list of namespaces.
139
"""
140
```
141
142
## Types
143
144
```python { .api }
145
class Item(TypedDict):
146
"""Stored item with metadata."""
147
namespace: list[str]
148
key: str
149
value: dict
150
created_at: str
151
updated_at: str
152
index: dict
153
154
class SearchItem(TypedDict):
155
"""Search result item with relevance score."""
156
namespace: list[str]
157
key: str
158
value: dict
159
created_at: str
160
updated_at: str
161
index: dict
162
score: float
163
164
class SearchItemsResponse(TypedDict):
165
"""Search results with pagination."""
166
items: list[SearchItem]
167
total: int
168
limit: int
169
offset: int
170
171
class ListNamespaceResponse(TypedDict):
172
"""Namespace listing response."""
173
namespaces: list[list[str]]
174
total: int
175
limit: int
176
offset: int
177
```
178
179
## Usage Examples
180
181
### Basic Item Operations
182
183
```python
184
# Store user preferences
185
user_prefs = {
186
"theme": "dark",
187
"language": "en",
188
"notifications": True,
189
"timezone": "America/New_York"
190
}
191
192
await client.store.put_item(
193
value=user_prefs,
194
namespace=["users", "user-123", "preferences"],
195
key="ui_settings"
196
)
197
198
# Retrieve user preferences
199
prefs = await client.store.get_item(
200
namespace=["users", "user-123", "preferences"],
201
key="ui_settings"
202
)
203
204
print(f"User theme: {prefs['value']['theme']}")
205
206
# Update preferences (store overwrites)
207
updated_prefs = prefs["value"].copy()
208
updated_prefs["theme"] = "light"
209
210
await client.store.put_item(
211
value=updated_prefs,
212
namespace=["users", "user-123", "preferences"],
213
key="ui_settings"
214
)
215
```
216
217
### Document Storage
218
219
```python
220
# Store conversation history
221
conversation = {
222
"messages": [
223
{"role": "human", "content": "Hello", "timestamp": "2023-12-01T10:00:00Z"},
224
{"role": "assistant", "content": "Hi there!", "timestamp": "2023-12-01T10:00:01Z"}
225
],
226
"summary": "Greeting exchange",
227
"participants": ["user-123", "assistant-456"]
228
}
229
230
await client.store.put_item(
231
value=conversation,
232
namespace=["conversations", "user-123"],
233
key="conv-2023-12-01",
234
index={
235
"participants": ["user-123", "assistant-456"],
236
"date": "2023-12-01",
237
"message_count": 2
238
}
239
)
240
241
# Store configuration
242
app_config = {
243
"api_endpoints": {
244
"auth": "https://auth.api.com",
245
"data": "https://data.api.com"
246
},
247
"features": {
248
"analytics": True,
249
"caching": True,
250
"rate_limiting": {"rpm": 1000}
251
},
252
"version": "1.2.0"
253
}
254
255
await client.store.put_item(
256
value=app_config,
257
namespace=["application", "config"],
258
key="production"
259
)
260
```
261
262
### Hierarchical Organization
263
264
```python
265
# Organize data hierarchically
266
namespaces = [
267
# User data
268
["users", "user-123", "profile"],
269
["users", "user-123", "preferences"],
270
["users", "user-123", "sessions"],
271
272
# Application data
273
["application", "config", "production"],
274
["application", "config", "staging"],
275
["application", "templates", "emails"],
276
277
# Analytics data
278
["analytics", "2023", "12", "daily"],
279
["analytics", "2023", "12", "weekly"],
280
]
281
282
# Store items in different namespaces
283
for namespace in namespaces:
284
await client.store.put_item(
285
value={"created": "2023-12-01", "type": namespace[-1]},
286
namespace=namespace,
287
key="metadata"
288
)
289
```
290
291
### Search Operations
292
293
```python
294
# Search user conversations
295
user_conversations = await client.store.search_items(
296
namespace_prefix=["conversations", "user-123"],
297
query="greeting",
298
limit=20
299
)
300
301
print(f"Found {user_conversations['total']} conversations")
302
for item in user_conversations["items"]:
303
print(f" {item['key']}: {item['value']['summary']}")
304
305
# Search with filters
306
recent_conversations = await client.store.search_items(
307
namespace_prefix=["conversations"],
308
filter={"date": "2023-12-01", "message_count": {"$gt": 5}},
309
limit=50
310
)
311
312
# Search application configs
313
configs = await client.store.search_items(
314
namespace_prefix=["application", "config"],
315
query="production OR staging"
316
)
317
```
318
319
### Namespace Management
320
321
```python
322
# List all user namespaces
323
user_namespaces = await client.store.list_namespaces(
324
prefix=["users"],
325
max_depth=3
326
)
327
328
print("User namespaces:")
329
for ns in user_namespaces["namespaces"]:
330
print(f" {'/'.join(ns)}")
331
332
# List application namespaces
333
app_namespaces = await client.store.list_namespaces(
334
prefix=["application"]
335
)
336
337
# Get all top-level namespaces
338
all_namespaces = await client.store.list_namespaces(max_depth=1)
339
```
340
341
### Session & Cache Management
342
343
```python
344
# Store session data
345
session_data = {
346
"user_id": "user-123",
347
"login_time": "2023-12-01T10:00:00Z",
348
"permissions": ["read", "write"],
349
"temporary_data": {"cart_items": [], "form_state": {}}
350
}
351
352
await client.store.put_item(
353
value=session_data,
354
namespace=["sessions", "active"],
355
key="session-abc123",
356
index={"user_id": "user-123", "active": True}
357
)
358
359
# Cache frequently accessed data
360
cache_data = {
361
"computed_result": [1, 2, 3, 4, 5],
362
"computation_time": 0.5,
363
"expires_at": "2023-12-01T11:00:00Z"
364
}
365
366
await client.store.put_item(
367
value=cache_data,
368
namespace=["cache", "computations"],
369
key="fibonacci-100",
370
index={"expires_at": "2023-12-01T11:00:00Z"}
371
)
372
```
373
374
### Thread-Shared Memory
375
376
```python
377
# Store shared state across multiple threads
378
shared_state = {
379
"active_users": ["user-123", "user-456"],
380
"global_config": {"maintenance_mode": False},
381
"counters": {"api_calls": 1000, "errors": 5}
382
}
383
384
await client.store.put_item(
385
value=shared_state,
386
namespace=["global", "runtime"],
387
key="current_state"
388
)
389
390
# Access from any thread
391
current_state = await client.store.get_item(
392
namespace=["global", "runtime"],
393
key="current_state"
394
)
395
396
# Update counters atomically (read-modify-write pattern)
397
state = current_state["value"]
398
state["counters"]["api_calls"] += 1
399
400
await client.store.put_item(
401
value=state,
402
namespace=["global", "runtime"],
403
key="current_state"
404
)
405
```
406
407
### Cleanup Operations
408
409
```python
410
# Find and delete expired items
411
expired_items = await client.store.search_items(
412
namespace_prefix=["cache"],
413
filter={"expires_at": {"$lt": "2023-12-01T10:00:00Z"}}
414
)
415
416
for item in expired_items["items"]:
417
await client.store.delete_item(
418
namespace=item["namespace"],
419
key=item["key"]
420
)
421
422
# Delete user data
423
user_namespaces = await client.store.list_namespaces(
424
prefix=["users", "user-123"]
425
)
426
427
# Delete all items in user namespaces (requires iteration)
428
for namespace in user_namespaces["namespaces"]:
429
# Note: You would need to search and delete individual items
430
# as there's no bulk delete operation shown in the API
431
items = await client.store.search_items(
432
namespace_prefix=namespace,
433
limit=1000
434
)
435
436
for item in items["items"]:
437
await client.store.delete_item(
438
namespace=item["namespace"],
439
key=item["key"]
440
)
441
```