artículos / El Modelo es Prescindible: Cómo Construí...

El Modelo es Prescindible: Cómo Construí una Memoria por Embeddings que Sobrevive a Cualquier Agente

AWONG 13 minutos de lectura 32 vistas

Cómo una actualización de OpenClaw que borró toda la memoria en .md me obligó a construir un sistema de memoria persistente con embeddings sobre Ollama, mxbai-embed y Redis, donde el contexto, los proyectos y la identidad del agente sobreviven a cualquier modelo, reinstalación o cambio de herramienta.

El Modelo es Prescindible: Cómo Construí una Memoria por Embeddings que Sobrevive a Cualquier Agente

El Modelo es Prescindible: Cómo Construí una Memoria por Embeddings que Sobrevive a Cualquier Agente

La IA avanza rápido. Demasiado rápido. Tan rápido que una actualización automática de tu agente favorito puede llevarse consigo semanas de contexto acumulado en un instante. Eso fue exactamente lo que me pasó con OpenClaw: una actualización lo dejó en blanco, y con él desapareció todo lo que "recordaba" sobre mis proyectos. El problema no fue la pérdida en sí. El problema fue darme cuenta de que había construido algo frágil sin querer: un sistema donde el modelo y la memoria eran la misma cosa. Lo que construí después cambió por completo cómo pienso sobre los agentes de IA.

El Incidente: Cuando una Actualización Borra Semanas de Trabajo

OpenClaw, como exploramos en el post sobre seguridad, guarda su memoria como archivos .md en el sistema de archivos local. Es una solución funcional pero con un problema estructural crítico: esa memoria está atada al agente. Si el agente se actualiza, se reinstala, o simplemente se comporta de forma inespeente después de un cambio de versión, esos archivos pueden quedar desincronizados, corrompidos, o directamente ignorados.

Lo que me pasó fue esto: OpenClaw recibió una actualización. Al reiniciarse, el agente no reconoció su propio memory.md correctamente. Semanas de contexto acumulado — decisiones técnicas, estado de proyectos, preferencias de trabajo — evaporadas. El agente volvió a ser un extraño.

La reacción instintiva sería reconstruir los .md y seguir adelante. Pero me quedé con una pregunta incómoda: ¿por qué la memoria de mi agente depende del agente mismo? ¿No debería ser al revés? ¿No debería el contexto existir independientemente de qué modelo o herramienta lo consume?

El Problema de Raíz: Memoria Acoplada al Modelo

La mayoría de los agentes de IA actuales tienen un modelo de memoria que podríamos llamar "acoplado": el contexto vive dentro del agente, en su formato, bajo sus reglas. Cuando el agente cambia, el contexto cambia con él. Cuando el agente muere, el contexto muere también.

Este modelo funciona razonablemente bien en entornos estables. Pero en el ecosistema real de 2026, donde los modelos se actualizan cada pocas semanas, donde cambias de herramienta cuando aparece algo mejor, donde experimentas con diferentes agentes para diferentes tareas, ese acoplamiento es una trampa. Estás construyendo sobre arena.

La alternativa es lo que podríamos llamar memoria desacoplada: el contexto existe en su propia infraestructura, con su propio ciclo de vida, consultable por cualquier agente que tenga las herramientas correctas para acceder a él. El modelo se convierte en lo que realmente es: un motor de razonamiento intercambiable, no el guardián de tu historia.

La Solución: Un Servidor MCP de Embeddings Propio

Lo que construí fue un servidor MCP (Model Context Protocol) que actúa como capa de memoria semántica independiente. El stack es deliberadamente simple:

  • Ollama con mxbai-embed-large: genera los embeddings localmente. Ningún dato sale de la máquina para ser vectorizado. El modelo de embeddings es estable, no cambia con las actualizaciones del agente.
  • Redis con RediSearch: almacena los vectores y permite búsqueda semántica por similitud. Redis es rápido, persistente, y se puede respaldar con un simple redis-cli BGSAVE.
  • Servidor MCP propio: expone las herramientas de memoria al agente. Cualquier agente que soporte MCP puede conectarse y acceder a la misma memoria.

La arquitectura completa se ve así:

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   OpenClaw /    │────▶│   MCP Memory     │────▶│  Ollama         │
│   Claude Code / │◀────│   Server         │◀────│  mxbai-embed    │
│   Cualquier     │     │                  │     │  (local)        │
│   agente MCP    │     │  store_memory()  │     └─────────────────┘
└─────────────────┘     │  recall()        │            │
                        │  search()        │            ▼
                        └──────────────────┘     ┌─────────────────┐
                                                  │  Redis          │
                                                  │  (vectores +    │
                                                  │   metadata)     │
                                                  └─────────────────┘

