Organización de la memoria de los agentes a escala: patrones de diseño de espacios de nombres en AgentCore Memory

Al crear agentes de IA, los desarrolladores luchan por organizar la memoria entre sesiones, lo que conduce a una recuperación de contexto irrelevante y vulnerabilidades de seguridad. Los agentes de IA que recuerdan el contexto entre sesiones necesitan algo más que almacenamiento. Necesitan una memoria organizada, recuperable y segura. En Amazon Bedrock AgentCore Memory, los espacios de nombres determinan cómo se organizan, recuperan y quién puede acceder a los registros de memoria a largo plazo. Lograr el diseño correcto del espacio de nombres es esencial para construir un sistema de memoria eficaz.

En esta publicación, aprenderá cómo diseñar jerarquías de espacios de nombres, elegir los patrones de recuperación correctos e implementar el control de acceso basado en AWS Identity and Access Management (IAM) para AgentCore Memory. Si es nuevo en AgentCore Memory, le recomendamos leer primero nuestra publicación de blog introductoria: Amazon Bedrock AgentCore Memory: creación de agentes sensibles al contexto.

¿Qué son los espacios de nombres?

Los espacios de nombres son rutas jerárquicas que organizan registros de memoria a largo plazo dentro de un recurso de memoria AgentCore. Piense en ellos como rutas de directorio en un sistema de archivos. Proporcionan una estructura lógica, permiten la recuperación con alcance y admiten el control de acceso.

Cuando AgentCore Memory extrae registros de memoria a largo plazo de sus conversaciones, cada registro de memoria se almacena en un espacio de nombres. Por ejemplo, las preferencias de un usuario pueden estar en /actor/customer-123/preferences/, mientras que sus resúmenes de sesión pueden almacenarse en /actor/customer-123/session/session-789/summary/. Con esta estructura, puede recuperar registros de memoria exactamente con el nivel correcto de granularidad.

Si ha trabajado con claves de partición en Amazon DynamoDB o estructuras de carpetas en Amazon Simple Storage Service (Amazon S3), el modelo mental se transfiere bien. Así como piensa en los patrones de acceso antes de elegir una clave de partición o diseñar su jerarquía de carpetas S3, debe pensar en sus patrones de recuperación antes de diseñar la estructura de su espacio de nombres. Determinar:

¿Quién necesita acceder a estas memorias: un único usuario? ¿Todos los usuarios de un agente? Granularidad de recuperación que necesita: ¿son resúmenes por sesión? ¿Preferencias entre sesiones? Límites de aislamiento que importan: ¿Los recuerdos de un usuario deberían ser visibles para otro? ¿Recuerdos del ámbito del agente?

La principal diferencia con una clave de partición es que los espacios de nombres admiten la recuperación jerárquica además de la coincidencia exacta. Puede realizar consultas en cada nivel de la jerarquía, no solo en el nivel de hoja. Puede utilizar un espacio de nombres bien diseñado para recuperar recuerdos de una sola sesión, de un único usuario en varias sesiones o de una agrupación más amplia, desde el mismo recurso de memoria. Los espacios de nombres son agrupaciones lógicas dentro del mismo almacenamiento subyacente. Proporcionan estructura organizativa y control de acceso, pero los registros de memoria a largo plazo en diferentes espacios de nombres coexisten dentro del mismo recurso de memoria. Su jerarquía es su herramienta principal para organizar datos para patrones de recuperación efectivos.

Plantillas de espacios de nombres y resolución.

Al crear un recurso de memoria, define plantillas de espacio de nombres utilizando el campo namespaceTemplate dentro de cada configuración de estrategia. Las plantillas admiten tres variables predefinidas:

{actorId} – resuelve el identificador de actor de los eventos que se procesan {sessionId} – resuelve el identificador de sesión de los eventos {memoryStrategyId} – resuelve el identificador de estrategia

A continuación se muestra un ejemplo de creación de un recurso de memoria con plantillas de espacio de nombres:

