Python - chaque méthode, en trois groupes.
Écrire, lire, supprimer. Chaque exemple ci-dessous a été exécuté contre l'API en production le 2026-08-01 ; les réponses sont verbatim.
pip install wontopos
from wontopos import Client mem = Client(api_key="wos-live-...") # or read from an env var
Choisir un modèle
La clé API détermine quelle mémoire (votre compte) ; le modèle détermine quel moteur la lit. Tous les modèles partagent une même mémoire : vous pouvez donc stocker avec l'un et rappeler avec un autre. Définissez un défaut sur le client ; surchargez un appel isolé en passant model=.
mem = Client(api_key="wos-live-...", model="tablet-1") # default engine mem.recall("...", user_id="alice") # tablet-1 mem.recall("...", user_id="alice", model="scroll-1") # or pick a model per call
list_models
Le catalogue - les ids que vous pouvez passer à model et la disponibilité de chacun. Les modèles memory: "shared" lisent le même store ; "isolated" garde le sien. Aucune clé API requise.
mem.list_models()[{"id": "tablet-1", "name": "Tablet 1", "available": true, "memory": "shared"},
{"id": "tablet-2", "name": "Tablet 2", "available": true, "memory": "shared"},
{"id": "scroll-1", "name": "Scroll 1", "available": true, "memory": "shared"},
{"id": "scroll-1.2", "name": "Scroll 1.2", "available": true, "memory": "shared"}]ping
Vérifiez la connexion et que votre clé API fonctionne : un contrôle en une ligne.
mem.ping() # True, or raises AuthenticationError / PaymentRequiredError
Le catalogue ci-dessus reflète toujours les modèles disponibles à l'instant même - passez tout autre id et vous obtenez une erreur claire. Les nouveaux modèles y apparaissent automatiquement dès leur sortie.
Écrire
add
Stocke un souvenir. Aucun appel LLM à l’entrée : vous ne payez que le tarif d’écriture.
mem.add("she prefers tea over coffee", user_id="alice") mem.add("I promised the summary by Friday", user_id="alice", speaker="me") # its own words - no registration needed
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}add_turn
Stocke un tour de conversation (utilisateur + assistant) à la fois en mémoire court terme et long terme.
mem.add_turn("hi", "hello!", user_id="alice")
{"status": "ok"}speaker
Chaque souvenir peut porter son locuteur. Enregistrez une personne une fois, puis passez son nom comme speaker ; "me" (les mots de l'assistant) n'a jamais besoin d'enregistrement. La recherche accepte aussi speaker, pour ne rappeler que les mots d'une personne.
mem.add_speaker("Bob", user_id="alice") # once per person; "me" needs no registration mem.add("I promised to send the report on Friday", user_id="alice", speaker="me") mem.add("Bob said the deadline moved to Tuesday", user_id="alice", speaker="Bob") mem.search("what did Bob say about deadlines?", user_id="alice", speaker="Bob")
[{"content": "Bob said the deadline moved to Tuesday", "speaker": "Bob", ...}]add_bulk
Importez un gros bloc de texte. Découpé et indexé côté serveur, idéal pour reprendre un historique existant.
mem.add_bulk("Alice moved to Brooklyn in March. She works at a design studio downtown.", user_id="alice")
{"elapsed_secs": 0.154154944, "status": "ok", "stored": 1, "total_chunks": 1}update
Un fait a changé. L'ancien souvenir est marqué superseded (conservé pour l'historique) ; le nouveau prend sa place dans le recall.
mem.update("576700aa-...", "she switched to coffee this year", user_id="alice")
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}Lire
search
Recherche sémantique, du plus pertinent au moins pertinent. N’importe quelle langue trouve n’importe quel souvenir, quelle que soit la langue dans laquelle il a été écrit. Le SDK renvoie directement le tableau memories ; le corps HTTP brut est affiché ci-dessous. Certains modèles répondent avec plusieurs ensembles de résultats et le SDK les renvoie fusionnés : le tableau peut donc contenir PLUS que max_results. Dimensionnez votre fenêtre de prompt sur ce que vous recevez, pas sur le nombre demandé.
r = mem.search("what does she drink?", user_id="alice", limit=1)
[{
"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624",
"content": "she prefers tea over coffee",
"category": "general",
"time_bucket": "2026-06",
"importance": 0.3,
"similarity": 0.6316057443618774,
"is_superseded": false,
"superseded_by": null,
"created_at": "2026-07-10T04:20:39.688276876Z"
}]| Champ | Signification |
|---|---|
| similarity | À quel point ce souvenir est proche de votre requête (0–1). |
| is_superseded | Vrai si ce fait a été remplacé par update(). |
| search_ms | Temps de récupération côté serveur. |
recall
Un seul aller-retour renvoie tout ce dont votre LLM a besoin - collez le résultat directement dans votre prompt : un contexte borné, de taille fixe, quel que soit le volume stocké.
ctx = mem.recall("what does she drink?", user_id="alice")
{"short_term": {"count": 2, "turns": [{"role": "user", "content": "hi", ...}]},
"long_term": {"count": 4, "memories": [{"content": "she prefers tea over coffee",
"similarity": 0.63, ...}]},
"context": {"count": 4, "around_top_memory": [
"[match] she prefers tea over coffee",
"[after] Alice moved to Brooklyn in March. ..."]},
"instruction": "Use short_term for recent context, long_term for relevant
past memories, context for surrounding conversation of the
most relevant memory."}history
Tours de conversation récents (mémoire court terme), du plus ancien au plus récent.
turns = mem.history("alice")
{"count": 2, "turns": [
{"role": "user", "content": "hi", "timestamp": "2026-07-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-07-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats
Compteurs de souvenirs pour un utilisateur.
mem.stats("alice")
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get
Récupère une mémoire par id - l'id renvoyé par add ou list_memories. Uniquement le texte original stocké et ses métadonnées. Un id d'un autre store, ou une mémoire supprimée ou invalidée, renvoie 404.
m = mem.get("alice", memory_id="576700aa-...")
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "created_at": "2026-07-10T04:20:39Z", "event_date": null,
"is_superseded": false, "superseded_by": null}{"memory": {"id": "8bd090de-...", "content": "the office moved to the seventh floor in June",
"category": "general", "created_at": "2026-07-31T18:20:30.531518060+00:00", "event_date": null,
"is_superseded": false, "superseded_by": null}, "user_id": "docs_livetest"}list_memories
Liste les mémoires d'un espace : uniquement le texte original que vous avez stocké et ses métadonnées. Paginé par curseur : renvoyez le next_cursor reçu pour la page suivante.
page = mem.list_memories("alice", limit=100)
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "created_at": "2026-07-10T04:20:39Z", "event_date": null,
"is_superseded": false, "superseded_by": null}
]}iter_memories · export_memories
Parcourez toutes les mémoires sans gérer le curseur, ou récupérez tout l'espace d'un coup.
for m in mem.iter_memories("alice"): # every page, no cursor bookkeeping print(m["id"], m["content"]) everything = mem.export_memories("alice") # the whole store as a list
Supprimer
delete
Supprime un souvenir unique par id.
mem.delete("alice", memory_id="576700aa-...")
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all
Efface tout pour un utilisateur - un seul appel, conforme RGPD.
mem.delete_all("alice")
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Erreurs et fiabilité
Chaque échec est une erreur typée : attrapez le cas précis (limite de débit, authentification, paiement) ou tous avec le WosError de base.
from wontopos import PaymentRequiredError, NotFoundError try: mem.add("...", user_id="alice") except NotFoundError: mem.create_store("alice") # store didn't exist yet except PaymentRequiredError: top_up() # out of credit - don't retry
rate_limit
Lisez le quota restant après chaque appel et ralentissez avant d'atteindre la limite.
mem.search("...", user_id="alice") rl = mem.rate_limit # {"limit": 150, "remaining": 3, "reset": ...}
search_self
Les deux voies en un seul appel sur un modèle à mémoire de soi (Scroll 1.2+) : ce que les autres ont dit, et les propres mots de l'agent - séparés, pour que le lecteur ne confonde jamais qui a parlé.
r = mem.search_self("what did I promise?", user_id="alice") r["memories"] # what others said / general memories r["self_memories"] # the agent's OWN words (speaker "me")
list_engrams
Demandez au service quels engrammes et formes de rendu le modèle sélectionné peut exécuter, au lieu de coder en dur des noms qui deviennent obsolètes dès qu'un nouveau sort.
cat = mem.list_engrams() [e["name"] for e in cat["engrams"]] # ask, never hard-code
filters
Restreint la recherche à une partie du magasin. Appliqué avant le classement : vous obtenez les meilleures correspondances à l'intérieur du filtre, pas un top-N filtré après coup.
mem.search("what did we decide", user_id="alice", filters={ "categories": ["work"], "event_from": "2026-01-01", # when it HAPPENED })
idempotency_key
Rend sûr le fait de répéter une écriture. À utiliser quand la reprise vient de vous - un job interrompu puis relancé, une file qui redélivre.
mem.add("she prefers tea", "alice", idempotency_key=f"import:{row.id}")
import:row-42), jamais une constante : une clé réutilisée pour deux écritures différentes rejoue la première, et la seconde est perdue en silence. Format : 1 à 128 caractères parmi [A-Za-z0-9._:-].with_timeout / with_retries / with_deadline
Ajustez un seul point d'appel sans toucher au client déjà construit : un clone avec un délai plus long pour une grosse reprise, ou sans reprises à l'intérieur de votre propre boucle de retry.
timeout borne une tentative, donc un appel qui réessaie peut lui survivre : avec les valeurs par défaut, un seul appel peut retenir une connexion 30 s, attendre, réessayer, puis réessayer encore. deadline borne l'appel entier : chaque tentative est plafonnée à ce qu'il reste, et aucune attente ne dort au-delà du budget. Réglez-le quand l'appelant a une vraie limite, comme un gestionnaire de requête disposant de cinq secondes.
mem.with_timeout(120).add_bulk(big_blob, "alice") # this slow call only mem.with_retries(0).add("...", "alice") # you retry, not the SDK mem.with_deadline(5).recall("...", "alice") # 5s for the whole call