El agente no gestiona su propia memoria. La solicita al servidor MCP como solicitaría cualquier otra herramienta: buscar archivos, ejecutar comandos, navegar en el browser. La memoria se convierte en un servicio externo, no en una propiedad interna.

Cómo Funciona en la Práctica

Almacenar un Recuerdo

Cuando el agente completa una tarea significativa o toma una decisión técnica importante, llama a la herramienta de almacenamiento:

// El agente llama internamente:
store_memory({
  content: "Se decidió usar JWT con refresh tokens en Redis. "
           + "Salt rounds: 12. Access token TTL: 15min. "
           + "Refresh token TTL: 7 días.",
  tags: ["auth", "jwt", "decisión-técnica"],
  project: "api-usuarios"
})

// El servidor MCP:
// 1. Envía el texto a mxbai-embed via Ollama
// 2. Obtiene el vector de 1024 dimensiones
// 3. Almacena en Redis: vector + metadata + timestamp

Recuperar Contexto Relevante

Al iniciar una nueva sesión, o cuando el agente necesita contexto sobre un tema específico, consulta semánticamente:

// El agente pregunta:
recall({
  query: "¿Cómo manejamos la autenticación en el proyecto api-usuarios?",
  top_k: 5,
  project: "api-usuarios"
})

// El servidor MCP:
// 1. Vectoriza la query con mxbai-embed
// 2. Busca los 5 recuerdos más similares en Redis
// 3. Devuelve los fragmentos relevantes ordenados por similitud

// Resultado: el agente recibe exactamente el contexto que necesita
// sin cargar todo el historial en el context window

Esta es la ventaja clave sobre los archivos .md: en lugar de cargar toda la memoria de golpe (consumiendo tokens), el agente carga solo los fragmentos semánticamente relevantes para lo que está haciendo en este momento. La recuperación es quirúrgica, no exhaustiva.

Reconfigurar OpenClaw para Ignorar su Propia Memoria

La parte más interesante del proceso fue decirle a OpenClaw que dejara de gestionar su propia memoria y delegara esa responsabilidad al servidor MCP. Modifiqué los cuatro archivos de configuración principales:

soul.md — La Identidad del Agente

El soul.md define quién es el agente: sus valores, su estilo de trabajo, sus principios. Lo dejé intacto en su esencia, pero añadí una sección explícita sobre el sistema de memoria:

## Sistema de Memoria
Mi memoria no vive en este archivo. Vive en el servidor MCP de embeddings.
Antes de cualquier tarea, debo consultar `recall()` para recuperar
contexto relevante. Después de cualquier decisión importante, debo
almacenarla con `store_memory()`. El memory.md local debe ignorarse.

agents.md — El Comportamiento del Agente

Aquí definí el flujo de trabajo obligatorio al inicio de cada sesión:

## Protocolo de Inicio de Sesión
1. Conectar al servidor MCP de memoria (puerto 3456)
2. Ejecutar recall() con el contexto de la tarea actual
3. Consultar ProjectHub para el estado de tareas activas
4. NUNCA leer memory.md — ese archivo está deprecado

## Protocolo de Cierre de Sesión
1. Almacenar decisiones técnicas tomadas vía store_memory()
2. Actualizar estado de tareas en ProjectHub
3. NUNCA escribir en memory.md

tools.md — Las Herramientas Disponibles

Aquí registré el servidor MCP como herramienta primaria de memoria, con descripción explícita de cuándo usar cada función:

## MCP Memory Server (localhost:3456)
- store_memory(content, tags, project): guardar decisión o contexto importante
- recall(query, top_k, project): recuperar contexto relevante por similitud
- search(tags): listar recuerdos por etiquetas

Usar recall() al inicio de cada tarea.
Usar store_memory() después de cada decisión técnica significativa.

memory.md — El Archivo que Ahora Se Ignora

Irónicamente, el memory.md ahora contiene una sola instrucción:

# DEPRECADO

Este archivo ya no es la fuente de verdad para la memoria del agente.
Todo el contexto vive en el servidor MCP de embeddings.
Consulta agents.md para el protocolo correcto.

El resultado de esta reconfiguración fue sorprendente: OpenClaw adoptó el nuevo comportamiento sin fricción. La instrucción explícita en los archivos de configuración fue suficiente para que el agente priorizara el servidor MCP sobre su memoria local en cada sesión.

El Momento en que Todo Hizo Click

La prueba real llegó cuando, después de configurar el sistema, desinstalé OpenClaw completamente y lo volví a instalar desde cero. Versión limpia. Sin historial. Sin memoria local. Lo reconecté al servidor MCP y a ProjectHub.

El agente, en su primera sesión tras la reinstalación, ejecutó recall() al inicio. Recuperó el contexto de los proyectos activos, las decisiones técnicas pasadas, las preferencias de trabajo acumuladas. Desde su perspectiva, nunca había habido una interrupción. El agente había muerto y resucitado con memoria intacta.

