Omem

Memoria para agentes de IA que rastrea qué se cree, cuándo y por qué. Las contradicciones se muestran en lugar de sobrescribirse, y la identidad está vinculada al proceso para que un modelo no pueda leer la memoria de otro agente o usuario.

Documentación

OMEM

CI PyPI Python License: MIT

El sistema de registro de lo que un agente de IA creyó e hizo. Solo de añadidura, con la evidencia bajo cada creencia, ambos lados de cada contradicción conservados, y una persona nombrada detrás de cada acción arriesgada. Así, cuando un agente actúa y alguien pregunta "¿por qué hizo eso?", respondes con un registro en lugar de una investigación.

OMEM se sitúa donde se sitúa una capa de memoria y hace un trabajo diferente. En lugar de verter texto en un almacén vectorial y esperar lo mejor, rastrea lo que cada agente cree a lo largo del tiempo, mantiene la evidencia bajo cada creencia y maneja las contradicciones explícitamente, para que un agente pueda razonar sobre lo que sabe, cuándo lo aprendió y por qué lo sostiene.

Y no empieza de la nada. Las instalaciones que eligen agrupar lo que descubren sobre las personas en general, como recuentos que no nombran a nadie, y una instalación joven toma prestada esa intuición desde el primer día en lugar de pasar seis meses ganándosela. Lo que contribuyes son recuentos; lo que recibes es el de todos los demás. Un patrón prestado nace más débil que uno que aprendiste tú mismo, y aun así cede en el momento en que la evidencia propia de una persona discrepa, de modo que lo general nunca anula lo individual.

El banco está vacío hoy. Ninguna instalación ha contribuido todavía, lo que significa que las primeras deciden lo que aprende, y vale la pena saber que un corpus de regularidades sobre personas puede llevar los sesgos de quien lo llenó. La regla de minería fue reconstruida para que un patrón tenga que superar la tasa base en lugar de montarse en ella (Documento de Trabajo No. 1); si la población que contribuye es representativa es una pregunta aparte y abierta.

Se ejecuta localmente sin servicios externos y sin dependencias que instalar.

pip install omem-infrastructure && omem-server

O despliega un servidor privado con un clic:

Deploy to Render

El plano aprovisiona un pequeño servicio con un disco persistente, autenticación por contraseña activada (el primer registro es la cuenta de operador) y una clave maestra generada. Fly.io también funciona: fly launch --copy-config con el fly.toml incluido.

Documentación: infrastructure.omem-cloud.com · Inicio rápido · Seguridad · Contribuir

¿Envías agentes a clientes? El rastro de auditoría y la puerta de aprobación son el punto: lo que pide la revisión de seguridad de un cliente, y un pequeño número de pilotos prácticos de socio de diseño están abiertos.

¿Quieres ver todo el patrón en funcionamiento antes de leer otra palabra? refund-desk es la integración de referencia: un agente de soporte que mueve dinero, con recibos. Un archivo, se ejecuta en un minuto, afirma cada reclamo que hace.

Reproducción de scripts/demo_reasoning.py: dos registros se fusionan en una persona, una regla declarada concluye, la premisa se retracta y la conclusión se retira en la misma solicitud, y una división es final para la máquina.

Eso es scripts/demo_reasoning.py, abreviado. Cada línea es un comportamiento afirmado que se ejecuta en CI, así que esta imagen no puede dejar silenciosamente de ser verdad.

El panel durante una ejecución real: dos fuentes discrepan sobre el plan de un cliente, OMEM conserva ambos lados y marca la proposición como CONTRADECIDA, y cada creencia se abre en la cadena de por qué se cree.

Dos fuentes discrepan. Ninguna es sobrescrita. Mira todo el sistema funcionando.

Qué lo hace diferente

