


Crear un servicio de memoria para agentes de IA sin mezclar los recuerdos de cada usuario
Úsalo al crear o ampliar la memoria a largo plazo de agentes de IA. Separa cada banco de memoria, distingue ingesta, recuperación y razonamiento, y cubre migraciones de base de datos, clientes de API, pruebas juzgadas por otro modelo y ajustes por inquilino o banco.
Para usar estas reglas de IA
## Separar los tipos de memoria y no mezclar datos entre bancos
Mantén separados los tipos de conocimiento almacenado, porque la ingesta, la recuperación y el razonamiento los utilizan de formas distintas.
### Modelar la memoria de forma explícita
- Los hechos del mundo representan conocimiento general.
- Los hechos de experiencia representan sucesos personales atribuidos a un usuario o agente.
- Los modelos mentales consolidan patrones sintetizados a partir de múltiples hechos.
- Permite que cada banco de memoria contenga contexto de fondo y rasgos de disposición, como escepticismo, literalidad y empatía, en una escala de 1–5.
- Aplica las disposiciones solo al razonamiento reflexivo; no permitas que alteren el recuerdo de hechos.
### Aislar los bancos
- Trata cada banco como un almacén de memoria independiente para un único usuario o agente.
- Impide las filtraciones entre bancos en el almacenamiento, la recuperación, el razonamiento y las pruebas.
- Opera exactamente sobre 1 banco por solicitud de API.
- Haz que los clientes orquesten cualquier flujo de trabajo con varios bancos, en vez de debilitar el límite del servidor.
## Separar ingesta, recuperación y razonamiento, y combinar varios métodos de búsqueda
Separa las tres operaciones principales y, a la vez, comparte abstracciones estables para modelos, incrustaciones, entidades y clasificación.
### Preservar la semántica de las operaciones
- Retain ingiere contenido y extrae hechos, entidades y relaciones.
- Recall recupera memorias existentes sin aplicar rasgos de disposición.
- Reflect realiza sobre las memorias y los modelos mentales consolidados un razonamiento que tiene en cuenta las disposiciones.
- Mantén la orquestación separada de la extracción de hechos, la normalización de entidades, la gestión de enlaces y los adaptadores de proveedores.
### Construir la recuperación como una canalización
- Ejecuta en paralelo 4 estrategias de recuperación complementarias: semántica, léxica BM25, de grafos y temporal.
- Fusiona los resultados clasificados mediante fusión recíproca de rangos antes de reordenarlos con un codificador cruzado.
- Mantén la expansión del grafo detrás de una interfaz de recuperación, de modo que las estrategias alternativas sigan siendo intercambiables.
- Admite proveedores locales y remotos de modelos, incrustaciones y reordenación mediante envoltorios de responsabilidad limitada.
### Sincronizar los contratos de API
- Regenera la especificación OpenAPI después de cambiar los puntos finales.
- Regenera todos los SDK de cliente compatibles, incluidos Python, TypeScript y Rust, después de cambiar la especificación.
- Cuando cambie un parámetro de API, actualiza conjuntamente la ruta del proxy, la extracción de la solicitud, la llamada al SDK, el tipo del cliente y cualquier interfaz que lo consuma.
## Escribir una migración que funcione en PostgreSQL y en Oracle
Usa un único historial de migraciones para todas las bases de datos compatibles, explicitando las diferencias entre dialectos.
### Definir la revisión
- Asigna a cada migración un identificador de revisión hexadecimal único de 12 caracteres y haz que `down_revision` apunte a su predecesor.
- Mantén emparejados los comportamientos de actualización y reversión.
- Despacha mediante un único enrutador de dialectos que seleccione la implementación a partir de la conexión activa.
- Haz que la prueba de forma de la migración falle cuando falte el despachador.
### Implementar cada dialecto
- Proporciona funciones de actualización y reversión separadas para PostgreSQL y las bases de datos compatibles con Oracle.
- Cualifica el SQL sin procesar de PostgreSQL con el esquema de inquilino configurado, cuando exista.
- Usa la ejecución a nivel de controlador solo para operaciones de base de datos que el marco de migración no pueda modelar, como operaciones especializadas de vectores, texto o particiones.
- Si una migración se aplica realmente a solo 1 dialecto, omite deliberadamente la otra ranura; nunca la dejes vacía por descuido.
- Considera durante la revisión la divergencia de esquemas entre dialectos.
### Verificar la ejecución
- Ejecuta las migraciones contra el esquema base y todos los esquemas de inquilinos.
- Admite también una ejecución dirigida contra 1 esquema de inquilino identificado por su nombre para realizar una verificación específica.
- Cuando las migraciones se ejecuten automáticamente al iniciar el servicio, prueba el inicio con todos los dialectos y ámbitos de inquilino compatibles.
## Pasar las comprobaciones obligatorias y la revisión de código antes del push
Usa la cadena de herramientas canónica después de cada cambio de implementación y distingue los defectos bloqueantes de la limpieza consultiva.
### Ejecutar las comprobaciones obligatorias
- Ejecuta el formateo, el linting y la comprobación de tipos después de realizar cambios en Python o TypeScript.
- Trata las importaciones y variables sin usar, los archivos de cliente huérfanos y las dependencias de paquetes no declaradas como fallos bloqueantes.
- Trata las funciones completas sin usar y las exportaciones intencionadamente amplias de bibliotecas de componentes como recomendaciones, salvo que la política del proyecto las eleve a obligatorias.
- Ejecuta las pruebas unitarias, las pruebas de integración de API y los benchmarks pertinentes mediante los comandos estándar del repositorio.
- Regenera las especificaciones de API y los clientes cuando corresponda, y comprueba después que no quede ninguna diferencia sin confirmar en los artefactos generados.
### Revisar antes de publicar
- Realiza una revisión de código estructurada después de la implementación.
- Corrige todos los hallazgos de corrección obligatoria relacionados con pruebas ausentes, código muerto, seguridad de tipos, aislamiento de datos o divergencias en archivos generados.
- No envíes código ni crees una solicitud de cambio hasta resolver los hallazgos de corrección obligatoria.
- No añadas manualmente entradas al registro de cambios de una versión aún no publicada; deja que el proceso de lanzamiento cree entradas versionadas.
## Probar la lógica fija directamente y hacer que otro modelo juzgue las respuestas del modelo
Elige las aserciones según si el comportamiento es mecánicamente determinista o depende de la interpretación del modelo.
### Probar directamente los mecanismos deterministas
- Usa aserciones directas para recuentos, campos obligatorios, composición de instrucciones, lógica de supresión y subcadenas inyectadas.
- Mantén rápidas la mayoría de las pruebas mediante modelos simulados o funciones puras.
- Combina las pruebas del comportamiento del modelo con pruebas unitarias que cubran la preparación determinista que las rodea.
### Evaluar el comportamiento semántico del modelo
1. Marca una prueba semántica para el trabajo del modelo principal con un solo proveedor; reserva el marcador de matriz de proveedores para la aceptación entre proveedores.
2. Llama a la canalización real configurada, no a una simulación.
3. Resume la respuesta con las etiquetas semánticas necesarias para la evaluación.
4. Pide a un modelo evaluador independiente que determine si la respuesta cumple los criterios explícitos del contexto proporcionado.
5. Nunca evalúes con la misma llamada al modelo que se está probando.
- Usa aserciones del modelo evaluador para la clasificación, la atribución, la preservación de dimensiones y el seguimiento de instrucciones.
- No codifiques de forma rígida cadenas exactas ni valores de enumeración para comportamientos que puedan variar válidamente entre modelos y ejecuciones.
## Llevar los cambios de la API a todos los clientes y añadir CI a las nuevas integraciones
Una integración solo está completa cuando coinciden el comportamiento en tiempo de ejecución, las pruebas, la integración continua, el registro de lanzamiento y las interfaces del cliente.
### Actualizar los consumidores de la API
- Cuando añadas un campo de solicitud, extráelo en la ruta del proxy y pásalo a la llamada del SDK.
- Actualiza el tipo del método del cliente y todas las interfaces que proporcionen o lean el campo.
- Limita cada solicitud a 1 banco y conserva la orquestación del lado del cliente para los casos de uso con varios bancos.
### Completar una integración
- Añade pruebas que simulen o ejerciten la interfaz del marco externo y comprueben que la integración llama correctamente al servicio de memoria.
- No consideres suficientes para la cobertura de integración las pruebas unitarias que solo prueban funciones auxiliares.
- Añade un trabajo de integración continua limitado al cambio que compile, instale las dependencias y ejecute las pruebas de integración.
- Registra la integración en el flujo de trabajo de lanzamiento estándar.
- Usa estructuras con tipos en lugar de diccionarios sin procesar para los datos estructurados y evita devolver tuplas con varios elementos.
- No hagas merge ni publiques mientras falten las pruebas, la detección de cambios de CI o el registro de lanzamiento.
## Decidir si un ajuste nuevo puede cambiar por inquilino o banco antes de añadirlo
Clasifica cada ajuste antes de implementarlo para mantener coherentes el ámbito de sobrescritura y la documentación.
### Elegir el nivel de configuración
- Resuelve los ajustes jerárquicos desde los valores globales del entorno, pasando por las sobrescrituras del inquilino, hasta las sobrescrituras de base de datos a nivel de banco.
- Usa la configuración jerárquica para proveedores y nombres de modelos, claves de API, opciones específicas de cada operación y marcas de funcionalidad específicas de cada cliente.
- Mantén estáticas en el servidor las direcciones, los hosts y los puertos de las bases de datos, los límites globales de concurrencia y las marcas de todo el sistema.
- No añadas un campo estático al conjunto de campos configurables de forma remota.
### Añadir un campo por completo
1. Define el nombre de la variable de entorno y el valor predeterminado.
2. Añade un campo con tipo al objeto central de configuración.
3. Añádelo a la lista de campos configurables permitidos solo cuando sean válidas las sobrescrituras de inquilino o banco.
4. Inicialízalo desde el entorno.
5. Añade una opción de línea de comandos solo cuando se requiera una sobrescritura desde la línea de comandos.
6. Lee los valores jerárquicos mediante el resolutor por banco y los valores estáticos mediante el descriptor de acceso global.
7. Actualiza la referencia de configuración y la plantilla de entorno con la descripción, el valor predeterminado y el estado jerárquico.
8. Sincroniza todas las copias incluidas de la plantilla de entorno y asegúrate de que la prueba de sincronización de plantillas siga superándose.
- Nunca expongas valores de credenciales reales en documentación, plantillas, registros ni pruebas.