respuesta = agentcore_client.create_memory( name="CustomerSupportMemory", descripción="Memoria para agentes de atención al cliente", eventExpiryDuration=30, MemoryStrategies=[ { "semanticMemoryStrategy": { "name": "customer-facts", "namespaceTemplate": "/actor/{actorId}/facts/" } }, { "summaryMemoryStrategy": { "name": "resúmenes de sesión", "namespaceTemplate": "/actor/{actorId}/session/{sessionId}/summary/" } } ] )

Cuando llegan eventos para actorId=customer-456 en sessionId=session-789, los espacios de nombres resueltos se convierten en:

/actor/cliente-456/hechos/ /actor/cliente-456/sesión/sesión-789/summary/

Diseño de espacio de nombres por estrategia de memoria.

Cada estrategia de memoria tiene diferentes necesidades de alcance y el diseño del espacio de nombres debe reflejar cómo se accederá a esos datos. A continuación se muestran algunos patrones de diseño de espacios de nombres comunes para diferentes estrategias de memoria.

1. Preferencias semánticas y de usuario: con alcance de actor

La memoria semántica captura hechos y conocimientos de conversaciones (por ejemplo, "La empresa del cliente tiene 500 empleados"). La memoria de preferencias del usuario captura opciones y estilos (por ejemplo, "El usuario prefiere Python para el trabajo de desarrollo"). Ambos tipos de memoria se acumulan con el tiempo y son relevantes en todas las sesiones. Un hecho conocido en enero debería poder recuperarse en marzo. Para estas estrategias, limite el espacio de nombres al actor:

/actor/{actorId}/facts/ /actor/{actorId}/preferencias/

Esto significa que los datos y preferencias de un usuario determinado se consolidan en un único espacio de nombres, independientemente de la sesión de la que se extrajeron. El motor de consolidación fusiona memorias relacionadas dentro del mismo espacio de nombres. Mire la figura 1 para ver un ejemplo de cómo el alcance afecta la lógica de consolidación.

El siguiente diagrama ilustra cómo se organizan las memorias semánticas y de preferencias del actor:

Recurso de memoria: CustomerSupportMemory │ ├── /actor/customer-123/ │ ├── facts/ │ │ ├── "La empresa tiene 500 empleados en Seattle, Austin y Boston" │ │ ├── "Actualmente está migrando de local a nube" │ │ └── "El contacto principal es el vicepresidente de ingeniería" │ └── preferencias/ │ ├── "Prefiere comunicación por correo electrónico por teléfono" │ └── "Usualmente prefiere explicaciones técnicas detalladas" │ ├── /actor/cliente-456/ │ ├── hechos/ │ │ ├── "Startup con 20 empleados" │ │ └── "Usando arquitectura sin servidor" │ └── preferencias/ │ └── "Prefiere resúmenes concisos y de alto nivel"

En algunos casos de uso, es posible que un administrador necesite recuperar información entre actores mientras mantiene los recuerdos organizados por actor. Por ejemplo, un agente de atención al cliente podría necesitar buscar problemas conocidos informados por otros clientes, o un agente de ventas podría necesitar encontrar perfiles de clientes similares en su base de usuarios. Para tales casos, estructure el espacio de nombres con el identificador del actor como hijo del tipo de memoria en lugar de como padre:

/problemas-clientes/{actorId}/ /ventas/{actorId}/

Con esta estructura invertida, puede utilizar namespacePath="/customer-issues/" para recuperar problemas comunes planteados en todos los clientes, manteniendo al mismo tiempo una organización por actor. Una consulta con alcance en namespace="/customer-issues/customer-123/" devuelve solo los problemas informados por ese actor, preservando el aislamiento cuando sea necesario.

2. Resumen: ámbito de sesión

La memoria resumida crea narrativas continuas de conversaciones, capturando puntos y decisiones principales. En lugar de introducir un historial de conversaciones completo en la ventana contextual del modelo de lenguaje grande (LLM), puede recuperar un resumen compacto que conserva la información clave y al mismo tiempo reduce significativamente el uso de tokens. Debido a que los resúmenes están inherentemente vinculados a una conversación específica, deben incluir el identificador de sesión:/actor/{actorId}/session/{sessionId}/summary/. Este alcance significa que cada sesión obtiene su propio resumen, sin dejar de estar organizada bajo el actor para la recuperación entre sesiones cuando sea necesario.

