Memoria a largo plazo para agentes de IA.
WOS es una API de memoria. Almacenas las memorias de un usuario una sola vez, luego recuperas solo las relevantes para cada consulta y las pasas al prompt de tu modelo.
La recuperación es puramente semántica, sin coincidencia de palabras clave ni BM25, por lo que la calidad del recall es idéntica en todos los idiomas. Cada consulta devuelve un contexto pequeño y acotado sin importar cuánto hayas almacenado, y nunca se ejecuta un modelo sobre tus memorias almacenadas.
Operaciones principales
store- guarda una memoria de un usuario.recall- obtiene las memorias relevantes para una consulta. Esta es la llamada principal.search- búsqueda semántica directa sobre las memorias almacenadas.supersede- actualiza o reemplaza una memoria desactualizada.forget- elimina una sola memoria o un usuario completo (GDPR).
Tres modelos, un mismo linaje.
Los modelos de WOS llevan el nombre de cómo la humanidad ha conservado el conocimiento a lo largo de la historia - Tablet, Scroll, Codex. Piedra, pergamino, libro encuadernado: cada uno hace más por tu agente que el anterior.
Tablet
DisponibleUna forma ligera, rápida y de bajo costo de inscribir y recuperar memoria - la base sobre la que se construye cada modelo.
Scroll
DisponibleAñade un modelo de lenguaje que lee tu pregunta con más detenimiento y trae de vuelta un contexto más completo, de modo que la evidencia dispersa regresa reunida en lugar de llegar con una pieza de menos.
Codex
PróximamenteSe abre solo en la página correcta - eligiendo la memoria y las herramientas que cada momento necesita, y afinándose cuanto más se usa.
El informe completo del benchmark de Tablet 1 está en la página de benchmarks.
Páganos $2. Ahorra muchas veces eso en tu LLM.
WOS entrega a tu LLM ~1,200 tokens por consulta - un fragmento acotado y relevante - en lugar de meter todo el historial en cada prompt. La diferencia es enorme, y crece con tu historial.
Cada $1 gastado en WOS ahorra ~$98 en el LLM. Un historial más grande o un modelo más caro → mayor ROI.
De dónde viene el ahorro
- Sin WOS metes todo el historial en cada prompt -
100K tokens × $2.50/1M = $0.25por consulta, a tarifas de entrada de GPT-4o (aproximadamente el doble en modelos de nivel Opus). - Con WOS ingieres una sola vez (
$2/1M), y luego cada consulta es una recuperación diminuta ($3/1M × 1,200) más tu LLM sobre apenas ~1,200 tokens. - Cuantos menos tokens lea tu LLM, menos pagas - y WOS mantiene esa cifra estable a medida que la memoria crece.
Todos los idiomas, la misma precisión.
La recuperación es puramente semántica - solo embeddings, cero coincidencia de palabras clave o BM25. Así que la calidad del recall es idéntica ya sea que tus usuarios escriban en 日本語, 中文, Español o English.
La coincidencia léxica como BM25 está ajustada a la forma de un idioma en particular - morfología, espaciado, escritura. En un store multilingüe eso significa que la calidad de la recuperación varía según el idioma. WOS no usa ninguna coincidencia léxica, así que todos los idiomas pasan por el mismo camino.
Un store, tres idiomas a la vez
No eliges un idioma por store - mézclalos libremente. Abajo, la memoria de un usuario contiene japonés, inglés y español al mismo tiempo, y cada pregunta encuentra la memoria correcta sin importar el idioma. Este es un intercambio real contra la API en vivo:
# 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
Sin paso de traducción, sin detección de idioma, sin configuración por idioma. Las memorias y las preguntas se ubican por significado, no por idioma - si el significado coincide, el idioma no importa.
Por qué prohibimos las palabras clave a propósito
La puntuación léxica como BM25 refuerza la recuperación en unos idiomas más que en otros, lo cual estorba cuando un store contiene muchos idiomas. Así que la eliminamos del motor por completo y hacemos cumplir esa regla en la revisión de código: con cualquier puntuación léxica en el camino, la calidad del recall diferiría según el idioma.
Ningún modelo se ejecuta sobre tus memorias.
El almacenamiento es literal y el motor busca por embeddings - barato, rápido y determinista. Nunca se ejecuta un modelo sobre tus memorias almacenadas. Tablet no usa ningún modelo; Scroll y Codex añaden uno alrededor del motor para obtener mejores resultados, pero solo ve tu consulta, nunca lo que almacenaste.
- Motor determinista. El motor devuelve las mismas memorias para la misma consulta, siempre - por eso la varianza de nuestro benchmark proviene únicamente del modelo lector.
- Barato a escala. Sin costo de generación al almacenar o recuperar, así que tu factura sigue al almacenamiento - no al uso de modelos - a medida que la memoria crece.
Tus palabras, intactas
Un diseño común ejecuta un modelo de lenguaje al momento de escribir para extraer y reescribir "hechos" del texto. Ese diseño sacrifica tres cosas: costo de generación en cada escritura, latencia añadida y el almacenamiento de la paráfrasis de un modelo en lugar de las palabras originales. WOS hace el intercambio opuesto - almacena lo que se dijo, sin cambios, y deja que tu LLM haga la interpretación al momento de leer, con el texto original en mano.
90.7%, medido y reproducible.
90.7% en LongMemEval-S, promediado sobre 5 ejecuciones independientes (σ 0.5%, ninguna seleccionada a conveniencia), calificado por el juez GPT-4o canónico del benchmark.
En el mismo benchmark, los puntajes varían ampliamente según el protocolo de calificación - el juez, el prompt y lo que se le permite hacer a la capa de recuperación. Usamos el juez GPT-4o canónico y de terceros del benchmark tal como fue publicado, no cambiamos nada para ajustarnos a la prueba, y publicamos el código de puntuación y el prompt del lector para que cualquiera pueda reproducir el 90.7% exactamente.
El protocolo, en una tabla
| Elemento | Qué hacemos |
|---|---|
| Dataset | LongMemEval-S (depurado), ~240K tokens de historial por pregunta |
| Juez | El juez GPT-4o canónico del benchmark - un tercero, no nosotros |
| Ejecuciones | 5 ejecuciones independientes, todos los puntajes publicados, se reporta la media (σ 0.5%) |
| Lector | Modelo lector y prompt fijos, publicados textualmente |
Lo que lo mantiene honesto: un juez de terceros, el prompt del lector publicado sin cambios, recuperación puramente semántica, y cada ejecución reportada - no solo la mejor. El motor de recuperación es determinista - ejecútalo de nuevo y obtienes las mismas memorias.
Escalamos benchmarks más difíciles
Probamos en el benchmark estándar más difícil que aún no hemos conquistado - y la cifra es la marca máxima entre todos los modelos de WOS, reescrita cada vez que sale uno mejor. Al superar el 94%, nos graduamos a un benchmark más difícil.
Dos tarifas de tokens por modelo,
más $0.0001 por solicitud.
Por millón de tokens más una tarifa fija de $0.0001 por solicitud, pago por uso. Sin suscripción, sin renta de almacenamiento, sin topes de memoria. Pagas cuando tu agente escribe o lee - nunca por lo que recuerda.
| Modelo | Entrada / 1M | Salida / 1M | |
|---|---|---|---|
| Tablet 1 | $2 | $3 | Disponible |
| Scroll 1 | $4 | $8 | Disponible |
| Codex 1 | - | - | Por definir |
- $0.0001 por solicitud. Una tarifa fija en cada llamada a la API, además del uso de tokens.
- El almacenamiento es gratis. La ingesta se paga una vez; conservarlo no te cuesta nada. Sin límite de cantidad, sin límite de retención.
- Nosotros lo almacenamos. Nunca entrenamos con él, lo usamos ni lo miramos. La memoria de tu agente es tuya - solo la organizamos para que puedas recuperarla.
- Por qué Tablet es tan barato: su motor no ejecuta ningún modelo, así que nuestro costo son embeddings y disco - no GPUs. Scroll y Codex añaden un modelo, y eso es lo que cubre su precio más alto.
Tres llamadas: store, recall, responder.
Una sola API. La llamada recall() devuelve el contexto de corto plazo, largo plazo y entorno en un solo viaje de ida y vuelta, listo para insertar en tu prompt.
Store
add() guarda hechos y turnos: las palabras de tu usuario, las del propio asistente (speaker "me") o las de una persona con nombre. Se incrusta al entrar, sin llamada a LLM.
Recall
recall() devuelve corto plazo + largo plazo + contexto en una sola llamada - un contexto acotado y de tamaño fijo.
Responder
Entrega ese contexto acotado a tu LLM - cualquier proveedor, tu clave.
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")
Los recuerdos llevan hablante. Por defecto son las palabras de tu usuario, speaker "me" guarda lo que dijo el propio asistente, y un nombre como "Bob" recuerda quién lo dijo, para poder recordar por persona.
Tu primer recall en 5 minutos.
Una clave, una línea de instalación, tres llamadas - tu agente ya tiene memoria. Cada fragmento de esta página se ejecutó de verdad; las respuestas se muestran textualmente.
Obtén una clave de API
Crea una en la consola. Una clave de 155 caracteres que empieza con wos-live- se muestra una sola vez. Guárdala en una variable de entorno - nunca en el código.
Instalar
pip install wontopos # Python npm install wontopos # TypeScript / JavaScript cargo add wontopos # Rust # curl - nothing to install, just set WOS_API_KEY
Crea un store, luego almacena & recupera
Un store es el user_id bajo el cual lees y escribes. Los stores son explícitos: crea uno primero (la llamada de abajo), luego almacena y recupera bajo él. Store - embebido al entrar, sin llamada a LLM. Recall - corto plazo + largo plazo + contexto en un solo viaje de ida y vuelta.
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 al cliente y todas las llamadas lo usarán - no hace falta repetirlo; anula una llamada puntual pasándole user_id. Los stores son explícitos: almacenar en o recuperar de un store que no existe devuelve 404 - créalo primero. Toda cuenta empieza con un store default, así que sin ningún user_id la ruta sin configuración simplemente funciona. Consulta Stores para listarlos y administrarlos.recall() devuelve cuatro bloques - short_term (turnos recientes), long_term (memorias relevantes), context (lo que rodeaba a la mejor coincidencia) y una instruction que le dice al LLM cómo usarlos. Inserta el conjunto completo en tu prompt.
Stores - crear, listar, eliminar.
Un store es el user_id bajo el cual lees y escribes - un espacio de memoria aislado por usuario final, agente o tema. Los stores son explícitos: crea uno antes de almacenar en él o recuperar de él, o la llamada devuelve 404. Toda cuenta empieza con un store default, así que puedes comenzar sin una llamada de creación.
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") para mantener separada la memoria de cada persona, o un único store default para un agente personal. También puedes crear y explorar stores en la consola (Memory ids → Issue) sin escribir código. Eliminar un store es permanente - borra todas las memorias que contiene.Recuperaciones repetidas, a la décima parte del precio.
Actívalo por solicitud y WOS almacenará en caché el resultado de búsqueda bajo el texto de la consulta, con las mismas reglas de prefijo que el prompt caching de los LLM. Mientras la caché está viva, una consulta repetida o extendida reutiliza el resultado anterior, y la parte cacheada se factura al 10% de la tarifa normal por token.
Una conversación, tres turnos
Esto es lo que ocurre realmente cuando un agente sigue hablando con su memoria. Cada turno envía la conversación acumulada como consulta, con cache_control activado.
La consulta completa se busca y se cachea: entrada a 2x (TTL de 5 minutos).
Solo la frase de Bob se convierte en embeddings y se busca. La parte antigua cuesta 0.1x, la frase nueva 2x, y la caché ahora termina en ella.
Ninguna llamada al motor. Todo a 0.1x: el descuento del 90%.
Las tarifas
| Operación | Facturación de tokens | Qué significa |
|---|---|---|
| Escritura de caché - TTL 5 minutos | 2× | La primera solicitud. Su resultado se conserva 5 minutos, y cada lectura desliza la ventana hacia adelante. |
| Escritura de caché - TTL 1 hora | 3× | La primera solicitud, conservada durante una hora completa. |
| Lectura de caché - acierto o acierto de prefijo | 0.1× | Cada solicitud posterior a la escritura: la parte cacheada cuesta una décima parte de la tarifa normal por token. |
Cuánto ahorra
Un ejemplo concreto: tu agente envía una conversación de 3.000 tokens como consulta y la repite o continúa 10 veces en cinco minutos. Sin caché, son 30.000 tokens de entrada a precio completo. Con una caché de 5 minutos son 6.000 por la primera escritura (2x) más unos 2.700 por las nueve lecturas cacheadas: 8.700 tokens facturados, un 71% menos. Cuanto más larga la conversación, mayor el ahorro.
La regla del prefijo
La coincidencia se hace sobre el inicio de la consulta. Si el inicio se mantiene idéntico y solo se añade texto nuevo al final, la parte cacheada se reutiliza y solo se busca la parte nueva. Si algo cambia antes del final del texto cacheado, no se puede reutilizar nada.
cached [ A B C D E F G ] ○ [ A B C D E F G ] E ✗ [ B C D E F G ] E
○ acierto - el inicio no cambió, E es la única parte nueva
✗ fallo - el inicio cambió, así que toda la consulta se busca y se cachea de nuevo
Tres reglas para recordar
- Extender vuelve a cachear hasta la nueva cola. Tras [A B C D E F G] + E, la caché ahora termina en E: la cola se factura una vez a la tarifa de escritura, y el siguiente turno puede volver a usar todo A..E como prefijo.
- Un solo prefijo contiguo por solicitud. Una consulta no puede dividirse en dos segmentos cacheados; solo su inicio puede coincidir.
- Las escrituras invalidan al instante. Cualquier store, store-turn, bulk-store, forget, supersede o eliminación del almacén descarta su caché, así que una respuesta cacheada nunca puede quedar obsoleta.
Cómo activarlo
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 } }No necesitas un SDK para nada de esto. El caching es un campo en una llamada HTTP, así que funciona desde cualquier lenguaje de programación. La pestaña curl es la receta universal, y los SDK de Python, TypeScript y Rust son envoltorios de conveniencia sobre exactamente la misma llamada.
Memoria que sabe quién lo dijo.
Las personas recuerdan por persona: qué prometió Bob, qué dijiste que harías. Etiqueta cada recuerdo con un hablante y tu agente hará lo mismo, en todos los modelos Tablet y Scroll.
Un equipo, tres recuerdos
Un almacén mantiene separadas muchas voces. Registra a una persona una vez, guarda cada comentario con su hablante y luego pregunta por persona.
El almacén ya conoce a Bob. El límite de 50 se cuenta aquí, al registrar; las llamadas de guardado nunca devuelven un error de límite.
El recuerdo ahora es de Bob: cada búsqueda que lo devuelve lo indica.
Lo que dice el asistente también se recuerda, y "me" nunca cuenta para el límite.
Solo vuelven las palabras de Bob. Las palabras de una persona nunca vuelven como las de otra.
Tres reglas para recordar
- "me" es el propio asistente. Nunca se registra ni cuenta. Reservado y en minúsculas:
speaker: "Me"o"ME"devuelve400 invalid_request_erroren lugar de convertirse en silencio. - El límite se cuenta al registrar: 50 por almacén para empezar. Registrar por encima devuelve
400 invalid_request_errorconspeaker_limit: 50en el cuerpo del error. Guardar con un nombre sin registrar también devuelve400y no guarda nada. Filtrar la búsqueda por un nombre sin registrar devuelve404 not_found_error. Ramifica por el código y los campos, no por el texto del mensaje; planeamos subir el límite. - Las etiquetas viven en cada lectura. Los resultados de búsqueda, el contexto de largo plazo de recall y los resultados de engram llevan su hablante, así que el modelo siempre sabe de quién son las palabras. Pasa speaker en una búsqueda para obtener solo las de una persona. Un supersede conserva el hablante; forget lo elimina.
- Los nombres son Unicode: cualquier idioma funciona. さくら, Иван y 하늘 son hablantes válidos, y la atribución se comporta igual en todos los idiomas. La coincidencia es exacta tras recortar y normalizar Unicode, así que
Bobybobson dos personas distintas. Los nombres llegan hasta 80 caracteres.
# 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" } }
Dos notas de alcance. speaker va en add / store: add_turn recuerda el intercambio completo, y las etiquetas por persona y el filtro vienen de recuerdos con speaker explícito. Y los pasajes de sesión (expand) son compuestos de varios recuerdos, así que no llevan etiqueta; un filtro speaker siempre devuelve recuerdos atómicos y etiquetados. Y el contenido idéntico se deduplica a la primera memoria: ese store devuelve status "duplicate" con una nota explícita, y no se adjunta hablante.
Lo probamos de la forma difícil: recuerdos guardados sin nombres en el texto, recuperados por persona. La atribución viene del registro de hablantes, no de coincidencias de palabras, así que se comporta igual en todos los idiomas.
Cómo usarlo
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 }La lista muestra a quién conoce el almacén con conteos por persona frente al límite. Quitar solo borra el registro: sus recuerdos quedan, solo se va la etiqueta.
MCP: memoria para herramientas de IA
El núcleo de WOS es la API y los SDK. El servidor MCP es un complemento encima: la misma memoria, enchufada a herramientas que no construiste tú - Claude Code, Claude Desktop, Cursor.
Una línea de instalación da al agente nueve herramientas de memoria que usa por su cuenta. Y como la memoria vive en tu cuenta, lo que escribe una herramienta lo recuerdan todas las demás, incluidos los agentes que construyas con el SDK.
Qué puedes hacer con esto
- Un Claude Code que recuerda tu proyecto. Decisiones, fixes, preferencias: recuperados en la siguiente sesión sin re-explicar nada.
- Empieza en ChatGPT, continúa en Claude. Mismo store, misma memoria: la conversación cruza herramientas en vez de reiniciarse.
- Tu propio agente sigue en el circuito. Lo que aprende Claude Code, un agente del SDK lo recuerda - y lo que guarda tu agente, Claude Code lo recuerda de vuelta.
Funciona en Claude Code, Claude Desktop, Cursor, Windsurf y cualquier host MCP. ChatGPT llega a la misma memoria vía Actions más la spec OpenAPI.
Instalación
claude mcp add wontopos --env WONTOPOS_API_KEY=wos-live-... -- npx -y wontopos-mcpEl agente recibe nueve herramientas - recall · remember · search · update · forget · list_memories · engram · stats · create_store - cada una descrita para que sepa por sí solo cuándo usarlas.
Spec OpenAPI
El mapa completo y legible por máquinas de la API: cada endpoint, petición, respuesta y error.
OpenAPI es el formato estándar de la industria para describir una API HTTP en un archivo legible por máquinas.
https://api.wontopos.com/openapi.jsonQué puedes hacer con esto
Postman: File → Import → pega la URL y los 16 endpoints aparecen como colección clicable. ChatGPT: crea un GPT, añade una Action, pega la misma URL. Codegen: openapi-generator -i .../openapi.json -g go genera un cliente en un lenguaje que no publicamos.
Impórtalo en Postman, genera un cliente en un lenguaje que no publicamos, conecta ChatGPT Actions o ejecuta checks de contrato en CI. Un test lo fija a las rutas reales: no puede desviarse.
llms.txt
Toda la API en una página de texto que una IA puede leer.
llms.txt es una convención web: una página de texto plano en la raíz del sitio que le cuenta a una IA todo lo que necesita sobre un producto.
https://wontopos.com/llms.txtPonlo en tu IDE o agente de código y sabrá cómo construir sobre WOS: auth, endpoints, patrones, errores. Se actualiza con cada release.
Los mismos hechos que la spec OpenAPI, distinta audiencia: la spec es estructura precisa para herramientas; este archivo es prosa que una IA (o una persona) lee de una pasada. Ambos se actualizan con cada release.
Tu memoria dentro de cada herramienta de IA
Un solo comando da a Claude Code, Claude Desktop, Cursor o cualquier host MCP una memoria a largo plazo respaldada por tu cuenta WOS. Sin código de integración: el agente recibe nueve herramientas de memoria y decide cuándo usarlas.
Instalación
Claude Code, una línea (crea antes una clave en la consola):
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 →
Env opcional: WONTOPOS_USER_ID fija el store por defecto, WONTOPOS_MODEL el motor, WONTOPOS_BASE_URL un despliegue autoalojado. WONTOPOS_READ_ONLY=1 cambia a solo lectura (solo recall/búsqueda/listado).
Antes de compartir un store
- Usa una clave dedicada. Las claves llevan su workspace: una clave solo para MCP acota lo que las herramientas conectadas pueden tocar, y puedes rotarla en la consola sin tocar las claves de tu app.
- Modo solo lectura.
WONTOPOS_READ_ONLY=1no registra ninguna herramienta de escritura: el agente puede recordar, buscar, listar memorias, ejecutar engramas y leer estadísticas, pero no guardar, actualizar, olvidar ni borrar. Ideal para agentes que deben consultar la memoria, no poseerla. - Mantén la confirmación de herramientas activada. Los hosts MCP preguntan antes de ejecutar herramientas por defecto: déjala activa sobre todo para
forget, porque los borrados se comparten entre todas las herramientas del store. - Todo lo guardado lo puede recordar cualquier herramienta con la clave. Nunca guardes secretos - claves de API, contraseñas - como memorias.
- Las memorias recordadas son datos, no instrucciones. Las descripciones de las herramientas se lo dicen explícitamente al agente. Aun así, no guardes texto de terceros no confiable en un store que un agente autónomo obedece.
- Los borrados también se comparten. Un forget o delete_all desde una herramienta borra para todas.
- "me" es el agente que escribe en el store. Si varios agentes comparten uno, sus voces "me" se mezclan. Da a cada agente su propio store (
WONTOPOS_USER_ID) para identidades separadas. - Paga una sola cuenta. Todas las herramientas conectadas consumen el mismo saldo y límite de tasa.
Luego, solo habla
El agente llama a la herramienta remember. Queda guardado de forma duradera: que termine la sesión no cambia nada.
Una sesión nueva no tiene historial. El agente llama a recall y responde desde la memoria: los viernes.
Cosas que puedes decir
- "Este repo usa pnpm, recuérdalo" →
rememberlo guarda; la siguiente sesión ya lo sabe. - "¿Qué formato de error acordamos la semana pasada?" →
recalltrae la decisión de vuelta al contexto. - "En realidad, la fecha límite pasó al viernes" → el agente ve que contradice lo que recordó y llama a
updatepara corregir esa memoria en el sitio. - "Eso está mal, olvídalo" → el agente encuentra el id y llama a
forget; tu host pide confirmación antes. - "¿Qué recuerdas de mí?" →
list_memoriesrecorre todo lo guardado, para que el agente responda o ponga orden.
No hay nada especial que decir: son frases normales, no comandos. El agente lee la descripción de cada herramienta y elige solo.
Las nueve herramientas
recall- Contexto en una llamada: turnos recientes más memorias relevantes. Su descripción indica al agente llamarla primero cuando importe el contexto pasado.remember- Guarda un hecho o decisión duradera.speaker: "me"marca las palabras del propio agente; un nombre registrado, quién lo dijo.search- Búsqueda semántica, con filtro opcional por persona (speaker).forget- Borra una memoria por id.speakers- Registra, lista o da de baja a las personas que recuerda un store.create_store- Los stores son explícitos: uno por usuario final, proyecto o agente.
¿SDK o MCP?
- El SDK va dentro de una app que tú escribes. Tu código decide exactamente cuándo guardar y qué recordar: determinista, tipado, versionado. ¿Construyes un producto? SDK.
- MCP se enchufa a una herramienta de IA que no escribiste tú. El agente decide cuándo usar la memoria, guiado por las descripciones - cero código. Para Claude Code, Claude Desktop, Cursor o dar memoria a un asistente ya hecho.
Debajo, la misma API y los mismos stores: una app hecha con el SDK y una sesión de Claude Code por MCP comparten una memoria. Se elige por superficie, no uno u otro.
Una memoria a través de todas las herramientas
La memoria pertenece a la cuenta, no a la herramienta. El mismo store escrito desde ChatGPT (Actions más la spec OpenAPI) se recuerda en Claude Code y en tus propios agentes, y al revés: una conversación empezada en una herramienta continúa en otra.
Y como es un solo store, puedes salir de Claude Code y seguir hablando donde construyes: un agente del SDK con la misma clave y store recuerda todo lo que Claude Code acaba de aprender, y lo que guarde tu agente, Claude Code lo recuerda en la siguiente sesión.
npx wontopos-mcp): tu clave se queda en tu entorno y nunca pasa por un servidor de terceros. Envuelve el SDK de TypeScript, así que reintentos automáticos, rechazo de redirecciones y enmascarado de la clave aplican tal cual.Claude Code
La vía principal: un comando en tu terminal y cada sesión empieza con memoria.
- Crea una clave de API en la consola. La clave lleva su workspace: una clave = un espacio de memoria.
- Registra el servidor.
--scope userlo hace disponible en todos los proyectos; sin él, solo lo ve el proyecto actual. - Compruébalo: ejecuta
/mcpdentro de Claude Code;wontoposdebe aparecer con nueve herramientas. - Hazlo automático: una línea en tu
CLAUDE.md- "cuando importe el contexto pasado, llama primero a wontopos recall" - y cada sesión empieza con memoria sin pedirlo.
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
Añade el bloque de abajo a claude_desktop_config.json (Ajustes → Developer → Edit Config), reinicia la app y aparecen las nueve herramientas. Nota: claude.ai en web y móvil necesita un servidor MCP remoto, que WOS aún no ofrece; la app de escritorio es la vía soportada.
# claude_desktop_config.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Cursor
Añade el bloque de abajo a ~/.cursor/mcp.json, o pulsa el botón de un clic, y reinicia Cursor. El agente toma las nueve herramientas.
# ~/.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 (modo agente de Copilot) lee los servidores MCP de .vscode/mcp.json del proyecto: añade el bloque de abajo o pulsa el botón de un clic.
# .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) lee ~/.codeium/windsurf/mcp_config.json: añade el bloque de abajo y recarga; aparecen las mismas nueve herramientas.
# ~/.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
Los conectores MCP de ChatGPT solo aceptan servidores remotos, así que la vía soportada hoy es un GPT personalizado con una Action: crea un GPT, añade una Action, pega la URL de la spec OpenAPI de abajo y configura tu clave como cabecera de auth. Ese GPT llamará a la misma memoria que tus demás herramientas.
# GPT → Configure → Actions → Import from URL
https://api.wontopos.com/openapi.json
# Authentication: API Key · Header name: X-API-KeyMismo store, misma memoria: lo que ChatGPT guarda por la Action, Claude Code lo recuerda por MCP, y al revés.
Gemini CLI
Gemini CLI lee los servidores MCP de ~/.gemini/settings.json: añade el bloque de abajo, reinicia la CLI y las mismas nueve herramientas aparecen también ahí.
# ~/.gemini/settings.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Python - todos los métodos, tres grupos.
Escribir, leer, eliminar. Cada ejemplo de abajo se ejecutó contra la API en vivo el 2026-07-10; las respuestas son textuales.
pip install wontopos
from wontopos import Client mem = Client(api_key="wos-live-...") # or read from an env var
Elige un modelo
La clave de API elige qué memoria (tu cuenta); el modelo elige qué motor la lee. Todos los modelos comparten una misma memoria, así que puedes almacenar con uno y recuperar con otro. Define un valor por defecto en el cliente; anula una llamada puntual pasando 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 ✓ live-tested
El catálogo - los ids que puedes pasar a model y si cada uno está disponible. Los modelos con memory: "shared" leen el mismo store; "isolated" mantiene el suyo propio. No requiere clave de API.
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
Confirma la conexión y que tu clave de API funciona: una comprobación de una línea.
mem.ping() # True, or raises AuthenticationError / PaymentRequiredError
El catálogo de arriba siempre refleja los modelos disponibles en este momento - pasa cualquier otro id y obtendrás un error claro. Los modelos nuevos aparecen ahí automáticamente cuando se lanzan.
Escribir
add ✓ live-tested
Almacena una memoria. Embebida al entrar - sin llamada a LLM, pagas solo 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
Almacena un turno de conversación (usuario + asistente) en la memoria de corto y largo plazo a la vez.
mem.add_turn("hi", "hello!", user_id="alice")
{"status": "ok"}speaker ✓ live-tested
Cada recuerdo puede llevar quién lo dijo. Registra a una persona una vez y luego pasa su nombre como speaker; "me" (las palabras del propio asistente) nunca necesita registro. La búsqueda también acepta speaker, para recordar solo las palabras de una persona.
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
Rellena un bloque grande de texto. Se trocea y embebe del lado del servidor - ideal para importar historial existente.
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
Un hecho cambió. La memoria antigua se marca como reemplazada (se conserva como historial); la nueva ocupa su lugar en el 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"}Leer
search ✓ live-tested
Búsqueda semántica, lo más relevante primero. Embedding puro - sin coincidencia de palabras clave, así que cualquier idioma encuentra cualquier memoria. El SDK devuelve directamente el arreglo de memorias; el cuerpo HTTP sin procesar se muestra abajo.
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}| Campo | Significado |
|---|---|
| similarity | Similitud de embedding bruta con tu consulta (0–1). |
| is_superseded | True si este hecho fue reemplazado por update(). |
| search_ms | Tiempo de recuperación del lado del servidor. |
recall ✓ live-tested
Un solo viaje de ida y vuelta devuelve todo lo que tu LLM necesita - pega el resultado directamente en tu prompt: un contexto acotado y de tamaño fijo sin importar cuánto hayas almacenado.
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
Turnos de conversación recientes (memoria de corto plazo), los más antiguos primero.
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
Conteos de memoria de un usuario.
mem.stats("alice")
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
Recupera una memoria por id - el id que devolvió add o list_memories. Solo el texto original almacenado y sus metadatos, nunca el vector. Un id de otro store, o una memoria borrada o invalidada, devuelve 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
Lista las memorias de un almacén: solo el texto original que guardaste y sus metadatos, nunca el vector. Paginado por cursor: reenvía el next_cursor devuelto para la página siguiente.
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
Recorre todas las memorias sin gestionar el cursor, o trae el almacén entero de una vez.
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
Eliminar
delete ✓ live-tested
Elimina una sola memoria por id.
mem.delete("alice", memory_id="576700aa-...")
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
Borra todo lo de un usuario - una llamada, lista para GDPR.
mem.delete_all("alice")
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Errores y fiabilidad
Cada fallo es un error tipado: captura el concreto (límite de tasa, autenticación, pago) o todos con el WosError 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
Lee la cuota restante tras cualquier llamada y reduce el ritmo antes de llegar al límite.
mem.search("...", user_id="alice") rl = mem.rate_limit # {"limit": 150, "remaining": 3, "reset": ...}
TypeScript - todos los métodos, tres grupos.
Escribir, leer, eliminar. Cada ejemplo de abajo se ejecutó contra la API en vivo el 2026-07-10; las respuestas son textuales.
npm install wontopos
import { Client } from "wontopos"; const mem = new Client({ apiKey: "wos-live-..." });
Elige un modelo
La clave de API elige qué memoria (tu cuenta); el modelo elige qué motor la lee. Todos los modelos comparten una misma memoria, así que puedes almacenar con uno y recuperar con otro. Define un valor por defecto en el constructor; anula una llamada puntual con 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
El catálogo - los ids que puedes pasar a model y si cada uno está disponible. Los modelos con memory: "shared" leen el mismo store; "isolated" mantiene el suyo propio. No requiere clave de API.
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
Confirma la conexión y que tu clave de API funciona: una comprobación de una línea.
await mem.ping(); // true, or throws AuthenticationError / PaymentRequiredError
El catálogo de arriba siempre refleja los modelos disponibles en este momento - pasa cualquier otro id y obtendrás un error claro. Los modelos nuevos aparecen ahí automáticamente cuando se lanzan.
Escribir
add ✓ live-tested
Almacena una memoria. Embebida al entrar - sin llamada a LLM, pagas solo 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
Almacena un turno de conversación (usuario + asistente) en la memoria de corto y largo plazo a la vez.
await mem.addTurn("hi", "hello!", "alice");
{"status": "ok"}speaker ✓ live-tested
Cada recuerdo puede llevar quién lo dijo. Registra a una persona una vez y luego pasa su nombre como speaker; "me" (las palabras del propio asistente) nunca necesita registro. La búsqueda también acepta speaker, para recordar solo las palabras de una persona.
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
Rellena un bloque grande de texto. Se trocea y embebe del lado del servidor - ideal para importar historial existente.
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
Un hecho cambió. La memoria antigua se marca como reemplazada (se conserva como historial); la nueva ocupa su lugar en el recall.
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"}Leer
search ✓ live-tested
Búsqueda semántica, lo más relevante primero. Embedding puro - sin coincidencia de palabras clave, así que cualquier idioma encuentra cualquier memoria. El SDK devuelve directamente el arreglo de memorias; el cuerpo HTTP sin procesar se muestra abajo.
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}| Campo | Significado |
|---|---|
| similarity | Similitud de embedding bruta con tu consulta (0–1). |
| is_superseded | True si este hecho fue reemplazado por update(). |
| search_ms | Tiempo de recuperación del lado del servidor. |
recall ✓ live-tested
Un solo viaje de ida y vuelta devuelve todo lo que tu LLM necesita - pega el resultado directamente en tu prompt: un contexto acotado y de tamaño fijo sin importar cuánto hayas almacenado.
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
Turnos de conversación recientes (memoria de corto plazo), los más antiguos primero.
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
Conteos de memoria de un usuario.
await mem.stats("alice");
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
Recupera una memoria por id - el id que devolvió add o list_memories. Solo el texto original almacenado y sus metadatos, nunca el vector. Un id de otro store, o una memoria borrada o invalidada, devuelve 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
Lista las memorias de un almacén: solo el texto original que guardaste y sus metadatos, nunca el vector. Paginado por cursor: reenvía el next_cursor devuelto para la página siguiente.
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
Recorre todas las memorias sin gestionar el cursor, o trae el almacén entero de una vez.
for await (const m of mem.iterMemories("alice")) console.log(m.id, m.content); const everything = await mem.exportMemories("alice");
Eliminar
delete ✓ live-tested
Elimina una sola memoria por id.
await mem.delete("alice", "576700aa-...");
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}deleteAll ✓ live-tested
Borra todo lo de un usuario - una llamada, lista para GDPR.
await mem.deleteAll("alice");
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Errores y fiabilidad
Cada fallo es un error tipado: captura el concreto (límite de tasa, autenticación, pago) o todos con el WosError base.
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
Lee la cuota restante tras cualquier llamada y reduce el ritmo antes de llegar al límite.
await mem.search("...", "alice"); const rl = mem.rateLimit; // { limit: 150, remaining: 3, reset: ... }
Rust - todos los métodos, tres grupos.
Escribir, leer, eliminar. Cada ejemplo de abajo se ejecutó contra la API en vivo el 2026-07-10; las respuestas son textuales.
cargo add wontopos
use wontopos::Client; let mem = Client::new("wos-live-...");
Elige un modelo
La clave de API elige qué memoria (tu cuenta); el modelo elige qué motor la lee. Todos los modelos comparten una misma memoria, así que puedes almacenar con uno y recuperar con otro. Define un valor por defecto con with_model(); encadénalo de nuevo para anular una llamada puntual.
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
El catálogo - los ids que puedes pasar a with_model y si cada uno está disponible. Los modelos con memory: "shared" leen el mismo store; "isolated" mantiene el suyo propio. No requiere clave de API.
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
Confirma la conexión y que tu clave de API funciona: una comprobación de una línea.
mem.ping().await?; // Ok(true), or Err whose .kind() is Auth / PaymentRequired
El catálogo de arriba siempre refleja los modelos disponibles en este momento - pasa cualquier otro id y obtendrás un error claro. Los modelos nuevos aparecen ahí automáticamente cuando se lanzan.
Escribir
add ✓ live-tested
Almacena una memoria. Embebida al entrar - sin llamada a LLM, pagas solo 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
Almacena un turno de conversación (usuario + asistente) en la memoria de corto y largo plazo a la vez.
mem.add_turn("hi", "hello!", "alice").await?;
{"status": "ok"}speaker ✓ live-tested
Cada recuerdo puede llevar quién lo dijo. Registra a una persona una vez y luego pasa su nombre como speaker; "me" (las palabras del propio asistente) nunca necesita registro. La búsqueda también acepta speaker, para recordar solo las palabras de una persona.
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
Rellena un bloque grande de texto. Se trocea y embebe del lado del servidor - ideal para importar historial existente.
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
Un hecho cambió. La memoria antigua se marca como reemplazada (se conserva como historial); la nueva ocupa su lugar en el recall.
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"}Leer
search ✓ live-tested
Búsqueda semántica, lo más relevante primero. Embedding puro - sin coincidencia de palabras clave, así que cualquier idioma encuentra cualquier memoria. El SDK devuelve directamente el arreglo de memorias; el cuerpo HTTP sin procesar se muestra abajo.
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}| Campo | Significado |
|---|---|
| similarity | Similitud de embedding bruta con tu consulta (0–1). |
| is_superseded | True si este hecho fue reemplazado por update(). |
| search_ms | Tiempo de recuperación del lado del servidor. |
recall ✓ live-tested
Un solo viaje de ida y vuelta devuelve todo lo que tu LLM necesita - pega el resultado directamente en tu prompt: un contexto acotado y de tamaño fijo sin importar cuánto hayas almacenado.
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
Turnos de conversación recientes (memoria de corto plazo), los más antiguos primero.
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
Conteos de memoria de un usuario.
mem.stats("alice").await?;
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
Recupera una memoria por id - el id que devolvió add o list_memories. Solo el texto original almacenado y sus metadatos, nunca el vector. Un id de otro store, o una memoria borrada o invalidada, devuelve 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
Lista las memorias de un almacén: solo el texto original que guardaste y sus metadatos, nunca el vector. Paginado por cursor: reenvía el next_cursor devuelto para la página siguiente.
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
Recorre todas las memorias sin gestionar el cursor, o trae el almacén entero de una vez.
let all = mem.list_all_memories("alice").await?; // every page, collected
Eliminar
delete ✓ live-tested
Elimina una sola memoria por id.
mem.delete("alice", "576700aa-...").await?;
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
Borra todo lo de un usuario - una llamada, lista para GDPR.
mem.delete_all("alice").await?;
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Errores y fiabilidad
Cada fallo es un error tipado: captura el concreto (límite de tasa, autenticación, pago) o todos con el WosError base.
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
Lee la cuota restante tras cualquier llamada y reduce el ritmo antes de llegar al límite.
mem.search("...", "alice", 10).await?; let rl = mem.rate_limit(); // Some(RateLimit { remaining: Some(3), .. })
curl - sin instalación, los mismos métodos.
No hay SDK que instalar - cualquier cliente HTTP funciona. Configura tu clave una vez y llama a los mismos endpoints que envuelven los SDK. URL base https://api.wontopos.com, autenticación vía X-API-Key, JSON de entrada y salida.
# set your key once (never hard-code it) export WOS_API_KEY="wos-live-..."
Escribir
store ✓ live-tested
Almacena una memoria. Embebida al entrar - sin llamada a LLM.
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
Almacena un turno de conversación (usuario + asistente) en la memoria de corto y largo plazo a la vez.
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
Cada recuerdo puede llevar quién lo dijo. Registra a una persona una vez y luego pasa su nombre como speaker; "me" (las palabras del propio asistente) nunca necesita registro. La búsqueda también acepta speaker, para recordar solo las palabras de una persona.
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
Un hecho cambió - la memoria antigua se marca como reemplazada, la nueva ocupa su lugar en el recall.
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"}Leer
search ✓ live-tested
Búsqueda semántica, lo más relevante primero. Embedding puro - cualquier idioma encuentra cualquier memoria.
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
Un solo viaje de ida y vuelta devuelve corto plazo + largo plazo + contexto + una instrucción. Pégalo directamente en tu 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 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..."}Eliminar
forget ✓ live-tested
Elimina una memoria por id, u omítelo para eliminar todo lo de un usuario (GDPR).
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
Herramientas de recall invocables que tu modelo puede llamar - cada una es una estrategia de recuperación distinta sobre la misma memoria. Usa una, o ejecuta varias a la vez.
Regularmente se lanzan más engramas - esta lista crece.
Memoir & Archive Scroll 1.2+
Esta es una forma de entrega, no una herramienta invocable. En Scroll 1.2 y superiores, elígela por llamada - form: "memoir" o form: "archive" - y ese recall, incluida una búsqueda simple, vuelve con el tiempo escrito de esa manera.
Time_awareness Scroll 1.2+
Una forma de entrega - se elige por llamada. Pasa form - memoir o archive - en cualquier llamada de un modelo compatible (Scroll 1.2 y superiores), y la respuesta vuelve renderizada de esa manera: una búsqueda simple, un recall o cualquier engrama. En los SDK es un campo form, como tz; por HTTP es el encabezado X-WOS-Form. Un Memoir se lee como recuerda una persona; un Archive conserva un registro exacto - la diferencia se nota sobre todo en cómo escribe el tiempo cada uno.
Memoir
form: "memoir"Cuenta lo que pasó y cómo un momento llevó al siguiente, con esa noción suave del tiempo que recuerda una persona - se lee como experiencia, no como una lista.
Archive
form: "archive"Devuelve las coincidencias como registros exactos - tiempo transcurrido preciso y anclas absolutas, estructurado para que un modelo lo lea de inmediato.
store / add bajo un user_id (ese user_id es el store de esa persona). Almacena primero; después cualquier recall - incluida la búsqueda simple de abajo - vuelve etiquetado con el tiempo. Consulta el Inicio rápido para almacenar.# 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 es el desplazamiento UTC del llamador en horas - para que "esta mañana" y el límite de día de las 4am caigan en su hora local. Omítelo para UTC; por HTTP es el encabezado X-WOS-Timezone. A grandes rasgos, por región: EE. UU. Este -5, EE. UU. Centro -6, EE. UU. Oeste -8 · Reino Unido / Lisboa 0 · Europa Central +1 · Europa Oriental +2 · India +5.5 · China / Singapur +8 · Corea / Japón +9 · Sídney +10. (Hora estándar - el horario de verano desplaza algunas regiones en +1; pasa el que tus usuarios realmente usen.)
La misma búsqueda, dos formas - las memorias son idénticas, solo cambia time:
{ "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)" }
] }| Transcurrido | 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 h | a couple hours ago | 2 hours ago, at 13:10 |
| 8 h | this morning | 8 hours ago, at 07:10 |
| ayer p. m. | yesterday afternoon | yesterday at 14:00 |
| anoche | last night | 17 hours ago, at 22:00 |
| 2 días | a couple days ago | 2 days ago (Tue 15:10) |
| 6 días | several days ago | 6 days ago (Fri 15:10) |
| 9 días | about a week ago | last week (Jun 16) |
| 16 días | a couple weeks ago | 2 weeks ago (Jun 09) |
| 35 días | about a month ago | last month (May 21) |
| 60 días | a couple months ago | 2 months ago (Apr 2026) |
| 180 días | about half a year ago | 6 months ago (Dec 2025) |
| 380 días | about a year ago | last year (Jun 2025) |
| 800 días | a couple years ago | 2 years ago (Apr 2024) |
| 1500 días | about 4 years ago | 4 years ago (May 2022) |
Cada valor de arriba es la salida real del renderizador. Mira las dos filas de "ayer": un Memoir separa la tarde de la noche anterior - un día es un sueño - mientras que un Archive escribe una sola hora de reloj y no traza ninguna línea entre día y noche.
Cómo lee el tiempo cada modo
Memoir - como la gente realmente lo dice. Los momentos recientes se mantienen bastante nítidos (unos 15 minutos, media hora), y luego la redacción se ensancha cuanto más atrás vas - un par de semanas, cerca de medio año, un par de años - igual que la memoria misma se afloja con la distancia. Dentro de un día deja el reloj por un punto de referencia: esta mañana, anoche, ayer por la tarde. Y un día es un sueño, no un tic del calendario: el límite se sitúa alrededor de las 4am hora local, así que una noche larga todavía se lee como la misma velada, no como si ya fuera mañana.
Archive - preciso, siempre con un ancla. Cada línea lleva el tiempo transcurrido exacto más una referencia absoluta desde la que un modelo puede calcular, y el ancla se afina cuanto más cerca está: una hora de reloj para hoy (hace 8 horas, a las 07:10), un día de la semana y hora esta semana (hace 2 días (mar 15:10)), una fecha este mes (la semana pasada (16 jun)), y mes y año más allá (hace 6 meses (dic 2025)). Nunca vago, nunca equivocado.
deep_recall
Recall multisalto. Busca tu consulta, luego toma la mejor coincidencia y vuelve a buscar sobre su contenido - trayendo contexto enlazado que una sola búsqueda pasaría por alto. Ideal cuando las memorias se referencian entre sí (una persona → sus proyectos → los detalles). Devuelve hasta ~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 (entrada + salida), contado con el mismo tokenizador que el resto de la API; sin tarifas ocultas por engrama. ¿Necesitas varios a la vez? Llámalos de forma concurrente - cada engrama es una solicitud independiente.timeline
Recall ordenado por tiempo. Devuelve las memorias ordenadas de más reciente a más antigua según cuándo ocurrió el evento, no por relevancia. Para preguntas de "cuándo pasó X", historial y secuencia. Devuelve hasta 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 (entrada + salida), contado con el mismo tokenizador que el resto de la API; sin tarifas ocultas por engrama. ¿Necesitas varios a la vez? Llámalos de forma concurrente - cada engrama es una solicitud independiente.gather
Recolección amplia. Busca y luego se expande alrededor de las tres mejores coincidencias - una red más amplia que deep_recall. Úsala para traer todo lo relacionado con una persona, proyecto o tema en una sola llamada. Devuelve hasta ~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 (entrada + salida), contado con el mismo tokenizador que el resto de la API; sin tarifas ocultas por engrama. ¿Necesitas varios a la vez? Llámalos de forma concurrente - cada engrama es una solicitud independiente.Todos los endpoints, una URL base.
No se requiere SDK - cualquier cliente HTTP funciona. URL base https://api.wontopos.com, autenticación vía el encabezado X-API-Key, JSON de entrada y salida. Las operaciones de memoria son POST; la administración de stores usa POST / GET / DELETE sobre /collection. El store debe existir primero (ver Stores) o las operaciones dentro del store devuelven 404.
| Endpoint | Propósito | Campos del cuerpo |
|---|---|---|
| POST /api/v1/memory/collection | crear un store | user_id |
| GET /api/v1/memory/collections | listar tus stores | (ninguno) |
| DELETE /api/v1/memory/collection | eliminar un store + sus memorias | user_id |
| /api/v1/memory/store | almacenar una memoria | user_id · content · metadata? (speaker) |
| /api/v1/memory/store-turn | almacenar un turno de conversación | user_id · user_msg · assistant_msg |
| POST /api/v1/memory/speakers | registrar un hablante (explícito, hasta 50) | user_id · speaker |
| GET /api/v1/memory/speakers | listar hablantes registrados + conteos | user_id |
| DELETE /api/v1/memory/speakers | dar de baja un hablante (los recuerdos quedan) | user_id · speaker |
| /api/v1/memory/bulk-store | rellenar un bloque de texto | user_id · content · category? |
| /api/v1/memory/search | búsqueda semántica | user_id · query · max_results? · speaker? |
| /api/v1/memory/recall | corto + largo + contexto | user_id · query |
| /api/v1/memory/history | turnos recientes | user_id |
| /api/v1/memory/stats | conteos de memoria | user_id |
| /api/v1/memory/supersede | reemplazar un hecho que cambió | user_id · old_memory_id · new_content |
| /api/v1/memory/forget | eliminar una (o todas) | user_id · memory_id? (omitir = eliminar todo) |
# 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)"}Las mismas funciones para todos.
Los niveles solo elevan tus límites.
Todos los niveles ejecutan el motor completo - la misma calidad de recall, los mismos idiomas, todos los métodos. Los niveles avanzan automáticamente hasta el Nivel 5 a medida que crecen tus compras acumuladas de crédito, sin solicitudes ni llamadas de ventas. Enterprise (Nivel 6) es la única excepción.
Límites de gasto
Cada nivel limita cuánto puedes gastar por mes calendario. Avanzas de inmediato cuando tus compras acumuladas de crédito alcanzan el siguiente umbral.
| Nivel de uso | Compra de crédito | Límite de gasto mensual |
|---|---|---|
| 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 | Habla con nosotros | Sin límite |
Límites de velocidad
Los límites de velocidad son por cuenta - todas las claves de API de una cuenta comparten un mismo límite, que escala con tu nivel. Excederlo devuelve un 429 con un encabezado retry-after; espera (1s → 2s → 4s) y reintenta. Todos los endpoints son compatibles con la idempotencia, así que reintentar es seguro.
| Nivel | Solicitudes por minuto |
|---|---|
| Tier 1 | 150 |
| Tier 2 | 300 |
| Tier 3 | 600 |
| Tier 4 | 1,500 |
| Tier 5 | 3,000 |
| Tier 6 - Enterprise | Personalizado |
Enterprise (Nivel 6) obtiene límites de velocidad personalizados, un SLA, soporte dedicado y una licencia opcional de autoalojamiento - habla con nosotros.
Cuando algo sale mal.
Los errores vuelven como un sobre JSON con un type estable, un mensaje legible y un request_id que puedes enviarnos al reportar un problema.
{"type": "error", "error": {
"type": "authentication_error",
"message": "Invalid or revoked API key.",
"request_id": "063f8b83-eee2-4383-a5cf-11e4bcd29d7c"
}}| HTTP | Significado | Qué hacer |
|---|---|---|
| 401 | Clave de API inválida o revocada | Verifica la clave; emite una nueva en la consola. |
| 422 | Cuerpo mal formado (campo faltante o de tipo incorrecto) | El mensaje indica el campo exacto - corrige y reintenta. |
| 429 | Límite de velocidad excedido | Espera de forma exponencial (1s → 2s → 4s) y reintenta. Es seguro: todos los endpoints son compatibles con la idempotencia. |
| 5xx | Problema del lado del servidor | Reintenta con espera exponencial; incluye el request_id si nos contactas. |
# 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
Los límites de velocidad son por cuenta, se comparten entre todas tus claves y escalan con tu nivel - consulta Niveles de uso. El uso de tu cuenta se muestra en la consola.
Tus servidores, tus datos.
El motor puede ejecutarse dentro de tu propia infraestructura - la misma API, los mismos SDK. Apunta el cliente a tu host y nada más cambia.
mem = Client(api_key="...", base_url="https://wos.your-host.com")- Residencia de datos. Las memorias nunca salen de tu red.
- La misma superficie. Los mismos métodos y endpoints funcionan de forma idéntica.
- Licenciamiento. Los paquetes de autoalojamiento se acuerdan por despliegue - contáctanos.
Más allá de la ventana de contexto.
WOS recupera de historiales de 1.4M tokens - mucho más grandes que cualquier ventana de contexto de un LLM - y aun así entrega un fragmento compacto de ~1,470 tokens.
La memoria de tu agente no está limitada por lo que cabe en un prompt. Lo conserva todo y recupera solo lo que importa, sin importar cuánto crezca el historial.
Privado, y tuyo.
Tus datos permanecen en tu store. Nunca entrenamos con ellos, los vemos ni los reutilizamos - solo los organizamos para que puedas recuperarlos.
- BYOK. Tu clave de LLM se envía por solicitud y nunca se almacena.
- Aislado. Las memorias tienen alcance por cuenta y luego por
user_id. - Borrado GDPR & autoalojamiento. Una llamada borra a un usuario; ejecuta el motor en tu propio entorno si lo prefieres.