Mnemos Python SDK
Typed sync + async clients for the Mnemos memory API (PRD §8): API-key auth with retry/backoff on 429/5xx, document batching, job polling, a session context manager, and webhook signature verification.
pip install mnemoscale-sdk # in this repo: uv sync --all-packages
Quickstart
from mnemos_sdk import MnemosClient
client = MnemosClient("https://api.example.com", api_key="mk_live_...")
with client.session(agent_id=AGENT_ID, namespace_id=NAMESPACE_ID) as s:
# Blocks until the extraction job completes (extract_async to fire-and-poll later).
s.extract([{"content": "the customer asked about delivery delays", "role": "user"}])
result = s.query("delivery delays", top_k=5, rerank=True)
for r in result["results"]:
if r["from_working_memory"]:
continue # session turns merged per PRD §7.1
print(r["hybrid_score"], r["content"])
AsyncMnemosClient mirrors the same surface with async/await.
Query controls (PRD §7.1)
result = client.query(
"what did the customer ask about delivery delays?",
agent_id=AGENT_ID,
routing="auto", # auto | keyword | semantic | hybrid
top_k=10,
metadata_filter={ # optional JSONB containment (@>) over source metadata —
"topics": ["billing"], # e.g. T-001 enrichment fields topics/people/actions/type;
}, # composes AND-wise with scenario_type
rerank=True, # cross-encoder reranking, Pro tier and above;
# lower tiers skip with reason "tier_disallowed"
scoring={ # optional per-query hybrid weights (normalized to 1.0)
"cosine_weight": 0.50,
"importance_weight": 0.30,
"recency_weight": 0.20,
"recency_half_life_days": 7,
},
ef_search=80, # optional HNSW beam width (10-400): recall ↔ latency
max_context_tokens=2048, # optional: pack merged results under a token budget
# (near-duplicate L0/search content suppressed)
)
print(result["query_id"], result["routing_used"], result["reranker_skipped_reason"])
Verifying webhooks (PRD §13.2)
Mnemos signs every delivery with X-Mnemos-Signature: t=<unix>,v1=<hex>
(HMAC-SHA-256 over "{t}.{body}", 300 s replay tolerance). Verify against the
raw request body before parsing it — any web framework works:
from mnemos_sdk import WebhookVerificationError, verify_webhook_signature
async def webhook_endpoint(request): # FastAPI/Starlette-style
raw = await request.body()
try:
verify_webhook_signature(
WEBHOOK_SECRET,
request.headers.get("X-Mnemos-Signature"),
raw,
)
except WebhookVerificationError as exc:
# exc.reason: malformed_header | stale_timestamp | signature_mismatch
return Response(status_code=400)
event = json.loads(raw)
...
Errors
Everything the SDK raises is a MnemosError, split into two branches:
MnemosError
├── MnemosApiError # the API answered with a failure status
│ ├── AuthenticationError (401) PaymentRequiredError (402)
│ ├── PermissionError (403) NotFoundError (404)
│ ├── ConflictError (409) ValidationError (422)
│ └── RateLimitError (429) ServerError (5xx)
├── MnemosConnectionError # the request never produced a response
├── MnemosTimeoutError # a request, or a job poll, ran out of time
└── WebhookVerificationError
Catch MnemosApiError for "any HTTP failure but not a transport failure". Each
one carries status_code, code (the machine-readable reason from a structured
body), correlation_id (the X-Correlation-Id the API echoed — quote it in a
support ticket), retryable, and the raw detail. PaymentRequiredError adds
manage_url; WebhookVerificationError carries a reason.
Transport failures are wrapped, so handling an unreachable API never requires
importing httpx — the underlying exception stays on __cause__:
from mnemos_sdk import MnemosApiError, MnemosConnectionError, RateLimitError
try:
result = client.query("delivery delays", agent_id=AGENT_ID)
except RateLimitError as exc:
... # exc.code, exc.retryable
except MnemosApiError as exc:
log.error("mnemos %s (correlation %s)", exc.status_code, exc.correlation_id)
except MnemosConnectionError as exc:
log.error("mnemos unreachable: %s", exc)
Retries and per-request options
429 and 500/502/503/504 are retried max_retries times (default 3) with
exponential backoff (retry_backoff_base * 2 ** (attempt - 1)), except a 429
carrying X-Mnemos-Retryable: false and a 402 — both permanent, so both
surface at once. A server-sent Retry-After (delay-seconds or HTTP-date) wins
over the backoff, clamped to retry_after_cap (30 s). Transport failures are
replayed only when the request provably never left (connection-phase) or is
replay-safe (GET/DELETE, or a body with an idempotency_key).
Every method takes agent_id, correlation_id and timeout alongside its own
arguments; the client takes default_headers for headers that ride on every
request:
client = MnemosClient(BASE_URL, API_KEY, default_headers={"X-Client-Name": "acme-agent"})
usage = client.get_usage(agent_id=AGENT_ID, correlation_id=request_id, timeout=5.0)
Parity with the TypeScript SDK
sdk-parity.json at the repo root is the shared surface contract between this
package and sdk-ts: methods, error taxonomy, constants, retry policy and
request options, named in both languages. tests/unit/test_sdk_parity.py and
sdk-ts/tests/parity.test.ts assert their own side against it, so adding
something to one SDK fails the other's suite until it lands there too. The
manifest's notes record the differences that are deliberate (seconds vs
milliseconds, sync+async vs async-only, and so on).
See quickstart.py at the repo root for the runnable end-to-end example.
To hand these operations to an LLM as tools rather than calling them yourself,
docs/Mnemos_ToolSpec_Cookbook_v1.0.md has copy-paste OpenAI and Anthropic
tool definitions for query/extract/feedback, plus the dispatcher that routes a
tool call to this client. Both are CI-verified against these signatures.
Release files for mnemoscale-sdk 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mnemoscale_sdk-0.1.1.tar.gz | 21.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mnemoscale_sdk-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.6 kB
Release files / mnemoscale_sdk-0.1.1.tar.gz
| Download URL | mnemoscale_sdk-0.1.1.tar.gz |
|---|---|
| Size | 21.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b031cf587e0cbc5a030ef322d6648ec0deea6f0a0151ee4ba2ce91095cb93f39
|
|
BLAKE2b-256 checksum How to use checksums |
9d81940ab4ec759740983e13625f64f6ee7fc4d2ab4db66bcaee8252124b6233
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / mnemoscale_sdk-0.1.1-py3-none-any.whl
| Download URL | mnemoscale_sdk-0.1.1-py3-none-any.whl |
|---|---|
| Size | 23.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
279cdfb35af19b756120365213c27e675c33e345be34bad424922c1a06864caf
|
|
BLAKE2b-256 checksum How to use checksums |
8338aa7dd865dff68033bb59c2214f8231fb56a98a2bced9b882d19742edbe99
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|