Sovant Memory-as-a-Service Python SDK
Project description
Sovant Python SDK
Sovant is a governed AI memory layer for AI agents and applications. Use it to store, search, and recall memories with profile awareness and enterprise-grade control over how memory is captured and used.
Installation
pip install sovant
Quick Start
from sovant import Sovant
# Initialize the client
client = Sovant(api_key="sk_live_your_api_key_here", base_url="https://sovant.ai")
# Create a memory
mem = client.memory.create({
"content": "User prefers dark mode",
"type": "preference",
"tags": ["ui", "settings"]
})
# Search memories
results = client.memory.search({
"query": "user preferences",
"limit": 10
})
# Update a memory
updated = client.memory.update(mem["id"], {
"tags": ["ui", "settings", "theme"]
})
# Delete a memory
client.memory.delete(mem["id"])
Recall vs Search
Sovant provides two ways to query memories:
-
memory_recall()– Hybrid recall, profile-aware Use for conversational queries: "What do you know about me?", "What happened on Project X?". Uses Sovant's hybrid pipeline (profile fast-path + thread-scoped lexical + vector semantic search) and prioritizes profile facts (name/age/location) when available. -
memory_search()– Semantic search Use for topic lookup and discovery. Pure vector similarity search without profile logic. Behavior unchanged from previous versions.
# Recall for conversational queries
context = client.memory_recall(
query="what do you know about me?",
limit=10
)
# Search for topic discovery
topics = client.memory_search({
"query": "project updates",
"limit": 5
})
Working with Threads
Threads let you organize related memories into conversations or sessions. Each thread has a title and can contain multiple memories.
from sovant import Sovant
client = Sovant(api_key="sk_live_your_api_key_here")
# Create a new thread
thread = client.threads_create(
title="Project Alpha Discussion",
description="Q1 planning meeting notes",
metadata={"project": "alpha", "quarter": "Q1"}
)
# Store memories in the thread
from sovant.models import MemoryCreate
mem1 = client.memory_create(MemoryCreate(
data="Decided to launch in March",
type="journal",
thread_id=thread["id"]
))
mem2 = client.memory_create(MemoryCreate(
data="Budget approved: $50k",
type="insight",
thread_id=thread["id"]
))
# Recall memories from this specific thread
thread_memories = client.memory_recall(
query="launch date",
thread_id=thread["id"],
limit=10
)
# Get thread with all its memories
thread_with_memories = client.threads_get(
thread["id"],
include_memories=True,
limit=50
)
# List all threads
threads = client.threads_list(limit=20, offset=0)
# Update thread
updated = client.threads_update(
thread["id"],
title="Project Alpha - Q1 Launch",
status="completed"
)
# Delete thread (keeps memories by default)
client.threads_delete(thread["id"])
# Delete thread AND all its memories
client.threads_delete(thread["id"], delete_memories=True)
Chat in 60 Seconds
Stream real-time chat responses with memory context:
from sovant import Sovant
import sys
client = Sovant(api_key="sk_live_your_api_key_here", base_url="https://sovant.ai")
# Create a chat session
session = client.chat.create_session({"title": "Demo"})
# Stream a response
stream = client.chat.send_message(
session["id"],
"hello",
{
"provider": "openai",
"model": "gpt-4o-mini",
"use_memory": True
},
stream=True
)
for ev in stream:
if ev["type"] == "delta":
sys.stdout.write(ev.get("data", ""))
elif ev["type"] == "done":
print("\n[done]")
# Get chat history
messages = client.chat.get_messages(session["id"])
Profile Recall Helpers
Save and recall user profile facts with canonical patterns:
# Extract profile entity from text
fact = client.recall.extract_profile("i'm from kuching")
# -> {"entity": "location", "value": "kuching"} | None
if fact:
client.recall.save_profile_fact(fact) # canonicalizes and persists
# Get all profile facts
profile = client.recall.get_profile_facts()
# -> {"name": "...", "age": "...", "location": "...", "preferences": [...]}
Configuration
from sovant import Sovant
client = Sovant(
api_key="sk_live_your_api_key_here", # Required
base_url="https://sovant.ai", # Optional, API endpoint
timeout=30.0, # Optional, request timeout in seconds (default: 30.0)
max_retries=3, # Optional, max retry attempts (default: 3)
debug=False, # Optional, enable debug logging (default: False)
)
The SDK handles dual authentication automatically, preferring the x-sovant-api-key header over Authorization: Bearer.
API Reference
Memory Operations
Create Memory
memory = client.memory.create({
"content": "Customer contacted support about billing",
"type": "observation", # 'journal' | 'insight' | 'observation' | 'task' | 'preference'
"tags": ["support", "billing"],
"metadata": {"ticket_id": "12345"},
"thread_id": "thread_abc123", # Optional thread association
})
List Memories
memories = client.memory.list({
"limit": 20, # Max items per page (default: 20)
"offset": 0, # Pagination offset
"tags": ["billing"], # Filter by tags
"type": "observation", # Filter by type
"is_archived": False, # Filter archived status
})
print(memories["memories"]) # Array of memories
print(memories["total"]) # Total count
print(memories["has_more"]) # More pages available
Get Memory by ID
memory = client.memory.get("mem_123abc")
Update Memory (Partial)
updated = client.memory.update("mem_123abc", {
"tags": ["support", "billing", "resolved"],
"metadata": {
**memory.get("metadata", {}),
"resolved": True,
},
"is_archived": True,
})
Replace Memory (Full)
replaced = client.memory.put("mem_123abc", {
"content": "Updated content here", # Required for PUT
"type": "observation",
"tags": ["updated"],
})
Delete Memory
client.memory.delete("mem_123abc")
Search Memories
# Semantic search
semantic_results = client.memory.search({
"query": "customer preferences about notifications",
"limit": 10,
"type": "preference",
})
# Filter-based search
filter_results = client.memory.search({
"tags": ["settings", "notifications"],
"from_date": "2024-01-01",
"to_date": "2024-12-31",
"limit": 20,
})
Batch Operations
batch = client.memory.batch({
"operations": [
{
"op": "create",
"data": {
"content": "First memory",
"type": "journal",
},
},
{
"op": "update",
"id": "mem_123abc",
"data": {
"tags": ["updated"],
},
},
{
"op": "delete",
"id": "mem_456def",
},
],
})
print(batch["results"]) # Individual operation results
print(batch["summary"]) # Summary statistics
Thread Management
Associate memories with conversation threads:
# Create a thread
thread = client.threads.create({
"title": "Customer Support Session",
"metadata": {"user_id": "user_123"}
})
# List threads
threads = client.threads.list({
"limit": 10,
"offset": 0
})
# Get thread by ID
thread = client.threads.get("thread_abc123")
# Update thread
updated_thread = client.threads.update("thread_abc123", {
"title": "Resolved: Billing Issue",
"metadata": {"status": "resolved"}
})
# Delete thread
client.threads.delete("thread_abc123")
# Link memory to thread
client.threads.link_memory("thread_abc123", "mem_123abc")
# Create memories within a thread
memory1 = client.memory.create({
"content": "User asked about pricing",
"type": "observation",
"thread_id": "thread_abc123",
})
memory2 = client.memory.create({
"content": "User selected enterprise plan",
"type": "observation",
"thread_id": "thread_abc123",
})
# List memories in a thread
thread_memories = client.memory.list({
"thread_id": "thread_abc123",
})
API Key Management
Manage API keys programmatically:
# List all API keys
keys = client.keys.list()
print(keys) # Array of key objects
# Create a new API key
new_key = client.keys.create({"name": "CI key"})
print(new_key["key"]) # The actual secret key (only shown once!)
# Update key metadata
client.keys.update(new_key["id"], {"name": "Production key"})
# Revoke a key
client.keys.revoke(new_key["id"])
Memory Types
- journal - Chronological entries and logs
- insight - Derived patterns and conclusions
- observation - Factual, observed information
- task - Action items and todos
- preference - User preferences and settings
Error Handling
The SDK provides typed errors for better error handling:
from sovant import Sovant, SovantError, AuthError, RateLimitError, NetworkError, TimeoutError
try:
memory = client.memory.get("invalid_id")
except AuthError as e:
print(f"Authentication failed: {e}")
# Handle authentication error
except RateLimitError as e:
print(f"Rate limit exceeded: {e}")
print(f"Retry after: {e.retry_after}")
# Handle rate limiting
except NetworkError as e:
print(f"Network error: {e}")
# Handle network issues
except TimeoutError as e:
print(f"Request timed out: {e}")
# Handle timeout
except SovantError as e:
print(f"API Error: {e}")
print(f"Status: {e.status}")
print(f"Request ID: {e.request_id}")
if e.status == 404:
# Handle not found
pass
elif e.status == 400:
# Handle bad request
pass
Advanced Features
Retry Configuration
The SDK automatically retries failed requests with exponential backoff:
client = Sovant(
api_key="sk_live_...",
max_retries=5, # Increase retry attempts
timeout=60.0, # Increase timeout for slow connections
)
Debug Mode
Enable debug logging to see detailed request/response information:
client = Sovant(
api_key="sk_live_...",
debug=True, # Enable debug output
)
Custom Base URL
Connect to different environments:
client = Sovant(
api_key="sk_live_...",
base_url="https://staging.sovant.ai",
)
Best Practices
- Use appropriate memory types - Choose the correct type for your use case
- Add meaningful tags - Tags improve searchability and organization
- Use threads - Group related memories together
- Handle errors gracefully - Implement proper error handling
- Batch operations - Use batch API for multiple operations
- Archive don't delete - Consider archiving instead of deleting
Examples
Customer Support Integration
# Track customer interaction
interaction = client.memory.create({
"content": "Customer reported slow dashboard loading",
"type": "observation",
"thread_id": f"ticket_{ticket_id}",
"tags": ["support", "performance", "dashboard"],
"metadata": {
"ticket_id": ticket_id,
"customer_id": customer_id,
"priority": "high",
},
})
# Record resolution
resolution = client.memory.create({
"content": "Resolved by clearing cache and upgrading plan",
"type": "insight",
"thread_id": f"ticket_{ticket_id}",
"tags": ["support", "resolved"],
"metadata": {
"ticket_id": ticket_id,
"resolution_time": "2h",
},
})
User Preference Tracking
# Store preference
preference = client.memory.create({
"content": "User prefers email notifications over SMS",
"type": "preference",
"tags": ["notifications", "email", "settings"],
"metadata": {
"user_id": user_id,
"setting": "notification_channel",
"value": "email",
},
})
# Query preferences
preferences = client.memory.search({
"query": "notification preferences",
"type": "preference",
"tags": ["notifications"],
})
Rate Limiting
The API implements rate limiting. The SDK automatically handles rate limit responses with retries. Rate limit headers are included in responses:
X-RateLimit-Limit- Request limit per windowX-RateLimit-Remaining- Remaining requestsX-RateLimit-Reset- Reset timestamp
Support
- Documentation: https://sovant.ai/docs
- API/Auth docs: https://sovant.ai/docs/security/auth
- Issues: GitHub Issues
- Support: support@sovant.ai
Changelog
See CHANGELOG.md for a detailed history of changes.
License & Use
- This SDK is MIT-licensed for integration convenience.
- The Sovant API and platform are proprietary to Sovant Technologies Sdn. Bhd.
- You may use this SDK to integrate with Sovant's hosted API.
- Hosting/redistributing the Sovant backend or any proprietary components is not permitted.
License
MIT - See LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sovant-1.3.0.tar.gz.
File metadata
- Download URL: sovant-1.3.0.tar.gz
- Upload date:
- Size: 20.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7380a5c75bd033dca7f6529ea361cc3138b4c86e42c1f97440a2b73139aed8f9
|
|
| MD5 |
83fefe5dfbed4884607b103962bdf464
|
|
| BLAKE2b-256 |
2088aab1bdde3c443f0af45e25faa0c264558f883324c65df0dc9ba1b795820d
|
File details
Details for the file sovant-1.3.0-py3-none-any.whl.
File metadata
- Download URL: sovant-1.3.0-py3-none-any.whl
- Upload date:
- Size: 18.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14c0c3c267aab78fe6a49e76ae80616341d6f9e9cb35ef9750dc888cdb20ba4c
|
|
| MD5 |
d95f32a7c2797a7b892989f86c2d194a
|
|
| BLAKE2b-256 |
829bf27f42401fd684df8b180fdf8466bf0b4b56a8aafeb8996e1719d4489bd0
|