{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ur8xi4C7S06n"
   },
   "outputs": [],
   "source": [
    "# Copyright 2025 Google LLC\n",
    "#\n",
    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "#     https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "JAPoU8Sm5E6e"
   },
   "source": [
    "# Get started with Vertex AI Memory Bank - CrewAI\n",
    "\n",
    "<table align=\"left\">\n",
    "  <td style=\"text-align: center\">\n",
    "    <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\">\n",
    "      <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n",
    "    </a>\n",
    "  </td>\n",
    "  <td style=\"text-align: center\">\n",
    "    <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fgemini%2Fagent-engine%2Fmemory%2Fget_started_with_memory_bank_crewai.ipynb\">\n",
    "      <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n",
    "    </a>\n",
    "  </td>\n",
    "  <td style=\"text-align: center\">\n",
    "    <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\">\n",
    "      <img src=\"https://www.gstatic.com/images/branding/gcpiconscolors/vertexai/v1/32px.svg\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n",
    "    </a>\n",
    "  </td>\n",
    "  <td style=\"text-align: center\">\n",
    "    <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\">\n",
    "      <img width=\"32px\" src=\"https://raw.githubusercontent.com/primer/octicons/refs/heads/main/icons/mark-github-24.svg\" alt=\"GitHub logo\"><br> View on GitHub\n",
    "    </a>\n",
    "  </td>\n",
    "</table>\n",
    "\n",
    "<div style=\"clear: both;\"></div>\n",
    "\n",
    "<b>Share to:</b>\n",
    "\n",
    "<a href=\"https://www.linkedin.com/sharing/share-offsite/?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\" target=\"_blank\">\n",
    "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/8/81/LinkedIn_icon.svg\" alt=\"LinkedIn logo\">\n",
    "</a>\n",
    "\n",
    "<a href=\"https://bsky.app/intent/compose?text=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\" target=\"_blank\">\n",
    "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg\" alt=\"Bluesky logo\">\n",
    "</a>\n",
    "\n",
    "<a href=\"https://twitter.com/intent/tweet?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\" target=\"_blank\">\n",
    "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/5a/X_icon_2.svg\" alt=\"X logo\">\n",
    "</a>\n",
    "\n",
    "<a href=\"https://reddit.com/submit?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\" target=\"_blank\">\n",
    "  <img width=\"20px\" src=\"https://redditinc.com/hubfs/Reddit%20Inc/Brand/Reddit_Logo.png\" alt=\"Reddit logo\">\n",
    "</a>\n",
    "\n",
    "<a href=\"https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agent-engine/memory/get_started_with_memory_bank_crewai.ipynb\" target=\"_blank\">\n",
    "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg\" alt=\"Facebook logo\">\n",
    "</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "84f0f73a0f76"
   },
   "source": [
    "| Author(s) |\n",
    "| --- |\n",
    "| [Ivan Nardini](https://github.com/inardini) |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "tvgnzT1CKxrO"
   },
   "source": [
    "## Overview\n",
    "\n",
    "This tutorial demonstrates how to integrate **Vertex AI Memory Bank** with **CrewAI** agents to provide them with persistent, long-term memory across conversations.\n",
    "\n",
    "### What you'll learn\n",
    "\n",
    "By the end of this tutorial, you will be able to:\n",
    "\n",
    "  * Provision a Vertex AI Agent Engine to serve as the backend for Memory Bank.\n",
    "  * Implement a custom CrewAI `Storage` class that connects to the Memory Bank API.\n",
    "  * Instantiate CrewAI agents and tasks that leverage this external, long-term memory.\n",
    "  * Assemble and run a crew that can recall information from past interactions to provide personalized responses.\n",
    "\n",
    "### Why this is important\n",
    "\n",
    "CrewAI provides a powerful framework for orchestrating autonomous agents to solve complex tasks. However, by default, these agents are stateless. By integrating a dedicated long-term memory service like Vertex AI Memory Bank, you can empower your crews to:\n",
    "\n",
    "  * **Maintain Context:** Remember user preferences, historical data, and previous interactions across multiple sessions.\n",
    "  * **Enhance Collaboration:** Allow different agents in a crew to access a shared pool of knowledge about a user or topic.\n",
    "  * **Deliver Personalization:** Build a deep, evolving understanding of users, leading to more effective and personalized assistance.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "61RBz8LLbxCR"
   },
   "source": [
    "## Get started"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "No17Cw5hgx12"
   },
   "source": [
    "### Install required packages\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "tFy3H3aPgx12"
   },
   "outputs": [],
   "source": [
    "%pip install --upgrade --quiet \"crewai\" \"google-cloud-aiplatform>=1.100.0\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dmWOrTJ3gx13"
   },
   "source": [
    "### Authenticate your notebook environment (Colab only)\n",
    "\n",
    "If you're running this notebook on Google Colab, run the cell below to authenticate your environment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "NyKGtVQjgx13"
   },
   "outputs": [],
   "source": [
    "# import sys\n",
    "\n",
    "# if \"google.colab\" in sys.modules:\n",
    "#     from google.colab import auth\n",
    "\n",
    "#     auth.authenticate_user()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "DF4l8DTdWgPY"
   },
   "source": [
    "### Set Google Cloud project information\n",
    "\n",
    "To get started using Vertex AI, you must have an existing Google Cloud project and [enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
    "\n",
    "Learn more about [setting up a project and a development environment](https://cloud.google.com/vertex-ai/docs/start/cloud-environment)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "0Q9k7TmH59fd"
   },
   "outputs": [],
   "source": [
    "import json\n",
    "import os\n",
    "import uuid\n",
    "\n",
    "import vertexai\n",
    "\n",
    "# Set project configuration\n",
    "PROJECT_ID = \"[your-project-id]\"  # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n",
    "if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\":\n",
    "    PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n",
    "    if not PROJECT_ID:\n",
    "        raise ValueError(\"Project ID not found. Please set it in the form above or as the GOOGLE_CLOUD_PROJECT environment variable.\")\n",
    "\n",
    "LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\", \"us-central1\")\n",
    "SERVICE_ACCOUNT_FILE = \"[your-service-account-file]\"  # @param {type:\"string\"}\n",
    "\n",
    "# Set environment variables for CrewAI\n",
    "os.environ[\"DEFAULT_VERTEXAI_PROJECT\"] = PROJECT_ID\n",
    "os.environ[\"DEFAULT_VERTEXAI_LOCATION\"] = LOCATION\n",
    "\n",
    "# Agent configuration\n",
    "MODEL_NAME = \"gemini-2.5-flash\"\n",
    "USER_ID = f\"user_{uuid.uuid4()}\"\n",
    "\n",
    "print(f\"Project: {PROJECT_ID}\")\n",
    "print(f\"Location: {LOCATION}\")\n",
    "print(f\"Session User ID: {USER_ID}\")\n",
    "\n",
    "# Initialize Vertex AI client\n",
    "client = vertexai.Client(\n",
    "    project=PROJECT_ID,\n",
    "    location=LOCATION,\n",
    ")\n",
    "\n",
    "# Load the service account credentials with Vertex AI User permission for the CrewAI LLM\n",
    "with open(SERVICE_ACCOUNT_FILE, \"r\") as file:\n",
    "    vertex_credentials = json.load(file)\n",
    "vertex_credentials_json = json.dumps(vertex_credentials)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5303c05f7aa6"
   },
   "source": [
    "### Import libraries\n",
    "\n",
    "Import the necessary libraries for building our agent crew."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "6fc324893334"
   },
   "outputs": [],
   "source": [
    "from datetime import datetime\n",
    "from typing import Any, Dict, List\n",
    "from crewai import LLM, Agent, Crew, Task\n",
    "from crewai.memory.external.external_memory import ExternalMemory\n",
    "from crewai.memory.storage.interface import Storage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5INaBikJ89-k"
   },
   "source": [
    "### Helper functions\n",
    "\n",
    "These functions create an interactive chat experience. The `run_single_turn` function encapsulates the logic for a single round of conversation, dynamically creating a new `Task` and `Crew` for each user input while reusing the same persistent memory object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Axwi9upN8-4C"
   },
   "outputs": [],
   "source": [
    "def run_single_turn(query: str, agent: Agent, memory: ExternalMemory):\n",
    "    \"\"\"Runs a single conversational turn with the CrewAI agent.\"\"\"\n",
    "    task = Task(\n",
    "        description=f\"Respond to the user's query: '{query}'\",\n",
    "        expected_output=\"A helpful and personalized response based on your memory of the user.\",\n",
    "        agent=agent,\n",
    "    )\n",
    "    crew = Crew(\n",
    "        agents=[agent],\n",
    "        tasks=[task],\n",
    "        external_memory=memory,\n",
    "    )\n",
    "    return crew.kickoff()\n",
    "\n",
    "\n",
    "def chat_loop(agent: Agent, memory: ExternalMemory) -> None:\n",
    "    \"\"\"Main chat interface loop.\"\"\"\n",
    "    print(\"\\nStarting chat. Type 'exit' or 'quit' to end.\")\n",
    "    print(\"Every message will be automatically stored in memory.\\n\")\n",
    "\n",
    "    while True:\n",
    "        user_input = input(\"\\nYou: \")\n",
    "        if user_input.lower() in [\"quit\", \"exit\", \"bye\"]:\n",
    "            print(\"\\nAssistant: Thank you for chatting. Have a great day!\")\n",
    "            break\n",
    "\n",
    "        response = run_single_turn(user_input, agent, memory)\n",
    "        print(f\"\\nAssistant: {response}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "uGTgIVPMA0kA"
   },
   "source": [
    "## Creating the Agent Engine with Memory Bank\n",
    "\n",
    "Vertex AI Memory Bank is part of the Vertex AI Agent Engine. To use Memory Bank, you first create a new Agent Engine instance, which provides the APIs to store and retrieve user-specific memories."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "8RWs1bTXA2ZM"
   },
   "outputs": [],
   "source": [
    "agent_engine = client.agent_engines.create()\n",
    "print(f\"Created Agent Engine: {agent_engine.api_resource.name}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "y8oPi1rEO55v"
   },
   "source": [
    "## (Optional) Initialize User Memory\n",
    "\n",
    "You can optionally pre-seed the Memory Bank with initial facts about a user. This demonstrates how to store information that the agent can reference from the very first interaction.\n",
    "We'll create an initial memory entry for our user. This demonstrates how to store facts that the agent can reference in future conversations.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "B6xRZ6-sg_7L"
   },
   "outputs": [],
   "source": [
    "import_initial_memory_op = client.agent_engines.create_memory(\n",
    "    name=agent_engine.api_resource.name,\n",
    "    fact=f\"The user's name is {USER_ID} and they have a passion for learning new things.\",\n",
    "    scope={\"user_id\": USER_ID},\n",
    ")\n",
    "\n",
    "# Pretty print the created memory\n",
    "memory = import_initial_memory_op.response\n",
    "print(\"Created initial memory:\")\n",
    "print(f\"  Fact: {memory.fact}\")\n",
    "print(f\"  User ID: {memory.scope.get('user_id')}\")\n",
    "print(f\"  Created at: {memory.create_time}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "VZwY1np4TyjF"
   },
   "outputs": [],
   "source": [
    "memories = client.agent_engines.retrieve_memories(\n",
    "    name=agent_engine.api_resource.name,\n",
    "    scope={\"user_id\": USER_ID},\n",
    ")\n",
    "\n",
    "for i, memory in enumerate(memories, 1):\n",
    "    if hasattr(memory, \"memory\") and hasattr(memory.memory, \"fact\"):\n",
    "        print(f\"{i}. {memory.memory.fact}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Ogkz7RTi6_ly"
   },
   "source": [
    "## Integrating Memory Bank with CrewAI\n",
    "\n",
    "To make Vertex AI Memory Bank compatible with CrewAI's memory system, we need to create a bridge between them.\n",
    "\n",
    "### Create a Custom Memory Storage Class\n",
    "\n",
    "The key to this integration is a custom storage class, `VertexAIMemoryBankStorage`, that inherits from CrewAI's `Storage` interface. This class translates CrewAI's generic `save` and `search` methods into specific API calls to the Vertex AI Memory Bank.\n",
    "\n",
    "  * **`save(value, metadata)`**: This method takes a piece of text (`value`) and associated `metadata` from CrewAI. It then calls the `generate_memories` endpoint of the Memory Bank API to save the information.\n",
    "  * **`search(query, **kwargs)`**: This method receives a search `query` from CrewAI. It calls the `retrieve_memories` endpoint, using semantic search if a query is provided, and formats the results into the dictionary structure that CrewAI expects.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "qjpgkilG7HkY"
   },
   "outputs": [],
   "source": [
    "class VertexAIMemoryBankStorage(Storage):\n",
    "    \"\"\"CrewAI storage implementation using Vertex AI Memory Bank.\"\"\"\n",
    "\n",
    "    def __init__(\n",
    "        self,\n",
    "        project: str,\n",
    "        location: str,\n",
    "        agent_engine_name: str,\n",
    "        use_semantic_search: bool = True,\n",
    "        default_user_id: str = \"default_user\",\n",
    "    ):\n",
    "        \"\"\"Initialize Vertex AI Memory Bank storage.\"\"\"\n",
    "        self.project = project\n",
    "        self.location = location\n",
    "        self.agent_engine_name = agent_engine_name\n",
    "        self.use_semantic_search = use_semantic_search\n",
    "        self.default_user_id = default_user_id\n",
    "\n",
    "        # Validate required parameters early\n",
    "        if not all([project, location, agent_engine_name]):\n",
    "            raise ValueError(\"project, location, and agent_engine_name are required\")\n",
    "\n",
    "    def save(self, value: str, metadata: Dict[str, Any]) -> None:\n",
    "        \"\"\"Save a memory to Vertex AI Memory Bank.\"\"\"\n",
    "\n",
    "        client = self._get_client()\n",
    "\n",
    "        # Extract user_id from metadata or use default\n",
    "        user_id = metadata.get(\"user_id\", self.default_user_id)\n",
    "\n",
    "        # Prepare memory event\n",
    "        event = {\n",
    "            \"content\": {\n",
    "                \"parts\": [{\"text\": value}],\n",
    "                \"role\": metadata.get(\"role\", \"user\"),\n",
    "            }\n",
    "        }\n",
    "\n",
    "        # Add timestamp if provided\n",
    "        if \"timestamp\" in metadata:\n",
    "            event[\"timestamp\"] = metadata[\"timestamp\"]\n",
    "\n",
    "        # Generate memory in Vertex AI\n",
    "        client.agent_engines.generate_memories(\n",
    "            name=self.agent_engine_name,\n",
    "            direct_contents_source={\"events\": [event]},\n",
    "            scope={\"user_id\": user_id},\n",
    "            config={\"wait_for_completion\": True},\n",
    "        )\n",
    "\n",
    "    def search(self, query: str, limit: int = 5, **kwargs) -> List[Dict[str, Any]]:\n",
    "        \"\"\"Search memories in Vertex AI Memory Bank.\n",
    "\n",
    "        Args:\n",
    "            query: Search query (used for semantic search if enabled)\n",
    "            limit: Maximum number of results to return\n",
    "            **kwargs: Additional parameters (e.g., user_id)\n",
    "\n",
    "        Returns:\n",
    "            List of memory dictionaries with 'value' and 'metadata' keys\n",
    "        \"\"\"\n",
    "        client = self._get_client()\n",
    "\n",
    "        # Extract user_id from kwargs or use default\n",
    "        user_id = kwargs.get(\"user_id\", self.default_user_id)\n",
    "        scope = {\"user_id\": user_id}\n",
    "\n",
    "        # Determine search method\n",
    "        if self.use_semantic_search and query:\n",
    "            retrieved_memories = client.agent_engines.retrieve_memories(\n",
    "                name=self.agent_engine_name,\n",
    "                scope=scope,\n",
    "                similarity_search_params={\"search_query\": query, \"top_k\": limit},\n",
    "            )\n",
    "        else:\n",
    "            retrieved_memories = client.agent_engines.retrieve_memories(\n",
    "                name=self.agent_engine_name, scope=scope, simple_retrieval_params={}\n",
    "            )\n",
    "\n",
    "        # Transform results to CrewAI format\n",
    "        results = []\n",
    "        for memory in retrieved_memories:\n",
    "            if hasattr(memory, \"memory\") and hasattr(memory.memory, \"fact\"):\n",
    "                result = {\n",
    "                    \"memory\": memory.memory.fact,\n",
    "                    \"metadata\": {\n",
    "                        \"user_id\": user_id,\n",
    "                        \"timestamp\": (\n",
    "                            memory.memory.update_time.isoformat()\n",
    "                            if hasattr(memory.memory, \"update_time\")\n",
    "                            else datetime.now().isoformat()\n",
    "                        ),\n",
    "                    },\n",
    "                }\n",
    "\n",
    "                results.append(result)\n",
    "\n",
    "        return results\n",
    "\n",
    "    def reset(self):\n",
    "        client = self._get_client()\n",
    "        client.agent_engines.delete(name=self.agent_engine_name)\n",
    "\n",
    "    def _get_client(self):\n",
    "        \"\"\"Create a Vertex AI client instance.\n",
    "\n",
    "        Returns a new client for each operation to ensure proper\n",
    "        event loop management in async contexts.\n",
    "        \"\"\"\n",
    "        return vertexai.Client(project=self.project, location=self.location)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Jh5pdQOb7Ook"
   },
   "source": [
    "## Define the CrewAI Components\n",
    "\n",
    "With the storage bridge in place, we can now define the elements of our crew.\n",
    "\n",
    "1.  **Instantiate the LLM**: We'll configure the Gemini model that our agent will use.\n",
    "2.  **Instantiate the Custom Storage and External Memory**: We create an instance of our `VertexAIMemoryBankStorage` class, passing in the necessary project and Agent Engine details. Then we initialize an `ExternalMemory` object configured with our custom `vertex_memory_bank` storage. This equips the entire crew with long-term memory.\n",
    "3.  **Create the Agent**: We define a `Personal Assistant` agent, providing it with a role, goal, backstory, and the configured LLM."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "1aDYi0KQR1k6"
   },
   "outputs": [],
   "source": [
    "# Instantiate the LLM\n",
    "llm = LLM(model=MODEL_NAME, temperature=0.7, vertex_credentials=vertex_credentials_json)\n",
    "\n",
    "# Instantiate your custom storage and the external memory\n",
    "vertex_memory_bank_storage = VertexAIMemoryBankStorage(\n",
    "    project=PROJECT_ID,\n",
    "    location=LOCATION,\n",
    "    agent_engine_name=agent_engine.api_resource.name,\n",
    "    default_user_id=USER_ID,\n",
    ")\n",
    "external_vertex_memory_bank = ExternalMemory(storage=vertex_memory_bank_storage)\n",
    "\n",
    "# Create a personal assistant agent\n",
    "assistant = Agent(\n",
    "    role=\"Personal Assistant\",\n",
    "    goal=\"Remember user information and provide personalized help\",\n",
    "    backstory=\"You are a helpful assistant with perfect memory of past conversations.\",\n",
    "    llm=llm,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "c4WVP3nuaIV-"
   },
   "source": [
    "## Interacting with the Agent\n",
    "\n",
    "Now, let's interact with our memory-enabled agent. Try the following phrases to see how the agent builds and uses its memory.\n",
    "\n",
    "```\n",
    "You: Hi\n",
    "You: I work as an agent engineer\n",
    "You: I love hiking and have a dog named Max\n",
    "You: I'm working on a recommendation system project\n",
    "You: What do you remember about me?\n",
    "You: Bye\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "-tqSiFUzaKBC"
   },
   "outputs": [],
   "source": [
    "chat_loop(assistant, external_vertex_memory_bank)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "6nbPcSzu7-Ol"
   },
   "source": [
    "## Check for Stored Memories\n",
    "\n",
    "After the run, we can query the Memory Bank directly to confirm that the information from our latest interaction (\"software engineer,\" \"love hiking\") has been successfully saved."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "r-0g4fvI8BHZ"
   },
   "outputs": [],
   "source": [
    "memories = client.agent_engines.retrieve_memories(\n",
    "    name=agent_engine.api_resource.name,\n",
    "    scope={\"user_id\": USER_ID},\n",
    ")\n",
    "\n",
    "for i, memory in enumerate(memories, 1):\n",
    "    if hasattr(memory, \"memory\") and hasattr(memory.memory, \"fact\"):\n",
    "        print(f\"{i}. {memory.memory.fact}\")\n",
    "\n",
    "print(f\"\\nTotal memories stored: {len(list(memories))}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "2a4e033321ad"
   },
   "source": [
    "## Cleaning Up\n",
    "\n",
    "To avoid incurring ongoing charges to your Google Cloud account for the resources used, it is important to delete the Agent Engine instance when you are finished."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "3p_JZNCq8QEy"
   },
   "outputs": [],
   "source": [
    "delete_engine = True\n",
    "\n",
    "if delete_engine:\n",
    "    client.agent_engines.delete(name=agent_engine.api_resource.name, force=True)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "get_started_with_memory_bank_crewai.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
