Déployer une application frontend Gradio qui appelle un agent ADK de backend, tous deux s'exécutant sur Cloud Run

1. Introduction

Présentation

Dans cet atelier de programmation, vous allez déployer un agent ADK sur Cloud Run en tant que service de backend, puis déployer un frontend Gradio pour l'agent ADK en tant que deuxième service Cloud Run. Cet atelier de programmation explique comment exiger l'authentification auprès de votre service d'agent ADK et comment effectuer des appels authentifiés à partir du service de frontend Gradio.

Points abordés

  • Déployer un agent ADK sur Cloud Run
  • Déployer une application Gradio sur Cloud Run
  • Effectuer des appels authentifiés de service à service dans Cloud Run

2. Activer les API

Tout d'abord, définissez votre projet Google Cloud.

gcloud config set project <YOUR_PROJECT_ID>

Vous pouvez confirmer votre projet Google Cloud en exécutant la commande suivante :

gcloud config get-value project

Cet atelier de programmation nécessite l'activation des API suivantes :

gcloud services enable run.googleapis.com \
    compute.googleapis.com \
    run.googleapis.com \
    cloudbuild.googleapis.com \
    artifactregistry.googleapis.com \
    aiplatform.googleapis.com

3. Préparation

Dans cette section, vous allez créer des comptes de service et leur attribuer les rôles IAM appropriés. Chaque service Cloud Run possède son propre compte de service.

Commencez par définir les variables d'environnement pour cet atelier de programmation, qui seront utilisées tout au long de celui-ci.

export PROJECT_ID=<YOUR_PROJECT_ID>
export REGION=<YOUR_REGION>

export SERVICE_ACCOUNT_ADK="adk-agent-cr"
export SERVICE_ACCOUNT_ADDRESS_ADK=$SERVICE_ACCOUNT_ADK@$PROJECT_ID.iam.gserviceaccount.com

export SERVICE_ACCOUNT_GRADIO="adk-agent-gradio"
export SERVICE_ACCOUNT_ADDRESS_GRADIO=$SERVICE_ACCOUNT_GRADIO@$PROJECT_ID.iam.gserviceaccount.com

export AGENT_APP_NAME="multi_tool_agent"

Créez ensuite le compte de service pour l'agent ADK.

gcloud iam service-accounts create $SERVICE_ACCOUNT_ADK \
--display-name="Service account for adk agent on cloud run"

Attribuez le rôle "Utilisateur Vertex AI" au compte de service ADK.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_ADDRESS_ADK" \
  --role="roles/aiplatform.user"

Créez maintenant le compte de service pour l'interface Gradio.

gcloud iam service-accounts create $SERVICE_ACCOUNT_GRADIO \
  --display-name="Service account for gradio frontend cloud run"

Accordez ensuite au frontend Gradio le rôle "Demandeur Cloud Run", qui lui permettra d'appeler l'agent ADK hébergé sur Cloud Run.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_ADDRESS_GRADIO" \
  --role="roles/run.invoker"

4. Créer une application ADK

À l'étape suivante, vous allez créer le code de l'application de démarrage rapide ADK.

Remarque : À la fin de l'atelier, la structure de vos fichiers devrait ressembler à ce qui suit :

- codelab-gradio-adk  <-- you'll deploy the ADK agent from here
  - gradio-frontend
    - app.py
    - requirements.txt
  - multi_tool_agent  <-- you'll deploy the gradio app from here
    - __init__.py
    - agent.py
    - requirements.txt

Commencez par créer un répertoire pour l'atelier de programmation.

mkdir codelab-gradio-adk
cd codelab-gradio-adk

Créez maintenant un répertoire pour le service d'agent ADK.

mkdir multi_tool_agent && cd multi_tool_agent

Créez un fichier __init__.py avec le contenu suivant :

from . import agent

Créez un fichier requirements.txt :

google-adk

Créez un fichier appelé agent.py.

import datetime
from zoneinfo import ZoneInfo
from google.adk.agents import Agent

def get_weather(city: str) -> dict:
    """Retrieves the current weather report for a specified city.

    Args:
        city (str): The name of the city for which to retrieve the weather report.

    Returns:
        dict: status and result or error msg.
    """
    if city.lower() == "new york":
        return {
            "status": "success",
            "report": (
                "The weather in New York is sunny with a temperature of 25 degrees"
                " Celsius (77 degrees Fahrenheit)."
            ),
        }
    else:
        return {
            "status": "error",
            "error_message": f"Weather information for '{city}' is not available.",
        }


