Skip to main content

UniContext

Universal Python SDK for agent memory and context with a unified API across multiple providers.

UniContext is HTTP-first: built-in providers call provider REST APIs via httpx. Switch providers by changing the provider name and API key.

Python 3.10+ License: MIT

Features

  • Unified, provider-agnostic client API
  • Typed models and input validation
  • Consistent error types across providers
  • Shared HTTP transport (connection pooling)

Installation

From PyPI:

pip install unicontext

From source (development):

pip install -e .

Optional development tools:

pip install -e ".[dev]"

Quick start

This example uses Letta (archives mode) because it has synchronous IDs you can get() and delete() immediately.

from unicontext import MemoryInput, Scope, SearchQuery, create_client

client = create_client(provider="letta", api_key="YOUR_LETTA_API_KEY")
scope = Scope(user_id="user_123")

created = client.add(MemoryInput(text="User prefers Python for backend"), scope)

hits = client.search(SearchQuery(query="backend", scope=scope, limit=5))
for hit in hits:
    print(hit.record.content)

fetched = client.get(memory_id=created.id, scope=scope)
print(fetched.content)

client.delete(memory_id=created.id, scope=scope)

Switching providers

from unicontext import create_client

mem0 = create_client(provider="mem0", api_key="YOUR_MEM0_API_KEY")
supermemory = create_client(provider="supermemory", api_key="YOUR_SUPERMEMORY_API_KEY")
zep = create_client(provider="zep", api_key="YOUR_ZEP_API_KEY")
letta = create_client(provider="letta", api_key="YOUR_LETTA_API_KEY")

Core concepts

Scope

Scope selects where the memory lives (user, agent, thread, tags).

from unicontext import Scope

Scope(user_id="user_123")
Scope(user_id="user_123", thread_id="thread_456")
Scope(user_id="user_123", tags=["preferences", "onboarding"])

Inputs

MemoryInput must provide exactly one of text or messages.

from unicontext import MemoryInput

MemoryInput(text="User prefers dark mode")
MemoryInput(messages=[{"role": "user", "content": "Hi"}])

Provider notes

UniContext normalizes the public API, but providers have different semantics.

Mem0

  • add() is asynchronous; the returned ID may be an event ID.
  • Use search() after processing completes to retrieve the finalized memory ID.
import time

from unicontext import MemoryInput, Scope, SearchQuery, create_client

client = create_client(provider="mem0", api_key="YOUR_MEM0_API_KEY")
scope = Scope(user_id="user_123")

client.add(MemoryInput(text="User likes espresso"), scope)
time.sleep(20)

hits = client.search(SearchQuery(query="espresso", scope=scope, limit=5))
if hits:
    memory_id = hits[0].record.id
    client.delete(memory_id=memory_id, scope=scope)

Supermemory

  • Scope is primarily tag-driven.
  • delete_by_scope() requires at least one tag to reduce accidental deletes.

Zep

  • Dual routing: if scope.thread_id is set, add() writes to a thread; otherwise it writes to the knowledge graph.
  • search() targets the knowledge graph.
  • get() and delete() are not supported for graph records.

Letta

  • Default mode uses archives and passages.
  • If you do not provide an archive ID, UniContext auto-creates and caches one per scope.user_id.

Error handling

from unicontext import Scope, SearchQuery, create_client
from unicontext.exceptions import AuthError, ProviderError, ValidationError

client = create_client(provider="letta", api_key="YOUR_LETTA_API_KEY")
scope = Scope(user_id="user_123")

try:
    client.search(SearchQuery(query="hello", scope=scope, limit=5))
except ValidationError as e:
    print(e.message)
except AuthError as e:
    print(e.message)
except ProviderError as e:
    print(e.message)

Development

Run unit tests:

python -m pytest -v

Run the pre-release checks:

python scripts/pre_release.py

Metadata

Release files for unicontext 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for unicontext 0.1.0
File Size Uploaded
unicontext-0.1.0.tar.gz 20.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for unicontext 0.1.0
File Interpreter ABI Platform
unicontext-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.8 kB

Release files / unicontext-0.1.0.tar.gz

Download URL unicontext-0.1.0.tar.gz
Size 20.5 kB
Tags Source
SHA-256 checksum
How to use checksums
64b18166d6753b7c1e6b33890f9905c79a1d01cd4c6fff08a5c09add31d8612e
BLAKE2b-256 checksum
How to use checksums
9c1d3a6bfeabe84b982e8d42c763a38e516fcc60342be888fcfb35eb55e9bf68
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release files / unicontext-0.1.0-py3-none-any.whl

Download URL unicontext-0.1.0-py3-none-any.whl
Size 26.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
51520a684af3910446efd9eaa1949440f3518a669061c378cd5e690bdb296e80
BLAKE2b-256 checksum
How to use checksums
5541cccd73cf3bc12ae74670252f7df1e86791a720cdb5c423377d136f6e0948
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page