From d91743b0a5bc2174edad34c4e48df558d539b41e Mon Sep 17 00:00:00 2001 From: Hemanand Date: Wed, 15 Jul 2026 11:59:07 +0530 Subject: [PATCH] fix: remove tenant account setup and fastapi request library --- ...rial_deploy_your_containerised_agent.ipynb | 194 ++---------------- 1 file changed, 17 insertions(+), 177 deletions(-) diff --git a/agents/agent_engine/tutorial_deploy_your_containerised_agent.ipynb b/agents/agent_engine/tutorial_deploy_your_containerised_agent.ipynb index 6de82f47d23..807230ba7f8 100644 --- a/agents/agent_engine/tutorial_deploy_your_containerised_agent.ipynb +++ b/agents/agent_engine/tutorial_deploy_your_containerised_agent.ipynb @@ -192,7 +192,7 @@ "\n", "# fmt: off\n", "PROJECT_ID = \"\" # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n", - "LOCATION = \"\" # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n", + "LOCATION = \"\" # @param {type: \"string\", placeholder: \"us-central1\", isTemplate: true}\n", "MODEL = \"gemini-3.1-flash-lite\" # @param {type: \"string\", placeholder: \"[gemini-3.1-flash-lite]\", isTemplate: true}\n", "MODEL_REGION = \"global\" # @param {type: \"string\", placeholder: \"[global]\", isTemplate: true}\n", "# fmt: on\n", @@ -368,11 +368,11 @@ "import json\n", "import logging\n", "import os\n", + "from typing import Any, Dict, Optional\n", "import uvicorn\n", "import vertexai\n", "from weather_agent.agent import root_agent\n", - "from fastapi import FastAPI, encoders, responses\n", - "from pydantic import BaseModel\n", + "from fastapi import FastAPI, encoders, responses, Request\n", "from vertexai import agent_engines\n", "\n", "app = FastAPI()\n", @@ -382,19 +382,10 @@ "LOCATION = config_json[\"LOCATION\"]\n", "MODEL_REGION = config_json[\"MODEL_REGION\"]\n", "\n", - "class QueryRequest(BaseModel):\n", - " input: dict | None = None\n", - " class_method: str | None = None\n", - "\n", - "vertexai.init(\n", - " project=PROJECT_ID,\n", - " location=MODEL_REGION,\n", - ")\n", - "\n", + "vertexai.init(project=PROJECT_ID, location=MODEL_REGION)\n", "adk_app = agent_engines.AdkApp(agent=root_agent)\n", "\n", "def _encode_chunk_to_json(chunk):\n", - " \"\"\"Encodes a chunk to a JSON string with a newline.\"\"\"\n", " try:\n", " json_chunk = encoders.jsonable_encoder(chunk)\n", " return json.dumps(json_chunk) + \"\\n\"\n", @@ -416,25 +407,26 @@ " return invocation_callable(**invocation_payload)\n", "\n", "@app.post(\"/api/reasoning_engine\")\n", - "async def query(request: QueryRequest) -> responses.JSONResponse:\n", - " method = getattr(adk_app, request.class_method)\n", - " output = await _invoke_callable_or_raise(method, request.input or {})\n", - "\n", + "async def query(request: Request) -> responses.JSONResponse:\n", + " request_json = await request.json()\n", + " class_method = request_json.get(\"class_method\")\n", + " input_val = request_json.get(\"input\")\n", + " method = getattr(adk_app, class_method)\n", + " output = await _invoke_callable_or_raise(method, input_val or {})\n", " try:\n", " json_serialized_content = encoders.jsonable_encoder({\"output\": output})\n", " except ValueError as encoding_error:\n", - " logging.exception(\n", - " \"FastAPI could not JSON-encode the response from invocation method\"\n", - " \" %s. Error: %s. Invocation method's original response: %r\",\n", - " request.class_method, encoding_error, output,\n", - " )\n", + " logging.exception(\"Failed to encode response\")\n", " raise encoding_error\n", " return responses.JSONResponse(content=json_serialized_content)\n", "\n", "@app.post(\"/api/stream_reasoning_engine\")\n", - "async def stream_query(request: QueryRequest) -> responses.StreamingResponse:\n", - " method = getattr(adk_app, request.class_method)\n", - " output = await _invoke_callable_or_raise(method, request.input or {})\n", + "async def stream_query(request: Request) -> responses.StreamingResponse:\n", + " request_json = await request.json()\n", + " class_method = request_json.get(\"class_method\")\n", + " input_val = request_json.get(\"input\")\n", + " method = getattr(adk_app, class_method)\n", + " output = await _invoke_callable_or_raise(method, input_val or {})\n", " return responses.StreamingResponse(\n", " content=json_generator(output),\n", " media_type=\"application/json\",\n", @@ -685,158 +677,6 @@ " ./weather-agent-code" ] }, - { - "cell_type": "markdown", - "metadata": { - "id": "eZDioJLZLUBw" - }, - "source": [ - "### Tenant Service Account - Identification & Permissions" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "7DtrAeZeQt8N" - }, - "source": [ - "A tenant service account (or tenant service agent) is a managed service account created and maintained by Google to perform actions on your behalf within a tenant project. It allows managed Google services to interact with your resources securely without requiring manual user credentials.
\n", - "\n", - "In this section, let's identify the tenant service account and grant the necessary permissions needed to access the container image from the Artifact Registry for the containerized agent deployment.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "3Yjb7Pl_Nhei" - }, - "outputs": [], - "source": [ - "!mkdir -p tenant_sa_setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "5k5PTRHENoDK" - }, - "outputs": [], - "source": [ - "%%writefile tenant_sa_setup/requirements.txt\n", - "google-cloud-aiplatform[agent_engines]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "IynotT-8NscP" - }, - "outputs": [], - "source": [ - "%%writefile tenant_sa_setup/my_agent.py\n", - "class MetadataAgent:\n", - "\n", - " def query(self):\n", - " import requests\n", - " url = \"http://metadata.google.internal/computeMetadata/v1/project/numeric-project-id\"\n", - " try:\n", - " response = requests.get(url, headers={\"Metadata-Flavor\": \"Google\"})\n", - " response.raise_for_status()\n", - " return f\"service-{response.text}@serverless-robot-prod.iam.gserviceaccount.com\"\n", - " except Exception:\n", - " return None\n", - "\n", - "root_agent = MetadataAgent()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "c8lSh3sTN6UZ" - }, - "outputs": [], - "source": [ - "tenant_sa_agent = client.agent_engines.create(\n", - " config={\n", - " \"source_packages\": [\"tenant_sa_setup\"],\n", - " \"entrypoint_module\": \"tenant_sa_setup.my_agent\",\n", - " \"entrypoint_object\": \"root_agent\",\n", - " \"requirements_file\": \"tenant_sa_setup/requirements.txt\",\n", - " \"class_methods\": [{\"api_mode\": \"\", \"name\": \"query\"}],\n", - " },\n", - ")\n", - "\n", - "tenant_sa_agent" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "e38a4eaa6859" - }, - "source": [ - "Let's copy the value of the tenant service account indicated by the cell containing `tenant_sa_agent.query()` into the variable `TENANT_SERVICE_ACCOUNT` present in the cell below." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "PXYsywieN9ou" - }, - "outputs": [], - "source": [ - "# Your tenant service account in the format \"service-{number}@serverless-robot-prod.iam.gserviceaccount.com\"\n", - "TENANT_SERVICE_ACCOUNT = tenant_sa_agent.query()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "pBZqAEmAN_jx" - }, - "outputs": [], - "source": [ - "# Delete the agent.\n", - "tenant_sa_agent.delete(force=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "mnSbrHt4UEZh" - }, - "source": [ - "Grant the Artifact Registry reader role to the Tenant Service Account." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "jdRssoqTOSNL" - }, - "outputs": [], - "source": [ - "!gcloud projects add-iam-policy-binding $PROJECT_NUMBER \\\n", - " --member=\"serviceAccount:$TENANT_SERVICE_ACCOUNT\" \\\n", - " --role=\"roles/artifactregistry.reader\" --condition=None" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5FT8LNYTqBos" - }, - "source": [ - "❗ Additionally, if your Organization enforces the `iam.allowedPolicyMemberDomains` organization policy constraint, you need to allow the Google's customer domain before adding the permissions to the Tenant Service account. For detailed instructions, check [Tenant Service Account Setup Documentation](https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/runtime/setup#tenant_service_account)" - ] - }, { "cell_type": "markdown", "metadata": {