Como implantar um app de front-end do Gradio que chama um agente do ADK de back-end, ambos executados no Cloud Run

1. Introdução

Visão geral

Neste codelab, você vai implantar um agente do ADK no Cloud Run como um serviço de back-end e, em seguida, implantar um front-end do gradio para o agente do ADK como um segundo serviço do Cloud Run. Este codelab mostra como exigir autenticação no serviço de agente do ADK e fazer chamadas autenticadas para ele no serviço de front-end do Gradio.

O que você vai aprender

  • Como implantar um agente do ADK no Cloud Run
  • Como implantar um app do Gradio no Cloud Run
  • Como fazer chamadas autenticadas de serviço a serviço no Cloud Run

2. Ativar APIs

Primeiro, defina seu projeto do Google Cloud.

gcloud config set project <YOUR_PROJECT_ID>

Para confirmar seu projeto do Google Cloud, execute o seguinte comando:

gcloud config get-value project

Este codelab exige a ativação das seguintes APIs:

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

3. Configuração e requisitos

Nesta seção, você vai criar algumas contas de serviço e conceder a elas os papéis do IAM adequados. Cada serviço do Cloud Run tem uma conta de serviço própria.

Primeiro, defina as variáveis de ambiente para este codelab, que serão usadas ao longo dele.

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"

Em seguida, crie a conta de serviço para o agente do ADK.

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

e conceda à conta de serviço do ADK o papel de "Usuário da Vertex AI".

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

Agora, crie a conta de serviço para o front-end do Gradio.

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

Conceda ao front-end do Gradio o papel de invocador do Cloud Run, que permite chamar o agente do ADK hospedado no Cloud Run.

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

4. Criar um app ADK

Na próxima etapa, você vai criar o código para o aplicativo de início rápido do ADK.

Observação: no final do laboratório, a estrutura do arquivo vai ficar assim:

- 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

Primeiro, crie um diretório para o codelab geral

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

Agora, crie um diretório para o serviço do agente do ADK.

mkdir multi_tool_agent && cd multi_tool_agent

Crie um arquivo __init__.py com o seguinte conteúdo:

from . import agent

Crie um arquivo requirements.txt:

google-adk

Crie um arquivo chamado 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. Implantar o agente do ADK

Nesta seção, você vai implantar o agente do ADK no Cloud Run. Em seguida, você vai verificar se a implantação funcionou usando a interface da Web de desenvolvimento fornecida pelo ADK. Por fim, você vai precisar de chamadas autenticadas para esse serviço.

Navegue até a pasta mãe.

OBSERVAÇÃO:o código do agente do ADK precisa incluir a pasta multi_tool_agent como pasta raiz.

cd ..

Primeiro, crie o serviço do Cloud Run:

OBSERVAÇÃO: o --with_ui é opcional para testar com a interface de desenvolvimento, conforme mostrado em uma etapa futura:

OBSERVAÇÃO: o comando -- permite transmitir flags da linha de comando para o comando gcloud run deploy subjacente.

OBSERVAÇÃO: o uvx --from executa um comando do pacote google-adk. O uvx cria um ambiente virtual temporário, instala o google-adk nele, executa o comando especificado e depois desativa o ambiente.

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

Em seguida, salve o URL como uma variável de ambiente que você vai usar na segunda parte deste codelab.

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

Agora, teste o agente

Abra o URL do serviço no navegador da Web e pergunte tell me about the weather in new york. Você vai receber uma resposta semelhante a "O tempo em Nova York está ensolarado com uma temperatura de 25 graus Celsius (77 graus Fahrenheit)".

Por fim, proteja o agente

Agora vamos proteger o acesso ao agente. Na próxima seção, você vai implantar um serviço do Cloud Run que faz uma chamada autenticada para esse serviço de back-end.

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

6. Implantar um front-end do Gradio

Nesta etapa, você vai criar um front-end do Gradio para seu agente do ADK.

Observação: você pode ter o app do Gradio no mesmo serviço que o agente do ADK. Este codelab oferece dois serviços separados para mostrar como fazer chamadas autenticadas de serviço para serviço no Cloud Run.

Primeiro, crie um app ao lado da pasta multi_tool_agent.

mkdir gradio-frontend && cd gradio-frontend

Em seguida, crie um arquivo requirements.txt que contenha o seguinte:

gradio
requests
google-auth

Agora crie um arquivo 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. Implante e teste seu app do Gradio

Nesta etapa, você vai implantar o app gradio de front-end no Cloud Run.

Verifique se você está no diretório do app gradio.

pwd

Você vai ver codelab-gradio-adk/gradio-frontend

Agora implante o app do Gradio.

Observação: embora esse serviço de front-end do Gradio seja um site disponível publicamente, o serviço de back-end exige autenticação. Para ilustrar por que você pode querer fazer isso, adicione a autenticação de usuário (por exemplo, o Firebase Auth) a esse serviço de front-end e permita que apenas usuários conectados façam chamadas para o serviço de back-end.

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

Depois de implantado, pergunte what's the weather in new york? e você vai receber uma resposta semelhante a The weather in New York is sunny with a temperature of 25 degrees Celsius (77 degrees Fahrenheit)..

8. Parabéns!

Parabéns por concluir o codelab!

Recomendamos que você consulte a documentação sobre hospedagem de apps e agentes de IA.

O que aprendemos

  • Como implantar um agente do ADK no Cloud Run
  • Como implantar um app do Gradio no Cloud Run
  • Como fazer chamadas autenticadas de serviço a serviço no Cloud Run

9. Limpar

Para evitar cobranças acidentais, por exemplo, se os serviços do Cloud Run forem invocados mais vezes do que sua alocação mensal de invocações do Cloud Run no nível sem custo financeiro, exclua o serviço do Cloud Run criado na etapa 6.

Para excluir os serviços do Cloud Run, acesse o console do Cloud Run em https://console.cloud.google.com/run e exclua os serviços my-adk-gradio-frontend e adk-agent-cr.

Para excluir todo o projeto, acesse Gerenciar recursos, selecione o projeto criado na etapa 2 e escolha "Excluir". Se você excluir o projeto, vai precisar mudar de projeto no SDK do Cloud. Para conferir a lista de todos os projetos disponíveis, execute gcloud projects list.