La mayoría de la memoria de agentes es una lista de hechos. Cuando dos hechos entran en conflicto, uno sobrescribe silenciosamente al otro y la historia desaparece. OMEM conserva ambos, rastrea cuál se cree actualmente y puede decirte por qué. Algunas cosas que hace que un almacén vectorial simple no hace:

  • Estado de creencia a lo largo del tiempo. Cada hecho tiene un estado (creído, contradicho, desconocido) que el motor calcula a partir de la evidencia, no una fila estática.
  • Manejo de contradicciones. La información conflictiva se muestra, no se pierde. Las afirmaciones nombradas X y not:X se tratan como opuestas automáticamente; para cualquier otra cosa, mem.contradict("prefers_annual", "prefers_monthly") lo dice una vez. OMEM nunca decide que dos afirmaciones discrepan leyéndolas, porque ese juicio es lo que impediría que la misma pregunta tuviera la misma respuesta un año después.
  • Procedencia. Pregunta por qué se cree algo y obtén la cadena que llevó hasta allí.
  • Memoria entre agentes. La memoria es privada para un agente por defecto; tú eliges qué compartir con un equipo o con todo el proyecto.
  • Recuperación semántica. Encuentra memorias relevantes incluso cuando la redacción difiere de cómo se almacenaron. Funciona sin conexión con una incrustación sin dependencias; establece OMEM_EMBED_MODEL para usar el modelo de incrustación real de tu proveedor, con vectores en caché y respaldo automático si el proveedor está caído.
  • Un bucle de aprendizaje. Las memorias que resultan útiles suben de rango con el tiempo.
  • Autocuración que se niega. OMEM registra fallos y ejecuta reparaciones bajo política, y no ejecutará una reparación que nadie autorizó. Un modelo puede proponer un plan; solo se ejecutan acciones registradas en código, y la clase de riesgo proviene del registro de OMEM en lugar de que el plan se autodeclare. Ver Autocuración.

Inicio rápido

Necesitas Python 3.9 o más reciente. Sin otras dependencias.

Opción 1: instalar desde PyPI (servidor incluido).

pip install omem-infrastructure
omem-server

¿Actualizando desde una versión anterior? pip install --upgrade omem-infrastructure. Un simple pip install en un paquete que ya tienes informa "Requisito ya satisfecho" y no hace nada, lo cual es una forma silenciosa de seguir ejecutando la versión que intentabas dejar. python -c "import omem; print(omem.__version__)" dice lo que realmente tienes.

Eso inicia el servidor en http://127.0.0.1:8787 y, en la primera ejecución, imprime un id de proyecto y una clave API: sin llamada de registro, sin visita al panel, nada que configurar. Pégalos directamente:

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 te lleva a una contradicción y una cadena de procedencia en unos cinco minutos, que es donde la diferencia con un almacén vectorial realmente se muestra.

Opción 2: ejecutar desde este repositorio.

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

Mismo servidor, mismo id de proyecto y clave de primera ejecución, iniciado desde el código fuente. La configuración toma aproximadamente un minuto de cualquier manera. Dos diferencias que vale la pena conocer:

  • La base de datos cae en un lugar diferente. Desde el código fuente está en server/data/omem.db; omem-server escribe ./omem-data/omem.db en el directorio desde el que lo ejecutaste. OMEM_DB anula cualquiera de los dos.
  • El panel necesita construirse una vez. El wheel incluye una copia construida; un clon no, así que el servidor imprime "panel no incluido" hasta que ejecutes cd web && OMEM_STATIC=1 npm run build. La API es idéntica de cualquier manera.

Opción 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 en 8787, panel en 3000, datos en el volumen nombrado. Los puertos están publicados en loopback a propósito: el contenedor se ejecuta en modo local, que no tiene contraseñas, así que la accesibilidad es el control de acceso. Ponerlo en una red significa establecer OMEM_AUTH=password y OMEM_MASTER_KEY primero, y docker-compose.yml en este repositorio muestra esa forma.

Autocuración

OMEM registra lo que se rompe y lo repara bajo política. Esto es infraestructura para tus agentes, no algo que OMEM se haga a sí mismo: registras un componente y los ganchos con los que se puede reparar, y OMEM posee la memoria, el límite de seguridad y el ciclo de vida.

La parte que importa es lo que se niega. Un modelo puede proponer un plan de reparación; OMEM decide lo que está permitido. Solo los tipos de acción registrados en código pueden ejecutarse, la clase de riesgo proviene de ese registro y nunca del plan, las acciones de alto riesgo necesitan aprobación explícita, y una reparación no tiene éxito hasta que verifica.

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 se ejecutó. El plan se conserva con la razón por la que cada acción fue permitida o denegada, así que la negativa es un registro en lugar de un silencio. El texto de error y la salida del modelo son datos aquí, y ninguno puede nombrar una acción a la existencia.

Todo lo demás que querrías también está aplicado: los fallos se identifican por huella para que mil errores idénticos sean una entrada, una tormenta de reparaciones está limitada por componente, una recuperación por componente está garantizada por reclamo en la base de datos, los secretos se eliminan antes de que se persista nada, y un error interno escala en lugar de reintentar a ciegas.

