Omem

Memória para agentes de IA que rastreia o que é acreditado, quando e por quê. Contradições são expostas em vez de sobrescritas, e a identidade é vinculada ao processo para que um modelo não possa ler a memória de outro agente ou usuário.

Documentação

OMEM

CI PyPI Python License: MIT

O sistema de registro do que um agente de IA acreditou e fez. Somente acréscimo, com a evidência sob cada crença, ambos os lados de cada contradição preservados, e uma pessoa nomeada por trás de cada ação arriscada. Então, quando um agente age e alguém pergunta "por que ele fez isso", você responde com um registro em vez de uma investigação.

OMEM fica onde uma camada de memória fica e faz um trabalho diferente. Em vez de despejar texto em um armazenamento vetorial e torcer para o melhor, ele rastreia o que cada agente acredita ao longo do tempo, mantém a evidência sob cada crença e lida com contradições explicitamente, para que um agente possa raciocinar sobre o que sabe, quando aprendeu e por que sustenta.

E não começa do nada. Instalações que optam por compartilhar o que descobrem sobre pessoas em geral, como contagens que não nomeiam ninguém, e uma instalação nova aproveita essa intuição no primeiro dia em vez de gastar seis meses conquistando-a. O que você contribui são contagens; o que você recebe de volta é o de todos os outros. Um padrão emprestado nasce mais fraco do que um que você aprendeu sozinho, e ainda assim cede no momento em que a evidência da própria pessoa discorda, então o geral nunca sobrepõe o individual.

O banco está vazio hoje. Nenhuma instalação contribuiu ainda, o que significa que as primeiras decidem o que ele aprende, e vale saber que um corpus de regularidades sobre pessoas pode carregar os vieses de quem o preencheu. A regra de mineração foi reconstruída para que um padrão tenha que superar a taxa base em vez de se aproveitar dela (Working Paper No. 1); se a população contribuinte é representativa é uma questão separada e em aberto.

Ele roda localmente sem serviços externos e sem dependências para instalar.

pip install omem-infrastructure && omem-server

Ou implante um servidor privado com um clique:

Deploy to Render

O blueprint provisiona um pequeno serviço com disco persistente, autenticação por senha ativada (o primeiro cadastro é a conta do operador) e uma chave mestre gerada. Fly.io também funciona: fly launch --copy-config com o fly.toml incluído.

Docs: infrastructure.omem-cloud.com · Quickstart · Security · Contributing

Enviando agentes para clientes? A trilha de auditoria e o portão de aprovação são o ponto: o que a revisão de segurança de um cliente pede, e um pequeno número de pilotos práticos de parceiros de design está aberto.

Quer ver o padrão inteiro rodando antes de ler mais uma palavra? refund-desk é a integração de referência: um agente de suporte que movimenta dinheiro, com recibos. Um arquivo, roda em um minuto, afirma cada alegação que faz.

Replay de scripts/demo_reasoning.py: dois registros se fundem em uma pessoa, uma regra declarada conclui, a premissa é retraída e a conclusão é retirada na mesma solicitação, e uma divisão é final para a máquina.

Isso é scripts/demo_reasoning.py, abreviado. Cada linha é um comportamento afirmado que roda em CI, então esta imagem não pode silenciosamente deixar de ser verdadeira.

O painel durante uma execução real: duas fontes discordam sobre o plano de um cliente, OMEM mantém ambos os lados e marca a proposição como CONTRADITADA, e cada crença se abre na cadeia de por que é acreditada.

Duas fontes discordam. Nenhuma é sobrescrita. Veja tudo rodando.

O que o torna diferente

A maioria da memória de agente é uma lista de fatos. Quando dois fatos entram em conflito, um silenciosamente sobrescreve o outro e o histórico se perde. OMEM mantém ambos, rastreia qual é atualmente acreditado e pode dizer por quê. Algumas coisas que ele faz que um armazenamento vetorial simples não faz:

  • Estado de crença ao longo do tempo. Cada fato tem um estado (acreditado, contraditado, desconhecido) que o motor calcula a partir da evidência, não uma linha estática.
  • Tratamento de contradição. Informações conflitantes são trazidas à tona, não perdidas. Alegações nomeadas X e not:X são tratadas como opostas automaticamente; para qualquer outra coisa, mem.contradict("prefers_annual", "prefers_monthly") diz isso uma vez. OMEM nunca decide que duas alegações discordam lendo-as, porque esse julgamento é o que impediria a mesma pergunta de ter a mesma resposta um ano depois.
  • Proveniência. Pergunte por que algo é acreditado e obtenha a cadeia que levou até lá.
  • Memória entre agentes. A memória é privada para um agente por padrão; você escolhe o que compartilhar com uma equipe ou com o projeto inteiro.
  • Recuperação semântica. Encontra memórias relevantes mesmo quando a redação difere de como foram armazenadas. Funciona offline com uma incorporação sem dependências; defina OMEM_EMBED_MODEL para usar o modelo de incorporação real do seu provedor, com vetores em cache e fallback automático se o provedor estiver fora do ar.
  • Um ciclo de aprendizado. Memórias que se mostram úteis ganham ranking maior ao longo do tempo.
  • Autocura que recusa. OMEM registra falhas e executa reparos sob política, e não executará um reparo que ninguém autorizou. Um modelo pode propor um plano; apenas ações registradas em código executam, e a classe de risco vem do registro do OMEM em vez do plano alegar a própria. Veja Self-healing.

Início rápido

Você precisa de Python 3.9 ou mais novo. Sem outras dependências.

Opção 1: instale do PyPI (servidor incluído).

pip install omem-infrastructure
omem-server

Atualizando de uma versão anterior? pip install --upgrade omem-infrastructure. Um simples pip install em um pacote que você já tem relata "Requirement already satisfied" e não faz nada, o que é uma maneira silenciosa de continuar rodando a versão que você estava tentando deixar. python -c "import omem; print(omem.__version__)" diz o que você realmente tem.

Isso inicia o servidor em http://127.0.0.1:8787 e, na primeira execução, imprime um id de projeto e uma chave de API: sem chamada de cadastro, sem visita ao painel, nada para configurar. Cole-os diretamente:

from omem import Memory

mem = Memory(api_key="omem_sk_...", base_url="http://127.0.0.1:8787",
             project="proj_...")
mem.remember(agent="support", about="customer:1", claim="prefers_annual_billing")
print(mem.believes(about="customer:1", claim="prefers_annual_billing"))
# -> BELIEVED_TRUE

QUICKSTART.md leva isso a uma contradição e a uma cadeia de proveniência em cerca de cinco minutos, que é onde a diferença de um armazenamento vetorial realmente aparece.

Opção 2: rode deste repositório.

cd server
python api.py            # or: python api.py 9000 for a different port

Mesmo servidor, mesmo id de projeto e chave de primeira execução, iniciado do código-fonte. A configuração leva cerca de um minuto de qualquer maneira. Duas diferenças que valem saber:

  • O banco de dados cai em um lugar diferente. Do código-fonte, fica em server/data/omem.db; omem-server escreve ./omem-data/omem.db no diretório de onde você o executou. OMEM_DB substitui qualquer um.
  • O painel precisa ser construído uma vez. A wheel envia uma cópia construída; um clone não, então o servidor imprime "dashboard not bundled" até você rodar cd web && OMEM_STATIC=1 npm run build. A API é idêntica de qualquer maneira.

Opção 3: Docker.

docker run -p 127.0.0.1:8787:8787 -p 127.0.0.1:3000:3000 \
  -v omem-data:/app/server/data ghcr.io/troybrandonc-bit/omem

API na 8787, painel na 3000, dados no volume nomeado. As portas são publicadas no loopback de propósito: o contêiner roda em modo local, que não tem senhas, então a alcançabilidade é o controle de acesso. Colocá-lo em uma rede significa definir OMEM_AUTH=password e OMEM_MASTER_KEY primeiro, e docker-compose.yml neste repositório mostra essa forma.

Autocura

OMEM registra o que quebra e repara sob política. Isso é infraestrutura para seus agentes, não algo que OMEM faz consigo mesmo: você registra um componente e os ganchos com os quais ele pode ser reparado, e OMEM é dono da memória, do limite de segurança e do ciclo de vida.

A parte que importa é o que ele recusa. Um modelo pode propor um plano de reparo; OMEM decide o que é permitido. Apenas tipos de ação registrados em código podem executar, a classe de risco vem desse registro e nunca do plano, ações de alto risco precisam de aprovação explícita, e um reparo não é bem-sucedido até verificar.

mem.healing.report_health("vector-index", "healthy", "12,400 vectors")

result = mem.healing.handle(
    error={"component": "vector-index", "error_type": "StaleShard"},
    plan={"diagnosis": "replica fell behind after a partition",
          "confidence": 0.8,
          "actions": [{"type": "rebuild_index"}, {"type": "exec_shell"}]},
)
result["status"]     # -> "denied"
result["decisions"]  # rebuild_index: permitted (low risk)
                     # exec_shell:    unknown action type (not registered)

Nada rodou. O plano é mantido com o motivo de cada ação ter sido permitida ou recusada, então a recusa é um registro em vez de um silêncio. Texto de erro e saída de modelo são dados aqui, e nenhum pode nomear uma ação à existência.

Tudo o mais que você gostaria também é aplicado: falhas são identificadas por impressão digital para que mil erros idênticos sejam uma entrada, uma tempestade de reparos é limitada por componente, uma recuperação por componente é reivindicada no banco de dados, segredos são removidos antes de qualquer coisa ser persistida, e um erro interno escala em vez de tentar novamente às cegas.

A tela Self-healing no painel mostra a saúde do componente, o registro de falha e até onde cada reparo chegou, com o passo em que parou marcado, e o diagnóstico em que agiu. server/healing.py é o subsistema inteiro e vale a pena ler se você está decidindo se confia nele.

O painel

O painel vem dentro do pacote. Inicie o servidor e abra o mesmo endereço, http://127.0.0.1:8787. Está tudo lá: memória, conflitos, o grafo de crenças, a linha do tempo, logs e a trilha de auditoria. Sem Node, sem segundo processo, sem segunda porta.

Em modo local (o padrão) não há login; ele abre no projeto que o servidor criou para você. Em um servidor rodando OMEM_AUTH=password, ele mostra um formulário de login em vez disso.

É uma exportação estática de web/, a única UI neste repositório, copiada para a wheel no momento da construção. Para trabalhar nela:

cd web
npm install
npm run dev          # http://localhost:3000, proxying to the API on 8787

e para reconstruir a cópia incluída, OMEM_STATIC=1 npm run build.

Autenticação

OMEM roda em um de dois modos, e a diferença importa antes de você colocá-lo em qualquer lugar que não seja sua própria máquina.

OMEM_AUTH=local: o padrão, e o que torna o início rápido um minuto. Não há login: o painel provisiona uma sessão contra o servidor que pode ver. Isso só é seguro enquanto nada mais puder alcançar o servidor, então o modo local recusa-se a vincular um endereço não-loopback. Se você quer dizer isso (um contêiner cujas portas são publicadas em 127.0.0.1, uma VM de usuário único), defina OMEM_ALLOW_INSECURE_BIND=1.

OMEM_AUTH=password: exigido para um servidor que outras pessoas possam alcançar. Contas têm senhas, com hash PBKDF2-SHA256. Cadastrar-se com um endereço que já tem senha retorna 409 em vez de uma sessão, TOTP é aplicado onde está inscrito, e o servidor recusa-se a iniciar a menos que OMEM_MASTER_KEY esteja definido para algo diferente do padrão de desenvolvimento.

export OMEM_AUTH=password
export OMEM_MASTER_KEY="$(python3 -c 'import secrets;print(secrets.token_urlsafe(32))')"
omem-server

TLS

Aponte OMEM_TLS_CERT e OMEM_TLS_KEY para um certificado e o servidor fala HTTPS por si só (piso TLS 1.2). Definir apenas um é um erro de inicialização, não um retorno silencioso para texto puro. Um proxy de terminação ainda é melhor em escala, mas rodar sem um não significa mais rodar em claro.

Criptografando memória em repouso

pip install "omem-infrastructure[encryption]"
export OMEM_ENCRYPT_AT_REST=1
export OMEM_MASTER_KEY="$(python3 -c 'import secrets;print(secrets.token_urlsafe(32))')"

Criptografa o log de operações, payloads de origem ingeridos e a evidência citada por trás de cada memória com AES-GCM. Linhas de texto puro existentes continuam funcionando, então pode ser ativado para um banco de dados que já tem dados. Ele recusa-se a iniciar com a chave mestre de desenvolvimento, e recusa-se a rodar sem uma biblioteca AEAD real em vez de cair para o keystream stdlib usado para tokens OAuth.

Perdeu a chave e os dados se foram: não há caminho de recuperação, e nenhuma ferramenta de rotação ainda.

Quando duas entidades são uma pessoa

A formação cunha ids de entidade do que pode ver, então um humano pode chegar duas vezes: person:sarah_chen de uma frase em um corpo de mensagem, person:sarah_chen@acme de escrever o e-mail. Cada id detém metade das crenças sobre uma pessoa, e eles não podem nem corroborar nem contradizer um ao outro.

curl -X POST "$OMEM/v1/memory/resolve?project=$PROJECT" \
  -H "Authorization: Bearer $KEY" -d '{}'

Evidência decisiva funde: o mesmo nome completo na mesma organização, que é a regra que a própria formação já aplica dentro de um caminho. A fusão é uma correferência registrada por agent:omem-resolution com uma derivação para seus âncoras, então /why explica e uma divisão a desfaz. Evidência sugestiva ("Sarah" contra "Sarah Chen" na acme) torna-se uma proposta em GET /v1/memory/merge-proposals que não muda nada até uma pessoa aprovar -- e a aprovação é registrada sob o nome do aprovador, não da máquina. As recusas são o recurso: nunca entre organizações, nunca sem uma, nunca em sobrenomes conflitantes ou vocabulário de papéis, nunca quando ambíguo, e nunca re-fundindo o que uma divisão separou. Passe {"apply": false} para uma execução de teste que não registra nada. Pelo SDK, é mem.resolve(), mem.merge_proposals() e mem.approve_merge(id, agent=...); a tela de Propostas do painel é a mesma fila com botões.

Regras que concluem, e retomam

A contradição é declarada, nunca inferida de texto. A inferência funciona da mesma forma: uma regra é um dado que você declara, e a máquina compõe exatamente o que você disse e nada mais.

curl -X POST "$OMEM/v1/rules?project=$PROJECT" -H "Authorization: Bearer $KEY" \
  -d '{"when": [{"rel": "works_at", "dir": "fwd"}, {"rel": "owns", "dir": "rev"}],
       "then": {"rel": "involves", "dir": "rev"}}'
curl -X POST "$OMEM/v1/memory/infer?project=$PROJECT" \
  -H "Authorization: Bearer $KEY" -d '{}'

Sarah trabalha na Beta; a Acme é dona da Beta; a OMEM conclui que a órbita da Acme envolve Sarah — como uma afirmação comum derivada das premissas exatas que usou, então /why caminha da conclusão até a evidência, e como uma aresta de grafo real, então a recuperação a alcança em um salto.

A razão para querer isso é o que acontece no caminho de volta. Retire a propriedade e a conclusão é retirada na mesma solicitação; uma conclusão que se apoia nessa conclusão cai depois dela. Cada retirada é uma retratação comum no log de operações. A evidência é gasta uma vez — uma conclusão que você fecha nunca é re-litigada a partir das mesmas premissas — e as conclusões de uma regra desativada são retiradas na próxima passagem.

Tudo isso é um script em vez de um parágrafo, o mesmo contrato da demonstração de recusa abaixo — cada comportamento afirmado, saída não zero se um deixar de valer, executado em CI:

python3 scripts/demo_reasoning.py

Formas que fazem perguntas

Duas crenças entram em conflito apenas sobre os mesmos sujeitos, o que mantém o estado de crença reproduzível — e isso significa que "Sarah trabalha na Acme" e "Sarah trabalha na Beta" nunca se contradizem. Se isso é aceitável é conhecimento de domínio, então você declara:

mem.declare_constraint("works_at", "one_dst_per_src")   # one employer at a time
mem.check()

Uma violação se torna uma tensão na fila de Propostas. A OMEM não escolhe o empregador mais novo: você nomeia o que sobrevive (os demais são retirados sob seu nome, e qualquer coisa que o mecanismo de regras concluiu deles cai na mesma solicitação), ou descarta, o que é permanente exatamente para aquela evidência. A máquina nunca incomoda duas vezes sobre uma pergunta que uma pessoa já respondeu.

Palpites com arquivos de caso

Humanos aprendem com um exemplo saltando para conclusões. Esse reflexo é também por que a memória humana confabula. A OMEM mantém a velocidade e descarta a confabulação: ela salta, e então duvida do salto mais do que você duvidaria.

mem.leap()                              # one similar case is enough
mem.expects(about="customer:gamma")
# -> wants_pdf_invoices, strength 0.35, "beta holds it; gamma resembles
#    beta (both prefer annual billing, both use crm)", docket attached
mem.interrogate()                       # the skeptic works every open case

Uma hipótese nunca é uma crença. Ela nunca entra no mecanismo, believes() permanece DESCONHECIDO por melhor que seja o palpite, e apenas a realidade sobre o alvo pode apoiá-la ou refutá-la — semelhantes apenas movem a força. Vereditos ensinam: uma fonte cujos saltos continuam sendo confirmados gera palpites mais fortes, uma que continua errando gera mais fracos, e um salto refutado nunca é feito novamente a partir da mesma evidência. Um caso que não se resolve começa a perguntar, e a pergunta cai no painel onde um sim ou não se torna evidência real sob seu nome — o veredito ainda vem da interrogação, nunca por decreto.

A semelhança funciona como a analogia humana: uma característica compartilhada rara une mais forte do que três comuns, experiência com palavras diferentes conta como a mesma experiência quando um modelo de incorporação está configurado, e contexto compartilhado pesa menos do que caráter compartilhado. E mem.calibration() é a metacognição: a OMEM sabe quais tipos de afirmações ela adivinha bem, e sua ousadia segue seu histórico.

Priores: o que aprende sobre pessoas em geral

Um salto projeta de uma pessoa semelhante. Um prior projeta de uma regularidade aprendida em muitas: "pessoas que têm P tendem a ter Q." A OMEM extrai isso do que já sabe e usa para interpretar alguém novo a partir de muito pouco.

Um par é mantido apenas onde ter P move mensuravelmente as chances de Q além de quão comum Q é por si só, e esse teste é aplicado ao limite inferior da taxa em vez da taxa em si, então um padrão apoiado em um punhado de pessoas deve ser muito mais limpo do que um apoiado em centenas.

mem.learn_priors()                      # mine regularities across everyone
mem.priors()
# -> holds likes_dashboards -> holds wants_pdf_invoices
#    in_population: 41 of 52     wants_pdf_invoices on its own: 0.29
#    kept because the lower bound of that rate clears 0.29, not
#    because wants_pdf_invoices happens to be common
#    when_applied: supported 3, refuted 0

Essa regra substituiu uma que perguntava apenas se sessenta por cento dos detentores de P também tinham Q. Medida contra 19.668 respondentes reais com uma estrutura latente conhecida, a regra antiga recuperou essa estrutura em 0,185 onde o acaso é 0,184: ela selecionava consequentes por quão comuns eram. A regra atual a recupera em 0,875, usando 94% menos priores que cobrem mais afirmações do que antes. O estudo é Documento de Trabalho nº 1 e o harness está em benchmarks/external/.

O ponto é que um prior nunca sobrepõe uma pessoa. Ele dispara apenas em um silêncio: se alguém tem P mas não disse nada sobre Q, a OMEM salta Q para eles como um palpite; no momento em que a evidência da própria pessoa fala, o prior é recusado, e se a evidência deles depois contradiz um palpite aceito, o loop de interrogação o refuta e o prior assume a perda. Dois números honestos viajam com cada prior: a taxa que ele manteve na população em que foi aprendido, e seu registro separado quando realmente aplicado. Um padrão visto em poucas pessoas demais não tem permissão para disparar de forma alguma.

Um prior armazena contagens, nunca uma pessoa. É conhecimento sobre pessoas em geral sem nenhum fato sobre alguém dentro, o que permite que você leia o conjunto inteiro, ou o entregue a alguém, sem vazar um único sujeito. O padrão geral sempre cede ao indivíduo, por construção em vez de por política.

Comportamento cotidiano também é memória

Nem tudo que vale lembrar é um contrato. "Manhãs funcionam melhor para mim", "e-mail é a melhor forma de me contatar", "não trabalho às sextas" são as pequenas preferências repetidas da correspondência comum, e a OMEM as extrai offline, sem exigir LLM. Uma frase em primeira pessoa se anexa à pessoa que a escreveu, o mesmo nó em que o emprego deles é inferido a partir do endereço de onde escrevem, enquanto "preferimos assíncrono" permanece um fato sobre a empresa. Um endereço de papel como support@ nunca cria uma pessoa falsa, e cada hábito carrega a frase de onde veio como evidência. Essas são exatamente as regularidades que a camada de priores generaliza: "pessoas que preferem manhãs geralmente preferem e-mail" é um padrão aprendido, não um palpite.

O direito de ser esquecido, executado

Retratação não é apagamento: um log somente de anexação mantém o histórico, e uma solicitação real de apagamento significa que os dados pessoais se foram. POST /v1/entities/{id}/forget reescreve o log de operações de verdade: cada registro que referencia a pessoa, tudo que cascateou desses, os eventos que carregaram apenas as palavras deles, e as citações de evidência, arestas, hipóteses e mensagens de origem bruta por trás deles. Uma frase deles citada sob uma crença sobrevivente é redigida, porque a frase é da pessoa mesmo quando a crença é de uma empresa. O log podado é verificado por reprodução através de um mecanismo de rascunho antes que qualquer coisa seja tocada, e o que permanece depois é uma linha contendo um hash, contagens e uma data: prova de que o apagamento ocorreu, retendo nada. É um ato administrativo, pede confirmação explícita, e não pode ser desfeito.

O bem comum, e o que nunca aceitará

Na primeira abertura, o painel faz uma pergunta: contribuir com padrões anônimos para o bem comum compartilhado da OMEM? O que sai da máquina se você disser sim são contagens, como "mantido por 5 de 7". Nunca um nome, uma empresa, uma mensagem, ou um número dos seus dados; o arquivo exato fica no seu próprio disco para inspeção, e qualquer resposta é revogável em Configurações. Silêncio não envia nada, para sempre. O bem comum agrega essas contagens entre instalações consentidas para estudar o comportamento de trabalho humano em geral. O anonimato é estrutural nas duas portas: uma contribuição que carrega qualquer coisa identificável é recusada na chegada, então o pool não pode vazar o que nunca manteve.

Ensinando IA como as pessoas são

O bem comum existe para um objetivo: conectar humanos e IA dando à IA uma melhor compreensão da nossa natureza e comportamento. Modelos hoje aprendem sobre pessoas de texto raspado que nunca foi oferecido e que nomeia todos dentro dele. O bem comum é a oferta oposta: regularidades em como as pessoas realmente trabalham, contribuídas de propósito, sem conter ninguém.

Ele é entregue como um corpus de treinamento. Uma linha JSON por padrão carrega as contagens e uma renderização em inglês simples ("sujeitos que preferem reuniões de manhã geralmente também preferem contato por e-mail: 24 de 31 com uma posição, 77%"), com um cartão de conjunto de dados declarando a proveniência, a história de consentimento e a licença, CC BY 4.0 com atribuição ao bem comum da OMEM. Um modelo treinado nele aprende a taxa, nunca uma pessoa, e o cartão diz a frase operativa em voz alta: taxas são tendências populacionais, nunca regras sobre indivíduos. Uma pessoa real pode e vai contradizer qualquer uma delas, e um sistema que respeita pessoas trata cada padrão como um prior que cede ao indivíduo, da mesma forma que a própria OMEM faz.

O que mudou enquanto você estava fora

A pergunta que todo agente faz no início da sessão, respondida pela mesma maquinaria as_of que toda consulta já usa:

d = mem.changes(since=last_seen)

Crenças que apareceram; crenças que fecharam, cada uma dizendo como — substituídas e por quê, ou retiradas; conflitos recém-abertos e recém-resolvidos; referentes que se fundiram ou dividiram. Somente leitura, determinístico e seguro por escopo: seu diff contém apenas o que você poderia ter recuperado.

Vendo o que recusa

O limite de autocura é a parte difícil de acreditar a partir de uma descrição, então é um script em vez de um parágrafo:

python3 scripts/demo_refusal.py

Ele dirige um servidor real através das duas maneiras como um plano de reparo realmente dá errado. Um modelo propõe reload_config (registrado) ao lado de exec_shell (não registrado em lugar nenhum): o primeiro é permitido por seus méritos, o segundo é recusado pelo nome, e o plano como um todo é negado. Um plano que afirma sua própria classe de risco a faz ser ignorada, porque o risco vem do registro. Uma instrução embutida na mensagem de erro que o modelo leu não executa nada. Cada veredito é mantido e legível depois, e um segredo no contexto de erro não está no armazenamento.

O registro acontece em código. Não há API que adicione um tipo de ação executável, então nenhum plano e nenhum prompt amplia o que é permitido.

Cada recusa nele é afirmada e ele sai não zero se uma parar de acontecer, então ele roda em CI. Uma demonstração que pode silenciosamente se tornar falsa é pior do que nenhuma.

O benchmark Witness

Benchmarks de memória medem recordação. Witness mede o dever oposto: um sistema de memória afirma coisas que ninguém disse a ele, continua repetindo o que foi retirado, resolve desacordos silenciosamente, funde duas pessoas que compartilham um nome, ou mantém conclusões cujas premissas morreram?

Seis cenários, dez eixos, pontuação determinística, sem juízes LLM. Adaptadores estão incluídos para OMEM, Mem0 e Graphiti; cada sistema é alimentado pelo seu próprio caminho nativo, e uma sonda que um sistema não pode expressar relata como não suportada em vez de aprovada ou reprovada. Este repositório não publica números que não executou: o cartão da OMEM, cada sonda passando em cada eixo, é afirmado por server/tests_witness_benchmark.py contra um servidor ao vivo em cada commit. Execute os outros com suas próprias chaves e leia seu próprio cartão.

O livro de reivindicações

Marketing que não pode falhar é indistinguível de marketing que é falso. CLAIMS.md mapeia cada frase de sustentação de carga que este projeto diz sobre si mesmo para a declaração executável que ficaria vermelha se ela parasse de ser verdadeira, e o livro é ele próprio guardado em CI: uma linha cujo arquivo desaparece falha a construção.

Duas linhas que valem destacar porque ninguém mais neste nicho pode escrevê-las. Ele não telefona para casa para ninguém: tests_airgap.py instala uma guarda sob a camada de socket, então dirige cada recurso principal através de um servidor ao vivo e falha em uma única conexão de saída ou consulta DNS que não seja loopback. Atualizações nunca reescrevem seu passado: um log congelado em 2026-08-29 reproduz para um resumo de estado byte-idêntico em cada commit, então nenhuma versão futura pode reinterpretar silenciosamente um histórico que você já registrou.

Provando que o estado segue do log

A memória é reconstruída reproduzindo um log somente de acréscimo. Isso é fácil de afirmar e não era verificável de fora, o que é um ponto fraco para um projeto cujo argumento central é que você pode reconstruir o que um agente acreditava e por quê.

omem-verify
proj_a14ce3f94fab  My first project
  replayed 4 operations -> 2 assertions, 2 propositions
  state digest  cd95d761079a2388...
  deterministic yes

Ele reproduz o log em dois motores novos independentes e compara o estado resultante. Uma diferença significaria que a reprodução depende de algo fora do log e que a mesma pergunta não dá a mesma resposta.

Essa verificação não consegue detectar adulteração, porque um log reescrito é reproduzido perfeitamente consistente consigo mesmo. Para isso, registre um resumo e mantenha-o em algum lugar onde o OMEM não possa gravar:

omem-verify --record          # writes .omem-state.json
omem-verify --anchor kept-elsewhere.json
  anchor        DOES NOT MATCH cd95d761079a2388... the log has changed
  audit chain  org_f4f3bdfa7a82  MISMATCH

O mesmo arquivo ancora a cabeça da cadeia de auditoria, pelo mesmo motivo. Essa cadeia é evidência de adulteração, e não prova contra adulteração: alguém com acesso de gravação pode reescrevê-la a partir da edição em diante e ela permanece internamente consistente. Somente um hash de cabeça mantido onde o OMEM não consegue alcançá-lo detecta isso. Duas âncoras em dois lugares são dois hábitos, e a que você pula é a que importava.

