sovant 1.3.0__py3-none-any.whl → 1.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sovant/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from .client import Sovant, SovantError
2
2
  from .models import MemoryCreate, MemoryResult, SearchQuery
3
3
 
4
- __version__ = "1.3.0"
4
+ __version__ = "1.3.1"
@@ -0,0 +1,381 @@
1
+ Metadata-Version: 2.4
2
+ Name: sovant
3
+ Version: 1.3.1
4
+ Summary: Sovant Python SDK — governed AI memory layer for AI agents and applications
5
+ Author: Sovant
6
+ License-Expression: MIT
7
+ Project-URL: Documentation, https://sovant.ai/docs
8
+ Project-URL: Source, https://github.com/hechin91/sovant-ai
9
+ Project-URL: Tracker, https://github.com/hechin91/sovant-ai/issues
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: httpx>=0.27.0
14
+ Requires-Dist: pydantic>=2.8.2
15
+ Dynamic: license-file
16
+
17
+ # Sovant Python SDK
18
+
19
+ **Sovant is a governed AI memory layer for AI agents and applications.**
20
+ Use it to store, search, and recall memories with profile awareness and enterprise-grade control over how memory is captured and used.
21
+
22
+ [![PyPI version](https://img.shields.io/pypi/v/sovant.svg)](https://pypi.org/project/sovant/)
23
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install sovant
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ```python
34
+ import os
35
+ from sovant import Sovant, MemoryCreate, SearchQuery
36
+
37
+ client = Sovant(api_key=os.environ["SOVANT_API_KEY"])
38
+
39
+ # Create a memory
40
+ mem = client.memory_create(MemoryCreate(
41
+ data="User prefers dark mode",
42
+ type="preference",
43
+ tags=["ui", "settings"],
44
+ ))
45
+
46
+ # Search memories
47
+ results = client.memory_search(SearchQuery(
48
+ query="user preferences",
49
+ limit=10,
50
+ ))
51
+
52
+ # Update a memory
53
+ updated = client.memory_update(mem["id"], {
54
+ "tags": ["ui", "settings", "theme"],
55
+ })
56
+
57
+ # Delete a memory
58
+ client.memory_delete(mem["id"])
59
+ ```
60
+
61
+ ## Recall vs Search
62
+
63
+ Sovant provides two ways to query memories:
64
+
65
+ - **`memory_recall()`** -- Hybrid recall, profile-aware.
66
+ Use for conversational queries: "What do you know about me?", "What happened on Project X?".
67
+ Uses Sovant's hybrid pipeline (profile fast-path + thread-scoped lexical + vector semantic search) and prioritizes profile facts (name/age/location) when available.
68
+
69
+ - **`memory_search()`** -- Semantic search.
70
+ Use for topic lookup and discovery. Pure vector similarity search without profile logic.
71
+
72
+ ```python
73
+ # Recall for conversational queries (returns { "results": [...], "total": N })
74
+ recall = client.memory_recall(
75
+ query="what do you know about me?",
76
+ limit=10,
77
+ )
78
+ for mem in recall.get("results", []):
79
+ print(mem["content"])
80
+
81
+ # Search for topic discovery
82
+ topics = client.memory_search(SearchQuery(
83
+ query="project updates",
84
+ limit=5,
85
+ ))
86
+ ```
87
+
88
+ ## Working with Threads
89
+
90
+ Threads let you organize related memories into conversations or sessions. Each thread has a `title` and can contain multiple memories.
91
+
92
+ ```python
93
+ import os
94
+ from sovant import Sovant, MemoryCreate
95
+
96
+ client = Sovant(api_key=os.environ["SOVANT_API_KEY"])
97
+
98
+ # Create a new thread
99
+ thread = client.threads_create(
100
+ title="Project Alpha Discussion",
101
+ description="Q1 planning meeting notes",
102
+ metadata={"project": "alpha", "quarter": "Q1"},
103
+ )
104
+
105
+ # Store memories in the thread
106
+ mem1 = client.memory_create(MemoryCreate(
107
+ data="Decided to launch in March",
108
+ type="journal",
109
+ thread_id=thread["id"],
110
+ ))
111
+
112
+ mem2 = client.memory_create(MemoryCreate(
113
+ data="Budget approved: $50k",
114
+ type="insight",
115
+ thread_id=thread["id"],
116
+ ))
117
+
118
+ # Recall memories from this specific thread
119
+ thread_recall = client.memory_recall(
120
+ query="launch date",
121
+ thread_id=thread["id"],
122
+ limit=10,
123
+ )
124
+ # thread_recall["results"] contains the matching memories
125
+
126
+ # Get thread with all its memories
127
+ thread_with_memories = client.threads_get(
128
+ thread["id"],
129
+ include_memories=True,
130
+ limit=50,
131
+ )
132
+
133
+ # List all threads
134
+ threads = client.threads_list(limit=20, offset=0)
135
+
136
+ # Update thread
137
+ updated = client.threads_update(
138
+ thread["id"],
139
+ title="Project Alpha - Q1 Launch",
140
+ status="completed",
141
+ )
142
+
143
+ # Delete thread (keeps memories by default)
144
+ client.threads_delete(thread["id"])
145
+
146
+ # Delete thread AND all its memories
147
+ client.threads_delete(thread["id"], delete_memories=True)
148
+ ```
149
+
150
+ ## Configuration
151
+
152
+ ```python
153
+ from sovant import Sovant
154
+
155
+ client = Sovant(
156
+ api_key="sk_live_...", # Required (or set SOVANT_API_KEY env var)
157
+ base_url="https://sovant.ai", # Optional, defaults to https://sovant.ai
158
+ timeout=30.0, # Optional, request timeout in seconds (default: 30.0)
159
+ max_retries=3, # Optional, max retry attempts (default: 3)
160
+ )
161
+ ```
162
+
163
+ The SDK handles authentication via the `Authorization: Bearer` header.
164
+
165
+ ## API Reference
166
+
167
+ ### Memory Operations
168
+
169
+ #### Create Memory
170
+
171
+ ```python
172
+ from sovant import MemoryCreate
173
+
174
+ memory = client.memory_create(MemoryCreate(
175
+ data="Customer contacted support about billing",
176
+ type="observation", # 'journal' | 'insight' | 'observation' | 'task' | 'preference'
177
+ tags=["support", "billing"],
178
+ metadata={"ticket_id": "12345"},
179
+ thread_id="thread_abc123", # Optional thread association
180
+ ))
181
+ ```
182
+
183
+ #### Get Memory by ID
184
+
185
+ ```python
186
+ memory = client.memory_get("mem_123abc")
187
+ ```
188
+
189
+ #### Update Memory
190
+
191
+ ```python
192
+ updated = client.memory_update("mem_123abc", {
193
+ "tags": ["support", "billing", "resolved"],
194
+ })
195
+ ```
196
+
197
+ #### Delete Memory
198
+
199
+ ```python
200
+ client.memory_delete("mem_123abc")
201
+ ```
202
+
203
+ #### Search Memories
204
+
205
+ ```python
206
+ from sovant import SearchQuery
207
+
208
+ # Semantic search
209
+ results = client.memory_search(SearchQuery(
210
+ query="customer preferences about notifications",
211
+ limit=10,
212
+ type="preference",
213
+ ))
214
+
215
+ # Filter-based search
216
+ results = client.memory_search(SearchQuery(
217
+ tags=["settings", "notifications"],
218
+ from_date="2024-01-01",
219
+ to_date="2024-12-31",
220
+ limit=20,
221
+ ))
222
+ ```
223
+
224
+ #### Recall Memories
225
+
226
+ Recall returns `{ "results": [...], "total": N, "query_type": "hybrid" }`.
227
+
228
+ ```python
229
+ # Hybrid recall with profile awareness
230
+ recall = client.memory_recall(
231
+ query="what do you know about me?",
232
+ limit=10,
233
+ )
234
+ for mem in recall.get("results", []):
235
+ print(mem["content"], mem.get("relevance"))
236
+
237
+ # Thread-scoped recall
238
+ recall = client.memory_recall(
239
+ query="launch timeline",
240
+ thread_id="thread_abc123",
241
+ limit=5,
242
+ )
243
+ ```
244
+
245
+ #### Batch Create
246
+
247
+ ```python
248
+ results = client.memory_create_batch([
249
+ {"data": "First memory", "type": "journal"},
250
+ {"data": "Second memory", "type": "insight", "tags": ["important"]},
251
+ ])
252
+ ```
253
+
254
+ ### Thread Management
255
+
256
+ ```python
257
+ # Create a thread
258
+ thread = client.threads_create(
259
+ title="Customer Support Session",
260
+ metadata={"user_id": "user_123"},
261
+ )
262
+
263
+ # List threads
264
+ threads = client.threads_list(limit=10, offset=0)
265
+
266
+ # Get thread by ID (with memories)
267
+ thread = client.threads_get("thread_abc123", include_memories=True)
268
+
269
+ # Update thread
270
+ updated = client.threads_update(
271
+ "thread_abc123",
272
+ title="Resolved: Billing Issue",
273
+ status="completed",
274
+ )
275
+
276
+ # Delete thread
277
+ client.threads_delete("thread_abc123")
278
+ ```
279
+
280
+ ## Memory Types
281
+
282
+ - **journal** -- Chronological entries and logs
283
+ - **insight** -- Derived patterns and conclusions
284
+ - **observation** -- Factual, observed information
285
+ - **task** -- Action items and todos
286
+ - **preference** -- User preferences and settings
287
+
288
+ ## Error Handling
289
+
290
+ The SDK raises `SovantError` for all API errors:
291
+
292
+ ```python
293
+ from sovant import Sovant, SovantError
294
+
295
+ try:
296
+ memory = client.memory_get("invalid_id")
297
+ except SovantError as e:
298
+ print(f"Error: {e}")
299
+ print(f"Code: {e.code}") # e.g. "NOT_FOUND", "HTTP_401"
300
+ print(f"Status: {e.status}") # e.g. 404, 401
301
+
302
+ if e.status == 404:
303
+ print("Memory not found")
304
+ elif e.status == 401:
305
+ print("Invalid API key")
306
+ elif e.status == 429:
307
+ print("Rate limited -- SDK retries automatically")
308
+ ```
309
+
310
+ The SDK automatically retries on rate limit (429) and server errors (5xx) with exponential backoff.
311
+
312
+ ## Examples
313
+
314
+ ### Customer Support Integration
315
+
316
+ ```python
317
+ from sovant import MemoryCreate
318
+
319
+ # Track customer interaction
320
+ interaction = client.memory_create(MemoryCreate(
321
+ data="Customer reported slow dashboard loading",
322
+ type="observation",
323
+ thread_id=f"ticket_{ticket_id}",
324
+ tags=["support", "performance", "dashboard"],
325
+ metadata={
326
+ "ticket_id": ticket_id,
327
+ "priority": "high",
328
+ },
329
+ ))
330
+
331
+ # Record resolution
332
+ resolution = client.memory_create(MemoryCreate(
333
+ data="Resolved by clearing cache and upgrading plan",
334
+ type="insight",
335
+ thread_id=f"ticket_{ticket_id}",
336
+ tags=["support", "resolved"],
337
+ ))
338
+ ```
339
+
340
+ ### User Preference Tracking
341
+
342
+ ```python
343
+ from sovant import MemoryCreate, SearchQuery
344
+
345
+ # Store preference
346
+ client.memory_create(MemoryCreate(
347
+ data="User prefers email notifications over SMS",
348
+ type="preference",
349
+ tags=["notifications", "email"],
350
+ ))
351
+
352
+ # Query preferences
353
+ preferences = client.memory_search(SearchQuery(
354
+ query="notification preferences",
355
+ type="preference",
356
+ ))
357
+ ```
358
+
359
+ ## Rate Limiting
360
+
361
+ The API enforces 60 requests per minute. The SDK automatically retries rate-limited requests with exponential backoff. Rate limit headers are included in responses:
362
+
363
+ - `X-RateLimit-Limit` -- Request limit per window
364
+ - `X-RateLimit-Remaining` -- Remaining requests
365
+ - `X-RateLimit-Reset` -- Reset timestamp
366
+
367
+ ## Support
368
+
369
+ - Documentation: [https://sovant.ai/docs](https://sovant.ai/docs)
370
+ - Issues: [GitHub Issues](https://github.com/hechin91/sovant-ai/issues)
371
+
372
+ ## License & Use
373
+
374
+ - This SDK is MIT-licensed for integration convenience.
375
+ - The Sovant API and platform are proprietary to Sovant Technologies Sdn. Bhd.
376
+ - You may use this SDK to integrate with Sovant's hosted API.
377
+ - Hosting/redistributing the Sovant backend or any proprietary components is not permitted.
378
+
379
+ ## License
380
+
381
+ MIT -- See [LICENSE](LICENSE) file for details.
@@ -1,4 +1,4 @@
1
- sovant/__init__.py,sha256=u5rAQYbVb4cDn8QvmJB-VusRtSXzQsFH6bAJrBMvvNI,122
1
+ sovant/__init__.py,sha256=t0XgMU44um_gJBNGkg8QnaEC1SXsIh56IF2TrdDgbuY,122
2
2
  sovant/base_client.py,sha256=Vmn6OGywGwLbH5cEeflSjVOFwn5iX_YdfTdUq9pWWxA,8778
3
3
  sovant/client.py,sha256=8VnTPSli1QgRky9PqUb9OAKdbMPTfXlGoUkmAYsFfCw,11804
4
4
  sovant/exceptions.py,sha256=MQMSgk7ckXnAbe7hPPpbKOnRBHSPxuCY7WSjqfJAvd0,1557
@@ -7,8 +7,8 @@ sovant/types.py,sha256=gnvdXksJt8LObti7nc6eHSBCB7Pz7SNpS5o_HRTq_kA,6098
7
7
  sovant/resources/__init__.py,sha256=cPFIM7h8duviDdeHudnVEAmv3F89RHQxdH5BCRWFteQ,193
8
8
  sovant/resources/memories.py,sha256=bKKE0uWqFkPa1OEvbK1LrdSD7v6N04RhJ_2VDoPPQBA,11379
9
9
  sovant/resources/threads.py,sha256=mN29xP0JODmZBKyfhpeqJyViUWNVMAx3TlYAW-1ruTs,12558
10
- sovant-1.3.0.dist-info/licenses/LICENSE,sha256=rnNP6-elrMIlQ9jf2aqnHZMyyQ_wvF3y1hTpVUusCWU,1062
11
- sovant-1.3.0.dist-info/METADATA,sha256=6-_NLCFzejStKM-YRnzYNXBLh9WWoNyO4K6cYvr02W4,14201
12
- sovant-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- sovant-1.3.0.dist-info/top_level.txt,sha256=za6eVEsYd_ZQQs8vrmEWNcAR58r1wCDge_jA60e4CvQ,7
14
- sovant-1.3.0.dist-info/RECORD,,
10
+ sovant-1.3.1.dist-info/licenses/LICENSE,sha256=rnNP6-elrMIlQ9jf2aqnHZMyyQ_wvF3y1hTpVUusCWU,1062
11
+ sovant-1.3.1.dist-info/METADATA,sha256=ej271WYl3oSvAlmWRCVIjr_ebFSkgzw4-C3NVCOm01k,9515
12
+ sovant-1.3.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
+ sovant-1.3.1.dist-info/top_level.txt,sha256=za6eVEsYd_ZQQs8vrmEWNcAR58r1wCDge_jA60e4CvQ,7
14
+ sovant-1.3.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,574 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: sovant
3
- Version: 1.3.0
4
- Summary: Sovant Memory-as-a-Service Python SDK
5
- Author: Sovant
6
- License: MIT
7
- Project-URL: Documentation, https://sovant.ai/docs
8
- Project-URL: Source, https://github.com/hechin91/sovant-ai
9
- Project-URL: Tracker, https://github.com/hechin91/sovant-ai/issues
10
- Requires-Python: >=3.10
11
- Description-Content-Type: text/markdown
12
- License-File: LICENSE
13
- Requires-Dist: httpx>=0.27.0
14
- Requires-Dist: pydantic>=2.8.2
15
- Dynamic: license-file
16
-
17
- # Sovant Python SDK
18
-
19
- **Sovant is a governed AI memory layer for AI agents and applications.**
20
- Use it to store, search, and recall memories with profile awareness and enterprise-grade control over how memory is captured and used.
21
-
22
- [![PyPI version](https://img.shields.io/pypi/v/sovant.svg)](https://pypi.org/project/sovant/)
23
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
24
-
25
- ## Installation
26
-
27
- ```bash
28
- pip install sovant
29
- ```
30
-
31
- ## Quick Start
32
-
33
- ```python
34
- from sovant import Sovant
35
-
36
- # Initialize the client
37
- client = Sovant(api_key="sk_live_your_api_key_here", base_url="https://sovant.ai")
38
-
39
- # Create a memory
40
- mem = client.memory.create({
41
- "content": "User prefers dark mode",
42
- "type": "preference",
43
- "tags": ["ui", "settings"]
44
- })
45
-
46
- # Search memories
47
- results = client.memory.search({
48
- "query": "user preferences",
49
- "limit": 10
50
- })
51
-
52
- # Update a memory
53
- updated = client.memory.update(mem["id"], {
54
- "tags": ["ui", "settings", "theme"]
55
- })
56
-
57
- # Delete a memory
58
- client.memory.delete(mem["id"])
59
- ```
60
-
61
- ## Recall vs Search
62
-
63
- Sovant provides two ways to query memories:
64
-
65
- - **`memory_recall()`** – Hybrid recall, profile-aware
66
- Use for conversational queries: "What do you know about me?", "What happened on Project X?".
67
- Uses Sovant's hybrid pipeline (profile fast-path + thread-scoped lexical + vector semantic search) and prioritizes profile facts (name/age/location) when available.
68
-
69
- - **`memory_search()`** – Semantic search
70
- Use for topic lookup and discovery. Pure vector similarity search without profile logic.
71
- Behavior unchanged from previous versions.
72
-
73
- ```python
74
- # Recall for conversational queries
75
- context = client.memory_recall(
76
- query="what do you know about me?",
77
- limit=10
78
- )
79
-
80
- # Search for topic discovery
81
- topics = client.memory_search({
82
- "query": "project updates",
83
- "limit": 5
84
- })
85
- ```
86
-
87
- ## Working with Threads
88
-
89
- Threads let you organize related memories into conversations or sessions. Each thread has a `title` and can contain multiple memories.
90
-
91
- ```python
92
- from sovant import Sovant
93
-
94
- client = Sovant(api_key="sk_live_your_api_key_here")
95
-
96
- # Create a new thread
97
- thread = client.threads_create(
98
- title="Project Alpha Discussion",
99
- description="Q1 planning meeting notes",
100
- metadata={"project": "alpha", "quarter": "Q1"}
101
- )
102
-
103
- # Store memories in the thread
104
- from sovant.models import MemoryCreate
105
-
106
- mem1 = client.memory_create(MemoryCreate(
107
- data="Decided to launch in March",
108
- type="journal",
109
- thread_id=thread["id"]
110
- ))
111
-
112
- mem2 = client.memory_create(MemoryCreate(
113
- data="Budget approved: $50k",
114
- type="insight",
115
- thread_id=thread["id"]
116
- ))
117
-
118
- # Recall memories from this specific thread
119
- thread_memories = client.memory_recall(
120
- query="launch date",
121
- thread_id=thread["id"],
122
- limit=10
123
- )
124
-
125
- # Get thread with all its memories
126
- thread_with_memories = client.threads_get(
127
- thread["id"],
128
- include_memories=True,
129
- limit=50
130
- )
131
-
132
- # List all threads
133
- threads = client.threads_list(limit=20, offset=0)
134
-
135
- # Update thread
136
- updated = client.threads_update(
137
- thread["id"],
138
- title="Project Alpha - Q1 Launch",
139
- status="completed"
140
- )
141
-
142
- # Delete thread (keeps memories by default)
143
- client.threads_delete(thread["id"])
144
-
145
- # Delete thread AND all its memories
146
- client.threads_delete(thread["id"], delete_memories=True)
147
- ```
148
-
149
- ## Chat in 60 Seconds
150
-
151
- Stream real-time chat responses with memory context:
152
-
153
- ```python
154
- from sovant import Sovant
155
- import sys
156
-
157
- client = Sovant(api_key="sk_live_your_api_key_here", base_url="https://sovant.ai")
158
-
159
- # Create a chat session
160
- session = client.chat.create_session({"title": "Demo"})
161
-
162
- # Stream a response
163
- stream = client.chat.send_message(
164
- session["id"],
165
- "hello",
166
- {
167
- "provider": "openai",
168
- "model": "gpt-4o-mini",
169
- "use_memory": True
170
- },
171
- stream=True
172
- )
173
-
174
- for ev in stream:
175
- if ev["type"] == "delta":
176
- sys.stdout.write(ev.get("data", ""))
177
- elif ev["type"] == "done":
178
- print("\n[done]")
179
-
180
- # Get chat history
181
- messages = client.chat.get_messages(session["id"])
182
- ```
183
-
184
- ## Profile Recall Helpers
185
-
186
- Save and recall user profile facts with canonical patterns:
187
-
188
- ```python
189
- # Extract profile entity from text
190
- fact = client.recall.extract_profile("i'm from kuching")
191
- # -> {"entity": "location", "value": "kuching"} | None
192
-
193
- if fact:
194
- client.recall.save_profile_fact(fact) # canonicalizes and persists
195
-
196
- # Get all profile facts
197
- profile = client.recall.get_profile_facts()
198
- # -> {"name": "...", "age": "...", "location": "...", "preferences": [...]}
199
- ```
200
-
201
- ## Configuration
202
-
203
- ```python
204
- from sovant import Sovant
205
-
206
- client = Sovant(
207
- api_key="sk_live_your_api_key_here", # Required
208
- base_url="https://sovant.ai", # Optional, API endpoint
209
- timeout=30.0, # Optional, request timeout in seconds (default: 30.0)
210
- max_retries=3, # Optional, max retry attempts (default: 3)
211
- debug=False, # Optional, enable debug logging (default: False)
212
- )
213
- ```
214
-
215
- The SDK handles dual authentication automatically, preferring the `x-sovant-api-key` header over `Authorization: Bearer`.
216
-
217
- ## API Reference
218
-
219
- ### Memory Operations
220
-
221
- #### Create Memory
222
-
223
- ```python
224
- memory = client.memory.create({
225
- "content": "Customer contacted support about billing",
226
- "type": "observation", # 'journal' | 'insight' | 'observation' | 'task' | 'preference'
227
- "tags": ["support", "billing"],
228
- "metadata": {"ticket_id": "12345"},
229
- "thread_id": "thread_abc123", # Optional thread association
230
- })
231
- ```
232
-
233
- #### List Memories
234
-
235
- ```python
236
- memories = client.memory.list({
237
- "limit": 20, # Max items per page (default: 20)
238
- "offset": 0, # Pagination offset
239
- "tags": ["billing"], # Filter by tags
240
- "type": "observation", # Filter by type
241
- "is_archived": False, # Filter archived status
242
- })
243
-
244
- print(memories["memories"]) # Array of memories
245
- print(memories["total"]) # Total count
246
- print(memories["has_more"]) # More pages available
247
- ```
248
-
249
- #### Get Memory by ID
250
-
251
- ```python
252
- memory = client.memory.get("mem_123abc")
253
- ```
254
-
255
- #### Update Memory (Partial)
256
-
257
- ```python
258
- updated = client.memory.update("mem_123abc", {
259
- "tags": ["support", "billing", "resolved"],
260
- "metadata": {
261
- **memory.get("metadata", {}),
262
- "resolved": True,
263
- },
264
- "is_archived": True,
265
- })
266
- ```
267
-
268
- #### Replace Memory (Full)
269
-
270
- ```python
271
- replaced = client.memory.put("mem_123abc", {
272
- "content": "Updated content here", # Required for PUT
273
- "type": "observation",
274
- "tags": ["updated"],
275
- })
276
- ```
277
-
278
- #### Delete Memory
279
-
280
- ```python
281
- client.memory.delete("mem_123abc")
282
- ```
283
-
284
- #### Search Memories
285
-
286
- ```python
287
- # Semantic search
288
- semantic_results = client.memory.search({
289
- "query": "customer preferences about notifications",
290
- "limit": 10,
291
- "type": "preference",
292
- })
293
-
294
- # Filter-based search
295
- filter_results = client.memory.search({
296
- "tags": ["settings", "notifications"],
297
- "from_date": "2024-01-01",
298
- "to_date": "2024-12-31",
299
- "limit": 20,
300
- })
301
- ```
302
-
303
- #### Batch Operations
304
-
305
- ```python
306
- batch = client.memory.batch({
307
- "operations": [
308
- {
309
- "op": "create",
310
- "data": {
311
- "content": "First memory",
312
- "type": "journal",
313
- },
314
- },
315
- {
316
- "op": "update",
317
- "id": "mem_123abc",
318
- "data": {
319
- "tags": ["updated"],
320
- },
321
- },
322
- {
323
- "op": "delete",
324
- "id": "mem_456def",
325
- },
326
- ],
327
- })
328
-
329
- print(batch["results"]) # Individual operation results
330
- print(batch["summary"]) # Summary statistics
331
- ```
332
-
333
- ### Thread Management
334
-
335
- Associate memories with conversation threads:
336
-
337
- ```python
338
- # Create a thread
339
- thread = client.threads.create({
340
- "title": "Customer Support Session",
341
- "metadata": {"user_id": "user_123"}
342
- })
343
-
344
- # List threads
345
- threads = client.threads.list({
346
- "limit": 10,
347
- "offset": 0
348
- })
349
-
350
- # Get thread by ID
351
- thread = client.threads.get("thread_abc123")
352
-
353
- # Update thread
354
- updated_thread = client.threads.update("thread_abc123", {
355
- "title": "Resolved: Billing Issue",
356
- "metadata": {"status": "resolved"}
357
- })
358
-
359
- # Delete thread
360
- client.threads.delete("thread_abc123")
361
-
362
- # Link memory to thread
363
- client.threads.link_memory("thread_abc123", "mem_123abc")
364
-
365
- # Create memories within a thread
366
- memory1 = client.memory.create({
367
- "content": "User asked about pricing",
368
- "type": "observation",
369
- "thread_id": "thread_abc123",
370
- })
371
-
372
- memory2 = client.memory.create({
373
- "content": "User selected enterprise plan",
374
- "type": "observation",
375
- "thread_id": "thread_abc123",
376
- })
377
-
378
- # List memories in a thread
379
- thread_memories = client.memory.list({
380
- "thread_id": "thread_abc123",
381
- })
382
- ```
383
-
384
- ### API Key Management
385
-
386
- Manage API keys programmatically:
387
-
388
- ```python
389
- # List all API keys
390
- keys = client.keys.list()
391
- print(keys) # Array of key objects
392
-
393
- # Create a new API key
394
- new_key = client.keys.create({"name": "CI key"})
395
- print(new_key["key"]) # The actual secret key (only shown once!)
396
-
397
- # Update key metadata
398
- client.keys.update(new_key["id"], {"name": "Production key"})
399
-
400
- # Revoke a key
401
- client.keys.revoke(new_key["id"])
402
- ```
403
-
404
- ## Memory Types
405
-
406
- - **journal** - Chronological entries and logs
407
- - **insight** - Derived patterns and conclusions
408
- - **observation** - Factual, observed information
409
- - **task** - Action items and todos
410
- - **preference** - User preferences and settings
411
-
412
- ## Error Handling
413
-
414
- The SDK provides typed errors for better error handling:
415
-
416
- ```python
417
- from sovant import Sovant, SovantError, AuthError, RateLimitError, NetworkError, TimeoutError
418
-
419
- try:
420
- memory = client.memory.get("invalid_id")
421
- except AuthError as e:
422
- print(f"Authentication failed: {e}")
423
- # Handle authentication error
424
- except RateLimitError as e:
425
- print(f"Rate limit exceeded: {e}")
426
- print(f"Retry after: {e.retry_after}")
427
- # Handle rate limiting
428
- except NetworkError as e:
429
- print(f"Network error: {e}")
430
- # Handle network issues
431
- except TimeoutError as e:
432
- print(f"Request timed out: {e}")
433
- # Handle timeout
434
- except SovantError as e:
435
- print(f"API Error: {e}")
436
- print(f"Status: {e.status}")
437
- print(f"Request ID: {e.request_id}")
438
-
439
- if e.status == 404:
440
- # Handle not found
441
- pass
442
- elif e.status == 400:
443
- # Handle bad request
444
- pass
445
- ```
446
-
447
- ## Advanced Features
448
-
449
- ### Retry Configuration
450
-
451
- The SDK automatically retries failed requests with exponential backoff:
452
-
453
- ```python
454
- client = Sovant(
455
- api_key="sk_live_...",
456
- max_retries=5, # Increase retry attempts
457
- timeout=60.0, # Increase timeout for slow connections
458
- )
459
- ```
460
-
461
- ### Debug Mode
462
-
463
- Enable debug logging to see detailed request/response information:
464
-
465
- ```python
466
- client = Sovant(
467
- api_key="sk_live_...",
468
- debug=True, # Enable debug output
469
- )
470
- ```
471
-
472
- ### Custom Base URL
473
-
474
- Connect to different environments:
475
-
476
- ```python
477
- client = Sovant(
478
- api_key="sk_live_...",
479
- base_url="https://staging.sovant.ai",
480
- )
481
- ```
482
-
483
- ## Best Practices
484
-
485
- 1. **Use appropriate memory types** - Choose the correct type for your use case
486
- 2. **Add meaningful tags** - Tags improve searchability and organization
487
- 3. **Use threads** - Group related memories together
488
- 4. **Handle errors gracefully** - Implement proper error handling
489
- 5. **Batch operations** - Use batch API for multiple operations
490
- 6. **Archive don't delete** - Consider archiving instead of deleting
491
-
492
- ## Examples
493
-
494
- ### Customer Support Integration
495
-
496
- ```python
497
- # Track customer interaction
498
- interaction = client.memory.create({
499
- "content": "Customer reported slow dashboard loading",
500
- "type": "observation",
501
- "thread_id": f"ticket_{ticket_id}",
502
- "tags": ["support", "performance", "dashboard"],
503
- "metadata": {
504
- "ticket_id": ticket_id,
505
- "customer_id": customer_id,
506
- "priority": "high",
507
- },
508
- })
509
-
510
- # Record resolution
511
- resolution = client.memory.create({
512
- "content": "Resolved by clearing cache and upgrading plan",
513
- "type": "insight",
514
- "thread_id": f"ticket_{ticket_id}",
515
- "tags": ["support", "resolved"],
516
- "metadata": {
517
- "ticket_id": ticket_id,
518
- "resolution_time": "2h",
519
- },
520
- })
521
- ```
522
-
523
- ### User Preference Tracking
524
-
525
- ```python
526
- # Store preference
527
- preference = client.memory.create({
528
- "content": "User prefers email notifications over SMS",
529
- "type": "preference",
530
- "tags": ["notifications", "email", "settings"],
531
- "metadata": {
532
- "user_id": user_id,
533
- "setting": "notification_channel",
534
- "value": "email",
535
- },
536
- })
537
-
538
- # Query preferences
539
- preferences = client.memory.search({
540
- "query": "notification preferences",
541
- "type": "preference",
542
- "tags": ["notifications"],
543
- })
544
- ```
545
-
546
- ## Rate Limiting
547
-
548
- The API implements rate limiting. The SDK automatically handles rate limit responses with retries. Rate limit headers are included in responses:
549
-
550
- - `X-RateLimit-Limit` - Request limit per window
551
- - `X-RateLimit-Remaining` - Remaining requests
552
- - `X-RateLimit-Reset` - Reset timestamp
553
-
554
- ## Support
555
-
556
- - Documentation: [https://sovant.ai/docs](https://sovant.ai/docs)
557
- - API/Auth docs: [https://sovant.ai/docs/security/auth](https://sovant.ai/docs/security/auth)
558
- - Issues: [GitHub Issues](https://github.com/sovant-ai/python-sdk/issues)
559
- - Support: support@sovant.ai
560
-
561
- ## Changelog
562
-
563
- See [CHANGELOG.md](./CHANGELOG.md) for a detailed history of changes.
564
-
565
- ## License & Use
566
-
567
- - This SDK is MIT-licensed for integration convenience.
568
- - The Sovant API and platform are proprietary to Sovant Technologies Sdn. Bhd.
569
- - You may use this SDK to integrate with Sovant's hosted API.
570
- - Hosting/redistributing the Sovant backend or any proprietary components is not permitted.
571
-
572
- ## License
573
-
574
- MIT - See [LICENSE](LICENSE) file for details.