La pantalla de Autocuración en el panel muestra la salud del componente, el registro de fallos y hasta dónde llegó cada reparación, con el paso en el que se detuvo marcado, y el diagnóstico sobre el que actuó. server/healing.py es todo el subsistema y vale la pena leerlo si estás decidiendo si confiar en él.

El panel

El panel viaja dentro del paquete. Inicia el servidor y abre la misma dirección, http://127.0.0.1:8787. Está todo allí: memoria, conflictos, el grafo de creencias, la línea de tiempo, registros y el rastro de auditoría. Sin Node, sin segundo proceso, sin segundo puerto.

En modo local (el predeterminado) no hay inicio de sesión; se abre en el proyecto que el servidor creó para ti. En un servidor que ejecuta OMEM_AUTH=password muestra un formulario de inicio de sesión en su lugar.

Es una exportación estática de web/, la única interfaz de usuario en este repositorio, copiada en el wheel en el momento de la compilación. Para trabajar en ella:

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

y para reconstruir la copia incluida, OMEM_STATIC=1 npm run build.

Autenticación

OMEM se ejecuta en uno de dos modos, y la diferencia importa antes de ponerlo en cualquier lugar que no sea tu propia máquina.

OMEM_AUTH=local: el predeterminado, y lo que hace que el inicio rápido sea un minuto. No hay inicio de sesión: el panel aprovisiona una sesión contra el servidor que puede ver. Eso solo es seguro mientras nada más pueda alcanzar el servidor, así que el modo local se niega a vincular una dirección que no sea de loopback. Si lo dices en serio (un contenedor cuyos puertos están publicados en 127.0.0.1, una VM de un solo usuario), establece OMEM_ALLOW_INSECURE_BIND=1.

OMEM_AUTH=password: requerido para un servidor que otras personas puedan alcanzar. Las cuentas tienen contraseñas, con hash PBKDF2-SHA256. Registrarse con una dirección que ya tiene una contraseña devuelve 409 en lugar de una sesión, TOTP se aplica donde está inscrito, y el servidor se niega a iniciar a menos que OMEM_MASTER_KEY esté establecido en algo diferente de su valor de desarrollo predeterminado.

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

TLS

Apunta OMEM_TLS_CERT y OMEM_TLS_KEY a un certificado y el servidor habla HTTPS por sí mismo (mínimo TLS 1.2). Establecer solo uno es un error de inicio, no una caída silenciosa a texto plano. Un proxy de terminación sigue siendo mejor a escala, pero ejecutar sin uno ya no significa ejecutar en claro.

Cifrado de memoria en reposo

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

Cifra el registro de operaciones, las cargas útiles de fuentes ingeridas y la evidencia citada detrás de cada memoria con AES-GCM. Las filas de texto plano existentes siguen funcionando, así que puede activarse para una base de datos que ya tiene datos. Se niega a iniciar con la clave maestra de desarrollo, y se niega a ejecutarse sin una biblioteca AEAD real en lugar de caer al flujo de claves de la biblioteca estándar usado para tokens OAuth.

Pierde la clave y los datos desaparecen: no hay ruta de recuperación, y no hay herramientas de rotación todavía.

Cuando dos entidades son una persona

La formación acuña ids de entidad a partir de lo que puede ver, así que un humano puede llegar dos veces: person:sarah_chen de una oración en el cuerpo de un mensaje, person:sarah_chen@acme de escribir el correo. Cada id tiene la mitad de las creencias sobre una persona, y no pueden ni corroborarse ni contradecirse entre sí.

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

La evidencia decisiva fusiona: el mismo nombre completo en la misma organización, que es la regla que la propia formación ya aplica dentro de un camino. La fusión es una correferencia registrada por agent:omem-resolution con una derivación a sus anclas, así que /why la explica y una división la deshace. La evidencia sugestiva ("Sarah" contra "Sarah Chen" en acme) se convierte en una propuesta en GET /v1/memory/merge-proposals que no cambia nada hasta que una persona la aprueba -- y la aprobación se registra bajo el nombre del aprobador, no del máquina. Las negativas son la característica: nunca entre organizaciones, nunca sin una, nunca sobre apellidos conflictivos o vocabulario de roles, nunca cuando es ambiguo, y nunca volviendo a fusionar lo que una división separó. Pasa {"apply": false} para una ejecución en seco que no registra nada. Desde el SDK es mem.resolve(), mem.merge_proposals() y mem.approve_merge(id, agent=...); la pantalla de Propuestas del panel es la misma cola con botones.

Reglas que concluyen, y lo retiran

La contradicción se declara, nunca se infiere del texto. La inferencia funciona igual: una regla es un dato que declaras, y la máquina compone exactamente lo que dijiste y nada más.

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 trabaja en Beta; Acme es dueña de Beta; OMEM concluye que la órbita de Acme involucra a Sarah — como una afirmación ordinaria derivada de las premisas exactas que usó, así que /why camina desde la conclusión hasta la evidencia, y como un borde de grafo real, el recuerdo la alcanza en un salto.

La razón para querer esto es lo que sucede en el camino hacia abajo. Retira la propiedad y la conclusión se retira en la misma solicitud; una conclusión que descansa sobre esa conclusión cae después. Cada retiro es una retracción ordinaria en el registro de operaciones. La evidencia se gasta una vez — una conclusión que cierras nunca se vuelve a litigar desde las mismas premisas — y las conclusiones de una regla desactivada se retiran en el siguiente pase.

Todo es un script en lugar de un párrafo, mismo contrato que la demo de negativa abajo — cada comportamiento afirmado, salida no cero si uno deja de cumplirse, ejecutado en CI:

python3 scripts/demo_reasoning.py

Formas que hacen preguntas

Dos creencias solo entran en conflicto sobre los mismos sujetos, lo que mantiene el estado de creencias reproducible — y significa que "Sarah trabaja en Acme" y "Sarah trabaja en Beta" nunca se contradicen. Si eso está bien es conocimiento de dominio, así que lo declaras:

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

Una violación se convierte en una tensión en la cola de Propuestas. OMEM no elige al empleador más nuevo: tú nombras al que sobrevive (los demás se retiran bajo tu nombre, y cualquier cosa que el motor de reglas concluyó de ellos cae en la misma solicitud), o lo descartas, lo cual es permanente exactamente para esa evidencia. La máquina nunca molesta dos veces sobre una pregunta que una persona ya respondió.

Corazonadas con expedientes

Los humanos aprenden de un ejemplo saltando a conclusiones. Ese reflejo es también por qué la memoria humana confabula. OMEM mantiene la velocidad y elimina la confabulación: salta, y luego duda del salto más de lo que tú lo harías.

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

Una hipótesis nunca es una creencia. Nunca entra al motor, believes() permanece DESCONOCIDO por muy buena que sea la corazonada, y solo la realidad sobre el objetivo puede apoyarla o refutarla — los parecidos solo mueven la fuerza. Los veredictos enseñan: una fuente cuyos saltos se confirman constantemente genera corazonadas más fuertes, una que se equivoca constantemente genera más débiles, y un salto refutado nunca se vuelve a hacer desde la misma evidencia. Un caso que no se resuelve comienza a preguntar, y la pregunta aterriza en el panel donde un sí o un no se convierte en evidencia real bajo tu nombre — el veredicto aún viene de la interrogación, nunca por decreto.

La semejanza funciona como la analogía humana: un rasgo compartido raro une más fuerte que tres comunes, la experiencia redactada de manera diferente cuenta como la misma experiencia cuando un modelo de incrustación está configurado, y el contexto compartido pesa menos que el carácter compartido. Y mem.calibration() es la metacognición: OMEM sabe qué tipos de afirmaciones adivina bien, y su audacia sigue su historial.

Priors: lo que aprende sobre las personas en general

Un salto proyecta desde una persona parecida. Un prior proyecta desde una regularidad aprendida a través de muchas: "las personas que tienen P tienden a tener Q." OMEM los extrae de lo que ya sabe y los usa para interpretar a alguien nuevo con muy poco.

Un par se mantiene solo donde tener P mueve mediblemente las probabilidades de Q más allá de cuán común es Q por sí solo, y esa prueba se aplica al límite inferior de la tasa en lugar de la tasa misma, así que un patrón que descansa en un puñado de personas debe ser mucho más limpio que uno que descansa en cientos.

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

Esa regla reemplazó a una que solo preguntaba si el sesenta por ciento de los que tienen P también tenían Q. Medido contra 19,668 encuestados reales con una estructura latente conocida, la regla antigua recuperó esa estructura en 0.185 donde el azar es 0.184: estaba seleccionando consecuentes por cuán comunes eran. La regla actual la recupera en 0.875, usando un 94% menos de priors que cubren más afirmaciones que antes. El estudio es Documento de Trabajo No. 1 y el arnés está en benchmarks/external/.

El punto es que un prior nunca anula a una persona. Solo se dispara en un silencio: si alguien tiene P pero no ha dicho nada sobre Q, OMEM salta Q sobre ellos como una corazonada; en el momento en que la propia evidencia de esa persona habla, el prior se rechaza, y si su evidencia luego contradice una corazonada aceptada, el bucle de interrogación la refuta y el prior asume la pérdida. Dos números honestos viajan con cada prior: la tasa que mantuvo en la población de la que se aprendió, y su registro separado cuando realmente se aplica. Un patrón visto en muy pocas personas no se permite disparar en absoluto.

Un prior almacena conteos, nunca una persona. Es conocimiento sobre personas en general sin ningún hecho sobre nadie en él, lo que te permite leer el conjunto completo, o entregárselo a alguien, sin filtrar un solo sujeto. El patrón general siempre cede ante el individuo, por construcción en lugar de por política.

El comportamiento cotidiano también es memoria

No todo lo que vale la pena recordar es un contrato. "Las mañanas me funcionan mejor", "el correo es la mejor manera de contactarme", "no trabajo los viernes" son las pequeñas preferencias repetidas de la correspondencia ordinaria, y OMEM las extrae sin conexión, sin necesidad de LLM. Una oración en primera persona se adjunta a la persona que la escribió, el mismo nodo en el que se infiere su empleo desde la dirección desde la que escribe, mientras que "preferimos async" sigue siendo un hecho sobre la empresa. Una dirección de rol como support@ nunca acuña una persona falsa, y cada hábito lleva la oración de la que proviene como evidencia. Estas son exactamente las regularidades que el nivel de priors generaliza: "las personas que prefieren mañanas usualmente prefieren correo" es un patrón aprendido, no una suposición.

El derecho al olvido, ejecutado

La retracción no es borrado: un registro de solo añadidura mantiene la historia, y una solicitud real de borrado significa que los datos personales han desaparecido. POST /v1/entities/{id}/forget reescribe el registro de operaciones de verdad: cada registro que referencia a la persona, todo lo que se derivó de esos, los eventos que llevaban solo sus palabras, y las citas de evidencia, bordes, hipótesis y mensajes fuente crudos detrás de ellos. Una oración suya citada bajo una creencia sobreviviente se redacta, porque la oración es de la persona incluso cuando la creencia es de una empresa. El registro podado se verifica por reproducción a través de un motor de prueba antes de tocar nada, y lo que queda después es una fila que contiene un hash, conteos y una fecha: prueba de que el borrado ocurrió, sin retener nada. Es un acto de administrador, pide confirmación explícita y no se puede deshacer.

El bien común, y lo que nunca tomará

Al abrir por primera vez, el panel hace una pregunta: ¿contribuir patrones anónimos al bien común compartido de OMEM? Lo que sale de la máquina si dices sí son conteos, como "mantenido por 5 de 7". Nunca un nombre, una empresa, un mensaje o un número de tus datos; el archivo exacto está en tu propio disco para inspeccionarlo, y cualquier respuesta es revocable en Configuración. El silencio no envía nada, para siempre. El bien común agrupa esos conteos entre instalaciones que consienten para estudiar el comportamiento laboral humano en general. El anonimato es estructural en ambas puertas: una contribución que lleva algo identificable se rechaza al llegar, así que el grupo no puede filtrar lo que nunca tuvo.

Enseñar a la IA cómo son las personas

El bien común existe para un objetivo: conectar humanos e IA dando a la IA una mejor comprensión de nuestra naturaleza y comportamiento. Los modelos de hoy aprenden sobre personas de texto raspado que nunca fue ofrecido y que nombra a todos en él. El bien común es la oferta opuesta: regularidades en cómo las personas realmente trabajan, contribuidas a propósito, sin retener a nadie.

Se entrega como un corpus de entrenamiento. Una línea JSON por patrón lleva los conteos y una representación en inglés sencillo ("sujetos que prefieren reuniones por la mañana usualmente también prefieren contacto por correo: 24 de 31 con una postura, 77%"), con una tarjeta de conjunto de datos que indica la procedencia, la historia de consentimiento y la licencia, CC BY 4.0 con atribución al bien común de OMEM. Un modelo entrenado en él aprende la tasa, nunca una persona, y la tarjeta dice la oración operativa en voz alta: las tasas son tendencias de población, nunca reglas sobre individuos. Una persona real puede y contradirá cualquiera de ellas, y un sistema que respeta a las personas trata cada patrón como un prior que cede ante el individuo, de la misma manera que OMEM mismo lo hace.

Qué cambió mientras estabas fuera

La pregunta que cada agente hace al inicio de la sesión, respondida desde la misma maquinaria as_of que cada consulta ya usa:

d = mem.changes(since=last_seen)

Creencias que aparecieron; creencias que se cerraron, cada una diciendo cómo — superadas y por qué, o retiradas; conflictos recién abiertos y recién resueltos; referentes que se fusionaron o dividieron. Solo lectura, determinista y seguro por alcance: tu diff contiene solo lo que podrías haber recordado.

Viendo lo que rechaza

El límite de autocuración es la parte difícil de creer desde una descripción, así que es un script en lugar de un párrafo:

python3 scripts/demo_refusal.py

Conduce un servidor real a través de las dos formas en que un plan de reparación realmente sale mal. Un modelo propone reload_config (registrado) junto a exec_shell (no registrado en ningún lado): el primero se permite por sus méritos, el segundo se rechaza por nombre, y el plan en su totalidad se deniega. Un plan que reclama su propia clase de riesgo la hace ignorar, porque el riesgo viene del registro. Una instrucción incrustada en el mensaje de error que el modelo leyó no ejecuta nada. Cada veredicto se guarda y es legible después, y un secreto en el contexto de error no está en el almacenamiento.

El registro ocurre en código. No hay API que agregue un tipo de acción ejecutable, así que ningún plan y ningún prompt amplía lo que está permitido.

Cada negativa en él se afirma y sale no cero si una deja de ocurrir, así que se ejecuta en CI. Una demo que puede volverse silenciosamente falsa es peor que ninguna.

El benchmark Witness

Los benchmarks de memoria miden el recuerdo. Witness mide el deber opuesto: ¿un sistema de memoria afirma cosas que nadie le dijo, sigue repitiendo lo que se retiró, resuelve desacuerdos silenciosamente, fusiona dos personas que comparten un nombre, o mantiene conclusiones cuyas premisas murieron?

Seis escenarios, diez ejes, puntuación determinista, sin jueces LLM. Se incluyen adaptadores para OMEM, Mem0 y Graphiti; cada sistema se alimenta a través de su propia ruta nativa, y una sonda que un sistema no puede expresar se reporta como no soportada en lugar de aprobada o fallida. Este repositorio no publica números que no ejecutó: la tarjeta de OMEM, cada sonda pasando en cada eje, es afirmada por server/tests_witness_benchmark.py contra un servidor en vivo en cada commit. Ejecuta los otros con tus propias claves y lee tu propia tarjeta.

El libro mayor de afirmaciones

El marketing que no puede fallar es indistinguible del marketing falso. CLAIMS.md mapea cada oración de carga que este proyecto dice sobre sí mismo a la declaración ejecutable que se pondría roja si dejara de ser verdad, y el libro mayor está a su vez protegido en CI: una fila cuyo archivo desaparece falla la compilación.

Dos filas que vale la pena mencionar porque nadie más en este nicho puede escribirlas. No llama a casa a nadie: tests_airgap.py instala un guardia bajo la capa de sockets, luego conduce cada característica principal a través de un servidor en vivo y falla en una sola conexión saliente o búsqueda DNS que no sea de bucle local. Las actualizaciones nunca reescriben tu pasado: un registro congelado el 2026-08-29 se reproduce a un resumen de estado byte-idéntico en cada commit, así que ninguna versión futura puede reinterpretar silenciosamente una historia que ya registraste.

Probando que el estado se sigue del registro

La memoria se reconstruye reproduciendo un registro de solo apéndice. Eso es fácil de afirmar y no era comprobable desde fuera, lo cual es un punto débil para un proyecto cuyo argumento completo es que puedes reconstruir lo que un agente creía y por qué.

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

Reproduce el registro en dos motores nuevos e independientes y compara el estado resultante. Una diferencia significaría que la reproducción depende de algo fuera del registro, y que la misma pregunta no da la misma respuesta.

Esa comprobación no puede detectar manipulación, porque un registro reescrito se reproduce perfectamente consistente consigo mismo. Para eso, registra un resumen y guárdalo en algún lugar donde OMEM no pueda escribir:

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

El mismo archivo ancla la cabecera de la cadena de auditoría, por la misma razón. Esa cadena es evidencia de manipulación más que a prueba de manipulación: alguien con acceso de escritura puede reescribirla desde la edición en adelante y permanece internamente consistente. Solo un hash de cabecera guardado donde OMEM no pueda alcanzarlo lo detecta. Dos anclas en dos lugares son dos hábitos, y el que omites es el que importaba.

Prueba que el estado se deriva del registro, y que ni el registro ni la cadena de auditoría han cambiado desde el ancla. No prueba que las creencias sean correctas, o que nada fue eliminado antes de que se tomara el primer ancla.

La lista de materiales

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

El servidor y el SDK no tienen dependencias en tiempo de ejecución, por lo que el SBOM es un componente y la superficie transitiva es la biblioteca estándar. Los extras opcionales se enumeran y se marcan como opcionales, porque "sin dependencias" de otro modo sería una media verdad. --check se ejecuta en CI para que la afirmación no pueda dejar de ser verdadera silenciosamente.

Rechazar escrituras sin fundamento

Cada creencia lleva un veredicto de fundamento: GROUNDED si su procedencia alcanza un evento registrado, UNGROUNDED si solo se apoya en otras afirmaciones. Ese veredicto se devuelve en cada lectura, para que un llamador pueda filtrar por él.

Filtrar solo ayuda al llamador que recuerda filtrar. Establece OMEM_REQUIRE_GROUNDED=1 y OMEM rechaza la escritura en su lugar:

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

La evidencia cuenta si es un evento registrado, o una afirmación que está a su vez fundamentada, por lo que una cadena de razonamiento que termina en algo observado se admite mientras que una cadena que termina en nada no se admite.

Se aplica a escrituras directas. Supersede y retract reemplazan una afirmación que ya pasó la admisión y heredan su procedencia, y la ruta de ingesta siempre ha tenido su propia puerta: cada candidato se califica antes de que el motor lo vea, y DO_NOT_STORE y LOW nunca se convierten en afirmaciones.

Desactivado por defecto, porque es una restricción real sobre cómo escribes y los llamadores existentes no deberían romperse al actualizar.

Qué hay en este repositorio

  • server/ es el servidor OMEM: una API HTTP que envuelve el motor de memoria. El motor en sí vive en server/omem_engine/ y es la fuente de verdad para todas las decisiones de memoria.

  • sdk/python/ es el SDK de Python y los comandos omem-server / omem-mcp. Es el que se publica: pip install omem-infrastructure.

  • sdk/typescript/ es el SDK de TypeScript, publicado como npm install @omem/sdk. Va por detrás del SDK de Python, y se construye y prueba a sí mismo contra un servidor real:

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

    test_parity.mjs inicia el servidor de Python, ejecuta el SDK compilado contra él y informa de lo que falta. Cerrar esa brecha es la contribución más útil disponible ahora mismo.

  • web/ es el panel de control.

Úsalo desde LangChain

OMEM implementa BaseStore de LangGraph, que es cómo los agentes de LangChain mantienen memoria a largo plazo:

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"}

Pásalo a create_react_agent(..., store=store) o a cualquier grafo de LangGraph, igual que InMemoryStore.

Animación de 26 segundos: dos llamadas store.put en la misma clave borran el primer valor en un almacén clave-valor; a través de OmemStore las mismas llamadas superseden en su lugar, el valor antiguo permanece en el registro, y mem.why responde de dónde vino la memoria.

La diferencia con los almacenes integrados es lo que ocurre en la segunda escritura. Ellos sobrescriben, y delete borra. Aquí un put sobre una clave existente supersede: el valor anterior permanece en el registro con el momento en que dejó de creerse, y delete retracta en lugar de destruir. Cada escritura se atribuye, por lo que mem.why(assertion_id) responde de dónde vino una memoria. Eso cuesta un viaje de ida y vuelta de red por operación, que es el intercambio.

La búsqueda vectorial en el almacén aún no está implementada. search() filtra por espacio de nombres y por campo; pasar query= lanza una excepción en lugar de devolver silenciosamente una coincidencia de subcadena disfrazada de búsqueda semántica.

Úsalo desde un cliente MCP

Instalar el paquete te da un comando omem-mcp que habla MCP sobre stdio, por lo que clientes MCP como Claude Desktop pueden usar OMEM como herramienta de memoria:

pip install omem-infrastructure

Luego, en la configuración de tu cliente MCP, la entrada completa es:

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

