Skip to content

feat(python-sdk): add Python SDK with async client, signing, and AI m…#80

Open
harrymove-ctrl wants to merge 3 commits intodevfrom
feat/python-sdk-memwal
Open

feat(python-sdk): add Python SDK with async client, signing, and AI m…#80
harrymove-ctrl wants to merge 3 commits intodevfrom
feat/python-sdk-memwal

Conversation

@harrymove-ctrl
Copy link
Copy Markdown
Collaborator

Summary

Port the MemWal SDK to Python mirrors the TypeScript client exactly with the same methods, same
relayer, same auth flow.

Why

Currently only a TypeScript SDK exists.

What changed

  • Core async client: MemWal.create() with remember, recall, analyze, ask, restore,
    health. Sync wrapper MemWalSync included for scripts and notebooks.
  • Ed25519 signing: PyNaCl-based request signing with the same message format as TypeScript:
    {timestamp}.{METHOD}.{path}.{sha256(body)}. Includes delegate_key_to_sui_address() and
    delegate_key_to_public_key() utils.
  • LangChain middleware: with_memwal_langchain(llm, ...) wraps any BaseChatModel. Recalls
    relevant memories before each call, injects them as a SystemMessage before the last user message,
    and fire-and-forgets analyze() after each call.
  • OpenAI SDK middleware: with_memwal_openai(client, ...) works with both AsyncOpenAI and
    OpenAI. Patches chat.completions.create with the same inject-before + analyze-after pattern.
  • tests: unit tests for signing utils, client (mocked with respx), middleware (LangChain +
    OpenAI), and integration tests against a live relayer.
  • docs/sdk/overview.md: Python SDK section added.

Types of Changes

  • New feature (non-breaking — new package, no existing code touched)
  • Bug fix
  • Breaking change
  • Documentation only
  • Refactor
  • Test

Testing

  • I have tested this code locally
  • I have added unit tests
  • I have added integration tests (run against relayer.dev.memwal.ai)

@harrymove-ctrl harrymove-ctrl requested a review from ducnmm April 7, 2026 09:29
import pytest

from memwal.client import MemWal, MemWalError, MemWalSync
from memwal.utils import bytes_to_hex
from __future__ import annotations

import asyncio
import json

import asyncio
import json
from typing import Any, List
import asyncio
import json
from typing import Any, List
from unittest.mock import AsyncMock, MagicMock, patch

import httpx
import nacl.signing
import pytest
Comment thread packages/python-sdk-memwal/memwal/middleware.py Dismissed
Comment thread packages/python-sdk-memwal/memwal/middleware.py Dismissed
@ducnmm
Copy link
Copy Markdown
Collaborator

ducnmm commented May 6, 2026

Hi @harrymove-ctrl please adjust this part to match the sdk part of the current typescript.

hien-p added 2 commits May 6, 2026 16:57
PR #121 made remember/analyze async on the server: client gets HTTP 202
+ job_id back in ~500ms instead of waiting ~18s for the full Walrus
upload + chain commit. Update the Python SDK to match the new TypeScript
SDK contract so all four downstream targets (Python apps, FastAPI, AI
middleware, OpenClaw plugin) get the same UX win.

Surface (mirrors TS):
- remember() / remember_async() now return RememberAcceptedResult
- wait_for_remember_job() polls /api/remember/{id} with jittered exp
  backoff + transient retry (matches TS pollingDelayMs +
  isTransientPollingStatus)
- remember_and_wait() convenience wraps both
- Bulk family: remember_bulk[_async] / get_remember_bulk_status /
  wait_for_remember_jobs / remember_bulk_and_wait
- analyze() returns job_ids + fact_count; analyze_and_wait() polls
  every fact's remember job to completion
- embed() exposes /api/embed for raw vectors
- New typed exceptions: MemWalRememberJobNotFound / Failed / Timeout
- MemWalSync wrapper exposes every new async method

Signing:
- build_signature_message() now includes the nonce + account_id segments
  the server requires (MED-1 replay protection + LOW-23 account-hint
  binding). Client generates a UUID nonce per request and sends
  x-nonce header; without this the server rejects with HTTP 426
  "unsupported legacy SDK".

Verified end-to-end against a local server (testnet):
- remember() returned 202 in 58ms (the PR #121 win)
- wait_for_remember_job() settled blob_id after ~30s of upload+commit
- recall() returned decrypted plaintext via SEAL
- remember_bulk_and_wait() handled 3 items across 3 wallets, all done
- See packages/python-sdk-memwal/examples/interactive_demo.py for the
  reproducible demo and the full server-log evidence.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants