MemoryCache & configuration¶
MemoryCache¶
memory_reuse.core.MemoryCache ¶
High-level cache client for AI agent workloads.
MemoryCache is the primary public interface. It wires together a
storage backend, the exact-match LLM cache, the TTL-backed tool cache,
and statistics tracking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
CacheConfig | None
|
Cache configuration. When omitted a default
:class: |
None
|
**kwargs
|
Any
|
Keyword arguments forwarded to :class: |
{}
|
Example::
from memory_reuse import MemoryCache, CacheConfig
cache = MemoryCache(CacheConfig(backend="memory", default_ttl=600))
cache.set_context(user_id="alice")
result = await cache.exact.get(["my-prompt"], scope="user",
scope_id="alice")
stats
property
¶
Current cache statistics snapshot.
Returns:
| Name | Type | Description |
|---|---|---|
A |
CacheStats
|
class: |
Example::
print(cache.stats.hit_rate)
from_env
classmethod
¶
Create a :class:MemoryCache from MEMORY_REUSE_* environment variables.
See :meth:~memory_reuse.config.CacheConfig.from_env for the full
list of recognised variables.
Returns:
| Type | Description |
|---|---|
MemoryCache
|
A configured :class: |
Example::
import os
os.environ["MEMORY_REUSE_BACKEND"] = "redis"
os.environ["MEMORY_REUSE_REDIS_URL"] = "redis://localhost:6379/0"
cache = MemoryCache.from_env()
set_context ¶
set_context(*, user_id: str | None = None, session_id: str | None = None, tenant_id: str | None = None) -> None
Set the user/session context for scoped cache keys.
Context values are used by the LangGraph decorators when no explicit
scope ID is passed. They do not affect calls that provide their
own scope_id argument.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_id
|
str | None
|
Identifier for the current user. |
None
|
session_id
|
str | None
|
Identifier for the current session. |
None
|
tenant_id
|
str | None
|
Identifier for the current tenant (future use). |
None
|
Example::
cache.set_context(user_id="alice", session_id="sess-123")
clear_context ¶
Reset all context values to None.
Call this between requests in a shared server context to avoid leaking one user's context into another request.
lookup
async
¶
lookup(key_parts: list, query_text: str, *, scope: str, scope_id: str | None, exact_only: bool = False, threshold: float | None = None) -> Any | None
Look up a cached value, trying the exact cache before the semantic cache.
The combined flow tries the fastest, cheapest path first: an exact hash-match is attempted before any embedding is computed. Only when the exact cache misses — and semantic caching is enabled and not disabled for this call — is the query embedded and matched by similarity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_parts
|
list
|
Ordered list of values identifying the exact-cache entry. |
required |
query_text
|
str
|
The natural-language query used for semantic matching. |
required |
scope
|
str
|
Cache scope — |
required |
scope_id
|
str | None
|
User or session identifier for non-global scopes. |
required |
exact_only
|
bool
|
When |
False
|
threshold
|
float | None
|
Optional per-call similarity threshold overriding
:attr: |
None
|
Returns:
| Type | Description |
|---|---|
Any | None
|
The cached value on an exact or semantic hit, or |
Raises:
| Type | Description |
|---|---|
ScopeViolationError
|
If |
store
async
¶
store(key_parts: list, query_text: str, value: Any, *, scope: str, scope_id: str | None, ttl: int | None = None, exact_only: bool = False) -> None
Store a value in the exact cache and, when enabled, the semantic cache.
The exact-match entry is always written so a subsequent identical request hits the faster exact path. When semantic caching is enabled and not disabled for this call, the query's embedding is also stored so reworded but equivalent requests can match later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_parts
|
list
|
Ordered list of values identifying the exact-cache entry. |
required |
query_text
|
str
|
The natural-language query whose embedding is stored. |
required |
value
|
Any
|
The value to cache. Must be JSON-serialisable. |
required |
scope
|
str
|
Cache scope — |
required |
scope_id
|
str | None
|
User or session identifier for non-global scopes. |
required |
ttl
|
int | None
|
Time-to-live in seconds. Falls back to
:attr: |
None
|
exact_only
|
bool
|
When |
False
|
Raises:
| Type | Description |
|---|---|
ScopeViolationError
|
If |
ping
async
¶
Check whether the backend is reachable.
Returns:
| Type | Description |
|---|---|
bool
|
|
close
async
¶
Close backend connections gracefully.
Should be called on application shutdown to prevent resource leaks, especially when using the Redis backend.
Example::
async with asyncio.timeout(5):
await cache.close()
flush
async
¶
Flush all cached entries from the backend.
Warning
This irreversibly removes every cached entry. Use only in development or test environments.
CacheConfig¶
memory_reuse.config.CacheConfig
dataclass
¶
CacheConfig(backend: Literal['memory', 'redis'] = 'memory', redis_url: str | None = None, default_ttl: int | None = 3600, default_scope: Literal['global', 'user', 'session'] = 'global', key_prefix: str = 'memreuse', max_key_size: int = 512, enable_stats: bool = True, semantic_enabled: bool = False, similarity_threshold: float = 0.95, embedding_provider: Literal['openai', 'local', 'litellm'] | None = None, embedding_model: str | None = None, max_vectors_per_namespace: int = 10000, store_exact_on_semantic_hit: bool = True, extract_answer: bool = False, extract_min_similarity: float = 0.5)
Configuration for the MemoryCache.
All values can be overridden via environment variables when using
:meth:MemoryCache.from_env.
Attributes:
| Name | Type | Description |
|---|---|---|
backend |
Literal['memory', 'redis']
|
Storage backend to use. |
redis_url |
str | None
|
Connection URL for the Redis backend. Should be supplied
via the |
default_ttl |
int | None
|
Default time-to-live in seconds for cached entries.
|
default_scope |
Literal['global', 'user', 'session']
|
Default cache scope applied when no explicit scope is passed to cache operations. |
key_prefix |
str
|
String prepended to every cache key for namespacing. |
max_key_size |
int
|
Maximum allowed cache-key length in bytes. Requests
that would produce a longer key raise |
enable_stats |
bool
|
When |
semantic_enabled |
bool
|
When |
similarity_threshold |
float
|
Minimum cosine similarity (normalised to
|
embedding_provider |
Literal['openai', 'local', 'litellm'] | None
|
Which embedding provider to use for semantic
lookups. |
embedding_model |
str | None
|
Optional model name passed to the embedding provider.
|
max_vectors_per_namespace |
int
|
Maximum number of stored vectors per scope namespace before LRU eviction applies. |
store_exact_on_semantic_hit |
bool
|
When |
extract_answer |
bool
|
When |
extract_min_similarity |
float
|
Minimum normalised cosine similarity
( |
Example::
config = CacheConfig(
backend="redis",
redis_url=os.environ["REDIS_URL"],
default_ttl=600,
default_scope="user",
)
from_env
classmethod
¶
Create a :class:CacheConfig from MEMORY_REUSE_* environment variables.
Recognised variables:
MEMORY_REUSE_BACKEND—"memory"or"redis"MEMORY_REUSE_REDIS_URL— Redis connection URLMEMORY_REUSE_DEFAULT_TTL— integer seconds or"none"MEMORY_REUSE_DEFAULT_SCOPE—"global","user", or"session"MEMORY_REUSE_KEY_PREFIX— string prefix for all keysMEMORY_REUSE_ENABLE_STATS—"true"/"false"MEMORY_REUSE_SEMANTIC_ENABLED—"true"/"false"MEMORY_REUSE_SIMILARITY_THRESHOLD— float in[0.0, 1.0]MEMORY_REUSE_EMBEDDING_PROVIDER—"openai","local", or"litellm"MEMORY_REUSE_EMBEDDING_MODEL— embedding model name
Returns:
| Name | Type | Description |
|---|---|---|
A |
CacheConfig
|
class: |
Statistics¶
memory_reuse.stats.CacheStats
dataclass
¶
CacheStats(hits: int = 0, exact_hits: int = 0, semantic_hits: int = 0, misses: int = 0, errors: int = 0, total_requests: int = 0)
Snapshot of cache performance counters.
Attributes:
| Name | Type | Description |
|---|---|---|
hits |
int
|
Number of successful cache lookups. Always equals
|
exact_hits |
int
|
Number of hits served by the exact (hash-based) cache. |
semantic_hits |
int
|
Number of hits served by the semantic (similarity) cache. |
misses |
int
|
Number of cache lookups that found no entry. |
errors |
int
|
Number of backend errors encountered during cache operations. |
total_requests |
int
|
Total number of cache lookup attempts (hits + misses). |
Example::
stats = cache.stats
print(f"Hit rate: {stats.hit_rate:.1%}")
hit_rate
property
¶
Fraction of requests that were cache hits, in the range [0.0, 1.0].
Returns:
| Type | Description |
|---|---|
float
|
|
to_dict ¶
Return a plain-dict representation of the stats snapshot.
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary with keys |
dict
|
|
memory_reuse.stats.StatsTracker ¶
Thread-safe, asyncio-compatible statistics tracker.
Uses an :class:asyncio.Lock to serialise counter updates so that
concurrent coroutines always see a consistent view of the counters.
Hits are tracked by type: :meth:record_exact_hit and
:meth:record_semantic_hit each also bump the aggregate hits counter,
so hits always equals exact_hits + semantic_hits.
Statistics recording is best-effort and never fatal: every record_*
method swallows any internal error so a cache operation can always return
its result even if recording fails.
Example::
tracker = StatsTracker()
tracker.record_exact_hit()
tracker.record_miss()
print(tracker.get_stats().hit_rate) # 0.5
record_exact_hit ¶
Record a hit served by the exact cache.
Increments the exact-hit counter, the aggregate hit counter, and the total-request counter. Any internal error is swallowed so recording is never fatal to the caller.
record_semantic_hit ¶
Record a hit served by the semantic cache.
Increments the semantic-hit counter, the aggregate hit counter, and the total-request counter. Any internal error is swallowed so recording is never fatal to the caller.
record_hit ¶
Record an exact hit. Alias for :meth:record_exact_hit.
Retained for backward compatibility with Phase 1 callers.
record_miss ¶
Increment the miss counter and total-request counter.
Any internal error is swallowed so recording is never fatal.
record_error ¶
Increment the error counter (does not affect total_requests).
Any internal error is swallowed so recording is never fatal.
get_stats ¶
Return an immutable snapshot of the current counters.
Returns:
| Name | Type | Description |
|---|---|---|
A |
CacheStats
|
class: |
Exceptions¶
memory_reuse.exceptions ¶
Custom exceptions for the memory-reuse package.
AgentMemoryError ¶
Bases: Exception
Base exception for all memory-reuse errors.
All exceptions raised by this library inherit from this class, making it easy to catch any library error with a single handler.
BackendConnectionError ¶
Bases: AgentMemoryError
Raised when the cache backend cannot be reached.
Typically wraps connection failures from Redis or other network
backends. Check your redis_url and network connectivity.
ScopeViolationError ¶
Bases: AgentMemoryError
Raised when user-scoped data would be cached under the global scope.
This is a safety guard: if you call a cache operation with
scope='user' but no user_id is available in the current
context, this exception is raised rather than silently caching
data that could be shared across users.
InvalidTTLError ¶
Bases: AgentMemoryError
Raised when a TTL value is not valid.
TTL must be a positive integer (seconds) or None for no expiry.
BackendNotAvailableError ¶
Bases: AgentMemoryError
Raised when the requested backend is not importable or configured.
For example, requesting the redis backend without the redis
package installed will raise this exception.
EmbeddingProviderError ¶
Bases: AgentMemoryError
Raised when an embedding provider cannot be used.
Typically raised when the provider's optional dependency is not
installed (naming the extra to install, e.g.
pip install "memory-reuse[semantic]") or when the provider's
backing model or API call fails.
ProviderMismatchError ¶
Bases: AgentMemoryError
Raised when embeddings from different providers or models are mixed.
Vectors are namespaced by provider:model. Comparing vectors from
incompatible providers or models is refused rather than silently
producing meaningless similarity scores.
ConfigurationError ¶
Bases: AgentMemoryError
Raised when a :class:CacheConfig value is invalid.
For example, a similarity_threshold outside [0.0, 1.0] or
enabling semantic_enabled without selecting an
embedding_provider.