Sin clave, sin URL, sin servidor separado que iniciar. En la primera ejecución inicia el servidor incluido, crea un proyecto y lo recuerda en ~/.omem. Reiniciar el cliente reutiliza la misma memoria.

Diez herramientas. Cinco son el registro: omem_recall, omem_observe, omem_remember, omem_why y omem_believes. Cinco son la capa de intuición, todas de lectura: omem_expects (lo que OMEM sospecha y no cree, con su expediente del caso), omem_priors (las regularidades que ha aprendido sobre las personas en general), omem_brief (una llamada al inicio de una tarea, en lugar de ensamblar la misma imagen desde otras cuatro), omem_ask (una pregunta, respondida desde lo que esta instalación ha visto por sí misma primero y el sentido común segundo, cada una etiquetada con las personas e instalaciones en las que se apoya), y omem_weigh (sopesa una creencia que ya tienes contra la población).

omem_ask rechaza en lugar de devolver nada cuando muy pocas personas respaldan una respuesta, porque "no existe tal patrón" y "muy pocas personas para decirlo" son respuestas diferentes y un agente actúa de manera diferente ante cada una. Lee desde el disco: la instantánea del sentido común ya está aquí, por lo que preguntar funciona con el sentido común inalcanzable o nunca contactado en absoluto.

No hay herramienta que promueva una hipótesis, responda su pregunta abierta o active un salto. Una corazonada recibe su veredicto de la realidad durante la interrogación, y un modelo no obtiene una palanca que marque una como verdadera al decirlo. Cualquier cosa que omem_expects enumere aún se lee UNKNOWN a través de omem_believes, y una prueba afirma exactamente eso.

observe entrega a OMEM conversación cruda y le permite decidir qué es duradero, que es lo que quieres sobre una transcripción. remember registra un hecho que ya has identificado:

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

Usa remember cuando conozcas el hecho. La extracción ejecuta un vocabulario determinista dirigido a decisiones y compromisos, por lo que una afirmación fuera de él no registra nada en absoluto, y un modelo que nombra una afirmación no es un modelo que decide qué es verdadero: OMEM sigue siendo dueño del estado de creencia, la contradicción y la procedencia.

La identidad se fija por el entorno, nunca por un argumento de herramienta, en ambos ejes que delimitan la memoria: OMEM_AGENT es el agente cuya memoria es esta, y OMEM_USER es el usuario final para el que actúa. Un modelo que habla MCP no puede nombrar ninguno de los dos, por lo que no puede pedir la memoria privada de otro agente u otro usuario. OMEM_USER es opcional; déjalo sin establecer y no se verá memoria con ámbito de usuario, que es el valor predeterminado correcto para un proceso al que no se le ha dicho para quién actúa.

Para conectarlo a Claude Desktop, inicia omem-server una vez para obtener un id de proyecto y clave, luego agrega esto a claude_desktop_config.json y reinicia la aplicación:

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

Ambos son opcionales. OMEM_AGENT nombra al agente cuya memoria es esta y OMEM_USER al usuario final para el que actúa; ninguno es un argumento de herramienta, por lo que un modelo no puede nombrar a ninguno de los dos. Apúntalo a un servidor que ya ejecutes estableciendo OMEM_API_KEY, OMEM_BASE_URL y OMEM_PROJECT en su lugar, y la configuración explícita siempre gana sobre la incluida.

El archivo de configuración vive en ~/Library/Application Support/Claude/claude_desktop_config.json en macOS y %APPDATA%\Claude\claude_desktop_config.json en Windows.

Estado y precio

Gratis, y gratis mientras permanezca en beta: sin planes, sin tarjeta, sin cuota.

Este es software temprano bajo desarrollo activo. Está destinado a pruebas y comentarios ahora mismo. La página de seguridad enumera lo que protege y, igual de importante, lo que aún no: sin SSO, sin certificaciones, sin rotación de claves, una cadena de auditoría que detecta manipulación en lugar de prevenirla, y un proceso que mantiene el estado autoritativo, aplicado ahora, por lo que un segundo se niega a iniciar en lugar de divergir, pero esa es la ausencia honesta de alta disponibilidad en lugar de su presencia. Lee eso antes de planificar en torno a ello. Si lo pruebas y algo se rompe o se siente mal, ese comentario es exactamente lo que es útil en esta etapa.

Licencia

MIT. Ver LICENSE.


El historial de desarrollo y las notas detalladas del motor están en CHANGELOG-dev-notes.md, ENGINE.md y ENGINE_VALIDATION.md.