Recurso de memoria: CustomerSupportMemory │ ├── /actor/customer-123/ │ ├── session/session-001/summary/ │ │ └── "El cliente preguntó sobre los precios empresariales, discutió │ │ el cronograma de implementación, solicitó una demostración de seguimiento" │ ├── session/session-002/summary/ │ │ └── "Seguimiento de la programación de la demostración, cronograma del tercer trimestre confirmado, │ │ discutió los requisitos de integración con CRM existente" │ └── session/session-003/summary/ │ └── "Profundización técnica sobre la integración de API, revisión │ opciones de autenticación, elección del enfoque OAuth 2.0"

3. Episódico: ámbito de sesión con jerarquía de reflexión

La memoria episódica captura rastros completos del razonamiento, incluido el objetivo, los pasos dados, los resultados y las reflexiones. Debido a que cada episodio representa lo que sucedió durante una interacción específica, los episodios deben limitarse a la sesión, de manera similar a los resúmenes. Por ejemplo, un agente de reservas de vuelos podría almacenar un episodio que capture cómo buscó vuelos, comparó opciones, gestionó una restricción de clase de tarifa y, en última instancia, volvió a reservar al cliente en una ruta alternativa. Ese episodio pertenece a la sesión donde ocurrió. Las reflexiones son conocimientos de varios episodios almacenados a nivel de los padres. Generalizan lo aprendido a lo largo de las sesiones, por ejemplo, "cuando una restricción de clase de tarifa bloquea una modificación, busque inmediatamente vuelos alternativos en lugar de simplemente explicar la política". El espacio de nombres para reflexiones debe ser una subruta del espacio de nombres para episodios:

Episodios: /actor/{actorId}/session/{sessionId}/episodes/ Reflexiones: /actor/{actorId}/

Patrones de recuperación

API de recuperación

AgentCore Memory proporciona tres API de recuperación principales para memoria a largo plazo, cada una adaptada a diferentes patrones de acceso. Elegir al adecuado es clave para crear agentes eficaces.

1. Búsqueda semántica con RetrieveMemoryRecords

Utilice RetrieveMemoryRecords para buscar recuerdos que sean semánticamente relevantes para una consulta. Este es el principal método de recuperación durante las interacciones con los agentes, ya que saca a la luz los recuerdos más relevantes basándose en el significado, en lugar de en la coincidencia exacta del texto.

# Recuperar recuerdos relevantes para la consulta del usuario actual recuerdos = agentcore_client.retrieve_memory_records( MemoryId="mem-12345abcdef", namespace="/actor/customer-123/facts/", searchCriteria={ "searchQuery": "¿Qué enfoque de migración a la nube está utilizando el cliente?", "topK": 5 } )

La consulta de búsqueda puede provenir de dos fuentes:

Directamente desde la consulta del usuario: pase la pregunta del usuario tal como está cuando se asigne naturalmente al tipo de información almacenada en la memoria. Por ejemplo, si el usuario pregunta "¿Cuál es mi presupuesto?", esa consulta funciona bien para recuperar recuerdos de preferencias o hechos. Consulta generada por el LLM: para escenarios más complejos, haga que el LLM de su agente formule una consulta de búsqueda específica. Esto es útil cuando la entrada sin procesar del usuario no se asigna directamente a los recuerdos almacenados. Por ejemplo, si el usuario dice "Ayúdame a planificar mi próximo viaje", el LLM podría generar una consulta de búsqueda como "preferencias de viaje, historial de destinos, restricciones presupuestarias" para recuperar los recuerdos más relevantes. Tenga en cuenta que esto agrega latencia.

2. Recuperación directa con ListMemoryRecords

Utilice ListMemoryRecords cuando necesite enumerar recuerdos dentro de un espacio de nombres específico, como mostrar las preferencias almacenadas de un usuario en la interfaz de usuario de una consola, auditar qué recuerdos existen o realizar operaciones masivas.

