En este tutorial, utilizará el paquete crewai-mongodb-memory para dar a un agente CrewAI una memoria duradera a largo plazo que persiste en MongoDB Atlas. El agente almacena las preferencias del usuario como registros de memoria y las recupera semánticamente con búsqueda vectorial de MongoDB, de modo que un equipo nuevo en una sesión posterior puede dar correctamente la respuesta recuperando los aprendizajes de una sesión anterior.
Para obtener más información sobre la integración de MongoDB CrewAI, consulta Integra MongoDB con CrewAI.
Requisitos previos
Para completar este tutorial, debes tener lo siguiente:
Python 3.10 o posterior.
Uno de los siguientes tipos de clúster de MongoDB:
Se requiere un clúster de Atlas que ejecute MongoDB 6.0.11 versión, 7.0.2 o posterior. Asegúrese de que su dirección IP esté incluida en la lista de acceso de su proyecto de Atlas.
Implementación local de Atlas creada con Python y Docker. Instale
atlas-local-lib-pypip install atlas-local-lib-py() para crear y administrar implementaciones locales mediante programación. Para obtener más información, consulte el repositorio atlas-local-lib-py.Un clúster de MongoDB Community con Search y búsqueda vectorial instalados.
Una clave de API de Voyage IA. Para crear una clave API, consulta Claves API del modelo.
Una clave API de grandes modelos de lenguaje (LLM), como Anthropic u OpenAI, para impulsar la inferencia del agente.
Cómo funciona la memoria del agente con MongoDB
El backend de crewai-mongodb-memory implementa el protocolo de StorageBackend de CrewAI. Almacena cada memoria como un registro en una colección de MongoDB y utiliza la búsqueda vectorial de MongoDB para recuperar registros relevantes semánticamente. El backend utiliza los siguientes componentes:
MongoDBStorageBackend: Se conecta a su clúster de Atlas, almacena registros de memoria y ejecuta$vectorSearchquery para recuperarlos.MemoryRecord: Representa una sola memoria, incluido su contenido de texto, un ámbito jerárquico como/users/alex/preferences, categorías opcionales y su incrustación vectorial.embed_text(): Genera incrustaciones de 1024dimensiones con el modelovoyage-4de Voyage AI tanto para documentos almacenados como para consultas.
Debido a que la memoria reside en Atlas en lugar del contexto en proceso del equipo, cualquier equipo que se conecte al mismo clúster y ámbito puede recuperar las memorias almacenadas.
{ "_id": "cff7db8d-aa2e-4d82-8234-e4b8f1ccccb6", "content": "The user always prefers window seats on flights.", "scope": "/users/alex/preferences", "categories": [ "preference" ], "metadata": {}, "importance": 0.5, "created_at": { "$date": "2026-07-14T22:06:59.162Z" }, "last_accessed": { "$date": "2026-07-14T22:06:59.162Z" }, "source": null, "private": false, "embedding": [ 0.03147803992033005, 0.015906454995274544, -0.007409059442579746, 0.028631621971726418, ... ], "scope_ancestors": [ "/users", "/users/alex", "/users/alex/preferences" ] }
Compilar y ejecutar el agente
Siga los siguientes pasos para compilar y ejecutar un agente que almacene y recupere las preferencias del usuario:
Configura el entorno.
Ejecuta los siguientes comandos en tu terminal para crear un nuevo directorio llamado
crewai-memory-projecte instalar las dependencias necesarias:mkdir crewai-memory-project cd crewai-memory-project pip install crewai-mongodb-memory crewai "crewai[google-genai]" voyageai python-dotenv En tu proyecto, crea un archivo
.envy añade las siguientes líneas:ATLAS_URI="<connection-string>" VOYAGE_API_KEY="<voyage-api-key>" ANTHROPIC_API_KEY="<anthropic-api-key>" MODEL="<anthropic-model>" Nota
Se debe sustituir
<connection-string>por la cadena de conexión del clúster Atlas o de la implementación local de Atlas.Su cadena de conexión debe usar el siguiente formato:
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net Para obtener más información, consulta Conectar a un clúster a través de bibliotecas de clientes.
Su cadena de conexión debe usar el siguiente formato:
mongodb://localhost:<port-number>/?directConnection=true Para obtener más información, consulta Cadenas de conexión.
Compila el agente.
Crea un archivo llamado main.py en tu proyecto y pega el siguiente código:
from __future__ import annotations import os import sys import time import warnings from dotenv import load_dotenv load_dotenv() warnings.filterwarnings("ignore") from crewai import Agent, Crew, Task from crewai.tools import tool from crewai_mongodb_memory import MemoryRecord, MongoDBStorageBackend, embed_text from crewai.events import CrewKickoffStartedEvent, CrewKickoffCompletedEvent, AgentExecutionCompletedEvent from crewai.events import BaseEventListener DEMO_DB = "crewai_mem_agent_demo" SCOPE = "/users/alex/preferences" MODEL = os.environ.get("ANTHROPIC_MODEL", "anthropic/claude-3-5-sonnet-latest") EMBEDDING_MODEL = os.environ.get("VOYAGE_MODEL", "voyage-4") # Module-level backend handle so the function tools can reach it. _BACKEND: MongoDBStorageBackend | None = None _SESSION_LABEL = "" # Custom event listener for logging Crew and Agent events. class EventListener(BaseEventListener): def __init__(self): super().__init__() def setup_listeners(self, crewai_event_bus): def on_crew_started(source, event): print(f"Crew '{event.crew_name}' has started execution!") def on_crew_completed(source, event): print(f"Crew '{event.crew_name}' has completed execution!") print(f"Output: {event.output}") def on_agent_execution_completed(source, event): print(f"Agent '{event.agent.role}' completed task") print(f"Output: {event.output}") def banner(title: str) -> None: print(f"\n{'=' * 70}\n{title}\n{'=' * 70}") def embed(text: str, input_type: str) -> list[float]: """Generate embeddings with an explicit Voyage model.""" try: return embed_text(text, input_type=input_type, model=EMBEDDING_MODEL) except TypeError: # Backward compatibility for older crewai-mongodb-memory versions. return embed_text(text, input_type=input_type) def remember_preference(fact: str) -> str: """Store a durable user preference in MongoDB Atlas long-term memory.""" assert _BACKEND is not None rec = MemoryRecord( content=fact, scope=SCOPE, categories=["preference"], embedding=embed(fact, input_type="document"), ) _BACKEND.save([rec]) return f"Stored preference: {fact}" def recall_preferences(query: str) -> str: """Retrieve relevant user preferences from Atlas via $vectorSearch.""" assert _BACKEND is not None qv = embed(query, input_type="query") hits = _BACKEND.search(qv, scope_prefix=SCOPE, limit=3) if not hits: return "No relevant preferences found." for rec, score in hits: print(f" - [{score:.3f}] {rec.content}") return "\n".join(f"- {rec.content} (score={score:.3f})" for rec, score in hits) def build_agent() -> Agent: return Agent( role="Personal Concierge", goal="Help the user with durable long-term memory stored in MongoDB Atlas.", backstory=( """You remember user preferences across sessions. When the user shares a durable preference, call remember_preference. When a request may depend on what you know about them, call recall_preferences first and use the results.""" ), tools=[remember_preference, recall_preferences], llm=MODEL, verbose=True, ) def run_task(description: str, expected_output: str) -> str: """Run a single-task crew (a fresh crew each call is a fresh session).""" agent = build_agent() task = Task(description=description, expected_output=expected_output, agent=agent) crew = Crew(agent, [task]) return str(crew.kickoff()) def main() -> None: global _BACKEND, _SESSION_LABEL uri = os.environ.get("ATLAS_URI") # Fast fail if the required environment variables are not set. if not all([uri, os.environ.get("ANTHROPIC_API_KEY"), os.environ.get("VOYAGE_API_KEY")]): print("This script needs ATLAS_URI, ANTHROPIC_API_KEY, and VOYAGE_API_KEY.") sys.exit(1) print(f"=== CrewAI and MongoDB Atlas long-term memory (model={MODEL}) ===") _BACKEND = MongoDBStorageBackend(uri, database_name=DEMO_DB) _BACKEND.delete(scope_prefix=SCOPE) # clean slate for a repeatable run print("Ensuring Atlas Vector Search index (first build can take ~1 min)...") if not _BACKEND.ensure_vector_index(wait=True): print("Vector index did not become queryable in time.") sys.exit(1) print("Index queryable.") # Initialize the event listener for the agent. listener = EventListener() # Session 1: the agent learns and stores preferences. banner("SESSION 1 - agent stores durable preferences in Atlas") session_1_input = ( """The user says: 'I'm vegetarian, I avoid dairy, and I always prefer window seats on flights.' Store each durable preference.""" ) _SESSION_LABEL = "SESSION 1" print(f" {session_1_input}") out1 = run_task( description=session_1_input, expected_output="A short confirmation of what was stored.", ) print(f"\nAgent (session 1): {out1}") # Atlas indexing is asynchronous, so wait until the facts are searchable. print("\nWaiting for Atlas to index the new memories...") for _ in range(20): if _BACKEND.search(embed("food", input_type="query"), scope_prefix=SCOPE, limit=1): break time.sleep(2) print("Memories searchable.") # Session 2: a brand-new crew with no shared state recalls from Atlas. banner("SESSION 2 - fresh crew answers via recall_preferences") session_2_input = ( """The user is booking a long flight and pre-ordering an in-flight meal. Recommend a seat and a meal that fit their preferences.""" ) _SESSION_LABEL = "SESSION 2" print(f" {session_2_input}") out2 = run_task( description=session_2_input, expected_output="A seat and meal recommendation grounded in recalled preferences.", ) print(f"\nAgent (session 2, brand-new crew): {out2}") banner("Proof: direct $vectorSearch recall over stored preferences") hits = _BACKEND.search( embed("dietary and seating preferences", input_type="query"), scope_prefix=SCOPE, limit=5, ) for rec, score in hits: print(f" - [{score:.3f}] {rec.content}") _BACKEND.delete(scope_prefix=SCOPE) _BACKEND.close() print("\nDone - CrewAI stored and recalled preferences via MongoDB Vector Search.") if __name__ == "__main__": main()
Este script realiza lo siguiente:
Se conecta a su clúster de Atlas con
MongoDBStorageBackendy garantiza que exista un índice de búsqueda vectorial de MongoDB en la colección de memoria.Define dos herramientas,
remember_preferenceyrecall_preferences, que el agente llama para almacenar y recuperar recuerdos.Define un agente de CrewAI que utiliza las herramientas de memoria y, a continuación, ejecuta un equipo que almacena las preferencias del usuario.
Ejecuta un segundo equipo completamente nuevo que recupera las preferencias almacenadas de Atlas y basa su recomendación en ellas.
Ejecute el archivo.
Ejecuta el siguiente comando para ejecutar el script:
python main.py
====================================================================== SESSION 1 - agent stores durable preferences in Atlas ====================================================================== The user says: 'I'm vegetarian, I avoid dairy, and I always prefer window seats on flights.' Store each durable preference. Crew 'crew' has started execution! ╭────────────────────────────── 🤖 Agent Started ──────────────────────────────╮ │ │ │ Agent: Personal Concierge │ │ │ │ Task: The user says: 'I'm vegetarian, I avoid dairy, and I always prefer │ │ window seats on flights.' Store each durable preference. │ │ │ ╰──────────────────────────────────────────────────────────────────────────────╯ Tool remember_preference executed with result: Stored preference: The user is vegetarian.... Tool remember_preference executed with result: Stored preference: The user avoids dairy.... Tool remember_preference executed with result: Stored preference: The user always prefers window seats on flights.... [Finalize] todos_count=0, todos_with_results=0 ╭─────────────────────────── ✅ Agent Final Answer ────────────────────────────╮ │ │ │ Agent: Personal Concierge │ │ │ │ Final Answer: │ │ Stored: │ │ - The user is vegetarian. │ │ - The user avoids dairy. │ │ - The user always prefers window seats on flights. │ │ │ ╰──────────────────────────────────────────────────────────────────────────────╯ Agent 'Personal Concierge' completed task Output: Stored: - The user is vegetarian. - The user avoids dairy. - The user always prefers window seats on flights. Crew 'crew' has completed execution! Output: Stored: - The user is vegetarian. - The user avoids dairy. - The user always prefers window seats on flights. Agent (session 1): Stored: - The user is vegetarian. - The user avoids dairy. - The user always prefers window seats on flights. Waiting for Atlas to index the new memories... Memories searchable. ====================================================================== SESSION 2 - fresh crew answers via recall_preferences ====================================================================== The user is booking a long flight and pre-ordering an in-flight meal. Recommend a seat and a meal that fit their preferences. Crew 'crew' has started execution! ╭────────────────────────────── 🤖 Agent Started ──────────────────────────────╮ │ │ │ Agent: Personal Concierge │ │ │ │ Task: The user is booking a long flight and pre-ordering an in-flight │ │ meal. │ │ Recommend a seat and a meal that fit their preferences. │ │ │ ╰──────────────────────────────────────────────────────────────────────────────╯ - [0.794] The user always prefers window seats on flights. - [0.748] The user is vegetarian. - [0.739] The user avoids dairy. Tool recall_preferences executed with result: - The user always prefers window seats on flights. (score=0.794) - The user is vegetarian. (score=0.748) - The user avoids dairy. (score=0.739)... [Finalize] todos_count=0, todos_with_results=0 ╭─────────────────────────── ✅ Agent Final Answer ────────────────────────────╮ │ │ │ Agent: Personal Concierge │ │ │ │ Final Answer: │ │ I recommend booking a **window seat** for the long flight, since you │ │ prefer window seats. │ │ │ │ For your in-flight meal, choose a **vegetarian dairy-free meal**. If the │ │ airline offers specific meal codes, look for something like **VGML / vegan │ │ meal**, since that will typically meet both preferences: vegetarian and no │ │ dairy. │ │ │ ╰──────────────────────────────────────────────────────────────────────────────╯ Agent 'Personal Concierge' completed task Output: I recommend booking a **window seat** for the long flight, since you prefer window seats. For your in-flight meal, choose a **vegetarian dairy-free meal**. If the airline offers specific meal codes, look for something like **VGML / vegan meal**, since that will typically meet both preferences: vegetarian and no dairy. Crew 'crew' has completed execution! Output: I recommend booking a **window seat** for the long flight, since you prefer window seats. For your in-flight meal, choose a **vegetarian dairy-free meal**. If the airline offers specific meal codes, look for something like **VGML / vegan meal**, since that will typically meet both preferences: vegetarian and no dairy. Agent (session 2, brand-new crew): I recommend booking a **window seat** for the long flight, since you prefer window seats. For your in-flight meal, choose a **vegetarian dairy-free meal**. If the airline offers specific meal codes, look for something like **VGML / vegan meal**, since that will typically meet both preferences: vegetarian and no dairy. ====================================================================== Proof: direct $vectorSearch recall over stored preferences ====================================================================== - [0.770] The user always prefers window seats on flights. - [0.768] The user is vegetarian. - [0.754] The user avoids dairy. Done - CrewAI stored and recalled preferences via MongoDB Vector Search.
Nota
Su resultado podría diferir, ya que las respuestas de LLM y las puntuaciones de búsqueda vectorial pueden variar entre ejecuciones.