sovant 1.3.0__tar.gz → 1.3.2__tar.gz
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-1.3.2/PKG-INFO +417 -0
- sovant-1.3.2/README.md +401 -0
- {sovant-1.3.0 → sovant-1.3.2}/pyproject.toml +3 -3
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/__init__.py +1 -1
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/client.py +55 -0
- sovant-1.3.2/src/sovant.egg-info/PKG-INFO +417 -0
- sovant-1.3.0/PKG-INFO +0 -574
- sovant-1.3.0/README.md +0 -558
- sovant-1.3.0/src/sovant.egg-info/PKG-INFO +0 -574
- {sovant-1.3.0 → sovant-1.3.2}/LICENSE +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/MANIFEST.in +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/setup.cfg +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/base_client.py +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/exceptions.py +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/models.py +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/resources/__init__.py +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/resources/memories.py +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/resources/threads.py +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant/types.py +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant.egg-info/SOURCES.txt +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant.egg-info/dependency_links.txt +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant.egg-info/requires.txt +0 -0
- {sovant-1.3.0 → sovant-1.3.2}/src/sovant.egg-info/top_level.txt +0 -0
sovant-1.3.2/PKG-INFO
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sovant
|
|
3
|
+
Version: 1.3.2
|
|
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
|
+
[](https://pypi.org/project/sovant/)
|
|
23
|
+
[](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
|
+
#### List Memories
|
|
255
|
+
|
|
256
|
+
Fetch memories with filtering and pagination. Use `memory_list()` to retrieve recent memories or filter by criteria — it's more efficient than `memory_search()` when you don't need vector similarity.
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
# List recent memories
|
|
260
|
+
result = client.memory_list(limit=20, offset=0)
|
|
261
|
+
for mem in result["memories"]:
|
|
262
|
+
print(mem["content"])
|
|
263
|
+
|
|
264
|
+
# Filter by thread
|
|
265
|
+
thread_mems = client.memory_list(thread_id="thread-uuid", limit=50)
|
|
266
|
+
|
|
267
|
+
# Filter by type and tags
|
|
268
|
+
prefs = client.memory_list(
|
|
269
|
+
type="preference",
|
|
270
|
+
tags=["settings"],
|
|
271
|
+
sort_by="updated_at",
|
|
272
|
+
sort_order="desc",
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# Pinned memories only
|
|
276
|
+
pinned = client.memory_list(is_pinned=True)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Available parameters:**
|
|
280
|
+
- `limit` — max results (default: 20, max: 100)
|
|
281
|
+
- `offset` — pagination offset
|
|
282
|
+
- `thread_id` — filter by thread
|
|
283
|
+
- `type` — filter by memory type
|
|
284
|
+
- `tags` — filter by tags (must have all)
|
|
285
|
+
- `is_pinned` — filter by pinned status
|
|
286
|
+
- `is_archived` — filter by archived status
|
|
287
|
+
- `sort_by` — `created_at`, `updated_at`, `importance`, or `type`
|
|
288
|
+
- `sort_order` — `asc` or `desc`
|
|
289
|
+
|
|
290
|
+
### Thread Management
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
# Create a thread
|
|
294
|
+
thread = client.threads_create(
|
|
295
|
+
title="Customer Support Session",
|
|
296
|
+
metadata={"user_id": "user_123"},
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# List threads
|
|
300
|
+
threads = client.threads_list(limit=10, offset=0)
|
|
301
|
+
|
|
302
|
+
# Get thread by ID (with memories)
|
|
303
|
+
thread = client.threads_get("thread_abc123", include_memories=True)
|
|
304
|
+
|
|
305
|
+
# Update thread
|
|
306
|
+
updated = client.threads_update(
|
|
307
|
+
"thread_abc123",
|
|
308
|
+
title="Resolved: Billing Issue",
|
|
309
|
+
status="completed",
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
# Delete thread
|
|
313
|
+
client.threads_delete("thread_abc123")
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Memory Types
|
|
317
|
+
|
|
318
|
+
- **journal** -- Chronological entries and logs
|
|
319
|
+
- **insight** -- Derived patterns and conclusions
|
|
320
|
+
- **observation** -- Factual, observed information
|
|
321
|
+
- **task** -- Action items and todos
|
|
322
|
+
- **preference** -- User preferences and settings
|
|
323
|
+
|
|
324
|
+
## Error Handling
|
|
325
|
+
|
|
326
|
+
The SDK raises `SovantError` for all API errors:
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
from sovant import Sovant, SovantError
|
|
330
|
+
|
|
331
|
+
try:
|
|
332
|
+
memory = client.memory_get("invalid_id")
|
|
333
|
+
except SovantError as e:
|
|
334
|
+
print(f"Error: {e}")
|
|
335
|
+
print(f"Code: {e.code}") # e.g. "NOT_FOUND", "HTTP_401"
|
|
336
|
+
print(f"Status: {e.status}") # e.g. 404, 401
|
|
337
|
+
|
|
338
|
+
if e.status == 404:
|
|
339
|
+
print("Memory not found")
|
|
340
|
+
elif e.status == 401:
|
|
341
|
+
print("Invalid API key")
|
|
342
|
+
elif e.status == 429:
|
|
343
|
+
print("Rate limited -- SDK retries automatically")
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
The SDK automatically retries on rate limit (429) and server errors (5xx) with exponential backoff.
|
|
347
|
+
|
|
348
|
+
## Examples
|
|
349
|
+
|
|
350
|
+
### Customer Support Integration
|
|
351
|
+
|
|
352
|
+
```python
|
|
353
|
+
from sovant import MemoryCreate
|
|
354
|
+
|
|
355
|
+
# Track customer interaction
|
|
356
|
+
interaction = client.memory_create(MemoryCreate(
|
|
357
|
+
data="Customer reported slow dashboard loading",
|
|
358
|
+
type="observation",
|
|
359
|
+
thread_id=f"ticket_{ticket_id}",
|
|
360
|
+
tags=["support", "performance", "dashboard"],
|
|
361
|
+
metadata={
|
|
362
|
+
"ticket_id": ticket_id,
|
|
363
|
+
"priority": "high",
|
|
364
|
+
},
|
|
365
|
+
))
|
|
366
|
+
|
|
367
|
+
# Record resolution
|
|
368
|
+
resolution = client.memory_create(MemoryCreate(
|
|
369
|
+
data="Resolved by clearing cache and upgrading plan",
|
|
370
|
+
type="insight",
|
|
371
|
+
thread_id=f"ticket_{ticket_id}",
|
|
372
|
+
tags=["support", "resolved"],
|
|
373
|
+
))
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### User Preference Tracking
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
from sovant import MemoryCreate, SearchQuery
|
|
380
|
+
|
|
381
|
+
# Store preference
|
|
382
|
+
client.memory_create(MemoryCreate(
|
|
383
|
+
data="User prefers email notifications over SMS",
|
|
384
|
+
type="preference",
|
|
385
|
+
tags=["notifications", "email"],
|
|
386
|
+
))
|
|
387
|
+
|
|
388
|
+
# Query preferences
|
|
389
|
+
preferences = client.memory_search(SearchQuery(
|
|
390
|
+
query="notification preferences",
|
|
391
|
+
type="preference",
|
|
392
|
+
))
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Rate Limiting
|
|
396
|
+
|
|
397
|
+
The API enforces 60 requests per minute. The SDK automatically retries rate-limited requests with exponential backoff. Rate limit headers are included in responses:
|
|
398
|
+
|
|
399
|
+
- `X-RateLimit-Limit` -- Request limit per window
|
|
400
|
+
- `X-RateLimit-Remaining` -- Remaining requests
|
|
401
|
+
- `X-RateLimit-Reset` -- Reset timestamp
|
|
402
|
+
|
|
403
|
+
## Support
|
|
404
|
+
|
|
405
|
+
- Documentation: [https://sovant.ai/docs](https://sovant.ai/docs)
|
|
406
|
+
- Issues: [GitHub Issues](https://github.com/hechin91/sovant-ai/issues)
|
|
407
|
+
|
|
408
|
+
## License & Use
|
|
409
|
+
|
|
410
|
+
- This SDK is MIT-licensed for integration convenience.
|
|
411
|
+
- The Sovant API and platform are proprietary to Sovant Technologies Sdn. Bhd.
|
|
412
|
+
- You may use this SDK to integrate with Sovant's hosted API.
|
|
413
|
+
- Hosting/redistributing the Sovant backend or any proprietary components is not permitted.
|
|
414
|
+
|
|
415
|
+
## License
|
|
416
|
+
|
|
417
|
+
MIT -- See [LICENSE](LICENSE) file for details.
|