def get_current_time(city: str) -> dict:
    """Returns the current time in a specified city.

    Args:
        city (str): The name of the city for which to retrieve the current time.

    Returns:
        dict: status and result or error msg.
    """

    if city.lower() == "new york":
        tz_identifier = "America/New_York"
    else:
        return {
            "status": "error",
            "error_message": (
                f"Sorry, I don't have timezone information for {city}."
            ),
        }

    tz = ZoneInfo(tz_identifier)
    now = datetime.datetime.now(tz)
    report = (
        f'The current time in {city} is {now.strftime("%Y-%m-%d %H:%M:%S %Z%z")}'
    )
    return {"status": "success", "report": report}


root_agent = Agent(
    name="weather_time_agent",
    model="gemini-2.5-flash",
    description=(
        "Agent to answer questions about the time and weather in a city."
    ),
    instruction=(
        "You are a helpful agent who can answer user questions about the time and weather in a city."
    ),
    tools=[get_weather, get_current_time],
)

5. Déployer l'agent ADK

Dans cette section, vous allez déployer l'agent ADK sur Cloud Run. Vous vérifierez ensuite que le déploiement a fonctionné à l'aide de l'interface utilisateur Web de développement fournie par ADK. Enfin, vous aurez besoin d'appels authentifiés à ce service.

Accédez au dossier parent.

REMARQUE : Le code de l'agent ADK doit inclure le dossier multi_tool_agent comme dossier racine.

cd ..

Commencez par créer le service Cloud Run :

REMARQUE : --with_ui est facultatif pour effectuer des tests avec l'UI de développement, comme indiqué dans une prochaine étape :

REMARQUE : La commande -- vous permet de transmettre des indicateurs de ligne de commande à la commande gcloud run deploy sous-jacente.

REMARQUE : uvx --from exécute une commande à partir du package google-adk. uvx crée un environnement virtuel temporaire, y installe google-adk, exécute la commande spécifiée, puis supprime l'environnement.

uvx --from google-adk \
adk deploy cloud_run \
    --project=$PROJECT_ID \
    --region=$REGION \
    --service_name=adk-agent-cr \
    --with_ui \
    ./multi_tool_agent \
    -- \
    --service-account=$SERVICE_ACCOUNT_ADDRESS_ADK \
    --allow-unauthenticated

Ensuite, enregistrez l'URL en tant que variable d'environnement que vous utiliserez dans la deuxième partie de cet atelier de programmation.

AGENT_SERVICE_URL=$(gcloud run services describe adk-agent-cr --region $REGION --format 'value(status.url)')

Maintenant, essayez l'agent.

Ouvrez l'URL du service dans votre navigateur Web et posez la question tell me about the weather in new york. Vous devriez obtenir une réponse semblable à "Le temps à New York est ensoleillé, avec une température de 25 degrés Celsius (77 degrés Fahrenheit)."

Enfin, sécurisez l'agent.

Sécurisons maintenant l'accès à l'agent. Dans la section suivante, vous allez déployer un service Cloud Run qui effectue un appel authentifié à ce service de backend.

gcloud run services remove-iam-policy-binding adk-agent-cr \
  --member="allUsers" \
  --role="roles/run.invoker" \
  --region=$REGION

6. Déployer une interface Gradio

Lors de cette étape, vous allez créer une interface utilisateur Gradio pour votre agent ADK.

Remarque : Vous pouvez avoir l'application Gradio dans le même service que l'agent ADK. Cet atelier de programmation fournit deux services distincts pour montrer comment effectuer des appels authentifiés de service à service dans Cloud Run.

Commencez par créer une application à côté du dossier multi_tool_agent.

mkdir gradio-frontend && cd gradio-frontend

Ensuite, créez un fichier requirements.txt contenant les éléments suivants :

gradio
requests
google-auth

Maintenant, créez un fichier app.py.

import gradio as gr
import requests
import json
import uuid
import os
import google.auth.transport.requests
import google.oauth2.id_token

# https://weather-time-service2-392295011265.us-west4.run.app
BASE_URL = os.environ.get("AGENT_SERVICE_URL")

# multi_tool_agent
APP_NAME = os.environ.get("AGENT_APP_NAME")

# Generate a unique user ID for each session of the Gradio app
USER_ID = f"gradio-user-{uuid.uuid4()}"

# API Endpoints
CREATE_SESSION_URL = f"{BASE_URL}/apps/{APP_NAME}/users/{USER_ID}/sessions"
RUN_SSE_URL = f"{BASE_URL}/run_sse"