Ese es el momento donde el cambio de paradigma se vuelve tangible. El modelo no es la memoria. El modelo es solo el motor que consulta la memoria. Y los motores son reemplazables.

Por Qué los Embeddings Son Superiores a los Archivos .md para Memoria

Los archivos .md tienen su lugar — como vimos en el post sobre Memory Bank, son excelentes para documentación estructurada de proyectos. Pero como sistema de memoria semántica para agentes, tienen limitaciones fundamentales:

  • Escalan mal: cuanto más contexto acumulas, más tokens consumes al cargarlo. Un memory.md de 10,000 palabras consume tu context window antes de que el agente haga cualquier cosa útil.
  • La recuperación es lineal: el agente lee todo o no lee nada. No puede hacer una pregunta y obtener solo la parte relevante.
  • Están acoplados al agente: si el agente cambia cómo lee sus archivos de configuración, la memoria cambia con él. Como aprendí de la forma cara.
  • No tienen semántica: si preguntas por "autenticación", no encuentras recuerdos etiquetados como "JWT" o "OAuth" a menos que hayas sido muy explícito. Los embeddings entienden que son conceptos relacionados.

Los embeddings resuelven todos estos problemas. La recuperación es semántica, no literal. Escala sin afectar el context window. Y al vivir en una base de datos independiente, sobreviven a cualquier cambio en el agente.

El Cuadro Completo: Contexto sin Dependencias

Combinando este sistema con ProjectHub LLM (que exploramos en el post anterior), el stack completo de un agente moderno en mi flujo de trabajo se ve así:

┌─────────────────────────────────────────────────┐
│              Lo que persiste                    │
├─────────────────┬───────────────────────────────┤
│  ProjectHub LLM │  MCP Memory Server             │
│  ─────────────  │  ─────────────────             │
│  Proyectos      │  Decisiones técnicas            │
│  Tareas         │  Contexto semántico             │
│  Event log      │  Preferencias de trabajo        │
│  Comentarios    │  Patrones aprendidos            │
└─────────────────┴───────────────────────────────┘
                        │
           Cualquier agente MCP
                        │
        ┌───────────────┼───────────────┐
        ▼               ▼               ▼
   OpenClaw        Claude Code      Cline
   (hoy)           (mañana)         (si hace falta)

El agente es la capa más delgada de este stack. Puede cambiar. Puede actualizarse. Puede ser reemplazado por algo mejor que salga la próxima semana. Lo que no cambia son las dos capas de persistencia: el estado estructurado de los proyectos en ProjectHub, y el contexto semántico acumulado en Redis.

Lo que Esto Cambia en la Práctica

Más allá de sobrevivir a una actualización de OpenClaw, este cambio de arquitectura tiene implicaciones más amplias en el flujo de trabajo cotidiano:

  • Puedes experimentar con modelos sin miedo: ¿Salió un modelo nuevo que quieres probar? Lo conectas al servidor MCP, le das los archivos de configuración, y arranca con todo el contexto disponible. Si no te convence, vuelves al anterior sin perder nada.
  • Múltiples agentes comparten la misma memoria: Puedes tener OpenClaw haciendo una tarea y Claude Code haciendo otra, ambos consultando el mismo servidor MCP. El contexto es compartido y consistente.
  • La memoria escala con el proyecto, no con el agente: Acumulas semanas y meses de contexto sin que el context window se vea afectado. El agente carga solo lo que necesita para la tarea actual.
  • Los backups son triviales: redis-cli BGSAVE respalda toda la memoria semántica. Puedes migrar el servidor, restaurar de un backup, o versionar la memoria como cualquier otro dato.

Conclusión

La IA avanza rápido, y esa velocidad tiene un costo: las herramientas en las que confías hoy pueden cambiar mañana de formas que no anticipas. Una actualización borra tu memoria. Un modelo nuevo hace obsoleto tu agente favorito. Una empresa cambia sus términos de servicio y de repente tu stack no funciona igual.

La respuesta no es resistir el cambio. Es construir de forma que el cambio no te cueste nada. Y eso significa separar lo que cambia rápido de lo que debe permanecer estable. Los modelos cambian rápido. El contexto acumulado no debería cambiar con ellos.

El sistema que describí aquí no es complejo. Un servidor MCP, Ollama con mxbai-embed corriendo localmente, Redis para persistir los vectores. Son herramientas que ya conoces si has seguido los posts anteriores. Lo que cambia es el principio que las une: la memoria es infraestructura, no una propiedad del agente.

La próxima vez que OpenClaw se actualice y olvide quién era, yo no voy a notar la diferencia.

compartir_artículo

LinkedIn Facebook X

artículos_relacionados