Isso prova que o estado decorre do log e que nem o log nem a cadeia de auditoria mudaram desde a âncora. Não prova que as crenças estão corretas, ou que nada foi removido antes da primeira âncora ser criada.

A lista de materiais

python3 scripts/gen_sbom.py > sbom.json     # CycloneDX
python3 scripts/gen_sbom.py --check         # fails if a runtime dep appears

O servidor e o SDK não têm dependências em tempo de execução, então o SBOM é um componente e a superfície transitiva é a biblioteca padrão. Os extras opcionais são listados e marcados como opcionais, porque "sem dependências" seria uma meia-verdade. --check roda em CI para que a afirmação não possa silenciosamente deixar de ser verdadeira.

Recusando gravações sem fundamento

Toda crença carrega um veredito de fundamentação: GROUNDED se sua proveniência alcança um evento registrado, UNGROUNDED se ela se apoia apenas em outras afirmações. Esse veredito é retornado em toda leitura, para que um chamador possa filtrar por ele.

Filtrar só ajuda o chamador que se lembra de filtrar. Defina OMEM_REQUIRE_GROUNDED=1 e o OMEM recusa a gravação:

OMEM_REQUIRE_GROUNDED=1 omem-server
mem.remember(agent="support", about="customer:1", claim="prefers_annual")
# -> 422 R_UNGROUNDED: cite `because` evidence that reaches a recorded event

mem.remember(agent="support", about="customer:1", claim="prefers_annual",
             because=["evt_call_2026_08_26"])   # accepted

Evidência conta se for um evento registrado, ou uma afirmação que é em si fundamentada, então uma cadeia de raciocínio que termina em algo observado é admitida, enquanto uma cadeia que termina em nada não é.

Isso se aplica a gravações diretas. Substituir e retratar substituem uma afirmação que já passou pela admissão e herdam sua proveniência, e o caminho de ingestão sempre teve seu próprio portão: todo candidato é avaliado antes que o motor o veja, e DO_NOT_STORE e LOW nunca se tornam afirmações.

Desativado por padrão, porque é uma restrição real sobre como você grava e os chamadores existentes não devem quebrar na atualização.

O que há neste repositório

  • server/ é o servidor OMEM: uma API HTTP que envolve o motor de memória. O próprio motor vive em server/omem_engine/ e é a fonte da verdade para todas as decisões de memória.

  • sdk/python/ é o SDK Python e os comandos omem-server / omem-mcp. É o que é publicado: pip install omem-infrastructure.

  • sdk/typescript/ é o SDK TypeScript, publicado como npm install @omem/sdk. Ele fica atrás do SDK Python, e ele compila e testa a si mesmo contra um servidor real:

    cd sdk/typescript
    npm install && npm test    # builds, then runs test_parity.mjs against a live server
    

    test_parity.mjs inicia o servidor Python, executa o SDK compilado contra ele e relata o que está faltando. Fechar essa lacuna é a contribuição mais útil disponível agora.

  • web/ é o painel.

Use-o com LangChain

OMEM implementa o BaseStore do LangGraph, que é como os agentes LangChain mantêm memória de longo prazo:

pip install "omem-infrastructure[langgraph]"
from omem import Memory
from omem.integrations.langgraph_store import OmemStore

store = OmemStore(Memory(api_key="omem_sk_...", project="proj_..."))
store.put(("memories", "alice"), "pref", {"text": "prefers annual billing"})
store.get(("memories", "alice"), "pref").value
# -> {"text": "prefers annual billing"}

Passe-o para create_react_agent(..., store=store) ou qualquer grafo LangGraph, da mesma forma que InMemoryStore.

Animação de 26 segundos: duas chamadas store.put na mesma chave apagam o primeiro valor em um armazenamento chave-valor; através do OmemStore as mesmas chamadas substituem em vez disso, o valor antigo permanece no registro, e mem.why responde de onde a memória veio.

A diferença dos armazenamentos embutidos é o que acontece na segunda gravação. Eles sobrescrevem, e delete apaga. Aqui um put sobre uma chave existente substitui: o valor anterior permanece no registro com o momento em que deixou de ser acreditado, e delete retrata em vez de destruir. Toda gravação é atribuída, então mem.why(assertion_id) responde de onde uma memória veio. Isso custa uma viagem de ida e volta de rede por operação, que é a troca.

A busca vetorial no armazenamento ainda não está implementada. search() filtra por namespace e por campo; passar query= gera um erro em vez de retornar silenciosamente uma correspondência de substring disfarçada de busca semântica.

Use-o com um cliente MCP

Instalar o pacote fornece um comando omem-mcp que fala MCP via stdio, então clientes MCP como Claude Desktop podem usar OMEM como uma ferramenta de memória:

pip install omem-infrastructure

Então, na configuração do seu cliente MCP, a entrada inteira é:

{ "mcpServers": { "omem": { "command": "omem-mcp" } } }

Sem chave, sem URL, sem servidor separado para iniciar. Na primeira execução, ele inicia o servidor incluído, cria um projeto e o lembra em ~/.omem. Reiniciar o cliente reutiliza a mesma memória.

Dez ferramentas. Cinco são o registro: omem_recall, omem_observe, omem_remember, omem_why e omem_believes. Cinco são a camada de intuição, todas leituras: omem_expects (o que OMEM suspeita e não acredita, com seu arquivo de caso), omem_priors (as regularidades que aprendeu sobre pessoas em geral), omem_brief (uma chamada no início de uma tarefa, em vez de montar a mesma imagem a partir de quatro outras), omem_ask (uma pergunta, respondida a partir do que esta instalação viu por si mesma primeiro e o senso comum em segundo, cada um rotulado com as pessoas e instalações em que se apoia), e omem_weigh (pese uma crença que você já tem contra a população).

omem_ask recusa em vez de retornar nada quando poucas pessoas apoiam uma resposta, porque "nenhum padrão desse tipo" e "poucas pessoas para dizer" são respostas diferentes e um agente age de forma diferente em cada uma. Ele lê do disco: o instantâneo do senso comum já está aqui, então perguntar funciona com o senso comum inacessível ou nunca contatado.

Não há ferramenta que promova uma hipótese, responda sua pergunta em aberto ou dispare um salto. Uma intuição recebe seu veredito da realidade durante a interrogação, e um modelo não recebe uma alavanca que marca uma como verdadeira ao dizê-lo. Qualquer coisa que omem_expects lista ainda lê UNKNOWN através de omem_believes, e um teste afirma exatamente isso.

observe entrega conversa bruta ao OMEM e deixa que ele decida o que é durável, o que é o que você quer sobre uma transcrição. remember registra um fato que você já identificou:

{"about": "customer:acme", "claim": "prefers_dark_mode",
 "because": "said on the 3 Nov call"}

Use remember quando você souber o fato. A extração executa um vocabulário determinístico voltado a decisões e compromissos, então uma afirmação fora dele não registra nada, e um modelo nomeando uma afirmação não é um modelo decidindo o que é verdadeiro: OMEM ainda possui o estado de crença, a contradição e a proveniência.

A identidade é fixada pelo ambiente, nunca por um argumento de ferramenta, em ambos os eixos que delimitam a memória: OMEM_AGENT é o agente cuja memória é esta, e OMEM_USER é o usuário final para quem ele age. Um modelo falando MCP não pode nomear nenhum dos dois, então não pode pedir a memória privada de outro agente ou de outro usuário. OMEM_USER é opcional; deixe-o não definido e nenhuma memória com escopo de usuário fica visível, que é o padrão correto para um processo que não foi informado para quem age.

Para conectá-lo ao Claude Desktop, inicie omem-server uma vez para obter um ID de projeto e chave, então adicione isto a claude_desktop_config.json e reinicie o aplicativo:

{
  "mcpServers": {
    "omem": {
      "command": "omem-mcp",
      "env": { "OMEM_AGENT": "claude", "OMEM_USER": "you@example.com" }
    }
  }
}

Ambos são opcionais. OMEM_AGENT nomeia o agente cuja memória é esta e OMEM_USER o usuário final para quem ele age; nenhum é um argumento de ferramenta, então um modelo não pode nomear nenhum dos dois. Aponte-o para um servidor que você já executa definindo OMEM_API_KEY, OMEM_BASE_URL e OMEM_PROJECT em vez disso, e a configuração explícita sempre vence a incluída.

O arquivo de configuração fica em ~/Library/Application Support/Claude/claude_desktop_config.json no macOS e %APPDATA%\Claude\claude_desktop_config.json no Windows.

Status e preço

Grátis, e grátis enquanto permanecer em beta: sem planos, sem cartão, sem cota.

Este é um software inicial em desenvolvimento ativo. Ele é destinado a testes e feedback agora. A página de segurança lista o que ele protege e, igualmente importante, o que ainda não protege: sem SSO, sem certificações, sem rotação de chaves, uma cadeia de auditoria que detecta adulteração em vez de preveni-la, e um processo mantendo o estado autoritativo, aplicado agora, então um segundo recusa iniciar em vez de divergir, mas essa é a ausência honesta de alta disponibilidade em vez da presença dela. Leia isso antes de planejar em torno dele. Se você experimentar e algo quebrar ou parecer errado, esse feedback é exatamente o que é útil nesta fase.

Licença

MIT. Veja LICENSE.


O histórico de desenvolvimento e notas detalhadas do motor estão em CHANGELOG-dev-notes.md, ENGINE.md e ENGINE_VALIDATION.md.