Memória de longo prazo para agentes de IA.
O WOS é uma API de memória. Você armazena as memórias de um usuário uma única vez e depois recupera apenas as relevantes para cada consulta, passando-as ao prompt do seu modelo.
A recuperação é puramente semântica, sem correspondência por palavras-chave nem BM25, então a qualidade do recall é idêntica em todos os idiomas. Cada consulta retorna um contexto pequeno e limitado, não importa quanto você tenha armazenado, e nenhum modelo é executado sobre as suas memórias armazenadas.
Operações principais
store- salva uma memória para um usuário.recall- obtém as memórias relevantes para uma consulta. Esta é a chamada principal.search- busca semântica bruta sobre as memórias armazenadas.supersede- atualiza ou substitui uma memória desatualizada.forget- exclui uma única memória ou um usuário inteiro (GDPR).
Três modelos, uma mesma linhagem.
Os modelos WOS recebem nomes das formas como as pessoas preservaram o conhecimento ao longo da história - Tablet, Scroll, Codex. Pedra, pergaminho, livro encadernado: cada um faz mais pelo seu agente do que o anterior.
Tablet
DisponívelUma forma enxuta, rápida e de baixo custo de inscrever e recuperar memória - a base sobre a qual todos os modelos são construídos.
Scroll
DisponívelAdiciona um modelo de linguagem para ler sua pergunta com mais atenção e trazer de volta um contexto mais completo, de modo que evidências dispersas voltem reunidas, em vez de faltar uma peça.
Codex
Em breveAbre sozinho na página certa - escolhendo a memória e as ferramentas de que cada momento precisa, e ficando mais afiado quanto mais é usado.
O relatório completo de benchmark do Tablet 1 está na página de benchmarks.
Pague $2 para nós. Economize muitas vezes esse valor no seu LLM.
O WOS entrega ao seu LLM ~1,200 tokens por consulta - uma fatia limitada e relevante - em vez de enfiar o histórico completo em cada prompt. A diferença é enorme, e cresce junto com o seu histórico.
Cada $1 gasto no WOS economiza ~$98 no LLM. Histórico maior ou modelo mais caro → ROI maior.
De onde vem a economia
- Sem o WOS, você enfia o histórico inteiro em cada prompt -
100K tokens × $2.50/1M = $0.25por consulta, às tarifas de entrada do GPT-4o (cerca de 2× isso em modelos do nível do Opus). - Com o WOS, você ingere uma única vez (
$2/1M) e cada consulta passa a ser uma pequena recuperação ($3/1M × 1,200) mais o seu LLM sobre apenas ~1,200 tokens. - Quanto menos tokens o seu LLM lê, menos você paga - e o WOS mantém esse número estável conforme a memória cresce.
Todos os idiomas, a mesma precisão.
A recuperação é puramente semântica - apenas embeddings, zero correspondência por palavras-chave ou BM25. Então a qualidade do recall é idêntica, quer seus usuários escrevam em 日本語, 中文, Español ou inglês.
A correspondência lexical, como o BM25, é ajustada ao formato de um idioma específico - morfologia, espaçamento, escrita. Em um store multilíngue, isso significa que a qualidade da recuperação varia por idioma. O WOS não usa nenhuma correspondência lexical, então todos os idiomas passam pelo mesmo caminho.
Um store, três idiomas ao mesmo tempo
Você não escolhe um idioma por store - misture-os livremente. Abaixo, a memória de um único usuário contém japonês, inglês e espanhol ao mesmo tempo, e cada pergunta encontra a memória certa independentemente do idioma. Esta é uma interação real com a API em produção:
# 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
Sem etapa de tradução, sem detecção de idioma, sem configuração por idioma. Memórias e perguntas são posicionadas pelo significado, não pelo idioma - se o significado corresponde, o idioma não importa.
Por que banimos palavras-chave de propósito
A pontuação lexical, como o BM25, fortalece a recuperação para alguns idiomas mais do que para outros, o que atrapalha quando um store contém muitos idiomas. Por isso, nós a removemos completamente do motor e aplicamos essa regra na revisão de código: com qualquer pontuação lexical no caminho, a qualidade do recall variaria por idioma.
Nenhum modelo é executado sobre suas memórias.
O armazenamento é literal e o motor busca por embeddings - barato, rápido e determinístico. Um modelo nunca é executado sobre as suas memórias armazenadas. O Tablet não usa modelo algum; o Scroll e o Codex adicionam um ao redor do motor para resultados mais fortes, mas ele só vê a sua consulta, nunca o que você armazenou.
- Motor determinístico. O motor retorna as mesmas memórias para a mesma consulta, todas as vezes - e é por isso que a variância do nosso benchmark vem apenas do modelo leitor.
- Barato em escala. Sem custo de geração para armazenar ou recuperar, então sua conta acompanha o armazenamento - não o uso de modelo - conforme a memória cresce.
Suas palavras, intocadas
Um design comum executa um modelo de linguagem no momento da escrita para extrair e reescrever "fatos" do texto. Esse design troca três coisas: custo de geração em cada escrita, latência adicional e o armazenamento da paráfrase de um modelo em vez das palavras originais. O WOS faz a troca oposta - armazena o que foi dito, sem alterações, e deixa que o seu LLM faça a interpretação no momento da leitura, com o texto original em mãos.
90.7%, medido e reproduzível.
90.7% no LongMemEval-S, média de 5 execuções independentes (σ 0.5%, nenhuma escolhida a dedo), avaliado pelo juiz canônico GPT-4o do benchmark.
No mesmo benchmark, as pontuações variam bastante conforme o protocolo de avaliação - o juiz, o prompt e o que a camada de recuperação pode fazer. Usamos o juiz terceiro canônico GPT-4o do benchmark tal como publicado, não mudamos nada para nos ajustar ao teste e publicamos o código de pontuação e o prompt do leitor para que qualquer pessoa possa reproduzir os 90.7% exatamente.
O protocolo, em uma única tabela
| Item | O que fazemos |
|---|---|
| Conjunto de dados | LongMemEval-S (limpo), ~240K tokens de histórico por pergunta |
| Juiz | O juiz canônico GPT-4o do benchmark - um terceiro, não nós |
| Execuções | 5 execuções independentes, todas as pontuações publicadas, média reportada (σ 0.5%) |
| Leitor | Modelo leitor e prompt fixos, publicados na íntegra |
O que mantém a honestidade: um juiz terceiro, o prompt do leitor publicado sem alterações, recuperação puramente semântica e todas as execuções reportadas - não apenas a melhor. O motor de recuperação é determinístico - execute de novo e você obtém as mesmas memórias.
Escalamos benchmarks mais difíceis
Testamos no benchmark padrão mais difícil que ainda não conquistamos - e o número é a marca máxima entre todos os modelos WOS, reescrita sempre que um modelo melhor é lançado. Ao superar 94%, avançamos para um benchmark mais difícil.
Duas tarifas de token por modelo,
mais $0.0001 por requisição.
Por milhão de tokens mais uma taxa fixa de $0.0001 por requisição, pagamento conforme o uso. Sem assinatura, sem aluguel de armazenamento, sem limites de memória. Você paga quando seu agente escreve ou lê - nunca pelo que ele lembra.
| Modelo | Entrada / 1M | Saída / 1M | |
|---|---|---|---|
| Tablet 1 | $2 | $3 | Disponível |
| Scroll 1 | $4 | $8 | Disponível |
| Codex 1 | - | - | A definir |
- $0.0001 por requisição. Uma taxa fixa em cada chamada de API, além do uso de tokens.
- O armazenamento é gratuito. A ingestão paga uma única vez; manter os dados não custa nada. Sem limite de quantidade, sem limite de retenção.
- Nós armazenamos. Nunca treinamos com os dados, os usamos ou olhamos para eles. A memória do seu agente é sua - nós apenas a organizamos para que você possa recuperá-la.
- Por que o Tablet é tão barato: seu motor não executa modelo algum, então nosso custo é embeddings e disco - não GPUs. O Scroll e o Codex adicionam um modelo, e é isso que o preço mais alto deles cobre.
Três chamadas: armazenar, recuperar, responder.
Uma única API. A chamada recall() retorna contexto de curto prazo, de longo prazo e do entorno em uma única ida e volta, pronto para inserir no seu prompt.
Armazenar
add() os fatos e turnos do seu usuário. Convertidos em embeddings na entrada - sem LLM.
Recuperar
recall() retorna curto prazo + longo prazo + contexto em uma única chamada - um contexto limitado e de tamanho fixo.
Responder
Entregue esse contexto limitado ao seu LLM - qualquer provedor, sua chave.
from wontopos import Client mem = Client(api_key="wos-...") mem.add("she prefers tea over coffee", user_id="alice") # one call: short + long + context ctx = mem.recall("what does alice drink?", user_id="alice")
Seu primeiro recall em 5 minutos.
Uma chave, uma linha de instalação, três chamadas - seu agente tem memória. Cada trecho de código nesta página foi realmente executado; as respostas são mostradas na íntegra.
Obtenha uma chave de API
Crie uma no console. Uma chave de 155 caracteres que começa com wos-live- é exibida uma única vez. Guarde-a em uma variável de ambiente - nunca no código.
Instale
pip install wontopos # Python npm install wontopos # TypeScript / JavaScript cargo add wontopos # Rust # curl - nothing to install, just set WOS_API_KEY
Crie um store, depois armazene & recupere
Um store é o user_id sob o qual você lê e escreve. Stores são explícitos: crie um primeiro (a chamada abaixo), depois armazene e recupere sob ele. Armazenar - embeddings gerados na entrada, sem chamada de LLM. Recuperar - curto prazo + longo prazo + contexto em uma única ida e volta.
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 ao cliente e todas as chamadas o usam - sem precisar repeti-lo; sobrescreva uma chamada específica passando user_id a ela. Stores são explícitos: armazenar em um store que não existe, ou recuperar dele, retorna 404 - crie-o primeiro. Toda conta começa com um store default, então sem nenhum user_id o caminho de configuração zero simplesmente funciona. Veja Stores para listá-los e gerenciá-los.recall() retorna quatro blocos - short_term (turnos recentes), long_term (memórias relevantes), context (o que cercava a melhor correspondência) e uma instruction dizendo ao LLM como usá-los. Insira tudo isso no seu prompt.
Stores - criar, listar, excluir.
Um store é o user_id sob o qual você lê e escreve - um espaço de memória isolado por usuário final, agente ou tópico. Stores são explícitos: crie um antes de armazenar nele ou recuperar dele, ou a chamada retorna 404. Toda conta começa com um store default, então você pode começar sem uma chamada de criação.
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 manter a memória de cada pessoa separada, ou um único store default para um agente pessoal. Você também pode criar e navegar pelos stores no console (Memory ids → Issue) sem escrever código. Excluir um store é permanente - remove todas as memórias sob ele.Python - todos os métodos, três grupos.
Escrever, ler, excluir. Todos os exemplos abaixo foram executados contra a API em produção em 2026-06-10; as respostas estão na íntegra.
pip install wontopos
from wontopos import Client mem = Client(api_key="wos-live-...") # or read from an env var
Escolha um modelo
A chave de API escolhe qual memória (sua conta); o modelo escolhe qual motor a lê. Todos os modelos compartilham uma mesma memória, então você pode armazenar com um e recuperar com outro. Defina um padrão no cliente; sobrescreva uma chamada específica passando 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="tablet-1") # or pick a model per call
list_models ✓ live-tested
O catálogo - os ids que você pode passar em model e se cada um está disponível. Modelos com memory: "shared" leem o mesmo store; "isolated" mantém o seu próprio. Não requer chave de API.
mem.list_models()[{"id": "tablet-1", "name": "Tablet 1", "available": true, "memory": "shared"}]O catálogo acima sempre reflete os modelos disponíveis neste momento - passe qualquer outro id e você recebe um erro claro. Novos modelos aparecem nele automaticamente quando são lançados.
Escrever
add ✓ live-tested
Armazena uma memória. Embeddings gerados na entrada - sem chamada de LLM, você paga apenas embeddings.
mem.add("she prefers tea over coffee", user_id="alice")
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}add_turn ✓ live-tested
Armazena um turno de conversa (usuário + assistente) na memória de curto e de longo prazo de uma só vez.
mem.add_turn("alice", "hi", "hello!")
{"status": "ok"}add_bulk ✓ live-tested
Faz backfill de um grande bloco de texto. Fragmentado e convertido em embeddings no servidor - ideal para importar um histórico 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
Um fato mudou. A memória antiga é marcada como substituída (mantida para histórico); a nova toma o lugar dela no recall.
mem.update("alice", old_memory_id="576700aa-...", new_content="she switched to coffee this year")
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}Ler
search ✓ live-tested
Busca semântica, os mais relevantes primeiro. Puramente embeddings - sem correspondência por palavras-chave, então qualquer idioma encontra qualquer memória. O SDK retorna o array de memórias diretamente; o corpo HTTP bruto é mostrado abaixo.
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-06-10T04:20:39.688276876Z"
}], "search_ms": 315, "total_found": 1}| Campo | Significado |
|---|---|
| similarity | Similaridade bruta de embedding com a sua consulta (0–1). |
| is_superseded | Verdadeiro se este fato foi substituído por update(). |
| search_ms | Tempo de recuperação no servidor. |
recall ✓ live-tested
Uma única ida e volta retorna tudo o que o seu LLM precisa - cole o resultado direto no seu prompt: um contexto limitado e de tamanho fixo, não importa quanto você tenha armazenado.
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 recentes da conversa (memória de curto prazo), do mais antigo para o mais recente.
turns = mem.history("alice")
{"count": 2, "turns": [
{"role": "user", "content": "hi", "timestamp": "2026-06-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-06-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats ✓ live-tested
Contagens de memórias de um usuário.
mem.stats("alice")
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}Excluir
delete ✓ live-tested
Exclui uma única memória pelo id.
mem.delete("alice", memory_id="576700aa-...")
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
Apaga tudo de um usuário - uma única chamada, pronta para o GDPR.
mem.delete_all("alice")
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}TypeScript - todos os métodos, três grupos.
Escrever, ler, excluir. Todos os exemplos abaixo foram executados contra a API em produção em 2026-06-10; as respostas estão na íntegra.
npm install wontopos
import { Client } from "wontopos"; const mem = new Client({ apiKey: "wos-live-..." });
Escolha um modelo
A chave de API escolhe qual memória (sua conta); o modelo escolhe qual motor a lê. Todos os modelos compartilham uma mesma memória, então você pode armazenar com um e recuperar com outro. Defina um padrão no construtor; sobrescreva uma chamada específica com withModel().
const mem = new Client({ apiKey: "wos-live-...", model: "tablet-1" }); // default mem.recall("...", "alice"); // tablet-1 mem.withModel("tablet-1").recall("...", "alice"); // or pick a model per call
listModels ✓ live-tested
O catálogo - os ids que você pode passar em model e se cada um está disponível. Modelos com memory: "shared" leem o mesmo store; "isolated" mantém o seu próprio. Não requer chave de API.
await mem.listModels();
[{"id": "tablet-1", "name": "Tablet 1", "available": true, "memory": "shared"}]O catálogo acima sempre reflete os modelos disponíveis neste momento - passe qualquer outro id e você recebe um erro claro. Novos modelos aparecem nele automaticamente quando são lançados.
Escrever
add ✓ live-tested
Armazena uma memória. Embeddings gerados na entrada - sem chamada de LLM, você paga apenas embeddings.
await mem.add("she prefers tea over coffee", "alice");
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}addTurn ✓ live-tested
Armazena um turno de conversa (usuário + assistente) na memória de curto e de longo prazo de uma só vez.
await mem.addTurn("alice", "hi", "hello!");
{"status": "ok"}addBulk ✓ live-tested
Faz backfill de um grande bloco de texto. Fragmentado e convertido em embeddings no servidor - ideal para importar um histórico 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
Um fato mudou. A memória antiga é marcada como substituída (mantida para histórico); a nova toma o lugar dela no recall.
await mem.update("alice", "576700aa-...", "she switched to coffee this year");
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}Ler
search ✓ live-tested
Busca semântica, os mais relevantes primeiro. Puramente embeddings - sem correspondência por palavras-chave, então qualquer idioma encontra qualquer memória. O SDK retorna o array de memórias diretamente; o corpo HTTP bruto é mostrado abaixo.
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-06-10T04:20:39.688276876Z"
}], "search_ms": 315, "total_found": 1}| Campo | Significado |
|---|---|
| similarity | Similaridade bruta de embedding com a sua consulta (0–1). |
| is_superseded | Verdadeiro se este fato foi substituído por update(). |
| search_ms | Tempo de recuperação no servidor. |
recall ✓ live-tested
Uma única ida e volta retorna tudo o que o seu LLM precisa - cole o resultado direto no seu prompt: um contexto limitado e de tamanho fixo, não importa quanto você tenha armazenado.
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 recentes da conversa (memória de curto prazo), do mais antigo para o mais recente.
const turns = await mem.history("alice");
{"count": 2, "turns": [
{"role": "user", "content": "hi", "timestamp": "2026-06-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-06-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats ✓ live-tested
Contagens de memórias de um usuário.
await mem.stats("alice");
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}Excluir
delete ✓ live-tested
Exclui uma única memória pelo id.
await mem.delete("alice", "576700aa-...");
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}deleteAll ✓ live-tested
Apaga tudo de um usuário - uma única chamada, pronta para o GDPR.
await mem.deleteAll("alice");
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}Rust - todos os métodos, três grupos.
Escrever, ler, excluir. Todos os exemplos abaixo foram executados contra a API em produção em 2026-06-10; as respostas estão na íntegra.
cargo add wontopos
use wontopos::Client; let mem = Client::new("wos-live-...");
Escolha um modelo
A chave de API escolhe qual memória (sua conta); o modelo escolhe qual motor a lê. Todos os modelos compartilham uma mesma memória, então você pode armazenar com um e recuperar com outro. Defina um padrão com with_model(); encadeie-o novamente para sobrescrever uma chamada específica.
let mem = Client::new("wos-live-...").with_model("tablet-1"); // default mem.recall("...", "alice").await?; // tablet-1 mem.with_model("tablet-1").recall("...", "alice").await?; // or pick a model per call
list_models ✓ live-tested
O catálogo - os ids que você pode passar em with_model e se cada um está disponível. Modelos com memory: "shared" leem o mesmo store; "isolated" mantém o seu próprio. Não requer chave de API.
mem.list_models().await?;
[{"id": "tablet-1", "name": "Tablet 1", "available": true, "memory": "shared"}]O catálogo acima sempre reflete os modelos disponíveis neste momento - passe qualquer outro id e você recebe um erro claro. Novos modelos aparecem nele automaticamente quando são lançados.
Escrever
add ✓ live-tested
Armazena uma memória. Embeddings gerados na entrada - sem chamada de LLM, você paga apenas embeddings.
mem.add("she prefers tea over coffee", "alice", json!({})).await?;
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}add_turn ✓ live-tested
Armazena um turno de conversa (usuário + assistente) na memória de curto e de longo prazo de uma só vez.
mem.add_turn("alice", "hi", "hello!").await?;
{"status": "ok"}add_bulk ✓ live-tested
Faz backfill de um grande bloco de texto. Fragmentado e convertido em embeddings no servidor - ideal para importar um histórico 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
Um fato mudou. A memória antiga é marcada como substituída (mantida para histórico); a nova toma o lugar dela no recall.
mem.update("alice", "576700aa-...", "she switched to coffee this year").await?;
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}Ler
search ✓ live-tested
Busca semântica, os mais relevantes primeiro. Puramente embeddings - sem correspondência por palavras-chave, então qualquer idioma encontra qualquer memória. O SDK retorna o array de memórias diretamente; o corpo HTTP bruto é mostrado abaixo.
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-06-10T04:20:39.688276876Z"
}], "search_ms": 315, "total_found": 1}| Campo | Significado |
|---|---|
| similarity | Similaridade bruta de embedding com a sua consulta (0–1). |
| is_superseded | Verdadeiro se este fato foi substituído por update(). |
| search_ms | Tempo de recuperação no servidor. |
recall ✓ live-tested
Uma única ida e volta retorna tudo o que o seu LLM precisa - cole o resultado direto no seu prompt: um contexto limitado e de tamanho fixo, não importa quanto você tenha armazenado.
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 recentes da conversa (memória de curto prazo), do mais antigo para o mais recente.
let turns = mem.history("alice").await?;
{"count": 2, "turns": [
{"role": "user", "content": "hi", "timestamp": "2026-06-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-06-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats ✓ live-tested
Contagens de memórias de um usuário.
mem.stats("alice").await?;
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}Excluir
delete ✓ live-tested
Exclui uma única memória pelo id.
mem.delete("alice", "576700aa-...").await?;
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
Apaga tudo de um usuário - uma única chamada, pronta para o GDPR.
mem.delete_all("alice").await?;
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}curl - sem instalação, os mesmos métodos.
Nenhum SDK para instalar - qualquer cliente HTTP funciona. Defina sua chave uma vez e chame os mesmos endpoints que os SDKs encapsulam. URL base https://api.wontopos.com, autenticação via X-API-Key, JSON na entrada e na saída.
# set your key once (never hard-code it) export WOS_API_KEY="wos-live-..."
Escrever
store ✓ live-tested
Armazena uma memória. Embeddings gerados na entrada - sem chamada de 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
Armazena um turno de conversa (usuário + assistente) na memória de curto e de longo prazo de uma só 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"}supersede ✓ live-tested
Um fato mudou - a memória antiga é marcada como substituída, a nova toma o lugar dela no 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"}Ler
search ✓ live-tested
Busca semântica, os mais relevantes primeiro. Puramente embeddings - qualquer idioma encontra qualquer memória.
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
Uma única ida e volta retorna curto prazo + longo prazo + contexto + uma instrução. Cole direto no seu 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..."}Excluir
forget ✓ live-tested
Exclui uma memória pelo id, ou omita-o para excluir tudo de um usuário (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
Ferramentas de recall invocáveis pelo seu modelo - cada uma é uma estratégia de recuperação diferente sobre a mesma memória. Use uma, ou execute várias ao mesmo tempo.
Novos engrams são lançados regularmente - esta lista cresce.
Memoir & Archive Em breve
Este é um modo de modelo, não uma ferramenta invocável. Selecione-o no modelo e todo recall, incluindo uma busca simples, volta com o tempo escrito dessa forma. Em breve.
Time_awareness Em breve
Um modo de modelo, não uma opção por chamada. Escolha o modelo - Time_awareness-memoir ou Time_awareness-archive - e todo recall volta renderizado dessa forma: uma busca simples, um recall ou qualquer engram, sem parâmetro extra. Um Memoir se lê do jeito que uma pessoa lembra; um Archive mantém um registro exato - a diferença aparece principalmente em como cada um escreve o tempo. O prefixo Time_awareness- deixa espaço para mais capacidades no futuro.
Memoir
Time_awareness-memoirConta o que aconteceu e como um momento levou ao seguinte, com a noção suave de tempo que uma pessoa recorda - lido como experiência, não como uma lista.
Archive
Time_awareness-archiveRetorna as correspondências como registros exatos - tempo decorrido preciso e âncoras absolutas, estruturados para um modelo ler diretamente.
store / add sob um user_id (esse user_id é o store daquela pessoa). Armazene primeiro; depois qualquer recall - incluindo a busca simples abaixo - volta com marcação de tempo. Veja o Início rápido para armazenar.# plain search - no engram - on a memoir model
r = mem.search("what does Alice drink?", user_id="alice", model="Time_awareness-memoir", tz=9)
# every hit gets a .time field → "a couple weeks ago" (archive model → "2 weeks ago (Jun 09)")tz é o deslocamento UTC de quem chama, em horas - assim, "esta manhã" e o limite de dia às 4h caem no horário local deles. Omita para UTC; via HTTP, é o cabeçalho X-WOS-Timezone. Aproximadamente, por região: Leste dos EUA -5, Centro dos EUA -6, Oeste dos EUA -8 · Reino Unido / Lisboa 0 · Europa Central +1 · Europa Oriental +2 · Índia +5.5 · China / Cingapura +8 · Coreia / Japão +9 · Sydney +10. (Horário padrão - o horário de verão desloca algumas regiões em +1; passe o que os seus usuários estiverem realmente usando.)
A mesma busca, dois modelos - as memórias são idênticas, apenas o time muda:
{ "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)" }
] }| Decorrido | 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 |
| ontem à tarde | yesterday afternoon | yesterday at 14:00 |
| ontem à noite | last night | 17 hours ago, at 22:00 |
| 2 dias | a couple days ago | 2 days ago (Tue 15:10) |
| 6 dias | several days ago | 6 days ago (Fri 15:10) |
| 9 dias | about a week ago | last week (Jun 16) |
| 16 dias | a couple weeks ago | 2 weeks ago (Jun 09) |
| 35 dias | about a month ago | last month (May 21) |
| 60 dias | a couple months ago | 2 months ago (Apr 2026) |
| 180 dias | about half a year ago | 6 months ago (Dec 2025) |
| 380 dias | about a year ago | last year (Jun 2025) |
| 800 dias | a couple years ago | 2 years ago (Apr 2024) |
| 1500 dias | about 4 years ago | 4 years ago (May 2022) |
Todos os valores acima são a saída real do renderizador. Observe as duas linhas de "ontem": um Memoir separa a tarde da noite anterior - um dia é um sono - enquanto um Archive escreve um único horário de relógio e não traça linha entre dia e noite.
Como cada modo lê o tempo
Memoir - do jeito que as pessoas realmente falam. Momentos recentes permanecem razoavelmente nítidos (uns 15 minutos, meia hora), e depois a formulação vai se alargando quanto mais para trás se vai - algumas semanas, cerca de meio ano, uns dois anos - do mesmo jeito que a própria memória se afrouxa com a distância. Dentro de um dia, ele troca o relógio por um marco: esta manhã, ontem à noite, ontem à tarde. E um dia é um sono, não um tique de calendário: o limite fica por volta das 4h no horário local, então uma madrugada ainda é lida como a mesma noite, não como o dia seguinte.
Archive - preciso, sempre com uma âncora. Cada linha traz o tempo decorrido exato mais uma referência absoluta a partir da qual um modelo pode calcular, e a âncora fica mais precisa conforme se aproxima do presente: um horário de relógio para hoje (8 horas atrás, às 07:10), um dia da semana e horário nesta semana (2 dias atrás (ter 15:10)), uma data neste mês (semana passada (16 jun)), um mês e ano além disso (6 meses atrás (dez 2025)). Nunca vago, nunca errado.
deep_recall
Recall multi-hop. Busca a sua consulta, depois pega a melhor correspondência e busca de novo sobre o conteúdo dela - trazendo contexto vinculado que uma busca única deixaria passar. Ideal quando as memórias referenciam umas às outras (uma pessoa → seus projetos → detalhes). Retorna até ~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 + saída), contado pelo mesmo tokenizador do restante da API; sem taxa oculta por engram. Precisa de vários de uma vez? Chame-os simultaneamente - cada engram é uma requisição independente.timeline
Recall em ordem temporal. Retorna memórias ordenadas do mais recente para o mais antigo por quando o evento aconteceu, não por relevância. Para perguntas de "quando foi X", histórico e sequência. Retorna até 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 + saída), contado pelo mesmo tokenizador do restante da API; sem taxa oculta por engram. Precisa de vários de uma vez? Chame-os simultaneamente - cada engram é uma requisição independente.gather
Coleta ampla. Busca e depois expande ao redor das três melhores correspondências - uma rede mais ampla que o deep_recall. Use-o para trazer tudo relacionado a uma pessoa, projeto ou tópico em uma única chamada. Retorna até ~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 + saída), contado pelo mesmo tokenizador do restante da API; sem taxa oculta por engram. Precisa de vários de uma vez? Chame-os simultaneamente - cada engram é uma requisição independente.Todos os endpoints, uma única URL base.
Nenhum SDK necessário - qualquer cliente HTTP funciona. URL base https://api.wontopos.com, autenticação via o cabeçalho X-API-Key, JSON na entrada e na saída. As operações de memória são POST; gerenciar stores usa POST / GET / DELETE em /collection. Um store precisa existir primeiro (veja Stores), ou as operações dentro do store retornam 404.
| Endpoint | Finalidade | Campos do corpo |
|---|---|---|
| POST /api/v1/memory/collection | criar um store | user_id |
| GET /api/v1/memory/collections | listar seus stores | (nenhum) |
| DELETE /api/v1/memory/collection | excluir um store + suas memórias | user_id |
| /api/v1/memory/store | armazenar uma memória | user_id · content · metadata? |
| /api/v1/memory/store-turn | armazenar um turno de conversa | user_id · user_msg · assistant_msg |
| /api/v1/memory/bulk-store | backfill de um bloco de texto | user_id · content · category? |
| /api/v1/memory/search | busca semântica | user_id · query · max_results? |
| /api/v1/memory/recall | curto + longo + contexto | user_id · query |
| /api/v1/memory/history | turnos recentes | user_id |
| /api/v1/memory/stats | contagens de memórias | user_id |
| /api/v1/memory/supersede | substituir um fato que mudou | user_id · old_memory_id · new_content |
| /api/v1/memory/forget | excluir uma (ou todas) | user_id · memory_id? (omitir = excluir tudo) |
# 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)"}Os mesmos recursos para todos.
Os níveis só aumentam seus limites.
Todo nível executa o motor completo - mesma qualidade de recall, mesmos idiomas, todos os métodos. Os níveis avançam automaticamente até o Nível 5 conforme suas compras acumuladas de créditos crescem, sem solicitação nem contato com vendas. Enterprise (Nível 6) é a única exceção.
Limites de gasto
Cada nível limita quanto você pode gastar por mês-calendário. Você avança imediatamente quando suas compras acumuladas de créditos atingem o próximo patamar.
| Nível de uso | Compra de créditos | Limite mensal de gasto |
|---|---|---|
| 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 | Fale conosco | Sem limite |
Limites de requisições
Os limites de requisições são por conta - todas as chaves de API de uma conta compartilham um mesmo limite, que escala com o seu nível. Excedê-lo retorna um 429 com um cabeçalho retry-after; recue (1s → 2s → 4s) e tente novamente. Todos os endpoints são compatíveis com idempotência, então repetir requisições é seguro.
| Nível | Requisições por minuto |
|---|---|
| Tier 1 | 150 |
| Tier 2 | 300 |
| Tier 3 | 600 |
| Tier 4 | 1,500 |
| Tier 5 | 3,000 |
| Tier 6 - Enterprise | Personalizado |
O Enterprise (Nível 6) recebe limites de requisições personalizados, um SLA, suporte dedicado e uma licença opcional de self-host - fale conosco.
Quando algo dá errado.
Os erros retornam como um envelope JSON com um type estável, uma mensagem legível e um request_id que você pode nos enviar ao relatar um problema.
{"type": "error", "error": {
"type": "authentication_error",
"message": "Invalid or revoked API key.",
"request_id": "063f8b83-eee2-4383-a5cf-11e4bcd29d7c"
}}| HTTP | Significado | O que fazer |
|---|---|---|
| 401 | Chave de API inválida ou revogada | Verifique a chave; emita uma nova no console. |
| 422 | Corpo malformado (campo ausente ou de tipo errado) | A mensagem indica o campo exato - corrija e tente novamente. |
| 429 | Limite de requisições excedido | Recue exponencialmente (1s → 2s → 4s) e tente novamente. Seguro: todos os endpoints são compatíveis com idempotência. |
| 5xx | Problema no servidor | Tente novamente com recuo; inclua o request_id se entrar em contato conosco. |
# 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
Os limites de requisições são por conta, compartilhados entre todas as suas chaves, e escalam com o seu nível - veja Níveis de uso. O uso da sua conta é exibido no console.
Seus servidores, seus dados.
O motor pode rodar dentro da sua própria infraestrutura - mesma API, mesmos SDKs. Aponte o cliente para o seu host e nada mais muda.
mem = Client(api_key="...", base_url="https://wos.your-host.com")- Residência de dados. As memórias nunca saem da sua rede.
- Mesma superfície. Os mesmos métodos e endpoints funcionam de forma idêntica.
- Licenciamento. Os pacotes de self-host são negociados por implantação - entre em contato.
Além da janela de contexto.
O WOS recupera de históricos de 1.4M tokens - muito maiores que qualquer janela de contexto de LLM - e ainda assim devolve uma fatia enxuta de ~1,470 tokens.
A memória do seu agente não é limitada pelo que cabe em um prompt. Ela guarda tudo e recupera apenas o que importa, não importa o quanto o histórico cresça.
Privado, e seu.
Seus dados permanecem no seu store. Nunca treinamos com eles, os visualizamos ou os reutilizamos - apenas os organizamos para que você possa recuperá-los.
- BYOK. Sua chave de LLM é enviada a cada requisição e nunca armazenada.
- Isolado. As memórias têm escopo por conta e, depois, por
user_id. - Exclusão GDPR & self-host. Uma única chamada apaga um usuário; execute o motor no seu próprio ambiente, se preferir.