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-08-01; 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("scroll-1").recall("...", "alice"); // or pick a model per call
listModels
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"},
{"id": "tablet-2", "name": "Tablet 2", "available": true, "memory": "shared"},
{"id": "scroll-1", "name": "Scroll 1", "available": true, "memory": "shared"},
{"id": "scroll-1.2", "name": "Scroll 1.2", "available": true, "memory": "shared"}]ping
Confirme a conexão e que sua chave de API funciona: uma verificação de uma linha.
await mem.ping(); // true, or throws AuthenticationError / PaymentRequiredError
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
Armazena uma memória. Sem chamada de LLM na entrada: você paga apenas a tarifa de escrita.
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
Armazena um turno de conversa (usuário + assistente) na memória de curto e de longo prazo de uma só vez.
await mem.addTurn("hi", "hello!", "alice");
{"status": "ok"}speaker
Cada memória pode carregar quem a disse. Registre uma pessoa uma vez e depois passe o nome como speaker; "me" (as palavras do próprio assistente) nunca precisa de registro. A busca também aceita speaker, para lembrar só as palavras de uma pessoa.
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
Faça backfill de um bloco grande de texto. Dividido e indexado no servidor, ideal para importar 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
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("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"}Ler
search
Busca semântica, os mais relevantes primeiro. Qualquer idioma encontra qualquer memória, seja qual for o idioma em que foi escrita. O SDK retorna o array memories diretamente; o corpo HTTP bruto aparece abaixo. Alguns modelos respondem com mais de um conjunto de resultados e o SDK os devolve mesclados, então o array pode conter MAIS do que max_results. Dimensione sua janela de prompt pelo que você recebe, não pelo número que pediu.
const r = await mem.search("what does she drink?", "alice", 1);
[{
"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624",
"content": "she prefers tea over coffee",
"category": "general",
"time_bucket": "2026-06",
"importance": 0.3,
"similarity": 0.6316057443618774,
"is_superseded": false,
"superseded_by": null,
"created_at": "2026-07-10T04:20:39.688276876Z"
}]| Campo | Significado |
|---|---|
| similarity | Quão próxima esta memória está da sua consulta (0–1). |
| is_superseded | Verdadeiro se este fato foi substituído por update(). |
| search_ms | Tempo de recuperação no servidor. |
recall
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
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-07-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-07-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats
Contagens de memórias de um usuário.
await mem.stats("alice");
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get
Busca uma memória pelo id - o id que add ou list_memories retornou. Apenas o texto original armazenado e seus metadados. Um id de outro store, ou uma memória apagada ou invalidada, retorna 404.
const m = await mem.get("alice", "576700aa-...");
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "created_at": "2026-07-10T04:20:39Z", "event_date": null,
"is_superseded": false, "superseded_by": null}listMemories
Lista as memórias de um armazenamento - apenas o texto original que você guardou e seus metadados. Paginado por cursor: reenvie o next_cursor retornado para a próxima página.
const page = await mem.listMemories("alice", { limit: 100 });
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "created_at": "2026-07-10T04:20:39Z", "event_date": null,
"is_superseded": false, "superseded_by": null}
]}iterMemories · exportMemories
Percorra todas as memórias sem gerenciar o cursor, ou traga o armazenamento inteiro de uma vez.
for await (const m of mem.iterMemories("alice")) console.log(m.id, m.content); const everything = await mem.exportMemories("alice");
Excluir
delete
Exclui uma única memória pelo id.
await mem.delete("alice", "576700aa-...");
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}deleteAll
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"}Erros e confiabilidade
Cada falha é um erro tipado - capture o específico (limite de taxa, autenticação, pagamento) ou todos com o 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
Leia a cota restante após qualquer chamada e desacelere antes de bater no limite.
await mem.search("...", "alice"); const rl = mem.rateLimit; // { limit: 150, remaining: 3, reset: ... }
searchSelf
As duas trilhas em uma única chamada num modelo de memória própria (Scroll 1.2+): o que os outros disseram e as palavras do PRÓPRIO agente - separadas, para que quem lê nunca confunda quem falou.
const { memories, self_memories } = await mem.searchSelf("what did I promise?", "alice"); // memories = what others said · self_memories = the agent's OWN words
listEngrams
Pergunte ao serviço quais engramas e formas de entrega o modelo selecionado consegue executar, em vez de fixar nomes que ficam desatualizados assim que um novo é lançado.
const { engrams, forms } = await mem.listEngrams(); // ask, never hard-code
filters
Restringe a busca a parte do repositório. Aplicado antes da ordenação, então você recebe as melhores correspondências dentro do filtro - não um top-N filtrado depois.
await mem.search("what did we decide", "alice", 10, { filters: { categories: ["work"], event_from: "2026-01-01" }, // when it HAPPENED });
idempotencyKey
Torna seguro repetir uma escrita. Use quando a repetição é sua - um job que caiu e foi reexecutado, uma fila que reentrega.
await mem.add("she prefers tea", "alice", {}, { idempotencyKey: `import:${row.id}` });
import:row-42), nunca uma constante: uma chave reutilizada em duas escritas diferentes repete a primeira e a segunda se perde em silêncio. Formato: 1-128 caracteres de [A-Za-z0-9._:-].withTimeout / withRetries / withDeadline
Ajuste um único ponto de chamada sem mexer no cliente já construído: um clone com timeout maior para um backfill grande, ou sem retentativas dentro do seu próprio laço de retry.
timeout limita uma tentativa, então uma chamada que repete pode durar mais que ele: nos valores padrão uma única chamada pode segurar uma conexão por 30 s, recuar, tentar de novo e de novo. deadline limita a chamada inteira: cada tentativa é cortada no que sobrou, e nenhuma espera dorme além do orçamento. Defina quando quem chama tem um limite real, como um handler de requisição com cinco segundos.
await mem.withTimeout(120_000).addBulk(bigBlob, "alice"); // this slow call only await mem.withRetries(0).add("...", "alice"); // you retry, not the SDK await mem.withDeadline(5_000).recall("...", "alice"); // 5s for the whole call await mem.withSignal(ctrl.signal).recall("...", "alice"); // caller can cancel