def get_id_token():
    """Get an ID token to authenticate with the other Cloud Run service."""
    audience = BASE_URL
    request = google.auth.transport.requests.Request()
    id_token = google.oauth2.id_token.fetch_id_token(request, audience)
    return id_token

def create_session() -> str | None:
    """Creates a new session and returns the session ID."""
    try:
        id_token = get_id_token()
        headers = {"Authorization": f"Bearer {id_token}"}
        response = requests.post(CREATE_SESSION_URL, headers=headers)
        response.raise_for_status()
        return response.json().get("id")
    except Exception as e:
        print(f"Error creating session: {e}")
        return None

def query_agent(prompt: str):
    """Sends a prompt to the agent and returns the streamed response."""
    session_id = create_session()
    if not session_id:
        return "Error: Could not create a session."

    id_token = get_id_token()
    headers = {
        "Content-Type": "application/json",
        "Accept": "text/event-stream",
        "Authorization": f"Bearer {id_token}",
    }
    payload = {
        "app_name": APP_NAME,
        "user_id": USER_ID,
        "session_id": session_id,
        "new_message": {"role": "user", "parts": [{"text": prompt}]},
        "streaming": True
    }

    full_response = ""
    try:
        with requests.post(RUN_SSE_URL, headers=headers, json=payload, stream=True) as response:
            response.raise_for_status()
            for chunk in response.iter_lines():
                if chunk and chunk.decode('utf-8').startswith('data:'):
                    json_data = chunk.decode('utf-8')[len('data:'):].strip()
                    try:
                        data = json.loads(json_data)
                        text = data.get("content", {}).get("parts", [{}])[0].get("text", "")
                        if text:
                            full_response = text
                    except json.JSONDecodeError:
                        pass # Ignore chunks that are not valid JSON
        return full_response
    except requests.exceptions.RequestException as e:
        return f"An error occurred: {e}"

iface = gr.Interface(
    fn=query_agent,
    inputs=gr.Textbox(lines=2, placeholder="e.g., What's the weather in new york?"),
    outputs="text",
    title="Weather and Time Agent",
    description="Ask a question about the weather or time in a specific location.",
)

if __name__ == "__main__":
    iface.launch()

7. Déployer et tester votre application Gradio

Dans cette étape, vous allez déployer l'application Gradio de l'interface sur Cloud Run.

Assurez-vous d'être dans le répertoire de l'application Gradio.

pwd

Vous devriez voir codelab-gradio-adk/gradio-frontend

Déployez maintenant votre application Gradio.

Remarque : Bien que ce service d'interface utilisateur Gradio soit un site Web accessible au public, le service de backend nécessite une authentification. Pour illustrer pourquoi vous pourriez vouloir le faire, vous pouvez ajouter l'authentification des utilisateurs (par exemple, Firebase Auth) à ce service frontend, puis n'autoriser que les utilisateurs connectés à effectuer des appels au service backend.

gcloud run deploy my-adk-gradio-frontend \
--source . \
--region $REGION \
--allow-unauthenticated \
--set-env-vars AGENT_SERVICE_URL=$AGENT_SERVICE_URL,AGENT_APP_NAME=$AGENT_APP_NAME \
--service-account=$SERVICE_ACCOUNT_ADDRESS_GRADIO

Une fois déployé, demandez what's the weather in new york? et vous devriez obtenir une réponse semblable à The weather in New York is sunny with a temperature of 25 degrees Celsius (77 degrees Fahrenheit)..

8. Félicitations !

Bravo ! Vous avez terminé cet atelier de programmation.

Nous vous recommandons de consulter la documentation sur l'hébergement d'applications et d'agents d'IA.

Points abordés

  • Déployer un agent ADK sur Cloud Run
  • Déployer une application Gradio sur Cloud Run
  • Effectuer des appels authentifiés de service à service dans Cloud Run

9. Effectuer un nettoyage

Pour éviter des frais involontaires, par exemple si les services Cloud Run sont appelés par inadvertance plus de fois que votre quota mensuel d'appels Cloud Run dans le niveau sans frais, vous pouvez supprimer le service Cloud Run que vous avez créé à l'étape 6.

Pour supprimer les services Cloud Run, accédez à la console Cloud Run à l'adresse https://console.cloud.google.com/run, puis supprimez les services my-adk-gradio-frontend et adk-agent-cr.

Pour supprimer l'intégralité du projet, accédez à Gérer les ressources, sélectionnez le projet que vous avez créé à l'étape 2, puis choisissez "Supprimer". Si vous supprimez le projet, vous devrez changer de projet dans votre SDK Cloud. Vous pouvez afficher la liste de tous les projets disponibles en exécutant gcloud projects list.