{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "li-5uLZMOWbm"
      },
      "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": "iY-d5cexcFzH"
      },
      "source": [
        "# Get started with Sessions and Memory Bank for ADK agents in Cloud Run\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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.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%2Fagents%2Fcloud_run%2Fagents_with_memory%2Fget_started_with_memory_for_adk_in_cloud_run.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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://www.svgrepo.com/show/512317/github-142.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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.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/agents/cloud_run/agents_with_memory/get_started_with_memory_for_adk_in_cloud_run.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": "OHNf0Rg1cHqf"
      },
      "source": [
        "| Author(s) |\n",
        "| --- |\n",
        "| [Vlad Kolesnikov](https://github.com/vladkol) |"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qlXbr9YbMyzc"
      },
      "source": [
        "## Overview\n",
        "\n",
        "This tutorial demonstrates how to build agents with short-term and long-term memory using\n",
        "ADK with [Vertex AI Agent Engine Sessions](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/sessions/overview?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog) service and\n",
        "[Vertex AI Agent Engine Memory Bank](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/overview?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog),\n",
        "and deploy them to [Cloud Run](https://cloud.google.com/run/docs/overview/what-is-cloud-run?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog).\n",
        "\n",
        "This tutorial will cover:\n",
        "* Registering agents with Vertex AI Agent Engine.\n",
        "* Storing ADK session data with Vertex AI Sessions.\n",
        "* Generating memories with ADK and Agent Engine Memory Bank.\n",
        "* Retrieving memories with ADK and Agent Engine Memory Bank.\n",
        "* Deploying agents to Cloud Run."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HSSuQi5wS-AY"
      },
      "source": [
        "## Get started"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ngEAiXw8cQRt"
      },
      "source": [
        "### Install Google Gen AI SDK and other required packages\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZNg0utat73eG"
      },
      "outputs": [],
      "source": [
        "%pip install google-adk google-cloud-aiplatform --upgrade --quiet"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mbeaDydxcdEo"
      },
      "source": [
        "### Set Google Cloud project information\n",
        "\n",
        "To get started using Vertex AI, you must have an existing Google Cloud project.\n",
        "\n",
        "Learn more about [setting up a project and a development environment](https://cloud.google.com/vertex-ai/docs/start/cloud-environment?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "70a32813d298"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "\n",
        "# fmt: off\n",
        "PROJECT_ID = \"[your-project-id]\"  # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n",
        "LOCATION = \"us-central1\" # @param {type: \"string\", placeholder: \"us-central1\", isTemplate: true}\n",
        "# fmt: on\n",
        "if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\":\n",
        "    raise ValueError(\"Please specify your Project Id.\")\n",
        "\n",
        "if not LOCATION:\n",
        "    LOCATION = \"us-central1\"\n",
        "\n",
        "# Set environment variables for ADK.\n",
        "os.environ[\"GOOGLE_GENAI_USE_VERTEXAI\"] = \"TRUE\"\n",
        "os.environ[\"GOOGLE_CLOUD_PROJECT\"] = PROJECT_ID\n",
        "os.environ[\"GOOGLE_CLOUD_LOCATION\"] = LOCATION"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bbArJaMNcWVz"
      },
      "source": [
        "### Authenticate with your Google Cloud account\n",
        "\n",
        "Depending on your Jupyter environment, you may have to manually authenticate. Run the cell below."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "oMmt34WM-08o"
      },
      "outputs": [],
      "source": [
        "!gcloud auth print-identity-token -q &> /dev/null || gcloud auth login --project=\"{PROJECT_ID}\" --update-adc --quiet"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3da78fbfa6b8"
      },
      "source": [
        "### Enable APIs\n",
        "\n",
        "Enable Cloud Run and Vertex AI APIs"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "801984a5778b"
      },
      "outputs": [],
      "source": [
        "!gcloud services enable run.googleapis.com aiplatform.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com --project=\"{PROJECT_ID}\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "01e088bd48e7"
      },
      "source": [
        "### Initialize Vertex AI Client"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "PKZ_ad_g_AuU"
      },
      "outputs": [],
      "source": [
        "import vertexai\n",
        "\n",
        "client = vertexai.Client(project=PROJECT_ID, location=LOCATION)  # type: ignore"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6cb2fa6c7d38"
      },
      "source": [
        "## ADK Sessions as short-term memory\n",
        "\n",
        "Every user interaction with an ADK agent gets a session, and that session is managed by the ADK BaseSessionService.\n",
        "Each session acts as a history of a multi-turn conversation, just like a chat,\n",
        "and contains important fields, like the session ID, user ID,\n",
        "event history (the conversation thread), and the [state](https://google.github.io/adk-docs/sessions/state/).\n",
        "\n",
        "By default, the ADK uses `InMemorySessionService`, and writes session data in memory. This means that if ADK's runner is shut down, all session data is lost.\n",
        "And if you're running a scaled, production-grade agent with ADK, with multiple instances of your ADK agent,\n",
        "you can't guarantee that user requests will always hit the same instance.\n",
        "This means that if request 1 goes to instance A, and request 2 goes to instance B, instance B won't have the in-memory session state stored inside instance A.\n",
        "\n",
        "So for production-grade agents, you should store session data outside of the agent's runtime.\n",
        "ADK provides two ways of doing this:\n",
        "\n",
        "* `DatabaseSessionService`: stores session data in a SQL database, like SQLLite, MySQL, or PostgreSQL.\n",
        "* `VertexAISessionService`: a scalable fully-managed [Agent Engine Sessions service](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/sessions/overview?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog).\n",
        "\n",
        "This notebook shows how to get started with `VertexAISessionService`."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "W0n_JRrHNUUX"
      },
      "source": [
        "## Long-term Memory for ADK Agents\n",
        "\n",
        "ADK offers foundation for long-term memory services - an interface for creating and searching for memories. The [`BaseMemoryService`](https://github.com/google/adk-python/blob/main/src/google/adk/memory/base_memory_service.py) defines the interface for managing this searchable, long-term knowledge store. Its primary responsibilities are:\n",
        "\n",
        "* Ingesting Information (`add_session_to_memory`): Taking the contents of a (usually completed) Session and adding relevant information to the long-term knowledge store.\n",
        "* Searching Information (`search_memory`): Allowing an agent (typically via a Tool) to query the knowledge store and retrieve relevant snippets or context based on a search query.\n",
        "\n",
        "ADK also provides 2 built-in memory tools:\n",
        "\n",
        "* PreloadMemory: Always retrieve memory at the beginning of each turn (similar to a callback).\n",
        "* LoadMemory: Retrieve memory when your agent decides it would be helpful.\n",
        "\n",
        "By default, ADK doesn't use any long-term memory service.\n",
        "For prototyping and simple testing scenarios where persistence isn't required, you can leverage\n",
        "[`InMemoryMemoryService`](https://github.com/google/adk-python/blob/main/src/google/adk/memory/in_memory_memory_service.py).\n",
        "It persists **all** information in-memory, and just like `InMemorySessionService`, if ADK's runner is shut down, all session data is lost.\n",
        "With in-memory sessions, the events are not condensed, and information is not extracted from them.\n",
        "\n",
        "Another Memory Service that ADK supports is [`VertexAiMemoryBankService`](https://github.com/google/adk-python/blob/main/src/google/adk/memory/vertex_ai_memory_bank_service.py).\n",
        "Vertex AI Memory Bank stores extracted memories, and only persists *meaningful* information. Not all conversations will result in generated memories. Additionally, the information will be condensed to individual, self-contained memories."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mTuaUZ1DWG7L"
      },
      "source": [
        "### Getting started with `VertexAISessionService` and `VertexAiMemoryBankService`\n",
        "\n",
        "To get started with Agent Engine Sessions and Memory Bank, you need to first create an Agent Engine. This only takes a few seconds.\n",
        "\n",
        "After that, you can start using sessions service and memory bank provided by Vertex AI through respective ADK components."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "rZP-0IVaQ5_N"
      },
      "outputs": [],
      "source": [
        "from google.adk.memory import VertexAiMemoryBankService\n",
        "from google.adk.sessions import VertexAiSessionService\n",
        "\n",
        "AGENT_NAME = \"weather_agent\"\n",
        "\n",
        "agent_engine = client.agent_engines.create(\n",
        "    config={\n",
        "        \"display_name\": AGENT_NAME,\n",
        "        \"context_spec\": {\n",
        "            \"memory_bank_config\": {\n",
        "                \"generation_config\": {\n",
        "                    \"model\": f\"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-2.5-flash\"\n",
        "                }\n",
        "            }\n",
        "        },\n",
        "    }\n",
        ")\n",
        "\n",
        "agent_engine_id = agent_engine.api_resource.name.split(\"/\")[-1]\n",
        "\n",
        "session_service = VertexAiSessionService(\n",
        "    project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id\n",
        ")\n",
        "memory_service = VertexAiMemoryBankService(\n",
        "    project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id\n",
        ")\n",
        "\n",
        "print(f\"Agent Engine Id: {agent_engine_id}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9ec906fad53e"
      },
      "source": [
        "Notice that we don't deploy the agent to Agent Engine service.\n",
        "Instead, we only register an Agent Engine resource so that Vertex AI Session Service and Memory Bank can use it to store respective sessions and memories\n",
        "in association to the agent."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rstDOvEhWogm"
      },
      "source": [
        "## Using Sessions and Memory in ADK agents\n",
        "\n",
        "Now, let's link our agent to Sessions and Memory, so that memories can be fetched by your agent and used for inference. This allows your agent to remember information from prior sessions in a new, empty session.\n",
        "\n",
        "You can use ADK's built-in tools to fetch memories and incorporate them in the prompt.\n",
        "When using the built-in memory tools, it's important to provide both a memory tool when creating your Agent and a memory service when defining your Runner.\n",
        "Similarly, the Runner also needs a session service.\n",
        "\n",
        "The code below demonstrates a simple weather agent with a special callback (`after_agent_callback` argument of Agent) that ensures generating memories after each agent turn.\n",
        "`add_session_to_memory` function takes care of that.\n",
        "\n",
        "We're also using `PreloadMemoryTool`, so the retrieved memories will be appended to the System Instructions."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "l1ENgxmkWnVl"
      },
      "outputs": [],
      "source": [
        "%%writefile agent.py\n",
        "\n",
        "from typing import Optional\n",
        "\n",
        "from google.adk.agents import Agent\n",
        "from google.adk.agents.callback_context import CallbackContext\n",
        "from google.adk.tools.preload_memory_tool import PreloadMemoryTool\n",
        "from google.genai import types\n",
        "\n",
        "\n",
        "def get_weather(city: str) -> dict:\n",
        "    \"\"\"Retrieves the current weather report for a specified city.\n",
        "\n",
        "    Args:\n",
        "        city (str): The name of the city for which to retrieve the weather report.\n",
        "\n",
        "    Returns:\n",
        "        dict: status and result or error msg.\n",
        "    \"\"\"\n",
        "    if city.lower() == \"new york\":\n",
        "        return {\n",
        "            \"status\": \"success\",\n",
        "            \"report\": (\n",
        "                \"The weather in New York is sunny with a temperature of 25 degrees\"\n",
        "                \" Celsius (77 degrees Fahrenheit).\"\n",
        "            ),\n",
        "        }\n",
        "    else:\n",
        "        return {\n",
        "            \"status\": \"error\",\n",
        "            \"error_message\": f\"Weather information for '{city}' is not available.\",\n",
        "        }\n",
        "\n",
        "\n",
        "\n",
        "async def add_session_to_memory(\n",
        "        callback_context: CallbackContext\n",
        ") -> Optional[types.Content]:\n",
        "    \"\"\"Automatically save completed sessions to memory bank \"\"\"\n",
        "    if hasattr(callback_context, \"_invocation_context\"):\n",
        "        invocation_context = callback_context._invocation_context\n",
        "        if invocation_context.memory_service:\n",
        "            await invocation_context.memory_service.add_session_to_memory(\n",
        "                invocation_context.session\n",
        "            )\n",
        "\n",
        "\n",
        "root_agent = Agent(\n",
        "    name=\"weather_agent\",\n",
        "    model=\"gemini-2.5-flash\",\n",
        "    description=(\n",
        "        \"Agent to answer questions about weather in a city.\"\n",
        "    ),\n",
        "    instruction=(\n",
        "        \"You are a helpful agent who can answer user questions about weather in a city.\"\n",
        "    ),\n",
        "    tools=[\n",
        "        get_weather,\n",
        "        PreloadMemoryTool() # This tool will be automatically executed by ADK\n",
        "    ],\n",
        "    after_agent_callback=add_session_to_memory\n",
        ")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0c3a4eb7e633"
      },
      "source": [
        "## Running the Agent\n",
        "\n",
        "To run the agent, we need an instance of ADK Runner."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "e07398744955"
      },
      "outputs": [],
      "source": [
        "from agent import root_agent  # type: ignore\n",
        "from google.adk.runners import Runner\n",
        "from google.genai import types\n",
        "\n",
        "USER_ID = \"user\"\n",
        "\n",
        "runner = Runner(\n",
        "    app_name=root_agent.name,  # type: ignore\n",
        "    agent=root_agent,\n",
        "    session_service=session_service,\n",
        "    memory_service=memory_service,\n",
        ")\n",
        "\n",
        "\n",
        "async def call_agent(query, runner):\n",
        "    session = await session_service.create_session(\n",
        "        app_name=root_agent.name,  # type: ignore\n",
        "        user_id=USER_ID,\n",
        "    )\n",
        "    content = types.Content(role=\"user\", parts=[types.Part(text=query)])\n",
        "    events = runner.run(\n",
        "        user_id=session.user_id, session_id=session.id, new_message=content\n",
        "    )\n",
        "\n",
        "    for event in events:\n",
        "        if event.is_final_response():\n",
        "            final_response = event.content.parts[0].text\n",
        "            print(\"\\nAgent Response: \", final_response)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "850039367017"
      },
      "source": [
        "`call_agent` is a function that helps us quickly test the agent.\n",
        "\n",
        "Notice that we create a new session every time we make a request.\n",
        "Therefore, the underlying LLM will only have access to the user's query itself **and long-term memories loaded by `PreloadMemoryTool`**.\n",
        "\n",
        "First, let's ask the agent a question it knows answer to."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "fTzgPdtU_9Qd"
      },
      "outputs": [],
      "source": [
        "await call_agent(\"What's the weather in New York?\", runner)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "c3857a98b93c"
      },
      "source": [
        "Now, ask a question it cannot answer."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "54732f742877"
      },
      "outputs": [],
      "source": [
        "await call_agent(\"What's the weather in Seattle?\", runner)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0fee2b961a5f"
      },
      "source": [
        "Since the agent only \"knows\" about New York weather, it cannot answer the question.\n",
        "\n",
        "But we can indicate our preference for this situation (Seattle weather)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "4840449b4300"
      },
      "outputs": [],
      "source": [
        "await call_agent(\n",
        "    \"Whenever asked about weather in Seattle, answer that it's raining as usual.\",\n",
        "    runner,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6b7b3d195cf8"
      },
      "source": [
        "Now, try again with Seattle."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "c618d309c12b"
      },
      "outputs": [],
      "source": [
        "await call_agent(\"What's the weather in Seattle?\", runner)\n",
        "\n",
        "print(\n",
        "    f\"\\nAgent Memories are here: https://console.cloud.google.com/vertex-ai/agents/locations/{LOCATION}/agent-engines/{agent_engine_id}/memories?project={PROJECT_ID}\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2afd3ac38b59"
      },
      "source": [
        "And you got the answer!\n",
        "\n",
        "Memory Bank generated a memory that carries across sessions."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "834ff28ca124"
      },
      "source": [
        "## Deploying the Agent to Cloud Run\n",
        "\n",
        "Deploying your agent to Cloud Run is a matter of running a single `adk deploy cloud_run`\n",
        "command.\n",
        "\n",
        "For using Sessions and Memory Bank, the important parameters are:\n",
        "\n",
        "```bash\n",
        "--session_service_uri=\"agentengine://AGENT_ENGINE_ID\"\n",
        "--memory_service_uri=\"agentengine://AGENT_ENGINE_ID\"\n",
        "```\n",
        "\n",
        "Run the command below to deploy the agent.\n",
        "\n",
        "> Parameters `--with_ui` and `--allow-unauthenticated` are added to make testing\n",
        "the agent easier with ADK Web UI.\n",
        ">\n",
        "> It's recommended to configure the service with authentication required (replace `--allow-unauthenticated` with `--no-allow-unauthenticated`), \n",
        "> and instead of ADK Web UI, to expose [ADK REST API endpoint](https://google.github.io/adk-docs/get-started/testing/#api-endpoints)\n",
        "or [A2A](https://google.github.io/adk-docs/a2a/quickstart-exposing/) endpoint (`--a2a` parameter)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "bcbff78ce962"
      },
      "outputs": [],
      "source": [
        "SERVICE_NAME=\"weather-agent\"\n",
        "\n",
        "!adk deploy cloud_run --project {PROJECT_ID} --region {LOCATION} \\\n",
        "    --service_name {SERVICE_NAME} \\\n",
        "    --session_service_uri=agentengine://{agent_engine_id} \\\n",
        "    --memory_service_uri=agentengine://{agent_engine_id} \\\n",
        "    --app_name {AGENT_NAME} \\\n",
        "    --with_ui \\\n",
        "    . \\\n",
        "    -- --allow-unauthenticated \\\n",
        "    --no-user-output-enabled \\\n",
        "    && echo \"Success!\" \\\n",
        "    && echo $(gcloud run services describe \\\n",
        "        {SERVICE_NAME} \\\n",
        "        --project {PROJECT_ID} --region {LOCATION} \\\n",
        "        --format 'value(status.url)')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "d9aca8c1e64d"
      },
      "source": [
        "You can now open the Agent's Web UI using Cloud Run Service URL."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "56e145fabf17"
      },
      "source": [
        "## Cleaning up\n",
        "\n",
        "It's always a best practice in cloud development to clean up resources you no longer need to avoid incurring unexpected costs."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "94e522751bf1"
      },
      "outputs": [],
      "source": [
        "delete_resources = True\n",
        "\n",
        "if delete_resources:\n",
        "    # Delete Agent Engine resource\n",
        "    client.agent_engines.delete(\n",
        "        name=f\"projects/{PROJECT_ID}/locations/{LOCATION}/reasoningEngines/{agent_engine_id}\",\n",
        "        force=True,\n",
        "    )\n",
        "    # Delete Cloud Run service\n",
        "    !gcloud run services delete $SERVICE_NAME --project $PROJECT_ID --region $LOCATION"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9d1414f9eae4"
      },
      "source": [
        "## References\n",
        "\n",
        "* [Agent Development Kit documentation](https://google.github.io/adk-docs/).\n",
        "* [Vertex AI Agent Engine Memory Bank documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/overview?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog).\n",
        "* [Vertex AI Agent Engine Sessions documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/sessions/overview?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog).\n",
        "* [Cloud Run documentation](https://cloud.google.com/run/docs/overview/what-is-cloud-run?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog).\n",
        "* [Host AI apps and agents on Cloud Run](https://cloud.google.com/run/docs/ai-agents?utm_campaign=CDR_0xc245fc42_default_b450333586&utm_medium=external&utm_source=blog).\n",
        "* [Deploying ADK agents to Cloud Run](https://google.github.io/adk-docs/deploy/cloud-run/).\n"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "get_started_with_memory_for_adk_in_cloud_run.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