# Listar todos los recuerdos en registros de un espacio de nombres específico = agentcore_client.list_memory_records(memoryId="mem-12345abcdef", namespace="/actor/customer-123/preferences/" )

3. ObtenerMemoryRecord y EliminarMemoryRecord

Cuando conozca el ID del registro de memoria específico (por ejemplo, de una lista anterior o de una llamada de recuperación), use GetMemoryRecord para una búsqueda directa o DeleteMemoryRecord para eliminar una memoria específica:

# Obtener un registro de memoria específico record = agentcore_client.get_memory_record( MemoryId="mem-12345abcdef", MemoryRecordId="rec-abc123" ) # Eliminar un registro de memoria específico agentcore_client.delete_memory_record( MemoryId="mem-12345abcdef", MemoryRecordId="rec-abc123" )

Son útiles para flujos de trabajo de administración de memoria que se utilizan para ayudar a los usuarios a ver, corregir o eliminar recuerdos específicos a través de la interfaz de usuario de su aplicación.

Espacio de nombres frente a ruta del espacio de nombres: coincidencia exacta frente a recuperación jerárquica

AgentCore Memory proporciona dos campos distintos para determinar el alcance de la recuperación y comprender la diferencia es fundamental para un comportamiento correcto.

1. espacio de nombres: coincidencia exacta

El campo del espacio de nombres realiza una coincidencia exacta. Solo devuelve registros de memoria almacenados en esa ruta precisa del espacio de nombres.

# Devuelve SÓLO registros almacenados en /actor/customer-123/facts/ records = agentcore_client.retrieve_memory_records( MemoryId="mem-12345abcdef", namespace="/actor/customer-123/facts/", searchCriteria={ "searchQuery": "cloud migración", "topK": 5 } )

Esta es la elección correcta cuando sabe exactamente qué espacio de nombres desea consultar y necesita un alcance preciso. Por ejemplo, recuperar solo las preferencias de un usuario sin incluir sus datos o resúmenes.

2. namespacePath: recuperación jerárquica

El campo namespacePath realiza una coincidencia jerárquica y devuelve los registros de memoria cuyo espacio de nombres se encuentra en la ruta especificada.

# Devuelve registros de # /actor/customer-123/facts/, # /actor/customer-123/preferences/, # /actor/customer-123/session/*/summary/, etc. registros = agentcore_client.retrieve_memory_records( MemoryId="mem-12345abcdef", namespacePath="/actor/customer-123/", searchCriteria={ "searchQuery": "migración a la nube", "topK": 5 } )

Esto es útil cuando desea buscar en los recuerdos del usuario independientemente del tipo, o cuando crea funciones como "muéstrame todo lo que sabemos sobre este cliente". Tenga en cuenta que es importante que piense en sus patrones de aislamiento y recuperación para asegurarse de que el recorrido del árbol no exponga datos no deseados.

Cuando usar cual

Ejemplo de campo de API de escenario 1 Recuperar preferencias de usuario semánticamente relevantes RetrieveMemoryRecords espacio de nombres /actor/customer-123/preferences/ 2 Recuperar un resumen de sesión específico Espacio de nombres ListMemoryRecords /actor/customer-123/session/session-001/summary/ 3 Enumerar todas las preferencias de un usuario Espacio de nombres ListMemoryRecords /actor/customer-123/preferences/ 4 Buscar en los recuerdos de un usuario RetrieveMemoryRecords namespacePath /actor/customer-123/ 5 Listar resúmenes de sesiones para un usuario ListMemoryRecords namespacePath /actor/customer-123/session/

Redacción de políticas de IAM para el control de acceso al espacio de nombres

Los espacios de nombres se integran con AWS Identity and Access Management (IAM) a través de claves de condición que restringen qué espacios de nombres puede incluir una entidad principal en sus solicitudes de API de memoria.

1. Políticas de coincidencia exacta

