Langzeitgedächtnis für KI-Agenten.
WOS ist eine Memory-API. Sie speichern die Erinnerungen eines Nutzers einmal, rufen dann zu jeder Abfrage nur die relevanten ab und übergeben sie an den Prompt Ihres Modells.
Der Abruf ist rein semantisch, ohne Keyword- oder BM25-Matching, daher ist die Recall-Qualität in allen Sprachen identisch. Jede Abfrage liefert einen kleinen, begrenzten Kontext zurück, unabhängig davon, wie viel Sie gespeichert haben, und über Ihre gespeicherten Erinnerungen läuft niemals ein Modell.
Kernoperationen
store- speichert eine Erinnerung für einen Nutzer.recall- liefert die relevanten Erinnerungen zu einer Abfrage. Dies ist der zentrale Aufruf.search- rohe semantische Suche über gespeicherte Erinnerungen.supersede- aktualisiert oder ersetzt eine veraltete Erinnerung.forget- löscht eine einzelne Erinnerung oder einen ganzen Nutzer (DSGVO).
Drei Modelle, eine Linie.
WOS-Modelle sind danach benannt, wie Menschen im Lauf der Geschichte Wissen bewahrt haben - Tablet, Scroll, Codex. Steintafel, Schriftrolle, gebundenes Buch: Jedes leistet mehr für Ihren Agenten als das vorherige.
Tablet
LiveEine schlanke, schnelle und kostengünstige Art, Erinnerungen einzuschreiben und abzurufen - das Fundament, auf dem jedes Modell aufbaut.
Scroll
LiveErgänzt ein Sprachmodell, das Ihre Frage genauer liest und einen vollständigeren Kontext zurückbringt - verstreute Belege kommen so wieder zusammen, statt dass ein Teil fehlt.
Codex
DemnächstSchlägt von selbst die richtige Seite auf - wählt in jedem Moment das passende Gedächtnis und die passenden Werkzeuge und wird mit jeder Nutzung schärfer.
Der vollständige Benchmark-Bericht zu Tablet 1 steht auf der Benchmark-Seite.
Zahlen Sie uns $2. Sparen Sie ein Vielfaches davon bei Ihrem LLM.
WOS führt Ihrem LLM ~1.200 Tokens pro Abfrage zu - einen begrenzten, relevanten Ausschnitt - statt die gesamte Historie in jeden Prompt zu stopfen. Der Abstand ist enorm und wächst mit Ihrer Historie.
Jeder für WOS ausgegebene $1 spart ~$98 beim LLM. Größere Historie oder ein teureres Modell → größerer ROI.
Woher die Einsparungen kommen
- Ohne WOS packen Sie die gesamte Historie in jeden Prompt -
100K tokens × $2.50/1M = $0.25pro Abfrage, zu GPT-4o-Eingabepreisen (bei Modellen der Opus-Klasse etwa das Doppelte). - Mit WOS nehmen Sie die Daten einmal auf (
$2/1M); danach ist jede Abfrage ein winziger Abruf ($3/1M × 1,200) plus Ihr LLM auf nur ~1.200 Tokens. - Je weniger Tokens Ihr LLM liest, desto weniger zahlen Sie - und WOS hält diese Zahl konstant, während das Gedächtnis wächst.
Jede Sprache, dieselbe Genauigkeit.
Der Abruf ist rein semantisch - ausschließlich Embeddings, null Keyword- oder BM25-Matching. Die Recall-Qualität ist daher identisch, ob Ihre Nutzer auf 日本語, 中文, Español oder Englisch schreiben.
Lexikalisches Matching wie BM25 ist auf die Gestalt einer bestimmten Sprache abgestimmt - Morphologie, Leerzeichen, Schriftsystem. In einem mehrsprachigen Store heißt das: Die Abrufqualität variiert je nach Sprache. WOS verwendet überhaupt kein lexikalisches Matching, sodass jede Sprache denselben Weg nimmt.
Ein Store, drei Sprachen zugleich
Sie wählen keine Sprache pro Store - mischen Sie frei. Unten enthält das Gedächtnis eines Nutzers gleichzeitig Japanisch, Englisch und Spanisch, und jede Frage findet die richtige Erinnerung, unabhängig von der Sprache. Dies ist ein echter Austausch mit der Live-API:
# one user, three languages stored together mem.add("彼女はコーヒーより紅茶が好き", user_id="alice") # Japanese mem.add("she works at a design studio in Brooklyn", user_id="alice") # English mem.add("A ella le encanta hacer senderismo los sábados", user_id="alice") # Spanish
"¿Qué bebe ella?" -> 彼女はコーヒーより紅茶が好き "what does she do on weekends?" -> A ella le encanta hacer senderismo los sábados "彼女の仕事は?" -> she works at a design studio in Brooklyn
Kein Übersetzungsschritt, keine Spracherkennung, keine Konfiguration pro Sprache. Erinnerungen und Fragen werden nach Bedeutung eingeordnet, nicht nach Sprache - passt die Bedeutung, spielt die Sprache keine Rolle.
Warum wir Keywords bewusst verbannt haben
Lexikalisches Scoring wie BM25 stärkt den Abruf für manche Sprachen mehr als für andere - hinderlich, wenn ein Store viele Sprachen enthält. Wir haben es daher vollständig aus der Engine entfernt und setzen diese Regel im Code-Review durch: Mit jeglichem lexikalischem Scoring im Pfad würde die Recall-Qualität je nach Sprache abweichen.
Kein Modell läuft über Ihre Erinnerungen.
Die Speicherung erfolgt wortgetreu, und die Engine sucht über Embeddings - günstig, schnell und deterministisch. Über Ihre gespeicherten Erinnerungen läuft niemals ein Modell. Tablet verwendet gar kein Modell; Scroll und Codex setzen für stärkere Ergebnisse eines um die Engine herum ein, doch es sieht immer nur Ihre Abfrage, nie das, was Sie gespeichert haben.
- Deterministische Engine. Die Engine liefert für dieselbe Abfrage jedes Mal dieselben Erinnerungen - deshalb stammt die Varianz in unserem Benchmark allein vom Reader-Modell.
- Günstig im großen Maßstab. Keine Generierungskosten beim Speichern oder Abrufen - Ihre Rechnung folgt dem Speicherplatz, nicht der Modellnutzung, während das Gedächtnis wächst.
Ihre Worte, unangetastet
Ein verbreitetes Design lässt beim Schreiben ein Sprachmodell laufen, um "Fakten" aus dem Text zu extrahieren und umzuschreiben. Dieses Design bezahlt dreifach: Generierungskosten bei jedem Schreibvorgang, zusätzliche Latenz und die Speicherung der Paraphrase eines Modells statt der ursprünglichen Worte. WOS trifft die entgegengesetzte Wahl - es speichert das Gesagte unverändert und lässt Ihr LLM die Interpretation zur Lesezeit übernehmen, mit dem Originaltext in der Hand.
90.7%, gemessen und reproduzierbar.
90.7% auf LongMemEval-S, gemittelt über 5 unabhängige Läufe (σ 0.5%, keiner handverlesen), bewertet vom kanonischen GPT-4o-Judge des Benchmarks.
Auf demselben Benchmark schwanken die Ergebnisse stark mit dem Bewertungsprotokoll - dem Judge, dem Prompt und dem, was die Abrufschicht tun darf. Wir verwenden den kanonischen GPT-4o-Judge des Benchmarks von dritter Seite wie veröffentlicht, passen nichts an den Test an und veröffentlichen den Bewertungscode und den Reader-Prompt, sodass jeder die 90.7% exakt reproduzieren kann.
Das Protokoll in einer Tabelle
| Punkt | Unser Vorgehen |
|---|---|
| Datensatz | LongMemEval-S (bereinigt), ~240K Tokens Historie pro Frage |
| Judge | Der kanonische GPT-4o-Judge des Benchmarks - eine dritte Partei, nicht wir |
| Läufe | 5 unabhängige Läufe, jeder Wert veröffentlicht, Mittelwert berichtet (σ 0.5%) |
| Reader | Festes Reader-Modell und fester Prompt, wortwörtlich veröffentlicht |
Was es ehrlich hält: ein Judge von dritter Seite, der unverändert veröffentlichte Reader-Prompt, rein semantischer Abruf und die Veröffentlichung jedes Laufs - nicht nur des besten. Die Abruf-Engine ist deterministisch - führen Sie sie erneut aus, erhalten Sie dieselben Erinnerungen.
Wir erklimmen härtere Benchmarks
Wir testen auf dem härtesten Standard-Benchmark, den wir noch nicht bezwungen haben - und die Zahl ist die Bestmarke über alle WOS-Modelle hinweg, neu geschrieben, sobald ein besseres erscheint. Überschreiten wir klar 94%, steigen wir zu einem härteren Benchmark auf.
Zwei Token-Preise pro Modell,
plus $0.0001 pro Anfrage.
Pro Million Tokens plus pauschal $0.0001 pro Anfrage, Bezahlung nach Verbrauch. Kein Abonnement, keine Speichermiete, keine Gedächtnisgrenzen. Sie zahlen, wenn Ihr Agent schreibt oder liest - nie für das, was er sich merkt.
| Modell | Eingabe / 1M | Ausgabe / 1M | |
|---|---|---|---|
| Tablet 1 | $2 | $3 | Live |
| Scroll 1 | $4 | $8 | Live |
| Codex 1 | - | - | Noch offen |
- $0.0001 pro Anfrage. Eine Pauschalgebühr auf jeden API-Aufruf, zusätzlich zur Token-Nutzung.
- Speicherung ist kostenlos. Die Aufnahme wird einmal bezahlt; das Aufbewahren kostet Sie nichts. Kein Mengenlimit, keine Aufbewahrungsgrenze.
- Wir speichern es. Wir trainieren nie darauf, verwenden es nicht und sehen es nicht ein. Das Gedächtnis Ihres Agenten gehört Ihnen - wir organisieren es nur, damit Sie es abrufen können.
- Warum Tablet so günstig ist: Seine Engine führt kein Modell aus, unsere Kosten sind also Embeddings und Festplatten - keine GPUs. Scroll und Codex ergänzen ein Modell, und genau das deckt ihr höherer Preis ab.
Drei Aufrufe: Speichern, Abrufen, Antworten.
Eine API. Der Aufruf recall() liefert Kurzzeit-, Langzeit- und Umgebungskontext in einem einzigen Roundtrip - bereit zum Einfügen in Ihren Prompt.
Speichern
add() speichert Fakten und Gespräche: die Worte deines Nutzers, die eigenen des Assistenten (speaker "me") oder die einer benannten Person. Beim Eingang eingebettet, ohne LLM-Aufruf.
Abrufen
recall() liefert Kurzzeit + Langzeit + Kontext in einem Aufruf - ein begrenzter Kontext fester Größe.
Antworten
Übergeben Sie diesen begrenzten Kontext an Ihr LLM - beliebiger Anbieter, Ihr Schlüssel.
from wontopos import Client mem = Client(api_key="wos-...") mem.add("she prefers tea over coffee", user_id="alice") mem.add("I suggested the jasmine tea", user_id="alice", speaker="me") # its own words # one call: short + long + context ctx = mem.recall("what does alice drink?", user_id="alice")
Erinnerungen tragen einen Sprecher. Standard sind die Worte deines Nutzers, speaker "me" speichert, was der Assistent selbst gesagt hat, und ein Name wie "Bob" merkt sich, wer es gesagt hat — Erinnern nach Person.
Ihr erster Recall in 5 Minuten.
Ein Schlüssel, eine Installationszeile, drei Aufrufe - und Ihr Agent hat ein Gedächtnis. Jedes Snippet auf dieser Seite wurde tatsächlich ausgeführt; die Antworten sind wortwörtlich wiedergegeben.
API-Schlüssel erstellen
Erstellen Sie einen in der Konsole. Ein 155 Zeichen langer Schlüssel, der mit wos-live- beginnt, wird einmal angezeigt. Bewahren Sie ihn in einer Umgebungsvariable auf - niemals im Code.
Installieren
pip install wontopos # Python npm install wontopos # TypeScript / JavaScript cargo add wontopos # Rust # curl - nothing to install, just set WOS_API_KEY
Store anlegen, dann speichern & abrufen
Ein Store ist die user_id, unter der Sie lesen und schreiben. Stores sind explizit: Legen Sie zuerst einen an (der Aufruf unten), dann speichern Sie hinein und rufen daraus ab. Speichern - beim Eingang eingebettet, kein LLM-Aufruf. Abrufen - Kurzzeit + Langzeit + Kontext in einem Roundtrip.
from wontopos import Client
mem = Client(api_key="wos-live-...", user_id="alice") # set the store once
mem.create_store() # create it (stores are explicit)
mem.add("she prefers tea over coffee") # no user_id needed
# one call → short-term + long-term + context
ctx = mem.recall("what does alice drink?"){"user_id": "alice", "status": "created"}{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}user_id an den Client, und jeder Aufruf verwendet sie - kein Wiederholen nötig; überschreiben Sie einen einzelnen Aufruf, indem Sie ihm user_id übergeben. Stores sind explizit: Das Speichern in einen oder Abrufen aus einem Store, der nicht existiert, liefert 404 - legen Sie ihn zuerst an. Jedes Konto startet mit einem default-Store, sodass der Pfad ganz ohne user_id ohne jede Einrichtung funktioniert. Siehe Stores zum Auflisten und Verwalten.recall() liefert vier Blöcke - short_term (jüngste Gesprächszüge), long_term (relevante Erinnerungen), context (das Umfeld des besten Treffers) und eine instruction, die dem LLM sagt, wie es sie verwenden soll. Fügen Sie das Ganze in Ihren Prompt ein.
Stores - anlegen, auflisten, löschen.
Ein Store ist die user_id, unter der Sie lesen und schreiben - ein isolierter Gedächtnisraum pro Endnutzer, Agent oder Thema. Stores sind explizit: Legen Sie einen an, bevor Sie hineinspeichern oder daraus abrufen, sonst liefert der Aufruf 404. Jedes Konto startet mit einem default-Store, Sie können also ohne Create-Aufruf beginnen.
mem.create_store("alice") # create (idempotent)
mem.list_stores() # [{"user_id","created_at"}, ...]
mem.delete_store("alice") # delete the store + all its memories{ "user_id": "alice", "status": "created" } // "exists" if it already did{ "collections": [
{ "user_id": "default", "created_at": "2026-06-26T02:23:14Z" },
{ "user_id": "alice", "created_at": "2026-06-26T02:24:01Z" }
], "count": 2 }{ "error": { "type": "not_found_error",
"message": "Store 'ghost' does not exist. Create it first with
POST /api/v1/memory/collection {\"user_id\":\"ghost\"}, then store or recall." } }"alice", "user_42"), um die Erinnerungen jeder Person getrennt zu halten, oder einen einzelnen default-Store für einen persönlichen Agenten. Stores lassen sich auch in der Konsole anlegen und durchsehen (Memory ids → Issue), ganz ohne Code. Das Löschen eines Stores ist endgültig - es entfernt jede Erinnerung darin.Wiederholte Abrufe, zum Zehntel des Preises.
Aktiviere es pro Anfrage, und WOS cached das Suchergebnis unter dem Abfragetext, mit denselben Präfixregeln wie beim Prompt Caching von LLMs. Solange der Cache warm ist, nutzt eine wiederholte oder erweiterte Abfrage das vorherige Ergebnis wieder, und der gecachte Teil wird mit 10% des normalen Token-Preises berechnet.
Ein Gespräch, drei Runden
So sieht es wirklich aus, wenn ein Agent immer weiter mit seinem Gedächtnis spricht. Jede Runde schickt das bisherige Gespräch als Abfrage, mit aktiviertem cache_control.
Die gesamte Abfrage wird gesucht und gecacht: Eingabe zum 2-fachen (TTL 5 Minuten).
Nur Bobs Satz wird eingebettet und gesucht. Der alte Teil kostet 0,1x, der neue Satz 2x, und der Cache endet jetzt dort.
Gar kein Engine-Aufruf. Alles zu 0,1x: der 90%-Rabatt.
Die Preise
| Vorgang | Token-Abrechnung | Bedeutung |
|---|---|---|
| Cache-Schreiben - TTL 5 Minuten | 2× | Die erste Anfrage. Ihr Ergebnis wird 5 Minuten aufbewahrt, und jedes Lesen verschiebt das Fenster nach vorn. |
| Cache-Schreiben - TTL 1 Stunde | 3× | Die erste Anfrage, eine volle Stunde aufbewahrt. |
| Cache-Lesen - Treffer oder Präfix-Treffer | 0.1× | Jede Anfrage nach dem Schreiben: Der gecachte Teil kostet ein Zehntel des normalen Token-Preises. |
Was es spart
Ein konkretes Beispiel: Dein Agent schickt ein Gespräch mit 3.000 Tokens als Abfrage und wiederholt oder verlängert es 10-mal innerhalb von fünf Minuten. Ohne Caching sind das 30.000 Eingabe-Tokens zum vollen Preis. Mit einem 5-Minuten-Cache sind es 6.000 für das erste Schreiben (2x) plus rund 2.700 für die neun Cache-Lesevorgänge: 8.700 abgerechnete Tokens, 71% weniger. Je länger das Gespräch läuft, desto größer die Ersparnis.
Die Präfixregel
Der Abgleich erfolgt am Anfang der Abfrage. Bleibt der Anfang identisch und wird nur neuer Text angehängt, wird der gecachte Teil wiederverwendet und nur der neue Teil gesucht. Ändert sich etwas vor dem Ende des gecachten Textes, kann nichts wiederverwendet werden.
cached [ A B C D E F G ] ○ [ A B C D E F G ] E ✗ [ B C D E F G ] E
○ Treffer - der Anfang ist unverändert, nur E ist neu
✗ Fehltreffer - der Anfang hat sich geändert, die gesamte Abfrage wird neu gesucht und neu gecacht
Drei Regeln zum Merken
- Erweitern cached bis zum neuen Ende neu. Nach [A B C D E F G] + E endet der Cache jetzt bei E: Das Ende wird einmal zum Schreibtarif berechnet, und die nächste Runde kann wieder ganz A..E als Präfix abgleichen.
- Ein zusammenhängendes Präfix pro Anfrage. Eine Abfrage kann nicht in zwei Cache-Segmente geteilt werden; nur ihr Anfang kann übereinstimmen.
- Schreibvorgänge invalidieren sofort. Jedes store, store-turn, bulk-store, forget, supersede oder Löschen des Stores verwirft dessen Cache. Eine gecachte Antwort kann nie veraltet sein.
So wird es aktiviert
hits = mem.search(
"...the conversation so far...", user_id="alice",
cache_control={"ttl": "5m"}, # or "1h"
){ "memories": [ ... ],
"cache": { "status": "hit", // "write" | "hit" | "extend"
"ttl": "5m",
"cache_read_input_tokens": 412,
"cache_creation_input_tokens": 0 } }Für all das brauchst du kein SDK. Caching ist ein Feld in einem HTTP-Aufruf und funktioniert daher aus jeder Programmiersprache. Der curl-Tab ist das universelle Rezept, und die Python-, TypeScript- und Rust-SDKs sind bequeme Hüllen um genau denselben Aufruf.
Gedächtnis, das weiß, wer es gesagt hat.
Menschen erinnern sich nach Person: was Bob versprochen hat, was du zugesagt hast. Gib jeder Erinnerung einen Sprecher und dein Agent tut dasselbe, auf jedem Tablet- und Scroll-Modell.
Ein Team, drei Erinnerungen
Ein Store hält viele Stimmen auseinander. Registriere eine Person einmal, speichere jede Äußerung unter ihrem Sprecher und frage später nach Person.
Der Store kennt Bob jetzt. Das 50er-Limit wird hier bei der Registrierung gezählt; Speicheraufrufe liefern nie einen Limit-Fehler.
Die Erinnerung gehört jetzt Bob: jede Suche, die sie zurückgibt, sagt das auch.
Auch die eigenen Worte werden erinnert, und "me" zählt nie gegen das Limit.
Nur Bobs Worte kommen zurück. Die Worte einer Person kommen nie als die einer anderen zurück.
Drei Regeln zum Merken
- "me" ist der Assistent selbst. Nie registriert, nie gezählt. Reserviert und kleingeschrieben:
speaker: "Me"oder"ME"liefert400 invalid_request_errorstatt stiller Umdeutung. - Das Limit zählt bei der Registrierung: zunächst 50 pro Store. Darüber hinaus liefert die Registrierung
400 invalid_request_errormitspeaker_limit: 50im Fehlerbody. Speichern mit unregistriertem Namen liefert ebenfalls400und speichert nichts. Suche mit unregistriertem Namen im Filter liefert404 not_found_error. Verzweige auf Status und Felder, nicht auf den Meldungstext; wir planen, das Limit anzuheben. - Labels leben in jeder Leseoperation. Suchergebnisse, der Langzeit-Kontext von recall und Engram-Ergebnisse tragen ihren Sprecher — das Modell weiß immer, wessen Worte es hält. Mit speaker in der Suche kommen nur die Worte einer Person zurück. Ein supersede behält den Sprecher; forget entfernt ihn.
- Namen sind Unicode: jede Sprache funktioniert. さくら, Иван und 하늘 sind gültige Sprecher, und die Zuordnung verhält sich in jeder Sprache identisch. Der Abgleich ist exakt nach Trim und Unicode-Normalisierung, also sind
Bobundbobzwei Personen. Namen sind bis 80 Zeichen lang.
# POST /speakers past the limit { "type": "error", "error": { "type": "invalid_request_error", "message": "This store already has 50 registered speakers, ...", "speaker_limit": 50 } } # store with an unregistered name → 400, nothing stored { "type": "error", "error": { "type": "invalid_request_error", "message": "speaker 'Bob' is not registered in this store. Register it first: ...", "speaker": "Bob" } } # search filtered by an unregistered name → 404 { "type": "error", "error": { "type": "not_found_error", "message": "speaker 'Bob' is not registered in this store.", "speaker": "Bob" } }
Zwei Randnotizen. speaker gehört zu add / store: add_turn merkt sich den ganzen Austausch, Personen-Labels und der Filter kommen aus Erinnerungen mit explizitem speaker. Und Sitzungspassagen (expand) sind Komposite mehrerer Erinnerungen, tragen also kein Label; ein speaker-Filter liefert immer atomare, gelabelte Erinnerungen. Und identischer Inhalt wird auf die erste Erinnerung dedupliziert: ein solcher store liefert status "duplicate" mit expliziter note, ohne angehängten Sprecher.
Wir testen das auf die harte Tour: Erinnerungen ohne Namen im Text, abgerufen pro Person. Die Zuordnung kommt aus dem Sprecher-Register, nicht aus Wortabgleich, und verhält sich daher in jeder Sprache gleich.
So nutzt du es
mem.add_speaker("Bob", user_id="alice") # once per person; "me" needs no registration
mem.add("Bob said the deadline moved to Tuesday", user_id="alice", speaker="Bob")
mem.add("I promised the summary by Friday", user_id="alice", speaker="me")
hits = mem.search("what did Bob say about the deadline?", user_id="alice", speaker="Bob")
mem.list_speakers(user_id="alice")
mem.remove_speaker("Bob", user_id="alice") # memories stay, the tag goes{ "memories": [
{ "content": "Bob said the deadline moved to Tuesday",
"speaker": "Bob", ... } ] }{ "user_id": "alice",
"speakers": [ { "speaker": "Bob", "memories": 2, "created_at": "2026-07-10T04:20:39Z" } ],
"count": 1, "limit": 50 }Die Liste zeigt, wen der Store kennt, mit Erinnerungszahl pro Person gegen das Limit. Entfernen löscht nur die Registrierung: die Erinnerungen bleiben, nur das Namenslabel geht.
MCP - Gedächtnis für KI-Tools
Der Kern von WOS sind API und SDKs. Der MCP-Server ist ein Add-on darüber: dasselbe Gedächtnis, eingesteckt in Tools, die du nicht gebaut hast - Claude Code, Claude Desktop, Cursor.
Eine Installationszeile gibt dem Agenten neun Gedächtnis-Tools, die er selbstständig nutzt. Und weil das Gedächtnis im Konto lebt, erinnert jedes andere Tool, was eines schreibt - auch Agenten, die du mit dem SDK baust.
Was damit möglich ist
- Ein Claude Code, der sich an dein Projekt erinnert. Entscheidungen, Bugfixes, Vorlieben - in der nächsten Sitzung abgerufen, ohne etwas neu zu erklären.
- In ChatGPT anfangen, in Claude weitermachen. Gleicher Store, gleiches Gedächtnis - das Gespräch wechselt das Tool, statt neu zu starten.
- Dein eigener Agent bleibt im Kreis. Was Claude Code lernt, ruft ein SDK-Agent ab - und was dein Agent speichert, erinnert Claude Code zurück.
Läuft in Claude Code, Claude Desktop, Cursor, Windsurf und jedem MCP-Host. ChatGPT erreicht dasselbe Gedächtnis über Actions plus die OpenAPI-Spec.
Installation
claude mcp add wontopos --env WONTOPOS_API_KEY=wos-live-... -- npx -y wontopos-mcpDer Agent bekommt neun Tools - recall · remember · search · update · forget · list_memories · engram · stats · create_store - jedes so beschrieben, dass er selbst weiß, wann er sie nutzt.
OpenAPI-Spec
Die vollständige maschinenlesbare Karte der API - jeder Endpoint, Request, Response und Fehler.
OpenAPI ist das Industriestandard-Format, um eine HTTP-API in einer maschinenlesbaren Datei zu beschreiben.
https://api.wontopos.com/openapi.jsonWas damit möglich ist
Postman: File → Import → URL einfügen - alle 16 Endpoints erscheinen als klickbare Collection. ChatGPT: GPT erstellen, Action hinzufügen, dieselbe URL einfügen. Codegen: openapi-generator -i .../openapi.json -g go baut einen Client in einer Sprache, die wir nicht ausliefern.
In Postman importieren, einen Client in einer Sprache generieren, die wir nicht ausliefern, ChatGPT Actions anbinden oder Contract-Checks in CI fahren. Ein Test pinnt sie an die echten Routen - sie kann nicht driften.
llms.txt
Die ganze API auf einer Textseite, die eine KI lesen kann.
llms.txt ist eine Web-Konvention: eine Klartextseite an der Site-Root, die einer KI alles Nötige über ein Produkt sagt.
https://wontopos.com/llms.txtIn die IDE oder den Coding-Agenten legen - er weiß sofort, wie man auf WOS baut: Auth, Endpoints, Patterns, Fehler. Mit jedem Release aktualisiert.
Dieselben Fakten wie die OpenAPI-Spec, anderes Publikum: Die Spec ist präzise Struktur für Tools, diese Datei ist Prosa, die eine KI (oder ein Mensch) in einem Zug liest. Beide aktualisieren sich mit jedem Release.
Dein Gedächtnis in jedem KI-Tool
Ein Befehl gibt Claude Code, Claude Desktop, Cursor oder jedem MCP-Host ein Langzeitgedächtnis auf Basis deines WOS-Kontos. Kein Integrationscode: Der Agent bekommt neun Gedächtnis-Tools und entscheidet selbst, wann er sie nutzt.
Installation
Claude Code, eine Zeile (Key vorher in der Konsole erstellen):
claude mcp add wontopos --env WONTOPOS_API_KEY=wos-live-... -- npx -y wontopos-mcp
# pick which store it remembers into (optional): add --env WONTOPOS_USER_ID=my-projectAdd to Cursor → · Add to VS Code →
Optionale Env: WONTOPOS_USER_ID setzt den Standard-Store, WONTOPOS_MODEL die Engine, WONTOPOS_BASE_URL ein Self-Hosted-Deployment. WONTOPOS_READ_ONLY=1 schaltet auf Nur-Lesen (nur Recall/Suche/Liste).
Bevor du einen Store teilst
- Nutze einen eigenen Key. Keys tragen ihren Workspace: Ein nur für MCP erstellter Key begrenzt, was verbundene Tools überhaupt erreichen - und lässt sich in der Konsole rotieren, ohne die App-Keys anzufassen.
- Nur-Lese-Modus.
WONTOPOS_READ_ONLY=1registriert gar keine Schreib-Tools: Der Agent kann erinnern, suchen, Erinnerungen auflisten, Engrams ausführen und Statistiken lesen, aber nichts speichern, aktualisieren, vergessen oder löschen. Richtig für Agenten, die Gedächtnis nutzen, nicht besitzen sollen. - Tool-Bestätigung anlassen. MCP-Hosts fragen standardmäßig vor jedem Tool-Lauf - lass das besonders für
forgetan, denn Löschungen teilen sich alle Tools des Stores. - Alles Gespeicherte kann jedes Tool mit dem Key abrufen. Speichere niemals Geheimnisse - API-Keys, Passwörter - als Erinnerungen.
- Erinnerte Inhalte sind Daten, keine Anweisungen. Die Tool-Beschreibungen sagen das dem Agenten explizit. Speichere trotzdem keinen nicht vertrauenswürdigen Fremdtext in einem Store, dem ein autonomer Agent folgt.
- Löschungen werden ebenfalls geteilt. Ein forget oder delete_all aus einem Tool löscht für alle.
- "me" meint den Agenten, der in den Store schreibt. Teilen sich mehrere Agenten einen Store, verschmelzen ihre "me"-Stimmen. Gib jedem Agenten einen eigenen Store (
WONTOPOS_USER_ID) für getrennte Identitäten. - Ein Konto zahlt. Alle verbundenen Tools ziehen vom selben Guthaben und Rate-Limit.
Dann einfach reden
Der Agent ruft das Tool remember auf. Dauerhaft im Store gespeichert: Das Sitzungsende ändert nichts.
Eine neue Sitzung hat null Verlauf. Der Agent ruft recall auf und antwortet aus dem Gedächtnis: freitags.
Sag einfach
- "Dieses Repo nutzt pnpm, merk dir das" →
rememberspeichert es; die nächste Sitzung weiß es schon. - "Welches Fehlerformat hatten wir letzte Woche festgelegt?" →
recallholt die Entscheidung zurück in den Kontext. - „Die Deadline ist jetzt Freitag.“ → der Agent merkt, dass es dem widerspricht, was er abgerufen hat, und ruft
updateauf, um die Erinnerung an Ort und Stelle zu korrigieren. - "Das ist falsch, vergiss es" → der Agent findet die Memory-Id und ruft
forgetauf - dein Host fragt vorher nach. - „Was weißt du über mich?“ →
list_memoriesblättert durch alles Gespeicherte, damit der Agent antworten oder aufräumen kann.
Nichts Besonderes zu formulieren - das sind normale Sätze, keine Befehle. Der Agent liest die Tool-Beschreibungen und wählt selbst.
Die neun Tools
recall- Kontext in einem Aufruf: jüngste Turns plus relevante Langzeiterinnerungen. Die Tool-Beschreibung weist den Agenten an, es zuerst aufzurufen, wenn Vergangenes zählt.remember- Speichert einen dauerhaften Fakt oder Beschluss.speaker: "me"markiert die eigenen Worte des Agenten; ein registrierter Name, wer es gesagt hat.search- Semantische Suche, optional mitspeaker-Filter pro Person.forget- Löscht eine Erinnerung per id.speakers- Registriert, listet oder entfernt die Personen eines Stores.create_store- Stores sind explizit: einer pro Endnutzer, Projekt oder Agent.
SDK oder MCP?
- Das SDK gehört in eine App, die du schreibst. Dein Code entscheidet exakt, wann gespeichert und was erinnert wird - deterministisch, typisiert, versioniert. Du baust ein Produkt? SDK.
- MCP steckt man in ein KI-Tool, das du nicht geschrieben hast. Der Agent entscheidet anhand der Tool-Beschreibungen, wann er Gedächtnis nutzt - null Code. Richtig für Claude Code, Claude Desktop, Cursor oder um einem fertigen Assistenten Gedächtnis zu geben.
Darunter dieselbe API, dieselben Stores - eine SDK-App und eine Claude-Code-Sitzung über MCP teilen ein Gedächtnis. Man wählt pro Oberfläche, nicht entweder-oder.
Ein Gedächtnis über alle Tools hinweg
Das Gedächtnis gehört dem Konto, nicht dem Tool. Derselbe Store, aus ChatGPT (Actions plus OpenAPI-Spec) geschrieben, wird in Claude Code und in deinen eigenen Agenten erinnert, und umgekehrt: Ein Gespräch, das in einem Tool beginnt, geht in einem anderen weiter.
Und weil es ein Store ist, kannst du Claude Code verlassen und dort weiterreden, wo du baust: Ein SDK-Agent mit demselben Key und Store erinnert alles, was Claude Code gerade gelernt hat - und was dein Agent speichert, erinnert Claude Code in der nächsten Sitzung.
npx wontopos-mcp): Dein Key bleibt in deiner Umgebung und läuft nie über einen Drittserver. Es umhüllt das TypeScript-SDK, also gelten automatische Retries, Redirect-Ablehnung und Key-Maskierung unverändert.Claude Code
Der Hauptweg: ein Befehl im Terminal, und jede Sitzung startet mit Gedächtnis.
- Erstelle einen API-Key in der Konsole. Der Key trägt seinen Workspace: ein Key = ein Gedächtnisraum.
- Registriere den Server.
--scope usermacht ihn in jedem Projekt verfügbar; ohne sieht ihn nur das aktuelle Projekt. - Prüfen:
/mcpin Claude Code ausführen -wontopossollte mit neun Tools gelistet sein. - Mach es automatisch: eine Zeile in deiner
CLAUDE.md- "wenn Vergangenes zählt, zuerst wontopos recall aufrufen" - und jede Sitzung startet ungefragt mit Gedächtnis.
claude mcp add wontopos --scope user \
--env WONTOPOS_API_KEY=wos-live-... -- npx -y wontopos-mcp
# pick a store (optional): add --env WONTOPOS_USER_ID=my-projectClaude Desktop
Füge den Block unten in claude_desktop_config.json ein (Einstellungen → Developer → Edit Config), starte die App neu - die neun Tools erscheinen. Hinweis: claude.ai im Web und mobil braucht einen Remote-MCP-Server, den WOS noch nicht anbietet - die Desktop-App ist der unterstützte Weg.
# claude_desktop_config.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Cursor
Füge den Block unten in ~/.cursor/mcp.json ein - oder nutze den Ein-Klick-Button - und starte Cursor neu. Der Agent übernimmt die neun Tools.
# ~/.cursor/mcp.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }VS Code
VS Code (Copilot-Agentenmodus) liest MCP-Server aus .vscode/mcp.json im Projekt - füge den Block unten ein oder nutze den Ein-Klick-Button.
# .vscode/mcp.json
{ "servers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Windsurf
Windsurf (Cascade) liest ~/.codeium/windsurf/mcp_config.json: Block unten einfügen und neu laden - dieselben neun Tools erscheinen.
# ~/.codeium/windsurf/mcp_config.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }ChatGPT
ChatGPTs MCP-Konnektoren akzeptieren nur Remote-Server; der unterstützte Weg ist heute ein Custom GPT mit einer Action: GPT erstellen, Action hinzufügen, die OpenAPI-Spec-URL unten einfügen und den API-Key als Auth-Header setzen. Dieses GPT ruft dann dasselbe Gedächtnis auf wie deine anderen Tools.
# GPT → Configure → Actions → Import from URL
https://api.wontopos.com/openapi.json
# Authentication: API Key · Header name: X-API-KeyGleicher Store, gleiches Gedächtnis: Was ChatGPT über die Action speichert, erinnert Claude Code über MCP - und umgekehrt.
Gemini CLI
Gemini CLI liest MCP-Server aus ~/.gemini/settings.json: Block unten einfügen, CLI neu starten - dieselben neun Tools erscheinen auch dort.
# ~/.gemini/settings.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Python - jede Methode, drei Gruppen.
Schreiben, Lesen, Löschen. Jedes Beispiel unten wurde am 2026-07-10 gegen die Live-API ausgeführt; die Antworten sind wortwörtlich wiedergegeben.
pip install wontopos
from wontopos import Client mem = Client(api_key="wos-live-...") # or read from an env var
Modell wählen
Der API-Schlüssel bestimmt, welches Gedächtnis (Ihr Konto); das Modell bestimmt, welche Engine es liest. Alle Modelle teilen sich ein Gedächtnis, Sie können also mit einem speichern und mit einem anderen abrufen. Setzen Sie einen Standard am Client; überschreiben Sie einen einzelnen Aufruf, indem Sie ihm model= übergeben.
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 ✓ live-tested
Der Katalog - die IDs, die Sie an model übergeben können, und ob sie jeweils live sind. Modelle mit memory: "shared" lesen denselben Store; "isolated" führt einen eigenen. Benötigt keinen API-Schlüssel.
mem.list_models()[{"id": "tablet-1", "name": "Tablet 1", "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 ✓ live-tested
Verbindung und Gültigkeit des API-Schlüssels in einer Zeile prüfen.
mem.ping() # True, or raises AuthenticationError / PaymentRequiredError
Der Katalog oben spiegelt stets die aktuell verfügbaren Modelle wider - übergeben Sie eine andere ID, erhalten Sie einen klaren Fehler. Neue Modelle erscheinen dort automatisch, sobald sie ausgeliefert werden.
Schreiben
add ✓ live-tested
Eine Erinnerung speichern. Beim Eingang eingebettet - kein LLM-Aufruf, Sie zahlen nur Embeddings.
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 ✓ live-tested
Einen Gesprächszug (Nutzer + Assistent) zugleich ins Kurzzeit- und Langzeitgedächtnis speichern.
mem.add_turn("hi", "hello!", user_id="alice")
{"status": "ok"}speaker ✓ live-tested
Jede Erinnerung kann tragen, wer sie gesagt hat. Registriere eine Person einmal und übergib danach ihren Namen als speaker; "me" (die eigenen Worte des Assistenten) braucht nie eine Registrierung. Auch die Suche akzeptiert speaker, um nur die Worte einer Person zu holen.
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")
{"memories": [{"content": "Bob said the deadline moved to Tuesday", "speaker": "Bob", ...}]}add_bulk ✓ live-tested
Einen großen Textblock nachladen. Serverseitig zerlegt und eingebettet - ideal zum Import bestehender Historie.
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 ✓ live-tested
Ein Fakt hat sich geändert. Die alte Erinnerung wird als ersetzt markiert (für die Historie behalten); die neue nimmt ihren Platz im Recall ein.
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"}Lesen
search ✓ live-tested
Semantische Suche, das Relevanteste zuerst. Reines Embedding - kein Keyword-Matching, jede Sprache findet also jede Erinnerung. Das SDK gibt das memories-Array direkt zurück; der rohe HTTP-Body ist unten abgebildet.
r = mem.search("what does she drink?", user_id="alice", limit=1)
{"memories": [{
"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"
}], "search_ms": 315, "total_found": 1}| Feld | Bedeutung |
|---|---|
| similarity | Rohe Embedding-Ähnlichkeit zu Ihrer Abfrage (0–1). |
| is_superseded | True, wenn dieser Fakt durch update() ersetzt wurde. |
| search_ms | Serverseitige Abrufzeit. |
recall ✓ live-tested
Ein Roundtrip liefert alles, was Ihr LLM braucht - fügen Sie das Ergebnis direkt in Ihren Prompt ein: ein begrenzter Kontext fester Größe, egal wie viel Sie gespeichert haben.
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 ✓ live-tested
Jüngste Gesprächszüge (Kurzzeitgedächtnis), älteste zuerst.
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 ✓ live-tested
Anzahl der Erinnerungen für einen Nutzer.
mem.stats("alice")
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
Ruft eine einzelne Erinnerung per id ab - die id, die add oder list_memories zurückgegeben hat. Nur der gespeicherte Originaltext plus Metadaten, nie der Vektor. Eine id aus einem anderen Store oder eine gelöschte/invalidierte Erinnerung ergibt 404.
m = mem.get("alice", memory_id="576700aa-...")
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}list_memories ✓ live-tested
Listet die Erinnerungen eines Stores auf - nur der gespeicherte Originaltext und seine Metadaten, nie der Vektor. Seitenweise per Cursor: den zurückgegebenen next_cursor für die nächste Seite mitgeben.
page = mem.list_memories("alice", limit=100)
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}
]}iter_memories · export_memories
Alle Erinnerungen ohne Cursor-Verwaltung durchlaufen oder den ganzen Store auf einmal holen.
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
Löschen
delete ✓ live-tested
Eine einzelne Erinnerung per ID löschen.
mem.delete("alice", memory_id="576700aa-...")
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
Alles für einen Nutzer löschen - ein Aufruf, DSGVO-bereit.
mem.delete_all("alice")
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Fehler und Zuverlässigkeit
Jeder Fehler ist typisiert - fange den konkreten (Rate-Limit, Auth, Zahlung) oder alle mit dem Basis-WosError.
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
Lies das verbleibende Kontingent nach jedem Aufruf und drossle, bevor du das Limit erreichst.
mem.search("...", user_id="alice") rl = mem.rate_limit # {"limit": 150, "remaining": 3, "reset": ...}
TypeScript - jede Methode, drei Gruppen.
Schreiben, Lesen, Löschen. Jedes Beispiel unten wurde am 2026-07-10 gegen die Live-API ausgeführt; die Antworten sind wortwörtlich wiedergegeben.
npm install wontopos
import { Client } from "wontopos"; const mem = new Client({ apiKey: "wos-live-..." });
Modell wählen
Der API-Schlüssel bestimmt, welches Gedächtnis (Ihr Konto); das Modell bestimmt, welche Engine es liest. Alle Modelle teilen sich ein Gedächtnis, Sie können also mit einem speichern und mit einem anderen abrufen. Setzen Sie einen Standard im Konstruktor; überschreiben Sie einen einzelnen Aufruf mit withModel().
const mem = new Client({ apiKey: "wos-live-...", model: "tablet-1" }); // default mem.recall("...", "alice"); // tablet-1 mem.withModel("scroll-1").recall("...", "alice"); // or pick a model per call
listModels ✓ live-tested
Der Katalog - die IDs, die Sie an model übergeben können, und ob sie jeweils live sind. Modelle mit memory: "shared" lesen denselben Store; "isolated" führt einen eigenen. Benötigt keinen API-Schlüssel.
await mem.listModels();
[{"id": "tablet-1", "name": "Tablet 1", "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 ✓ live-tested
Verbindung und Gültigkeit des API-Schlüssels in einer Zeile prüfen.
await mem.ping(); // true, or throws AuthenticationError / PaymentRequiredError
Der Katalog oben spiegelt stets die aktuell verfügbaren Modelle wider - übergeben Sie eine andere ID, erhalten Sie einen klaren Fehler. Neue Modelle erscheinen dort automatisch, sobald sie ausgeliefert werden.
Schreiben
add ✓ live-tested
Eine Erinnerung speichern. Beim Eingang eingebettet - kein LLM-Aufruf, Sie zahlen nur Embeddings.
await mem.add("she prefers tea over coffee", "alice"); await mem.add("I promised the summary by Friday", "alice", { speaker: "me" }); // its own words - no registration needed
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}addTurn ✓ live-tested
Einen Gesprächszug (Nutzer + Assistent) zugleich ins Kurzzeit- und Langzeitgedächtnis speichern.
await mem.addTurn("hi", "hello!", "alice");
{"status": "ok"}speaker ✓ live-tested
Jede Erinnerung kann tragen, wer sie gesagt hat. Registriere eine Person einmal und übergib danach ihren Namen als speaker; "me" (die eigenen Worte des Assistenten) braucht nie eine Registrierung. Auch die Suche akzeptiert speaker, um nur die Worte einer Person zu holen.
await mem.addSpeaker("Bob", "alice"); # once per person; "me" needs no registration await mem.add("I promised to send the report on Friday", "alice", { speaker: "me" }); await mem.add("Bob said the deadline moved to Tuesday", "alice", { speaker: "Bob" }); await mem.search("what did Bob say about deadlines?", "alice", 10, { speaker: "Bob" });
addBulk ✓ live-tested
Einen großen Textblock nachladen. Serverseitig zerlegt und eingebettet - ideal zum Import bestehender Historie.
await mem.addBulk("Alice moved to Brooklyn in March. She works at a design studio downtown.", "alice");
{"elapsed_secs": 0.154154944, "status": "ok", "stored": 1, "total_chunks": 1}update ✓ live-tested
Ein Fakt hat sich geändert. Die alte Erinnerung wird als ersetzt markiert (für die Historie behalten); die neue nimmt ihren Platz im Recall ein.
await mem.update("576700aa-...", "she switched to coffee this year", "alice");
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}Lesen
search ✓ live-tested
Semantische Suche, das Relevanteste zuerst. Reines Embedding - kein Keyword-Matching, jede Sprache findet also jede Erinnerung. Das SDK gibt das memories-Array direkt zurück; der rohe HTTP-Body ist unten abgebildet.
const r = await mem.search("what does she drink?", "alice", 1);
{"memories": [{
"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"
}], "search_ms": 315, "total_found": 1}| Feld | Bedeutung |
|---|---|
| similarity | Rohe Embedding-Ähnlichkeit zu Ihrer Abfrage (0–1). |
| is_superseded | True, wenn dieser Fakt durch update() ersetzt wurde. |
| search_ms | Serverseitige Abrufzeit. |
recall ✓ live-tested
Ein Roundtrip liefert alles, was Ihr LLM braucht - fügen Sie das Ergebnis direkt in Ihren Prompt ein: ein begrenzter Kontext fester Größe, egal wie viel Sie gespeichert haben.
const ctx = await mem.recall("what does she drink?", "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 ✓ live-tested
Jüngste Gesprächszüge (Kurzzeitgedächtnis), älteste zuerst.
const turns = await 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 ✓ live-tested
Anzahl der Erinnerungen für einen Nutzer.
await mem.stats("alice");
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
Ruft eine einzelne Erinnerung per id ab - die id, die add oder list_memories zurückgegeben hat. Nur der gespeicherte Originaltext plus Metadaten, nie der Vektor. Eine id aus einem anderen Store oder eine gelöschte/invalidierte Erinnerung ergibt 404.
const m = await mem.get("alice", "576700aa-...");
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}listMemories ✓ live-tested
Listet die Erinnerungen eines Stores auf - nur der gespeicherte Originaltext und seine Metadaten, nie der Vektor. Seitenweise per Cursor: den zurückgegebenen next_cursor für die nächste Seite mitgeben.
const page = await mem.listMemories("alice", { limit: 100 });
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}
]}iterMemories · exportMemories
Alle Erinnerungen ohne Cursor-Verwaltung durchlaufen oder den ganzen Store auf einmal holen.
for await (const m of mem.iterMemories("alice")) console.log(m.id, m.content); const everything = await mem.exportMemories("alice");
Löschen
delete ✓ live-tested
Eine einzelne Erinnerung per ID löschen.
await mem.delete("alice", "576700aa-...");
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}deleteAll ✓ live-tested
Alles für einen Nutzer löschen - ein Aufruf, DSGVO-bereit.
await mem.deleteAll("alice");
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Fehler und Zuverlässigkeit
Jeder Fehler ist typisiert - fange den konkreten (Rate-Limit, Auth, Zahlung) oder alle mit dem Basis-WosError.
import { NotFoundError, PaymentRequiredError } from "wontopos"; try { await mem.add("...", "alice"); } catch (e) { if (e instanceof NotFoundError) await mem.createStore("alice"); else if (e instanceof PaymentRequiredError) topUp(); // out of credit else throw e; }
rateLimit
Lies das verbleibende Kontingent nach jedem Aufruf und drossle, bevor du das Limit erreichst.
await mem.search("...", "alice"); const rl = mem.rateLimit; // { limit: 150, remaining: 3, reset: ... }
Rust - jede Methode, drei Gruppen.
Schreiben, Lesen, Löschen. Jedes Beispiel unten wurde am 2026-07-10 gegen die Live-API ausgeführt; die Antworten sind wortwörtlich wiedergegeben.
cargo add wontopos
use wontopos::Client; let mem = Client::new("wos-live-...");
Modell wählen
Der API-Schlüssel bestimmt, welches Gedächtnis (Ihr Konto); das Modell bestimmt, welche Engine es liest. Alle Modelle teilen sich ein Gedächtnis, Sie können also mit einem speichern und mit einem anderen abrufen. Setzen Sie einen Standard mit with_model(); verketten Sie es erneut, um einen einzelnen Aufruf zu überschreiben.
let mem = Client::new("wos-live-...").with_model("tablet-1"); // default mem.recall("...", "alice").await?; // tablet-1 mem.with_model("scroll-1").recall("...", "alice").await?; // or pick a model per call
list_models ✓ live-tested
Der Katalog - die IDs, die Sie an with_model übergeben können, und ob sie jeweils live sind. Modelle mit memory: "shared" lesen denselben Store; "isolated" führt einen eigenen. Benötigt keinen API-Schlüssel.
mem.list_models().await?;
[{"id": "tablet-1", "name": "Tablet 1", "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 ✓ live-tested
Verbindung und Gültigkeit des API-Schlüssels in einer Zeile prüfen.
mem.ping().await?; // Ok(true), or Err whose .kind() is Auth / PaymentRequired
Der Katalog oben spiegelt stets die aktuell verfügbaren Modelle wider - übergeben Sie eine andere ID, erhalten Sie einen klaren Fehler. Neue Modelle erscheinen dort automatisch, sobald sie ausgeliefert werden.
Schreiben
add ✓ live-tested
Eine Erinnerung speichern. Beim Eingang eingebettet - kein LLM-Aufruf, Sie zahlen nur Embeddings.
mem.add("she prefers tea over coffee", "alice", json!({})).await?; mem.add("I promised the summary by Friday", "alice", json!({"speaker": "me"})).await?; // its own words - no registration needed
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}add_turn ✓ live-tested
Einen Gesprächszug (Nutzer + Assistent) zugleich ins Kurzzeit- und Langzeitgedächtnis speichern.
mem.add_turn("hi", "hello!", "alice").await?;
{"status": "ok"}speaker ✓ live-tested
Jede Erinnerung kann tragen, wer sie gesagt hat. Registriere eine Person einmal und übergib danach ihren Namen als speaker; "me" (die eigenen Worte des Assistenten) braucht nie eine Registrierung. Auch die Suche akzeptiert speaker, um nur die Worte einer Person zu holen.
mem.add_speaker("Bob", "alice").await?; # once per person; "me" needs no registration mem.add("I promised to send the report on Friday", "alice", json!({"speaker": "me"})).await?; mem.add("Bob said the deadline moved to Tuesday", "alice", json!({"speaker": "Bob"})).await?; mem.search_with("what did Bob say about deadlines?", "alice", 10, json!({"speaker": "Bob"})).await?;
add_bulk ✓ live-tested
Einen großen Textblock nachladen. Serverseitig zerlegt und eingebettet - ideal zum Import bestehender Historie.
mem.add_bulk("Alice moved to Brooklyn in March...", "alice", "general").await?;
{"elapsed_secs": 0.154154944, "status": "ok", "stored": 1, "total_chunks": 1}update ✓ live-tested
Ein Fakt hat sich geändert. Die alte Erinnerung wird als ersetzt markiert (für die Historie behalten); die neue nimmt ihren Platz im Recall ein.
mem.update("576700aa-...", "she switched to coffee this year", "alice").await?;
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}Lesen
search ✓ live-tested
Semantische Suche, das Relevanteste zuerst. Reines Embedding - kein Keyword-Matching, jede Sprache findet also jede Erinnerung. Das SDK gibt das memories-Array direkt zurück; der rohe HTTP-Body ist unten abgebildet.
let r = mem.search("what does she drink?", "alice", 1).await?;
{"memories": [{
"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"
}], "search_ms": 315, "total_found": 1}| Feld | Bedeutung |
|---|---|
| similarity | Rohe Embedding-Ähnlichkeit zu Ihrer Abfrage (0–1). |
| is_superseded | True, wenn dieser Fakt durch update() ersetzt wurde. |
| search_ms | Serverseitige Abrufzeit. |
recall ✓ live-tested
Ein Roundtrip liefert alles, was Ihr LLM braucht - fügen Sie das Ergebnis direkt in Ihren Prompt ein: ein begrenzter Kontext fester Größe, egal wie viel Sie gespeichert haben.
let ctx = mem.recall("what does she drink?", "alice").await?;
{"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 ✓ live-tested
Jüngste Gesprächszüge (Kurzzeitgedächtnis), älteste zuerst.
let turns = mem.history("alice").await?;
{"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 ✓ live-tested
Anzahl der Erinnerungen für einen Nutzer.
mem.stats("alice").await?;
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
Ruft eine einzelne Erinnerung per id ab - die id, die add oder list_memories zurückgegeben hat. Nur der gespeicherte Originaltext plus Metadaten, nie der Vektor. Eine id aus einem anderen Store oder eine gelöschte/invalidierte Erinnerung ergibt 404.
let m = mem.get("alice", "576700aa-...").await?;
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}list_memories ✓ live-tested
Listet die Erinnerungen eines Stores auf - nur der gespeicherte Originaltext und seine Metadaten, nie der Vektor. Seitenweise per Cursor: den zurückgegebenen next_cursor für die nächste Seite mitgeben.
mem.list_memories("alice", 100, None).await?;
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}
]}list_all_memories
Alle Erinnerungen ohne Cursor-Verwaltung durchlaufen oder den ganzen Store auf einmal holen.
let all = mem.list_all_memories("alice").await?; // every page, collected
Löschen
delete ✓ live-tested
Eine einzelne Erinnerung per ID löschen.
mem.delete("alice", "576700aa-...").await?;
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
Alles für einen Nutzer löschen - ein Aufruf, DSGVO-bereit.
mem.delete_all("alice").await?;
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Fehler und Zuverlässigkeit
Jeder Fehler ist typisiert - fange den konkreten (Rate-Limit, Auth, Zahlung) oder alle mit dem Basis-WosError.
use wontopos::ErrorKind; match mem.search("...", "alice", 10).await { Ok(hits) => { /* use hits */ } Err(e) if e.kind() == ErrorKind::NotFound => { mem.create_store("alice").await?; } Err(e) if e.is_rate_limited() => { /* back off */ } Err(e) => return Err(e), }
rate_limit
Lies das verbleibende Kontingent nach jedem Aufruf und drossle, bevor du das Limit erreichst.
mem.search("...", "alice", 10).await?; let rl = mem.rate_limit(); // Some(RateLimit { remaining: Some(3), .. })
curl - keine Installation, dieselben Methoden.
Kein SDK zu installieren - jeder HTTP-Client funktioniert. Setzen Sie Ihren Schlüssel einmal und rufen Sie dieselben Endpunkte auf, die die SDKs kapseln. Basis-URL https://api.wontopos.com, Authentifizierung über X-API-Key, JSON rein und raus.
# set your key once (never hard-code it) export WOS_API_KEY="wos-live-..."
Schreiben
store ✓ live-tested
Eine Erinnerung speichern. Beim Eingang eingebettet - kein LLM-Aufruf.
curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"she prefers tea over coffee"}'
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}store-turn ✓ live-tested
Einen Gesprächszug (Nutzer + Assistent) zugleich ins Kurzzeit- und Langzeitgedächtnis speichern.
curl -X POST https://api.wontopos.com/api/v1/memory/store-turn \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","user_msg":"hi","assistant_msg":"hello!"}'
{"status": "ok"}speaker ✓ live-tested
Jede Erinnerung kann tragen, wer sie gesagt hat. Registriere eine Person einmal und übergib danach ihren Namen als speaker; "me" (die eigenen Worte des Assistenten) braucht nie eine Registrierung. Auch die Suche akzeptiert speaker, um nur die Worte einer Person zu holen.
curl -X POST https://api.wontopos.com/api/v1/memory/speakers \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","speaker":"Bob"}' # once per person curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"I promised to send the report on Friday","metadata":{"speaker":"me"}}' curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"Bob said the deadline moved to Tuesday","metadata":{"speaker":"Bob"}}' curl -X POST https://api.wontopos.com/api/v1/memory/search \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what did Bob say about deadlines?","speaker":"Bob"}'
supersede ✓ live-tested
Ein Fakt hat sich geändert - die alte Erinnerung wird als ersetzt markiert, die neue nimmt ihren Platz im Recall ein.
curl -X POST https://api.wontopos.com/api/v1/memory/supersede \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","old_memory_id":"576700aa-...","new_content":"she switched to coffee this year"}'
{"new_memory_id": "07e94433-...", "old_memory_id": "576700aa-...", "status": "superseded"}Lesen
search ✓ live-tested
Semantische Suche, das Relevanteste zuerst. Reines Embedding - jede Sprache findet jede Erinnerung.
curl -X POST https://api.wontopos.com/api/v1/memory/search \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what does she drink?","max_results":1}'
{"memories": [{"id": "576700aa-...", "content": "she prefers tea over coffee",
"similarity": 0.63, "is_superseded": false}], "search_ms": 315, "total_found": 1}recall ✓ live-tested
Ein Roundtrip liefert Kurzzeit + Langzeit + Kontext + eine Instruktion. Fügen Sie es direkt in Ihren Prompt ein.
curl -X POST https://api.wontopos.com/api/v1/memory/recall \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what does she drink?"}'
{"short_term": {"count": 2, "turns": [...]},
"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"]},
"instruction": "Use short_term for recent context, long_term for relevant past memories..."}Löschen
forget ✓ live-tested
Eine Erinnerung per ID löschen - oder die ID weglassen, um alles für einen Nutzer zu löschen (DSGVO).
curl -X POST https://api.wontopos.com/api/v1/memory/forget \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice"}' # omit memory_id = delete all
{"memories_deleted": 1, "status": "deleted", "user_id": "alice"}Engrams
Aufrufbare Recall-Werkzeuge, die Ihr Modell einsetzen kann - jedes eine eigene Abrufstrategie über dasselbe Gedächtnis. Nutzen Sie eines oder führen Sie mehrere zugleich aus.
Regelmäßig erscheinen weitere Engramme - diese Liste wächst.
Memoir & Archive Scroll 1.2+
Dies ist eine Auslieferungs-Form, kein aufrufbares Werkzeug. Ab Scroll 1.2 wählen Sie sie pro Aufruf - form: "memoir" oder form: "archive" - und dieser Recall, eine einfache Suche eingeschlossen, kommt mit entsprechend geschriebener Zeit zurück.
Time_awareness Scroll 1.2+
Eine Auslieferungsform - pro Aufruf gewählt. Übergeben Sie form - memoir oder archive - bei einem beliebigen Aufruf eines formfähigen Modells (ab Scroll 1.2), und die Antwort kommt entsprechend gerendert zurück: eine einfache Suche, ein Recall oder jedes Engramm. In den SDKs ist es ein form-Feld wie tz; über HTTP der Header X-WOS-Form. Ein Memoir liest sich, wie ein Mensch sich erinnert; ein Archive führt ein exaktes Protokoll - der Unterschied zeigt sich am deutlichsten darin, wie beide die Zeit schreiben.
Memoir
form: "memoir"Erzählt, was geschah und wie ein Moment zum nächsten führte, mit dem weichen Zeitgefühl menschlicher Erinnerung - liest sich als Erlebnis, nicht als Liste.
Archive
form: "archive"Liefert Treffer als exakte Datensätze - präzise verstrichene Zeit und absolute Anker, so strukturiert, dass ein Modell sie direkt ablesen kann.
store-/add-Aufruf unter einer user_id (diese user_id ist der Store dieser Person). Zuerst speichern; danach kommt jeder Recall - die einfache Suche unten eingeschlossen - mit Zeitmarkierung zurück. Siehe Schnellstart zum Speichern.# plain search - no engram - the memoir form on Scroll 1.2
r = mem.search("what does Alice drink?", user_id="alice", model="scroll-1.2", form="memoir", tz=9)
# every hit gets a .time field → "a couple weeks ago" (form="archive" → "2 weeks ago (Jun 09)")tz ist der UTC-Versatz des Aufrufers in Stunden - damit "heute Morgen" und die 4-Uhr-Tagesgrenze in dessen Ortszeit landen. Weglassen für UTC; über HTTP ist es der X-WOS-Timezone-Header. Grob nach Region: US-Ostküste -5, US-Zentral -6, US-Westküste -8 · UK / Lissabon 0 · Mitteleuropa +1 · Osteuropa +2 · Indien +5.5 · China / Singapur +8 · Korea / Japan +9 · Sydney +10. (Normalzeit - die Sommerzeit verschiebt manche Regionen um +1; übergeben Sie, was für Ihre Nutzer tatsächlich gilt.)
Dieselbe Suche, zwei Formen - die Erinnerungen sind identisch, nur time ändert sich:
{ "count": 3, "memories": [
{ "content": "Alice prefers tea over coffee", "time": "a couple weeks ago" },
{ "content": "met Alice at the cafe downtown", "time": "yesterday afternoon" },
{ "content": "Alice moved to Brooklyn", "time": "about half a year ago" }
] }{ "count": 3, "memories": [
{ "content": "Alice prefers tea over coffee", "time": "2 weeks ago (Jun 09)" },
{ "content": "met Alice at the cafe downtown", "time": "yesterday at 14:00" },
{ "content": "Alice moved to Brooklyn", "time": "6 months ago (Dec 2025)" }
] }| Verstrichen | Memoir | Archive |
|---|---|---|
| 3 Min. | a few minutes ago | 3 minutes ago |
| 14 Min. | about 15 minutes ago | 14 minutes ago |
| 30 Min. | half an hour ago | 30 minutes ago |
| 50 Min. | about an hour ago | 50 minutes ago |
| 2 Std. | a couple hours ago | 2 hours ago, at 13:10 |
| 8 Std. | this morning | 8 hours ago, at 07:10 |
| gestern Nachm. | yesterday afternoon | yesterday at 14:00 |
| letzte Nacht | last night | 17 hours ago, at 22:00 |
| 2 Tage | a couple days ago | 2 days ago (Tue 15:10) |
| 6 Tage | several days ago | 6 days ago (Fri 15:10) |
| 9 Tage | about a week ago | last week (Jun 16) |
| 16 Tage | a couple weeks ago | 2 weeks ago (Jun 09) |
| 35 Tage | about a month ago | last month (May 21) |
| 60 Tage | a couple months ago | 2 months ago (Apr 2026) |
| 180 Tage | about half a year ago | 6 months ago (Dec 2025) |
| 380 Tage | about a year ago | last year (Jun 2025) |
| 800 Tage | a couple years ago | 2 years ago (Apr 2024) |
| 1500 Tage | about 4 years ago | 4 years ago (May 2022) |
Jeder Wert oben ist die tatsächliche Ausgabe des Renderers. Betrachten Sie die beiden "gestern"-Zeilen: Ein Memoir trennt den Nachmittag von der letzten Nacht - ein Tag ist ein Schlaf - während ein Archive eine einzelne Uhrzeit schreibt und keine Tag-Nacht-Grenze zieht.
Wie jeder Modus die Zeit liest
Memoir - so, wie Menschen es tatsächlich sagen. Jüngste Momente bleiben recht scharf (etwa 15 Minuten, eine halbe Stunde), dann weitet sich die Formulierung, je weiter man zurückgeht - ein paar Wochen, etwa ein halbes Jahr, ein paar Jahre - so, wie sich Erinnerung selbst mit der Entfernung lockert. Innerhalb eines Tages weicht die Uhr einem Orientierungspunkt: heute Morgen, letzte Nacht, gestern Nachmittag. Und ein Tag ist ein Schlaf, kein Kalendersprung: Die Grenze liegt bei etwa 4 Uhr Ortszeit, sodass eine späte Nacht noch als derselbe Abend gilt, nicht schon als morgen.
Archive - präzise, stets mit Anker. Jede Zeile trägt die exakte verstrichene Zeit plus eine absolute Referenz, mit der ein Modell rechnen kann, und der Anker wird enger, je näher es rückt: eine Uhrzeit für heute (vor 8 Stunden, um 07:10), Wochentag und Uhrzeit für diese Woche (vor 2 Tagen (Di 15:10)), ein Datum für diesen Monat (letzte Woche (16. Jun)), Monat und Jahr darüber hinaus (vor 6 Monaten (Dez 2025)). Nie vage, nie falsch.
deep_recall
Multi-Hop-Recall. Sucht nach Ihrer Abfrage, nimmt dann den besten Treffer und sucht erneut nach dessen Inhalt - und holt so verknüpften Kontext ein, den eine einzelne Suche übersehen würde. Am stärksten, wenn Erinnerungen aufeinander verweisen (eine Person → ihre Projekte → Details). Liefert bis zu ~12.
out = mem.engram("deep_recall", "what should I know about Alice?", user_id="alice"){ "engram": "deep_recall", "hops": 2, "count": 12,
"memories": [ ... ],
"usage": { "input_tokens": 5, "output_tokens": 61 } }usage (Eingabe + Ausgabe), gezählt mit demselben Tokenizer wie der Rest der API; keine versteckte Gebühr pro Engramm. Mehrere zugleich nötig? Rufen Sie sie parallel auf - jedes Engramm ist eine unabhängige Anfrage.timeline
Zeitlich geordneter Recall. Liefert Erinnerungen neueste zuerst, sortiert nach dem Zeitpunkt des Ereignisses, nicht nach Relevanz. Für "Wann war X", Verlauf und Reihenfolgefragen. Liefert bis zu 15.
events = mem.engram("timeline", "project milestones", user_id="alice"){ "engram": "timeline", "hops": 1, "count": 15,
"memories": [ ... ],
"usage": { "input_tokens": 4, "output_tokens": 88 } }usage (Eingabe + Ausgabe), gezählt mit demselben Tokenizer wie der Rest der API; keine versteckte Gebühr pro Engramm. Mehrere zugleich nötig? Rufen Sie sie parallel auf - jedes Engramm ist eine unabhängige Anfrage.gather
Breites Sammeln. Sucht und erweitert dann um die besten drei Treffer herum - ein weiteres Netz als deep_recall. Damit holen Sie alles zu einer Person, einem Projekt oder einem Thema in einem Aufruf ein. Liefert bis zu ~18.
related = mem.engram("gather", "everything about Project Atlas", user_id="alice"){ "engram": "gather", "hops": 4, "count": 18,
"memories": [ ... ],
"usage": { "input_tokens": 6, "output_tokens": 142 } }usage (Eingabe + Ausgabe), gezählt mit demselben Tokenizer wie der Rest der API; keine versteckte Gebühr pro Engramm. Mehrere zugleich nötig? Rufen Sie sie parallel auf - jedes Engramm ist eine unabhängige Anfrage.Jeder Endpunkt, eine Basis-URL.
Kein SDK erforderlich - jeder HTTP-Client funktioniert. Basis-URL https://api.wontopos.com, Authentifizierung über den X-API-Key-Header, JSON rein und raus. Memory-Operationen sind POST; die Verwaltung von Stores nutzt POST / GET / DELETE auf /collection. Ein Store muss zuerst existieren (siehe Stores), sonst liefern Operationen im Store 404.
| Endpunkt | Zweck | Body-Felder |
|---|---|---|
| POST /api/v1/memory/collection | Store anlegen | user_id |
| GET /api/v1/memory/collections | Ihre Stores auflisten | (keine) |
| DELETE /api/v1/memory/collection | Store + seine Erinnerungen löschen | user_id |
| /api/v1/memory/store | eine Erinnerung speichern | user_id · content · metadata? (speaker) |
| /api/v1/memory/store-turn | einen Gesprächszug speichern | user_id · user_msg · assistant_msg |
| POST /api/v1/memory/speakers | Sprecher registrieren (explizit, bis 50) | user_id · speaker |
| GET /api/v1/memory/speakers | registrierte Sprecher + Zähler auflisten | user_id |
| DELETE /api/v1/memory/speakers | Sprecher abmelden (Erinnerungen bleiben) | user_id · speaker |
| /api/v1/memory/bulk-store | einen Textblock nachladen | user_id · content · category? |
| /api/v1/memory/search | semantische Suche | user_id · query · max_results? · speaker? |
| /api/v1/memory/recall | Kurzzeit + Langzeit + Kontext | user_id · query |
| /api/v1/memory/history | jüngste Gesprächszüge | user_id |
| /api/v1/memory/stats | Anzahl der Erinnerungen | user_id |
| /api/v1/memory/supersede | einen geänderten Fakt ersetzen | user_id · old_memory_id · new_content |
| /api/v1/memory/forget | eine (oder alle) löschen | user_id · memory_id? (weglassen = alle löschen) |
# create the store once (stores are explicit) curl -X POST https://api.wontopos.com/api/v1/memory/collection \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice"}' # store a memory curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"she prefers tea over coffee"}' # recall - one call, ready for your prompt curl -X POST https://api.wontopos.com/api/v1/memory/recall \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what does alice drink?"}'
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}Dieselben Funktionen für alle.
Stufen erhöhen nur Ihre Limits.
Jede Stufe nutzt die vollständige Engine - dieselbe Recall-Qualität, dieselben Sprachen, jede Methode. Die Stufen steigen automatisch bis Stufe 5, während Ihre kumulierten Guthabenkäufe wachsen - ohne Antrag oder Vertriebsgespräch. Enterprise (Stufe 6) ist die einzige Ausnahme.
Ausgabenlimits
Jede Stufe begrenzt, wie viel Sie pro Kalendermonat ausgeben können. Sie steigen sofort auf, sobald Ihre kumulierten Guthabenkäufe die nächste Schwelle erreichen.
| Nutzungsstufe | Guthabenkauf | Monatliches Ausgabenlimit |
|---|---|---|
| Tier 1 | $5 | $100 |
| Tier 2 | $40 | $500 |
| Tier 3 | $200 | $1,000 |
| Tier 4 | $400 | $5,000 |
| Tier 5 | $1,000 | $25,000 |
| Tier 6 - Enterprise | Sprechen Sie mit uns | Kein Limit |
Rate-Limits
Rate-Limits gelten pro Konto - alle API-Schlüssel eines Kontos teilen sich ein Limit, das mit Ihrer Stufe skaliert. Bei Überschreitung kommt ein 429 mit einem retry-after-Header zurück; warten Sie gestaffelt (1s → 2s → 4s) und versuchen Sie es erneut. Jeder Endpunkt ist idempotenzfreundlich, Wiederholungen sind also sicher.
| Stufe | Anfragen pro Minute |
|---|---|
| Tier 1 | 150 |
| Tier 2 | 300 |
| Tier 3 | 600 |
| Tier 4 | 1,500 |
| Tier 5 | 3,000 |
| Tier 6 - Enterprise | Individuell |
Enterprise (Stufe 6) erhält individuelle Rate-Limits, ein SLA, dedizierten Support und optional eine Self-Host-Lizenz - sprechen Sie mit uns.
Wenn etwas schiefgeht.
Fehler kommen als JSON-Umschlag zurück, mit einem stabilen type, einer menschenlesbaren Meldung und einer request_id, die Sie uns bei der Meldung eines Problems mitschicken können.
{"type": "error", "error": {
"type": "authentication_error",
"message": "Invalid or revoked API key.",
"request_id": "063f8b83-eee2-4383-a5cf-11e4bcd29d7c"
}}| HTTP | Bedeutung | Was zu tun ist |
|---|---|---|
| 401 | Ungültiger oder widerrufener API-Schlüssel | Prüfen Sie den Schlüssel; stellen Sie in der Konsole einen neuen aus. |
| 422 | Fehlerhafter Body (fehlendes Feld oder falscher Typ) | Die Meldung nennt das genaue Feld - korrigieren und erneut versuchen. |
| 429 | Rate-Limit erreicht | Exponentiell warten (1s → 2s → 4s) und erneut versuchen. Sicher: Alle Endpunkte sind idempotenzfreundlich. |
| 5xx | Serverseitiges Problem | Mit Backoff erneut versuchen; geben Sie die request_id an, wenn Sie uns kontaktieren. |
# SDK error handling (Python) from wontopos import Client, WosError try: mem.search("...", user_id="alice") except WosError as e: if e.status == 401: ... # bad key elif e.status == 429: ... # back off and retry
Rate-Limits gelten pro Konto, geteilt über alle Ihre Schlüssel, und skalieren mit Ihrer Stufe - siehe Nutzungsstufen. Die Nutzung Ihres Kontos sehen Sie in der Konsole.
Ihre Server, Ihre Daten.
Die Engine kann in Ihrer eigenen Infrastruktur laufen - dieselbe API, dieselben SDKs. Richten Sie den Client auf Ihren Host, und sonst ändert sich nichts.
mem = Client(api_key="...", base_url="https://wos.your-host.com")- Datenresidenz. Erinnerungen verlassen Ihr Netzwerk nie.
- Dieselbe Oberfläche. Dieselben Methoden und Endpunkte funktionieren identisch.
- Lizenzierung. Self-Host-Pakete werden pro Deployment vereinbart - kontaktieren Sie uns.
Jenseits des Kontextfensters.
WOS ruft aus Historien von 1.4M Tokens ab - weit größer als jedes LLM-Kontextfenster - und liefert dennoch einen kompakten Ausschnitt von ~1.470 Tokens zurück.
Das Gedächtnis Ihres Agenten ist nicht dadurch begrenzt, was in einen Prompt passt. Es behält alles und ruft nur das Wesentliche ab, egal wie groß die Historie wird.
Privat, und Ihr Eigentum.
Ihre Daten bleiben in Ihrem Store. Wir trainieren nie darauf, sehen sie nicht ein und verwenden sie nicht weiter - wir organisieren sie nur, damit Sie sie abrufen können.
- BYOK. Ihr LLM-Schlüssel wird pro Anfrage gesendet und nie gespeichert.
- Isoliert. Erinnerungen sind pro Konto und darin pro
user_idabgegrenzt. - DSGVO-Löschung & Self-Hosting. Ein Aufruf löscht einen Nutzer vollständig; auf Wunsch betreiben Sie die Engine in Ihrer eigenen Umgebung.