Skip to main content

Sovant Memory-as-a-Service Python SDK

Project description

Sovant Python SDK

Sovant is Memory-as-a-Service: a durable, queryable memory layer for AI apps with cross-model recall, hybrid (semantic + deterministic) retrieval, and simple SDKs.

PyPI version License: MIT

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"])

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

  1. Use appropriate memory types - Choose the correct type for your use case
  2. Add meaningful tags - Tags improve searchability and organization
  3. Use threads - Group related memories together
  4. Handle errors gracefully - Implement proper error handling
  5. Batch operations - Use batch API for multiple operations
  6. 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 window
  • X-RateLimit-Remaining - Remaining requests
  • X-RateLimit-Reset - Reset timestamp

Support

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sovant-1.1.0.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sovant-1.1.0-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

Details for the file sovant-1.1.0.tar.gz.

File metadata

  • Download URL: sovant-1.1.0.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for sovant-1.1.0.tar.gz
Algorithm Hash digest
SHA256 0939377361a9bc3a1642ae2cbe08013fff533d53676e7c7c1e54b8ac3e6a412a
MD5 40ae210b9fc396c5d4bdb493229aa531
BLAKE2b-256 79dab83e38c1fe7de839cdb2aef0106aa90b49abc82334542a55a77fdd776271

See more details on using hashes here.

File details

Details for the file sovant-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: sovant-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for sovant-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 08c146663a4614146fc68e6b514bee7d69589291f418e19f72810fe3c36f2f31
MD5 9af5cdd8eff01fca6cb13580cbdeed0c
BLAKE2b-256 1ceac9f78cca80074ab0dba658d6ff719766e38f1de041702677022ba54c02e4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page