Memória que sabe quem disse.
As pessoas lembram por pessoa: o que o Bob prometeu, o que você disse que faria. Marque cada memória com um falante e seu agente faz o mesmo, em todos os modelos Tablet e Scroll.
Um time, três memórias
Um armazenamento mantém muitas vozes separadas. Registre uma pessoa uma vez, salve cada fala com seu falante e depois pergunte por pessoa.
O armazenamento agora conhece o Bob. O limite de 50 é contado aqui, no registro; chamadas de salvamento nunca retornam erro de limite.
A memória agora é do Bob: toda busca que a devolve indica isso.
A fala do próprio assistente também vira memória, e "me" nunca conta para o limite.
Só as palavras do Bob voltam. As palavras de uma pessoa nunca voltam como as de outra.
Três regras para lembrar
- "me" é o próprio assistente. Nunca registrado, nunca contado. Reservado e minúsculo:
speaker: "Me"ou"ME"retorna400 invalid_request_errorem vez de ser convertido em silêncio. - O limite é contado no registro: 50 por armazenamento para começar. Registrar além disso retorna
400 invalid_request_errorcomspeaker_limit: 50no corpo do erro. Salvar com um nome não registrado também retorna400e nada é salvo. Filtrar a busca por um nome não registrado retorna404 not_found_error. Ramifique pelo status e pelos campos, não pelo texto da mensagem; planejamos aumentar o limite. - Rótulos vivem em toda leitura. Resultados de busca, o contexto de longo prazo do recall e resultados de engram carregam seu falante — o modelo sempre sabe de quem são as palavras. Passe speaker numa busca para obter só as de uma pessoa. Um supersede mantém o falante; forget o remove.
- Nomes são Unicode: qualquer idioma funciona. さくら, Иван e 하늘 são falantes válidos, e a atribuição se comporta igual em todos os idiomas. A correspondência é exata após trim e normalização Unicode, então
Bobebobsão duas pessoas. Nomes vão até 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" } }
Duas notas de escopo. speaker acompanha add / store: add_turn lembra a troca inteira, e rótulos por pessoa e o filtro vêm de memórias com speaker explícito. E passagens de sessão (expand) são compostos de várias memórias, então não carregam rótulo; um filtro speaker sempre devolve memórias atômicas e rotuladas. E uma escrita cujo significado esteja próximo o suficiente de uma memória já guardada é descartada: a correspondência é semântica, não textual. Esse store devolve status "duplicate" com uma nota explícita, não guarda nada e não anexa falante. Um facto genuinamente novo que varie apenas num detalhe de um existente ("alergia a marisco" depois de "alergia a amendoim") cai na mesma regra, por isso leia status em vez de assumir que a escrita foi concluída.
Testamos do jeito difícil: memórias sem nomes no texto, lembradas por pessoa. A atribuição vem do registro de falantes, não de casamento de palavras, então funciona igual em qualquer idioma.
Como usar
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 }A lista mostra quem o armazenamento conhece, com contagens por pessoa contra o limite. Remover apaga só o registro: as memórias ficam, apenas o rótulo do nome vai embora.
Ler as memórias de uma pessoa
by_speaker retorna o que uma pessoa disse, da mais recente para a mais antiga, sem consulta. "me" devolve as próprias palavras do assistente. A paginação por cursor é a mesma das imagens: devolva next_before e next_skip_ids.
page = mem.by_speaker("Bob", limit=50)
page["memories"], page["chunks"]| Campo | O que faz |
|---|---|
| memories | As memórias, da mais recente para a mais antiga. O mesmo formato que uma busca retorna. |
| chunks | Os fragmentos em nível de frase por trás dessas memórias - o que uma exclusão de fato removeria. Normalmente maior que o número de memórias; exiba-o antes de alguém confirmar uma exclusão. Também informado como points_to_delete. |
| next_before | Cursor para a próxima página, junto com next_skip_ids. Os dois são necessários porque memórias podem compartilhar o mesmo timestamp. |
speaker aqui é a etiqueta gravada no momento do armazenamento, não uma busca sobre o texto. Uma memória armazenada sem falante é alcançável por busca, mas nunca por by_speaker, inclusive sob "me".Listar, navegar e remover falantes
mem.list_speakers() # who is registered
mem.by_speaker("Bob") # what Bob said, newest first
mem.remove_speaker("Bob") # unregister; the memories stay