Utilice StringEquals con la clave de condición bedrock-agentcore:namespace para restringir el acceso a un espacio de nombres específico:

{ "Versión": "2012-10-17", "Declaración": [ { "Efecto": "Permitir", "Acción": [ "bedrock-agentcore:RetrieveMemoryRecords", "bedrock-agentcore:ListMemoryRecords" ], "Recurso": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/mem-12345abcdef", "Condition": { "StringEquals": { "bedrock-agentcore:namespace": "/actor/${aws:PrincipalTag/userId}/preferences/" } } } ] }

Esta política garantiza que un usuario solo pueda recuperar recuerdos de su propio espacio de nombres de preferencias, utilizando la etiqueta principal userId (inyectada) para el alcance dinámico.

2. Políticas de recuperación jerárquicas

Utilice StringLike con la clave de condición bedrock-agentcore:namespacePath para acceso jerárquico:

{ "Versión": "2012-10-17", "Declaración": [ { "Efecto": "Permitir", "Acción": [ "bedrock-agentcore:RetrieveMemoryRecords", "bedrock-agentcore:ListMemoryRecords" ], "Recurso": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/mem-12345abcdef", "Condition": { "StringLike": { "bedrock-agentcore:namespacePath": "/actor/${aws:PrincipalTag/userId}/*" } } } ] }

Con esto, un usuario puede realizar una recuperación jerárquica en sus espacios de nombres (hechos, preferencias, resúmenes) y al mismo tiempo ayuda a evitar el acceso a los datos de otros usuarios.

Conclusión

El diseño del espacio de nombres es fundamental para crear sistemas de memoria eficaces con AgentCore Memory. Al igual que diseñar un esquema clave para una base de datos o una estructura de prefijo en el almacenamiento de objetos, pensar en sus patrones de acceso desde el principio le ayuda a crear una jerarquía de espacio de nombres que admita una recuperación precisa, un aislamiento limpio entre usuarios y un control de acceso basado en IAM. Las conclusiones clave:

Piense en sus patrones de acceso y límites de aislamiento antes de crear plantillas de espacios de nombres. Alcance las memorias semánticas y de preferencias del actor (/actor/{actorId}/) para la consolidación entre sesiones. Alcance los resúmenes de la sesión (/actor/{actorId}/session/{sessionId}/) ya que son específicos de la conversación (cuando sea necesario, como resúmenes o episodios). Utilice el espacio de nombres para una coincidencia exacta cuando conozca la ruta precisa, y namespacePath para la jerárquica. recuperación cuando necesite buscar en un subárbol Utilice barras diagonales iniciales y finales en las rutas de los espacios de nombres para mantenerlas coherentes y ayudar a evitar colisiones de prefijos Utilice claves de condición de IAM (bedrock-agentcore:namespace y bedrock-agentcore:namespacePath) para controlar qué espacios de nombres se pueden solicitar

Para comenzar, visite los siguientes recursos:

Sobre los autores

Noor Randhawa

Noor Randhawa es el líder tecnológico de AgentCore Memory en Amazon Web Services (AWS), que crea sistemas que permiten a los desarrolladores crear agentes inteligentes y conscientes del contexto impulsados ​​por Memory. Anteriormente trabajó en Amazon Retail y AWS EKS, diseñando plataformas distribuidas y altamente escalables.

Akarsha Sehwag

Akarsha Sehwag es un científico de datos de IA generativa del equipo de AgentCore Memory. Con más de siete años de experiencia en el desarrollo de productos de IA/ML, ha brindado soluciones de nivel empresarial para clientes en una amplia gama de industrias. Fuera del trabajo, le gusta aprender cosas nuevas y explorar el aire libre.

Piradeep Kandasamy

Piradeep Kandasamy es gerente de desarrollo de software para AgentCore Memory. A lo largo de su carrera en Amazon, ha creado y ampliado sistemas en Amazon Alexa, Amazon ECS y AWS CloudFormation, aportando una profunda experiencia en sistemas distribuidos y servicios en la nube a gran escala a su trabajo actual en infraestructura de memoria para agentes de IA.