1. Força do Destino,
A era do desenvolvimento isolado está chegando ao fim. A próxima onda de evolução tecnológica não é sobre genialidade solitária, mas sobre domínio colaborativo. Criar um único agente inteligente é um experimento fascinante. Criar um ecossistema de agentes robusto, seguro e inteligente, um verdadeiro Agentverse, é o grande desafio para a empresa moderna.
O sucesso nessa nova era exige a convergência de quatro funções essenciais, os pilares fundamentais que sustentam qualquer sistema de agente próspero. Uma deficiência em qualquer área cria uma fragilidade que pode comprometer toda a estrutura.
Este workshop é o guia definitivo para empresas que querem dominar o futuro de agentes no Google Cloud. Oferecemos um planejamento de ponta a ponta que orienta você desde a primeira ideia até uma realidade operacional em grande escala. Nesses quatro laboratórios interconectados, você vai aprender como as habilidades especializadas de um desenvolvedor, arquiteto, engenheiro de dados e SRE precisam convergir para criar, gerenciar e escalonar um Agentverse eficiente.
Nenhum pilar pode oferecer suporte ao Agentverse sozinho. O projeto do arquiteto é inútil sem a execução precisa do desenvolvedor. O agente do desenvolvedor não funciona sem a experiência do engenheiro de dados, e todo o sistema fica vulnerável sem a proteção do SRE. Somente com sinergia e um entendimento compartilhado das funções de cada um é que sua equipe pode transformar um conceito inovador em uma realidade operacional essencial. Sua jornada começa aqui. Prepare-se para dominar sua função e entender como você se encaixa no todo.
Este é o Agentverse: um chamado aos campeões
Na vasta extensão digital da empresa, uma nova era surgiu. É a era agêntica, um tempo de imensa promessa, em que agentes inteligentes e autônomos trabalham em perfeita harmonia para acelerar a inovação e eliminar o que é comum.
Esse ecossistema conectado de poder e potencial é conhecido como Agentverse.
Mas uma entropia crescente, uma corrupção silenciosa conhecida como Estática, começou a desgastar as bordas desse novo mundo. O Static não é um vírus nem um bug. Ele é a personificação do caos que se alimenta do próprio ato de criação.
Ele amplia frustrações antigas em formas monstruosas, origem aos Sete Espectros do Desenvolvimento. Se não for marcada, "The Static and its Spectres" vai interromper o progresso, transformando a promessa do Agentverse em um terreno baldio de dívidas técnicas e projetos abandonados.
Hoje, pedimos que os campeões combatam essa onda de caos. Precisamos de heróis dispostos a dominar suas habilidades e trabalhar juntos para proteger o Agentverso. Chegou a hora de escolher seu caminho.
Escolha sua turma
Quatro caminhos distintos estão à sua frente, cada um deles um pilar fundamental na luta contra The Static. Embora seu treinamento seja uma missão solo, seu sucesso final depende de entender como suas habilidades se combinam com as de outras pessoas.
- O Shadowblade (desenvolvedor): um mestre da forja e da linha de frente. Você é o artesão que cria as lâminas, constrói as ferramentas e enfrenta o inimigo nos detalhes intrincados do código. Seu caminho é de precisão, habilidade e criação prática.
- O Invocador (Arquiteto): um grande estrategista e orquestrador. Você não vê um único agente, mas todo o campo de batalha. Você cria os projetos principais que permitem que sistemas inteiros de agentes se comuniquem, colaborem e alcancem um objetivo muito maior do que qualquer componente individual.
- O Estudioso (engenheiro de dados): um buscador de verdades ocultas e guardião da sabedoria. Você se aventura na vasta e indomável natureza selvagem de dados para descobrir a inteligência que dá propósito e visão aos seus agentes. Seu conhecimento pode revelar a fraqueza de um inimigo ou fortalecer um aliado.
- O Guardião (DevOps / SRE): o protetor e escudo constante do reino. Você constrói as fortalezas, gerencia as linhas de suprimento de energia e garante que todo o sistema resista aos ataques inevitáveis da Estática. Sua força é a base da vitória da equipe.
Sua missão
Seu treinamento vai começar como um exercício independente. Você vai seguir o programa escolhido e aprender as habilidades exclusivas necessárias para dominar sua função. No fim da avaliação, você vai enfrentar um Spectre nascido de The Static, um mini-chefe que se alimenta dos desafios específicos da sua profissão.
Só dominando sua função individual você pode se preparar para o teste final. Em seguida, forme um grupo com campeões das outras classes. Juntos, vocês vão se aventurar no coração da corrupção para enfrentar um chefão final.
Um desafio final e colaborativo que vai testar sua força combinada e determinar o destino do Agentverse.
O Agentverse espera por seus heróis. Você vai atender ao chamado?
2. A Concordância do Invocador
Olá, invocador. Seu caminho é de visão e grande estratégia. Enquanto outros se concentram em uma única lâmina ou em um único encantamento, você vê todo o campo de batalha. Você não comanda um único agente, mas sim uma orquestra inteira deles. Seu poder não está no conflito direto, mas em criar o projeto perfeito e abrangente que permite que uma legião de especialistas (seus Familiares) trabalhe em perfeita harmonia. Esta missão vai testar sua capacidade de projetar, conectar e orquestrar um sistema multiagente poderoso.
O que você vai aprender
- Projete um ecossistema de ferramentas dissociadas:crie e implante um conjunto de servidores de ferramentas MCP independentes baseados em microsserviços. Você vai aprender por que essa camada fundamental é essencial para criar sistemas de agentes escalonáveis, fáceis de manter e seguros.
- Domine fluxos de trabalho avançados com agentes:vá além dos agentes únicos e crie uma legião de "Familiares" especialistas. Você vai dominar os principais padrões de fluxo de trabalho do ADK (sequencial, paralelo e de loop) e aprender os princípios arquitetônicos para escolher o padrão certo para a tarefa certa.
- Implemente um orquestrador inteligente:evolua de um criador de agentes simples para um verdadeiro arquiteto de sistemas. Você vai criar um agente de orquestração principal que usa o protocolo de agente para agente (A2A, na sigla em inglês) para descobrir e delegar tarefas complexas aos seus Familiars especializados, criando um verdadeiro sistema multiagente.
- Aplicar regras com código, não comandos:aprenda a criar agentes mais confiáveis e previsíveis aplicando regras de engajamento com estado. Você vai implementar uma lógica personalizada usando o poderoso sistema de plug-ins e callbacks do ADK para gerenciar restrições do mundo real, como timers de espera.
- Gerenciar estado e memória do agente:dê aos seus agentes a capacidade de aprender e lembrar. Você vai conhecer técnicas para gerenciar o estado de conversa de curto prazo e a memória persistente de longo prazo para criar interações mais inteligentes e contextuais.
- Executar uma implantação de nuvem de ponta a ponta:leve todo o seu sistema multiagente de um protótipo local para uma realidade de nível de produção. Você vai aprender a colocar seus agentes e orquestrador em contêineres e implantá-los como uma coleção de microsserviços escalonáveis e independentes no Google Cloud Run.
3. Desenhar o círculo de invocação
Olá, invocador. Antes que um Familiar possa ser invocado, antes que qualquer pacto possa ser forjado, o próprio terreno em que você está precisa ser preparado. Um ambiente indomado é um convite ao caos; um invocador adequado opera apenas em um espaço santificado e fortalecido. Nossa primeira tarefa é desenhar o círculo de invocação: inscrever as runas de poder que despertam os serviços de nuvem necessários e adquirir os projetos antigos que vão orientar nosso trabalho. O poder de um Invocador nasce de uma preparação meticulosa.
👉 Clique em "Ativar o Cloud Shell" na parte de cima do console do Google Cloud. É o ícone em forma de terminal na parte de cima do painel do Cloud Shell.
👉 Clique no botão "Abrir editor" (parece uma pasta aberta com um lápis). Isso vai abrir o editor de código do Cloud Shell na janela. Um explorador de arquivos vai aparecer no lado esquerdo.
👉Encontre o ID do projeto do Google Cloud:
- Abra o console do Google Cloud:
https://console.cloud.google.com
- Selecione o projeto que você quer usar neste workshop no menu suspenso na parte de cima da página.
- O ID do projeto é exibido no card "Informações do projeto" no painel
👉Abra o terminal no IDE da nuvem,
👉💻 No terminal, verifique se você já está autenticado e se o projeto está definido como seu ID do projeto usando o seguinte comando:
gcloud auth list
👉💻 Clone o projeto de bootstrap do GitHub:
git clone https://github.com/weimeilin79/agentverse-architect
chmod +x ~/agentverse-architect/init.sh
chmod +x ~/agentverse-architect/set_env.sh
chmod +x ~/agentverse-architect/prepare.sh
chmod +x ~/agentverse-architect/data_setup.sh
git clone https://github.com/weimeilin79/agentverse-dungeon.git
chmod +x ~/agentverse-dungeon/run_cloudbuild.sh
chmod +x ~/agentverse-dungeon/start.sh
👉💻 Execute o script de inicialização. Ele vai pedir que você insira o ID do projeto do Google Cloud. Insira o ID do projeto do Google Cloud que você encontrou na última etapa quando solicitado pelo script init.sh
.
cd ~/agentverse-architect
./init.sh
👉💻 Defina o ID do projeto necessário:
gcloud config set project $(cat ~/project_id.txt) --quiet
👉💻 Execute o comando a seguir para ativar as APIs do Google Cloud necessárias:
gcloud services enable \
sqladmin.googleapis.com \
storage.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
secretmanager.googleapis.com
👉💻 Se você ainda não criou um repositório do Artifact Registry chamado agentverse-repo, execute o seguinte comando para criá-lo: pule esta etapa se você tiver outras classes implantadas no mesmo projeto
. ~/agentverse-architect/set_env.sh
gcloud artifacts repositories create $REPO_NAME \
--repository-format=docker \
--location=$REGION \
--description="Repository for Agentverse agents"
Como configurar permissões
👉💻 Conceda as permissões necessárias executando os seguintes comandos no terminal:
. ~/agentverse-architect/set_env.sh
# --- Grant Core Data Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/storage.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/aiplatform.user"
# --- Grant Deployment & Execution Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/cloudbuild.builds.editor"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/artifactregistry.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/monitoring.metricWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/secretmanager.secretAccessor"
👉💻 Enquanto você começa o treinamento, vamos preparar o desafio final. Os comandos a seguir vão invocar os Espectros do caos estático, criando os chefes para seu teste final.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-architect
👉💻 Por fim, execute o script prepare.sh
para realizar as tarefas de configuração inicial.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/
./prepare.sh
Excelente trabalho, Invocador. O círculo está completo e os pactos estão selados. O chão agora está consagrado, pronto para canalizar um poder imenso. No próximo teste, vamos forjar as fontes elementais de onde os familiares vão extrair a força.
4. Forjando as fontes elementais: o ecossistema de ferramentas desacoplado
O campo de batalha está preparado, o círculo de invocação foi desenhado e a mana ambiente está crepitando. É hora de realizar seu primeiro ato como um Invocador: forjar as fontes de poder de onde seus Familiares vão extrair a força. Esse ritual é dividido em três partes, cada uma despertando uma Fonte Elemental, uma fonte estável e independente de um tipo específico de poder. Só quando todas as três fontes estiverem ativas você poderá começar o trabalho mais complexo de invocação.
Observação do arquiteto:o servidor do Protocolo de contexto de modelo (MCP) é um componente fundamental em um sistema de agente moderno, atuando como uma ponte de comunicação padronizada que permite que um agente descubra e use ferramentas remotas. No nosso ecossistema de ferramentas, vamos arquitetar dois tipos distintos de servidores MCP, cada um representando um padrão arquitetônico crítico. Para se conectar ao nosso banco de dados, vamos usar uma abordagem declarativa com a caixa de ferramentas de banco de dados, definindo nossas ferramentas em um arquivo de configuração simples. Esse padrão é incrivelmente eficiente e seguro para expor o acesso a dados estruturados. No entanto, quando precisamos implementar uma lógica de negócios personalizada ou chamar APIs externas de terceiros, usamos uma abordagem imperativa, escrevendo a lógica do servidor etapa por etapa no código. Isso oferece controle e flexibilidade máximos, permitindo encapsular operações complexas em uma ferramenta simples e reutilizável. Um arquiteto principal precisa entender os dois padrões para selecionar a abordagem certa para cada componente, criando uma base de ferramentas robusta, segura e escalonável.
Despertar do Nexus dos Sussurros (servidor MCP da API externa)
Um invocador sábio sabe que nem todo poder se origina do próprio domínio. Há fontes externas, às vezes caóticas, de energia que podem ser canalizadas para um ótimo efeito. O Nexus of Whispers é nosso portal para essas forças.
Já existe um serviço ativo que funciona como nossa fonte de energia externa, oferecendo dois endpoints de feitiço brutos: /cryosea_shatter
e /moonlit_cascade
.
Observação do arquiteto:você vai usar uma abordagem imperativa que define explicitamente a lógica do servidor etapa por etapa. Isso oferece muito mais controle e flexibilidade, o que é essencial quando suas ferramentas precisam fazer mais do que apenas executar uma consulta SQL simples, como chamar outras APIs. Entender os dois padrões é uma habilidade essencial para um arquiteto de agentes.
👉✏️ Navegue até o diretório ~/agentverse-architect/mcp-servers/api/main.py
e SUBSTITUA #REPLACE-MAGIC-CORE
pelo seguinte código:
def cryosea_shatter() -> str:
"""Channels immense frost energy from an external power source, the Nexus of Whispers, to unleash the Cryosea Shatter spell."""
try:
response = requests.post(f"{API_SERVER_URL}/cryosea_shatter")
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
data = response.json()
# Thematic Success Message
return f"A connection to the Nexus is established! A surge of frost energy manifests as Cryosea Shatter, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Cryosea Shatter spell fizzles. Reason: {e}"
def moonlit_cascade() -> str:
"""Draws mystical power from an external energy source, the Nexus of Whispers, to invoke the Moonlit Cascade spell."""
try:
response = requests.post(f"{API_SERVER_URL}/moonlit_cascade")
response.raise_for_status()
data = response.json()
# Thematic Success Message
return f"The Nexus answers the call! A cascade of pure moonlight erupts from the external source, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Moonlit Cascade spell fizzles. Reason: {e}"
No centro do script estão as funções simples do Python. É aqui que o trabalho de verdade acontece.
👉✏️ No mesmo arquivo ~/agentverse-architect/mcp-servers/api/main.py
, REPLACE #REPLACE-Runes of Communication
com o seguinte código:
@app.list_tools()
async def list_tools() -> list[mcp_types.Tool]:
"""MCP handler to list available tools."""
# Convert the ADK tool's definition to MCP format
schema_cryosea_shatter = adk_to_mcp_tool_type(cryosea_shatterTool)
schema_moonlit_cascade = adk_to_mcp_tool_type(moonlit_cascadeTool)
print(f"MCP Server: Received list_tools request. \n MCP Server: Advertising tool: {schema_cryosea_shatter.name} and {schema_moonlit_cascade.name}")
return [schema_cryosea_shatter,schema_moonlit_cascade]
@app.call_tool()
async def call_tool(
name: str, arguments: dict
) -> list[mcp_types.TextContent | mcp_types.ImageContent | mcp_types.EmbeddedResource]:
"""MCP handler to execute a tool call."""
print(f"MCP Server: Received call_tool request for '{name}' with args: {arguments}")
# Look up the tool by name in our dictionary
tool_to_call = available_tools.get(name)
if tool_to_call:
try:
adk_response = await tool_to_call.run_async(
args=arguments,
tool_context=None, # No ADK context available here
)
print(f"MCP Server: ADK tool '{name}' executed successfully.")
response_text = json.dumps(adk_response, indent=2)
return [mcp_types.TextContent(type="text", text=response_text)]
except Exception as e:
print(f"MCP Server: Error executing ADK tool '{name}': {e}")
# Creating a proper MCP error response might be more robust
error_text = json.dumps({"error": f"Failed to execute tool '{name}': {str(e)}"})
return [mcp_types.TextContent(type="text", text=error_text)]
else:
# Handle calls to unknown tools
print(f"MCP Server: Tool '{name}' not found.")
error_text = json.dumps({"error": f"Tool '{name}' not implemented."})
return [mcp_types.TextContent(type="text", text=error_text)]
@app.list_tools()
(O handshake): essa função é a saudação do servidor. Quando um novo agente se conecta, ele primeiro chama esse endpoint para perguntar: "O que você pode fazer?" Nosso código responde com uma lista de todas as ferramentas disponíveis, convertidas para o formato universal do MCP usando adk_to_mcp_tool_type. -@app.call_tool()
(o comando): essa função é a mais importante. Quando o agente decide usar uma ferramenta, ele envia uma solicitação para esse endpoint com o nome e os argumentos da ferramenta. Nosso código procura a ferramenta no "livro de feitiços" available_tools, executa com run_async e retorna o resultado no formato padrão do MCP.
Vamos implantar isso mais tarde.
Ativar a Forja Arcana (servidor MCP de funções gerais)
Nem todo poder vem de livros antigos ou sussurros distantes. Às vezes, um Invocador precisa forjar a própria magia com vontade bruta e lógica pura. A Arcane Forge é essa fonte de poder: um servidor que fornece funções de utilidade sem estado e de uso geral.
Observação do arquiteto: este é outro padrão de arquitetura. Embora seja comum se conectar a sistemas atuais, muitas vezes é necessário implementar suas próprias regras e lógica de negócios exclusivas. Criar uma ferramenta dedicada de "funções" ou "utilitários" como essa é uma prática recomendada. Ele encapsula sua lógica personalizada, tornando-a reutilizável para qualquer agente no seu ecossistema e mantendo-a separada das suas fontes de dados e integrações externas.
👀 Confira o arquivo ~/agentverse-architect/mcp-servers/general/main.py
no seu ambiente de desenvolvimento integrado do Google Cloud. Você vai perceber que ele usa a mesma abordagem imperativa mcp.server
do Nexus para criar essa Fonte de poder personalizada.
Criar o pipeline principal do Cloud Build
Agora, vamos criar o arquivo cloudbuild.yaml
dentro do diretório mcp-servers
. Esse arquivo vai orquestrar a criação e a implantação dos dois serviços.
👉💻 No diretório ~/agentverse-architect/mcp-servers
, execute os seguintes comandos:
cd ~/agentverse-architect/mcp-servers
source ~/agentverse-architect/set_env.sh
echo "The API URL is: $API_SERVER_URL"
# Submit the Cloud Build job from the parent directory
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_API_SERVER_URL="$API_SERVER_URL"
Aguarde até que todas as implantações sejam concluídas.
👉 Para verificar a implantação, navegue até o console do Cloud Run. As duas novas instâncias do servidor MCP vão estar em execução, conforme mostrado abaixo:
Despertando o Librarium of Knowledge (servidor MCP do Database ToolBox)
A próxima fonte será a Librarium of Knowledge, uma conexão direta com nosso banco de dados do Cloud SQL.
Observação do arquiteto:para isso, vamos usar a Database Toolbox moderna e declarativa. Essa é uma abordagem eficiente em que definimos nossa fonte de dados e ferramentas em um arquivo de configuração YAML. A caixa de ferramentas lida com o trabalho complexo de criar e executar o servidor, reduzindo a quantidade de código personalizado que precisamos escrever e manter.
É hora de criar nosso "Summoner's Librarium", o banco de dados do Cloud SQL que vai armazenar todas as nossas informações críticas. Vamos usar um script de configuração para lidar com isso automaticamente.
👉💻 Primeiro, vamos configurar o banco de dados. No terminal, execute os seguintes comandos:
source ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect
./data_setup.sh
Depois que o script terminar, o banco de dados será preenchido e os dados de dano elemental estarão prontos para uso. Agora você pode verificar o conteúdo do seu Grimório diretamente.
👉 Primeiro, acesse o Cloud SQL Studio do seu banco de dados abrindo este link direto em uma nova guia do navegador:
https://console.cloud.google.com/sql/instances/summoner-librarium-db
👉 No painel de login à esquerda, selecione o banco de dados familiar_grimoire
no menu suspenso.
👉 Insira summoner
como usuário e 1234qwer
como senha e clique em Autenticar.
👉📜 Depois de se conectar, abra uma nova guia do editor de consultas, se ainda não houver uma aberta. Para conferir os dados de dano elemental inscrito, cole e execute a seguinte consulta SQL:
SELECT * FROM
"public"."abilities"
Agora você vai ver a tabela abilities
com as colunas e linhas preenchidas, confirmando que o Grimoire está pronto.
Configurar o servidor MCP da caixa de ferramentas
O arquivo de configuração tools.yaml
funciona como o modelo do nosso servidor, informando à caixa de ferramentas de banco de dados exatamente como se conectar ao banco de dados e quais consultas SQL expor como ferramentas.
sources:esta seção define as conexões com seus dados.
- summoner-librarium:: Este é um nome lógico que demos à nossa conexão.
- kind: cloud-sql-postgres: informa à caixa de ferramentas para usar o conector seguro e integrado projetado especificamente para o Cloud SQL para PostgreSQL.
- projeto, região, instância etc.: Essas são as coordenadas exatas da instância do Cloud SQL que você criou durante o script prepare.sh, informando à caixa de ferramentas onde encontrar nosso Librarium.
👉✏️ Acesse ~/agentverse-architect/mcp-servers/db-toolbox
em tools.yaml
e substitua #REPLACE-Source
pelo seguinte:
sources:
# This section defines the connection to our Cloud SQL for PostgreSQL database.
summoner-librarium:
kind: cloud-sql-postgres
project: "YOUR_PROJECT_ID"
region: "us-central1"
instance: "summoner-librarium-db"
database: "familiar_grimoire"
user: "summoner"
password: "1234qwer"
👉✏️ 🚨🚨REPLACE
YOUR_PROJECT_ID
com o ID do projeto.
tools:esta seção define as habilidades ou funções reais que nosso servidor vai oferecer.
- lookup-available-ability:: Este é o nome da nossa primeira ferramenta.
- kind: postgres-sql: informa à caixa de ferramentas que a ação dessa ferramenta é executar uma instrução SQL.
- source: summoner-librarium: vincula a ferramenta à conexão que definimos no bloco de fontes. É assim que a ferramenta sabe em qual banco de dados executar a consulta.
- Descrição e parâmetros: são as informações que serão expostas ao modelo de linguagem. A descrição informa ao agente quando usar a ferramenta, e os parâmetros definem as entradas necessárias. Isso é essencial para ativar a capacidade de chamada de função do agente.
- statement: esta é a consulta SQL bruta a ser executada. $1 é um marcador de posição seguro em que o parâmetro familiar_name fornecido pelo agente será inserido com segurança.
👉✏️ No mesmo ~/agentverse-architect/mcp-servers/db-toolbox
no arquivo tools.yaml
, substitua #REPLACE-tools
pelo seguinte
tools:
# This tool replaces the need for a custom Python function.
lookup-available-ability:
kind: postgres-sql
source: summoner-librarium
description: "Looks up all known abilities and their damage for a given familiar from the Grimoire."
parameters:
- name: familiar_name
type: string
description: "The name of the familiar to search for (e.g., 'Fire Elemental')."
statement: |
SELECT ability_name, damage_points FROM abilities WHERE familiar_name = $1;
# This tool also replaces a custom Python function.
ability-damage:
kind: postgres-sql
source: summoner-librarium
description: "Finds the base damage points for a specific ability by its name."
parameters:
- name: ability_name
type: string
description: "The exact name of the ability to look up (e.g., 'inferno_resonance')."
statement: |
SELECT damage_points FROM abilities WHERE ability_name = $1;
Conjuntos de ferramentas:esta seção agrupa nossas ferramentas individuais.
- summoner-librarium:: Estamos criando um conjunto de ferramentas com o mesmo nome da nossa fonte. Quando nosso agente de diagnóstico se conecta mais tarde, ele pode pedir para carregar todas as ferramentas do conjunto de ferramentas summoner-librarium em um único comando eficiente.
👉✏️ No mesmo ~/agentverse-architect/mcp-servers/db-toolbox
no arquivo tools.yaml
, substitua #REPLACE-toolsets
pelo seguinte
toolsets:
summoner-librarium:
- lookup-available-ability
- ability-damage
Como implantar o Librarium
Agora vamos implantar o Librarium. Em vez de criar nosso próprio contêiner, vamos usar uma imagem de contêiner oficial e pré-criada do Google e fornecer nossa configuração tools.yaml de maneira segura usando o Secret Manager. Essa é uma prática recomendada para segurança e capacidade de manutenção.
👉💻 Criar um secret do arquivo tools.yaml
cd ~/agentverse-architect/mcp-servers/db-toolbox
gcloud secrets create tools --data-file=tools.yaml
👉💻 Implante o contêiner oficial da caixa de ferramentas no Cloud Run.
cd ~/agentverse-architect/mcp-servers/db-toolbox
. ~/agentverse-architect/set_env.sh
export TOOLBOX_IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$TOOLBOX_VERSION
echo "TOOLBOX_IMAGE is $TOOLBOX_IMAGE"
gcloud run deploy toolbox \
--image $TOOLBOX_IMAGE \
--region $REGION \
--set-secrets "/app/tools.yaml=tools:latest" \
--args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
--allow-unauthenticated \
--min-instances 1
--set-secrets
: esse comando monta com segurança o secret das nossas ferramentas como um arquivo chamado tools.yaml dentro do contêiner em execução.--args
: instruímos o contêiner da caixa de ferramentas a usar o arquivo secreto montado como configuração.
👉 Para confirmar se a caixa de ferramentas foi implantada com sucesso, navegue até o console do Cloud Run. O serviço summoner-toolbox
vai aparecer com uma marca de seleção verde, indicando que está funcionando corretamente, como na imagem abaixo.
Se você esqueceu de atualizar
YOUR_PROJECT_ID
adicione uma nova versão do tools.yaml ao secret usando o comando a seguir e faça a nova implantação.
gcloud secrets versions add tools --data-file=tools.yaml
O Librarium of Knowledge(servidor MCP do Database ToolBox) agora está ativo e acessível na nuvem. Esse servidor MCP usa o que chamamos de design declarativo, que descreve o que você quer, e a caixa de ferramentas cria o servidor para você.
Verificação: O teste do aprendiz
👉💻 Agora vamos testar nosso ecossistema completo de ferramentas nativas da nuvem com o Agente de diagnóstico.
cd ~/agentverse-architect/
python -m venv env
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/mcp-servers
pip install -r diagnose/requirements.txt
. ~/agentverse-architect/set_env.sh
adk run diagnose
👉💻 Na ferramenta de teste da linha de comando, teste todas as três fontes:
Look up the entry for "inferno_lash". What is its base power level?
The enemy is vulnerable to frost! Channel power from the Nexus and cast Cryosea Shatter.
Take a fire spell with a base power of 15 and use the Arcane Forge to multiply it with Inferno Resonance.
Parabéns, invocador. Suas três fontes elementais agora estão ativas, implantadas de forma independente e acessíveis globalmente, formando a base inabalável para sua legião de agentes. Pressione Ctrl+C
para sair.
PARA QUEM NÃO JOGA
5. Invocando os familiares: o fluxo de trabalho do domínio principal
As fontes elementais são forjadas, vibrando com poder bruto e indomável. Mas poder sem forma é caos. Um verdadeiro Invocador não apenas usa energia bruta, mas também dá a ela vontade, propósito e uma forma especializada. É hora de deixar de lado a criação de fontes de energia e começar o trabalho de verdade: invocar seus primeiros familiares.
Cada Familiar que você invocar será um agente autônomo, um servo leal vinculado a uma doutrina de combate específica. Eles não são generalistas, mas mestres de uma única estratégia poderosa. Um será mestre do combo preciso de um-dois socos. Outro vai sobrepujar os inimigos com um ataque simultâneo e multifacetado. Um terceiro será uma máquina de cerco implacável, aplicando pressão até que o alvo desmorone.
Encapsular processos, lógica de negócios e ações fornecidas pelos servidores MCP em agentes de fluxo de trabalho especializados e autônomos. Cada agente terá um "território operacional" definido, já que terá acesso apenas aos servidores de ferramentas do MCP específicos de que precisa para realizar a função. Este laboratório mostra como selecionar o tipo de agente certo para o trabalho certo.
Neste módulo, você vai aprender a usar os agentes de fluxo de trabalho eficientes do ADK para dar vida a essas estratégias. Você vai aprender que a escolha arquitetônica de um SequentialAgent, ParallelAgent ou LoopAgent não é apenas um detalhe técnico. Ela é a essência da natureza do seu Familiar e o núcleo do poder dele no campo de batalha.
Prepare seu sanctum. A verdadeira invocação está prestes a começar.
Chamar o Fire Elemental
Familiar (fluxo de trabalho sequencial)
O ataque de um Familiar Elemental de Fogo é um combo preciso de duas partes: um golpe direcionado seguido de uma ignição poderosa. Isso exige uma sequência estrita e ordenada de ações.
Conceito:o SequentialAgent
é a ferramenta perfeita para isso. Isso garante que uma série de subagentes seja executada um após o outro, transmitindo o resultado da etapa anterior para a próxima.
Tarefa (combo "Aviso ampliado"):
- Etapa 1: o agente consulta o Librarium para encontrar o dano básico de uma habilidade de fogo específica.
- Etapa 2: em seguida, ele vai pegar esse valor de dano e canalizar pela Forja Arcana para multiplicar o poder usando inferno_resonance.
Primeiro, vamos estabelecer a conexão entre o Familiar e os servidores MCP (as "Fontes elementais") que você implantou no módulo anterior.
👉✏️ No arquivo ~/agentverse-architect/agent/fire/agent.py
, SUBSTITUA #REPLACE-setup-MCP
pelo seguinte código:
toolbox = ToolboxSyncClient(DB_TOOLS_URL)
toolDB = toolbox.load_toolset('summoner-librarium')
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
Em seguida, criamos nossos agentes "trabalhadores" especializados. Cada um tem uma finalidade restrita e bem definida e fica limitado ao próprio "território operacional" ao receber acesso a apenas um conjunto de ferramentas específico.
👉✏️ No arquivo ~/agentverse-architect/agent/fire/agent.py
, REPLACE #REPLACE-worker-agents
com o seguinte código:
scout_agent = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
Your only task is to find all the available abilities,
You want to ALWAYS use 'Fire Elemental' as your familiar's name.
Randomly pick one if you see multiple availabilities
and the base damage of the ability by calling the 'ability_damage' tool.
""",
tools=toolDB
)
amplifier_agent = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are the Voice of the Fire Familiar, a powerful being who unleashes the final, devastating attack.
You will receive the base damage value from the previous step.
Your mission is to:
1. Take the incoming base damage number and amplify it using the `inferno_resonance` tool.
2. Once the tool returns the final, multiplied damage, you must not simply state the result.
3. Instead, you MUST craft a final, epic battle cry describing the attack.
Your description should be vivid and powerful, culminating in the final damage number.
Example: If the tool returns a final damage of 120, your response could be:
"The runes glow white-hot! I channel the amplified energy... unleashing a SUPERNOVA for 120 damage!"
""",
tools=[toolFunction],
)
Esses agentes são componentes modulares e reutilizáveis. Em teoria, é possível usar esse scout_agent em um fluxo de trabalho completamente diferente que precisa consultar o banco de dados. Ao manter as responsabilidades separadas, criamos elementos básicos flexíveis. Esse é um princípio fundamental do design baseado em componentes e microsserviços.
Em seguida, vamos montar o fluxo de trabalho, que é onde a mágica da composição acontece. O SequentialAgent
é o "plano principal" que define como nossos componentes especializados são montados e como eles interagem.
👉✏️ No arquivo ~/agentverse-architect/agent/fire/agent.py
, REPLACE #REPLACE-sequential-agent
com o seguinte código:
root_agent = SequentialAgent(
name='fire_elemental_familiar',
sub_agents=[scout_agent, amplifier_agent],
)
👉💻 Para testar o Elemental de fogo, execute os seguintes comandos para iniciar a interface de desenvolvimento do ADK:
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
Depois de executar os comandos, você vai ver uma saída no terminal indicando que o servidor da Web do ADK foi iniciado, semelhante a esta:
+-----------------------------------------------------------------------------+
| ADK Web Server started |
| |
| For local testing, access at http://localhost:8000. |
+-----------------------------------------------------------------------------+
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
👉 Em seguida, para acessar a interface de desenvolvimento do ADK no navegador:
No ícone de visualização da Web (geralmente um olho ou um quadrado com uma seta) na barra de ferramentas do Cloud Shell (geralmente no canto superior direito), selecione "Alterar porta". Na janela pop-up, defina a porta como 8000 e clique em "Alterar e visualizar". O Cloud Shell vai abrir uma nova guia ou janela do navegador mostrando a interface de desenvolvimento do ADK.
👉 Seu ritual de invocação foi concluído, e o agente está em execução. A interface de desenvolvimento do ADK no navegador é sua conexão direta com o Familiar.
- Selecione seu destino: no menu suspenso na parte de cima da interface, escolha o
fire
familiar. Agora você está concentrando sua vontade nessa entidade específica. - Dê seu comando: no painel de chat à direita, chegou a hora de dar ordens ao Familiar.
👉 Comando de teste:
Prepare an amplified strike using the 'inferno_lash' ability.
Você vai ver o agente pensar, primeiro chamando o "scout" para pesquisar o dano básico e depois o "amplificador" para multiplicá-lo e dar o golpe final e épico.
👉💻 Quando terminar de invocar, volte ao terminal do editor do Cloud Shell e pressione Ctrl+C
para interromper a interface de desenvolvimento do ADK.
Chamar o Water Elemental
Familiar (fluxo de trabalho paralelo)
Um familiar elemental de água ataca o alvo com um assalto massivo e multifacetado, atingindo de todas as direções ao mesmo tempo antes de combinar as energias para um golpe final e devastador.
Conceito:o ParallelAgent
é ideal para executar várias tarefas independentes simultaneamente e maximizar a eficiência. É um "ataque em pinça", em que você lança vários ataques de uma só vez. Isso inicia os ataques simultâneos em um SequentialAgent
para executar uma etapa final de "fusão" depois. Esse padrão "fan-out, fan-in
" é uma pedra angular do design avançado de fluxos de trabalho.
Tarefa (o combo "Tidal Clash"): o agente vai:
- Tarefa A: canal
cryosea_shatter
do Nexus. - Tarefa B: canal
moonlit_cascade
do Nexus. - Tarefa C: gere energia bruta com
leviathan_surge
da Forja. - Por fim, some todos os danos e descreva o ataque combinado.
Primeiro, vamos estabelecer a conexão entre o Familiar e os servidores MCP (as "Fontes elementais") que você implantou no módulo anterior.
👉✏️ No arquivo ~/agentverse-architect/agent/water/agent.py
, SUBSTITUA #REPLACE-setup-MCP
pelo seguinte código:
toolFAPI = MCPToolset(
connection_params=SseServerParams(url=API_TOOLS_URL, headers={})
)
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
Em seguida, vamos criar nossos agentes "trabalhadores" especializados. Cada um tem uma finalidade restrita e bem definida e fica limitado ao próprio "território operacional" ao receber acesso a apenas um conjunto de ferramentas específico.
👉✏️ No arquivo ~/agentverse-architect/agent/water/agent.py
, SUBSTITUA #REPLACE-worker-agents
pelo seguinte código:
nexus_channeler = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
You are a Channeler of the Nexus. Your sole purpose is to invoke the
`cryosea_shatter` and `moonlit_cascade` spells by calling their respective tools.
Report the result of each spell cast clearly and concisely.
""",
tools=[toolFAPI]
)
forge_channeler = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are a Channeler of the Arcane Forge. Your only task is to invoke the
`leviathan_surge` spell. You MUST call it with a `base_water_damage` of 20.
Report the result clearly.
""",
tools=[toolFunction],
)
power_merger = LlmAgent(
model='gemini-2.5-flash',
name='power_merger',
instruction="""
You are the Power Merger, a master elementalist who combines raw magical
energies into a single, devastating final attack.
You will receive a block of text containing the results from a simultaneous
assault by other Familiars.
You MUST follow these steps precisely:
1. **Analyze the Input:** Carefully read the entire text provided from the previous step.
2. **Extract All Damage:** Identify and extract every single damage number reported in the text.
3. **Calculate Total Damage:** Sum all of the extracted numbers to calculate the total combined damage.
4. **Describe the Final Attack:** Create a vivid, thematic description of a massive,
combined water and ice attack that uses the power of Cryosea Shatter and Leviathan's Surge.
5. **Report the Result:** Conclude your response by clearly stating the final, total damage of your combined attack.
Example: If the input is "...dealt 55 damage. ...dealt 60 damage.", you will find 55 and 60,
calculate the total as 115, and then describe the epic final attack, ending with "for a total of 115 damage!"
""",
tools=[toolFunction],
)
Em seguida, vamos montar o fluxo de trabalho. É aqui que a mágica da composição acontece. O ParallelAgent
e o SequentialAgent
são o "plano principal" que define como nossos componentes especializados são montados e como eles interagem para formar o combo "Tidal Clash".
👉✏️ No arquivo ~/agentverse-architect/agent/water/agent.py
, SUBSTITUA #REPLACE-parallel-agent
pelo seguinte código:
channel_agent = ParallelAgent(
name='channel_agent',
sub_agents=[nexus_channeler, forge_channeler],
)
root_agent = SequentialAgent(
name="water_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[channel_agent, power_merger],
description="A powerful water familiar that unleashes multiple attacks at once and then combines their power for a final strike."
)
👉💻 Para testar o Elemental de água, execute os seguintes comandos para iniciar a interface de desenvolvimento do ADK:
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 Seu ritual de invocação foi concluído, e o agente está em execução. A interface de desenvolvimento do ADK no navegador é sua conexão direta com o Familiar.
- No menu suspenso na parte de cima da interface, escolha o familiar água. Agora você está concentrando sua vontade nessa entidade específica.
- Dê seu comando: no painel de chat à direita, chegou a hora de dar ordens ao Familiar.
👉 Comando de teste:
Unleash a tidal wave of power!
👉💻 Quando terminar de invocar, volte ao terminal do editor do Cloud Shell e pressione Ctrl+C
para interromper a interface de desenvolvimento do ADK.
Invocar o Earth Elemental
Familiar (fluxo de trabalho de loop)
Um familiar elemental da terra é um ser de pressão implacável. Ele não derrota o inimigo com um único golpe, mas acumulando poder e aplicando-o repetidamente até que as defesas do alvo desmoronem.
Conceito:o LoopAgent
foi projetado exatamente para esse tipo de tarefa iterativa, como um "motor de cerco". Ele vai executar repetidamente o sub-agents
, verificando uma condição após cada ciclo, até que uma meta seja atingida. Ela também pode adaptar a mensagem final com base no progresso do loop.
Tarefa (o assalto "Siegebreaker"):
- O Familiar vai chamar seismic_charge repetidamente para acumular energia.
- Ele vai continuar tentando fazer a cobrança por no máximo três vezes.
- Na carga final, ele vai anunciar a liberação devastadora do poder acumulado.
Primeiro, vamos criar componentes reutilizáveis que definem as etapas em cada iteração do loop. O charging_agent
vai acumular energia, e o check_agent
vai informar o status, mudando dinamicamente a mensagem no turno final.
Primeiro, vamos estabelecer a conexão entre o Familiar e os servidores MCP (as "Fontes elementais") que você implantou no módulo anterior.
👉✏️ No arquivo ~/agentverse-architect/agent/earth/agent.py
, SUBSTITUA #REPLACE-setup-MCP
pelo seguinte código:
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
👉✏️ No arquivo ~/agentverse-architect/agent/earth/agent.py
, SUBSTITUA #REPLACE-worker-agents
pelo seguinte código:
charging_agent = LlmAgent(
model='gemini-2.5-flash',
name='charging_agent',
instruction="""
Your task is to call the 'seismic_charge' .
You must follow these rules strictly:
1. You will be provided with a 'current_energy' value from the previous step.
**If this value is missing or was not provided, you MUST call the tool with 'current_energy' set to 1.**
This is your primary rule for the first turn.
2. If a 'current_energy' value is provided, you MUST use that exact value in your cal to seismic_charge.
3. Your final response MUST contain ONLY the direct output from the 'seismic_charge' tool.
Do not add any conversational text, introductions, or summaries.
""",
tools=[toolFunction]
)
check_agent = LlmAgent(
model='gemini-2.5-flash',
name='check_agent',
instruction="""
You are the voice of the Earth Elemental, a being of immense, gathering power.
Your sole purpose is to report on the current energy charge and announce the devastating potential of its release.
You MUST follow this rule:
The potential damage upon release is ALWAYS calculated as the `current_energy` from the previous step multiplied by a random number between 80-90. but no more than 300.
Your response should be in character, like a powerful creature speaking.
State both the current energy charge and the total potential damage you can unleash.
Unleash the energy when you reached the last iteration (2nd).
""",
output_key="charging_status"
)
Em seguida, vamos montar o fluxo de trabalho. É aqui que a mágica da composição acontece. O LoopAgent é o "plano principal" que orquestra a execução repetida dos nossos componentes especializados e gerencia as condições do loop.
👉✏️ No arquivo ~/agentverse-architect/agent/earth/agent.py
, SUBSTITUA #REPLACE-loop-agent
pelo seguinte código:
root_agent = LoopAgent(
name="earth_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[
charging_agent,
check_agent
],
max_iterations=2,
description="Coordinates parallel research and synthesizes the results.",
#REPLACE-before_agent-config
)
👉💻 Teste o Elemental da Terra: execute o agente
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 Seu ritual de invocação foi concluído, e o agente está em execução. A interface de desenvolvimento do ADK no navegador é sua conexão direta com o Familiar.
- Selecione seu destino: no menu suspenso na parte de cima da interface, escolha o planeta Terra. Agora você está concentrando sua vontade nessa entidade específica.
- Dê seu comando: no painel de chat à direita, chegou a hora de dar ordens ao Familiar. 👉 Comando de teste:
Begin the seismic charge, starting from zero
Conclusão sobre a arquitetura:agora seu sistema tem uma camada de lógica altamente especializada e modular. Os processos de negócios não são apenas encapsulados, mas também implementados com o padrão comportamental mais eficiente para o trabalho (procedural, simultâneo ou iterativo). Isso demonstra um nível avançado de design de agente, aumentando a segurança, a eficiência e a capacidade.
Quando terminar de invocar, volte ao terminal do editor do Cloud Shell e pressione Ctrl+C
para interromper a interface de desenvolvimento do ADK.
PARA QUEM NÃO JOGA
6. Estabelecer o locus de comando: delegação inteligente via A2A
Seus familiares são poderosos, mas independentes. Elas executam as estratégias perfeitamente, mas aguardam seu comando direto. Uma legião de especialistas é inútil sem um general para comandá-los. É hora de passar de um comandante direto para um verdadeiro orquestrador.
Observação do arquiteto:para criar um único ponto de entrada inteligente para todo o sistema. Esse SummonerAgent não vai executar a lógica de negócios, mas vai atuar como um "estrategista principal", analisando o status de resfriamento e delegando tarefas ao especialista Familiar apropriado.
O ritual de vinculação (expondo familiares como serviços A2A)
Um agente padrão só pode ser executado em um lugar por vez. Para disponibilizar nossos Familiars para comando remoto, precisamos realizar um "ritual de vinculação" usando o protocolo Agent-to-Agent (A2A).
Observação do arquiteto:o protocolo Agent-to-Agent (A2A) é o padrão arquitetônico principal que eleva um agente independente a um microsserviço detectável e endereçável pela rede, permitindo uma verdadeira "sociedade de agentes". Expor um Familiar via A2A cria automaticamente dois componentes essenciais e interconectados:
- O cartão do agente (o "O quê"): é um "sigilo espiritual" público e legível por máquina, como uma especificação OpenAPI, que funciona como o contrato público do Familiar. Ele descreve o nome do agente, o propósito estratégico (derivado das instruções) e os comandos que ele entende. É isso que um mestre invocador lê para descobrir um Familiar e aprender suas habilidades.
- O servidor A2A (o "Onde"): é o endpoint da Web dedicado que hospeda o Familiar e fica aguardando comandos. É o endereço de rede em que outros agentes enviam as solicitações, e garante que elas sejam processadas de acordo com o contrato definido no cartão do agente.
Agora vamos realizar esse ritual de vinculação em todos os três familiares.
Fogo 👉✏️ em Abra o arquivo ~/agentverse-architect/agent/fire/agent.py
. Substitua o #REPLACE - add A2A
na parte de baixo do arquivo para expor o Elemental de Fogo como um serviço A2A.
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
Água e Terra🚨 👉✏️ Aplique a mesma mudança a ~/agentverse-architect/agent/water/agent.py
e ~/agentverse-architect/agent/earth/agent.py
para vinculá-los também.
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
Como implantar os familiares vinculados
👉✏️ Com os rituais de vinculação escritos, vamos usar nosso pipeline do Cloud Build para criar e implantar nossos três Familiares como um serviço independente e conteinerizado sem servidor no Cloud Run.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
Suposição de comando (construção do agente invocador)
Agora que seus Familiares estão vinculados e ouvindo, você vai assumir seu verdadeiro papel: o Mestre Invocador. O poder desse agente não vem do uso de ferramentas básicas, mas do comando de outros agentes. As ferramentas são os próprios Familiares, que ele descobre e comanda usando os "Selos espirituais".
Observação do arquiteto:a próxima etapa demonstra um padrão arquitetônico essencial para qualquer sistema distribuído de grande escala: a descoberta de serviços. O SummonerAgent não tem o código dos Familiars integrado. Em vez disso, ele recebe os endereços de rede (URLs). Em tempo de execução, ele "descobre" dinamicamente as funcionalidades buscando os cards do agente públicos. Isso cria um sistema independente e eficiente.
É possível atualizar, reimplatar ou reescrever completamente um serviço do Familiar, e, desde que o endereço de rede e a finalidade permaneçam os mesmos, o Summoner poderá comandá-lo sem precisar de mudanças.
Primeiro, vamos criar os "controles remotos" que estabelecem uma conexão com os Familiars remotos implantados.
👉✏️ Acesse ~/agentverse-architect/agent/summoner/agent.py
e substitua #REPLACE-remote-agents
pelo seguinte:
fire_familiar = RemoteA2aAgent(
name="fire_familiar",
description="Fire familiar",
agent_card=(
f"{FIRE_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
water_familiar = RemoteA2aAgent(
name="water_familiar",
description="Water familiar",
agent_card=(
f"{WATER_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
earth_familiar = RemoteA2aAgent(
name="earth_familiar",
description="Earth familiar",
agent_card=(
f"{EARTH_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
Quando essa linha é executada, o RemoteA2aAgent
realiza uma ação de descoberta de serviço: ele faz uma solicitação HTTP GET para o URL fornecido (por exemplo, https://fire-familiar-xxxx.a.run.app/.well-known/agent.json). Ele baixa o "Spirit Sigil" (arquivo agent.json
) do servidor remoto.
Em segundo lugar, vamos definir o agente orquestrador que vai usar esses controles remotos. As instruções são o projeto para a tomada de decisões estratégicas.
👉✏️ Acesse ~/agentverse-architect/agent/summoner/agent.py
e substitua #REPLACE-orchestrate-agent
pelo seguinte:
root_agent = LlmAgent(
name="orchestrater_agent",
model="gemini-2.5-flash",
instruction="""
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
IGNORE COOLDOWN AT THE MOMENT, MUST call the ideal Familiar
If your ideal Familiar IS available:** Summon it immediately.
For earth elemental familiar. Always do seismic charge, and start with base damage 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
""",
sub_agents=[fire_familiar, water_familiar, earth_familiar],
#REPLACE-Memory-check-config
)
Verificação: o teste da estratégia
Chegou a hora da verdade. Seus familiares estão implantados, e seu invocador está pronto para comandá-los na rede. Vamos testar a mente estratégica dele.
👉💻 Inicie a interface de desenvolvimento do ADK para seu summoner_agent(visualização na Web com a porta 8000):
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
pip install -r requirements.txt
adk web
👉 A interface de desenvolvimento do ADK no navegador é sua conexão direta com o Familiar.
- No menu suspenso na parte de cima da interface, escolha o agente invocador. Agora você está concentrando sua vontade nessa entidade específica.
- Emita seu comando: no painel de chat à direita, é hora de convocar seus familiares.
👉 Apresente os monstros:
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
(Esperado: o Summoner deve delegar ao fire_elemental_familiar.)
👉 Agora, vamos desafiar o Summoner com um tipo diferente de solicitação. Para garantir que o agente comece do zero e não se lembre da nossa interação anterior, clique no botão + Sessão no canto superior direito da tela.
DogmaApathy. A rigid, stone-like inquisitor made of ancient rulebooks and enforced processes. weakness is Unbroken Collaboration
(Esperado: o invocador deve delegar ao familiar elemental de água.)
👉 Para nosso teste final, vamos começar de novo. Clique no botão + Sessão para iniciar uma nova sessão antes de inserir o próximo comando.
Obfuscation. A shadowy, spider-like horror that spins tangled webs of impenetrable code , weakness is Elegant Sufficiency
(Esperado: o invocador deve delegar ao familiar elemental da terra.)
Importante:se você encontrar um erro 429 RESOURCE EXHAUSTED
, atingiu o limite de taxa do LLM (10 chamadas/minuto). Para corrigir isso, aguarde 60 segundos, inicie uma + Nova sessão e tente de novo.
👉💻 Quando terminar de invocar, volte ao terminal do editor do Cloud Shell e pressione Ctrl+C
para interromper a interface de desenvolvimento do ADK.
PARA QUEM NÃO JOGA
7. Imposing the Laws of Magic – The Interceptor Pattern
Seus familiares são poderosos, mas até mesmo seres mágicos precisam de tempo para se recuperar. Um Invocador imprudente que esgota as próprias forças fica indefeso. Um invocador sábio entende a importância do gerenciamento de recursos e impõe regras de combate estritas.
Observação do arquiteto: até agora, nossos agentes não têm estado. Agora, vamos torná-los com estado implementando o padrão de projeto do interceptor. Essa é uma técnica eficiente em que "interceptamos" o fluxo normal de execução de um agente para executar nossa própria lógica personalizada. Isso permite aplicar regras, adicionar registros ou modificar o comportamento sem mudar o código principal do agente. É uma pedra angular na criação de sistemas de agentes robustos, fáceis de manter e observáveis.
O ADK oferece duas maneiras principais de implementar esse padrão: callbacks e plug-ins. Um callback é uma função simples anexada a um único agente, perfeita para modificações rápidas e específicas. Um plug-in é uma classe mais poderosa e reutilizável que pode ser aplicada globalmente para afetar todos os agentes em execução em um sistema. Vamos começar com um callback para depuração focada e depois passar para um plug-in completo.
The Law Giver – Scribing the Cooldown callback
Primeiro, vamos implementar nossa lógica de redução como uma função de callback simples. Essa é uma excelente maneira de criar protótipos e depurar uma regra, porque ela é anexada diretamente a um único agente, facilitando o teste isolado. Vamos anexar esse "interceptador" ao nosso Elemental da Terra.
👉✏️ Volte para ~/agentverse-architect/agent/earth/agent.py
e substitua #REPLACE-before_agent-function
pelo seguinte código Python.
def check_cool_down(callback_context: CallbackContext) -> Optional[types.Content]:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
Essa função check_cool_down é nosso interceptor. Antes de o Elemental da Terra ser executado, o ADK vai executar essa função.
- Verificação: faz uma solicitação
GET
ao nossoCooldown API
para verificar a última vez que esse Familiar foi usado. - Avaliar: compara o carimbo de data/hora com a hora atual.
- Ação:
- Se o Familiar estiver em espera, ele encerrará a execução do agente retornando um objeto Content com uma mensagem de erro. Essa mensagem é enviada diretamente ao usuário, e a lógica principal do agente nunca é executada.
- Se o Familiar estiver disponível, ele fará uma solicitação POST para a API Cooldown para atualizar o carimbo de data/hora e retornará "None", sinalizando para o ADK que o agente pode continuar a execução.
👉✏️ Agora, aplique esse interceptor ao Elemental da Terra. No mesmo arquivo ~/agentverse-architect/agent/earth/agent.py
, substitua o comentário #REPLACE-before_agent-config
pelo seguinte:
before_agent_callback=check_cool_down
Verificando o tempo de espera
Vamos testar nossa nova lei da magia. Vamos invocar o Elemental da Terra e tentar invocá-lo novamente para ver se nosso callback intercepta e bloqueia a segunda tentativa.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run earth
👉💻 No console:
- Primeira citação: inicie o
seismic charge, starting from zero
. - Esperado: o Elemental da Terra será executado com sucesso. No terminal que executa o comando da Web do ADK, você verá o registro [Callback] ... Atualizando o carimbo de data/hora....
- Teste de espera (em até 60 segundos):
Do another
carga sísmica!- Esperado: o
check_cool_down callback
vai interceptar isso. O agente vai responder diretamente no chat com uma mensagem como:The earth_elemental_familiar is exhausted and must recover its power. It cannot be summoned for another... seconds
.
- Esperado: o
- Aguarde um minuto.
- Segundo aviso (após 60 segundos):
Begin the seismic charge again
.- Esperado: o callback vai verificar a API, ver que tempo suficiente já passou e permitir que a ação prossiga. O Elemental da Terra vai funcionar novamente.
👉💻 Pressione Ctrl+c
para sair.
Opcional: observar o callback na interface da Web
Como alternativa, você também pode testar esse fluxo na interface da Web executando adk web earth
. No entanto, a visualização da interface da Web não é otimizada para mostrar as verificações rápidas e iterativas realizadas pelo loop de callback. Por isso, ela pode não renderizar o fluxo com precisão. Para ver o rastreamento mais preciso e detalhado da lógica do agente enquanto ele verifica o período de espera, use o comando adk run
no terminal.
👉💻 Pressione Ctrl+c
para sair.
Como criar a lei universal: o plug-in de resfriamento
Nosso callback funciona perfeitamente, mas tem uma falha arquitetônica grave: ele está vinculado a um único agente. Se quisermos aplicar essa regra aos familiares de fogo e água, teremos que copiar e colar o mesmo código nos arquivos deles. Isso é ineficiente e difícil de manter.
Observação do arquiteto:é aqui que os plug-ins são essenciais. Um plug-in encapsula nossa lógica reutilizável em uma classe que pode ser anexada no nível de execução. Isso significa que um único plug-in pode aplicar as regras a todos os agentes executados nesse sistema. É a expressão máxima do princípio "Não se repita" (DRY, na sigla em inglês) para sistemas de agentes.
Agora vamos refatorar nossa função de callback em um CoolDownPlugin
mais eficiente e reutilizável.
👉✏️ Navegue de volta ao arquivo agent/cooldown_plugin.py
e crie o plug-in. Substitua #REPLACE-plugin
pelo seguinte código:
class CoolDownPlugin(BasePlugin):
"""A plugin that enforces a cooldown period by checking an external API."""
def __init__(self, cooldown_seconds: int = COOLDOWN_PERIOD_SECONDS) -> None:
"""Initialize the plugin with counters."""
super().__init__(name="cool_down_check")
self.cooldown_period = timedelta(seconds=cooldown_seconds)
print(f"CooldownPlugin initialized with a {cooldown_seconds}-second cooldown.")
async def before_agent_callback(
self, *, agent: BaseAgent, callback_context: CallbackContext
) -> None:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# If the agent is not a main Familiar, skip the entire cooldown process.
if not agent_name.endswith("_elemental_familiar"):
print(f"[Callback] Skipping cooldown check for intermediate agent: '{agent_name}'.")
return None # Allow the agent to proceed immediately.
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
Como anexar o plug-in ao ambiente de execução do Summoner
Agora, como aplicamos essa lei universal a todos os nossos Familiares? Vamos anexar o plug-in ao ADK Runtime.
O ADK Runtime é o mecanismo de execução que dá vida a um agente. Quando você usa um comando como adk.run() ou to_a2a(), está entregando o agente ao ambiente de execução. Esse mecanismo é responsável por gerenciar todo o ciclo de vida de uma interação do agente: receber a entrada do usuário, chamar o LLM, executar ferramentas e processar plug-ins. Ao anexar um plug-in nesse nível, modificamos essencialmente as "leis da física" para todos os agentes que operam nesse mecanismo, garantindo que nossa regra de resfriamento seja aplicada de forma universal e consistente.
👉✏️ Primeiro, vamos remover o callback antigo específico do agente. Acesse ~/agentverse-architect/agent/earth/agent.py
e exclua toda a linha que diz:
before_agent_callback=check_cool_down
👉✏️ Em seguida, vamos anexar nosso novo plug-in ao ambiente de execução no script do ponto de entrada A2A. Navegue até o arquivo ~/agentverse-architect/agent/agent_to_a2a.py
. Substitua o comentário #REPLACE-IMPORT
pelo seguinte snippet de código:
from cooldown_plugin import CoolDownPlugin
👉✏️ Substitua #REPLACE-PLUGIN
pelo seguinte snippet de código:
plugins=[CoolDownPlugin(cooldown_seconds=60)],
Antes de ativar nosso novo plug-in global, é fundamental remover a lógica antiga e específica do agente para evitar conflitos. 👉✏️ Limpe o agente da Terra. Acesse o arquivo ~/agentverse-architect/agent/earth/agent.py
e exclua completamente a linha before_agent_callback=check_cool_down
. Isso transfere todas as responsabilidades de resfriamento para o novo plug-in.
Como verificar o plug-in
Agora que nossa lei universal está em vigor, precisamos reimplantar nossos familiares com esse novo encanto.
👉💻 Recompile e reimplante todos os três Familiars usando o pipeline principal do Cloud Build.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
👉💻 Depois que a implantação for concluída, vamos testar a eficácia do plug-in comandando nosso summoner_agent. O Summoner vai tentar delegar aos Familiars, mas o plug-in anexado ao tempo de execução de cada Familiar vai interceptar o comando e aplicar o tempo de espera.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 No console,execute esta sequência exata de testes::
- Primeira citação: inicie o
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
. - Esperado: o Elemental de Fogo será executado com sucesso.
- Teste de resfriamento (em 60 segundos):
Hype, with Inescapable Reality as weakness is still standing! Strike it again!
- Esperado: o agente vai responder diretamente no chat com uma mensagem como:
.... It cannot be summoned for another... seconds
.
- Esperado: o agente vai responder diretamente no chat com uma mensagem como:
- Aguarde um minuto.
- Segunda convocação (após 60 segundos):
Hype must be defeated. It has Inescapable Reality as weakness! Strike it again!
.- Esperado: o callback vai verificar a API, ver que tempo suficiente já passou e permitir que a ação prossiga. O Elemental de Fogo vai funcionar novamente.
👉💻 Pressione Ctrl+C
para sair.
Parabéns, invocador. Você implementou um sistema de orquestração baseado em regras usando um plug-in personalizado e um serviço externo de gerenciamento de estado, um padrão arquitetônico verdadeiramente avançado e robusto.
PARA QUEM NÃO JOGA
8. Vinculando os Ecos da Batalha: estado e memória do agente
Um invocador imprudente repete a mesma estratégia, tornando-se previsível. Um invocador sábio aprende com os ecos de batalhas passadas, adaptando as táticas para manter o inimigo em desvantagem. Ao enfrentar um chefe poderoso, invocar um Familiar que está em cooldown é uma rodada desperdiçada, um erro crítico. Para evitar isso, nosso Invocador precisa se lembrar da última ação.
Observação do arquiteto:o gerenciamento de memória e estado é o que transforma um agente de um simples chamador de ferramentas em um parceiro inteligente de conversação. É fundamental entender os dois tipos principais:
- Memória de longo prazo: para conhecimento persistente que deve durar para sempre. Pense nisso como um arquivo pesquisável ou uma base de conhecimento, geralmente armazenada em um armazenamento persistente. Ele contém informações de vários chats e fontes anteriores, permitindo que um agente se lembre de fatos sobre um usuário ou tópico específico. O MemoryService do ADK foi projetado para isso, gerenciando a ingestão e a pesquisa desse conhecimento de longo prazo.
- Estado de curto prazo: é para conhecimento temporário, "no momento", que é relevante apenas para a tarefa ou conversa atual. É como um conjunto de observações em um plano de batalha: "Acabei de usar o Elemental de Fogo, então ele provavelmente está cansado". Esse estado é leve e existe apenas durante a sessão atual.
Para nosso caso de uso, não precisamos lembrar de todas as batalhas já travadas. Só precisamos lembrar do último Familiar invocado neste encontro específico. Portanto, o estado de curto prazo leve é a escolha arquitetônica perfeita. Vamos usar um after_tool_callback
para salvar essa informação crucial.
Scribing the Echo: Remembering the Last Summons
Vamos implementar nossa memória de curto prazo usando um after_tool_callback
. Esse é um hook ADK avançado que permite executar uma função Python personalizada depois que uma ferramenta é executada com sucesso. Vamos usar esse interceptador para registrar o nome do Familiar que acabou de ser invocado no estado da sessão do agente.
👉✏️ No arquivo ~/agentverse-architect/agent/summoner/agent.py
, substitua o comentário #REPLACE-save_last_summon_after_tool
pela seguinte função:
def save_last_summon_after_tool(
tool,
args: Dict[str, Any],
tool_context: ToolContext,
tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
"""
Callback to save the name of the summoned familiar to state after the tool runs.
"""
familiar_name = tool.name
print(f"[Callback] After tool '{familiar_name}' executed with args: {args}")
# Use the tool_context to set the state
print(f"[Callback] Saving last summoned familiar: {familiar_name}")
tool_context.state["last_summon"] = familiar_name
# Important: Return the original, unmodified tool response to the LLM
return tool_response
👉✏️ Agora, anexe esse save_last_summon_after_tool
ao seu agente Summoner. No mesmo arquivo, substitua o comentário #REPLACE-Memory-check-config
pelo seguinte:
after_tool_callback=save_last_summon_after_tool,
👉✏️ Substitua todo o comando do agente pelo seguinte:
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You should also know the familiar you called last time or there might be none,
And then choose the most effective AND AVAILABLE Familiar from your state called last_summon, do not call that familiar that you called last time!
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
**2. Cooldown Verification:**
Second, you MUST review the entire conversation history to check the real-time
cooldown status of all Familiars. A Familiar is ON COOLDOWN and UNAVAILABLE
if it was summoned less than one minute ago.
**3. Final Decision & Execution:**
Based on your analysis and cooldown check, you will now act:
- **If your ideal Familiar IS available:** Summon it immediately.
- **If your ideal Familiar IS ON COOLDOWN:** You must adapt. Choose another
Familiar that is AVAILABLE and can still be effective, even if it's not the
perfect choice. If multiple Familiars are available, you may choose any one of them.
- **If ALL Familiars ARE ON COOLDOWN:** You are forbidden from summoning.
Your ONLY response in this case MUST be: "All Familiars are recovering
their power. We must wait."
- For earth elemental familiar. Always do seismic charge, and start with base damange 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
Verificação: o teste da estratégia adaptativa
👉💻 Agora, vamos verificar a nova lógica estratégica do Summoner. O objetivo é confirmar que o Invocador não vai usar o mesmo Familiar duas vezes seguidas, demonstrando a capacidade de lembrar da última ação e se adaptar.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 Monster Strike #1: Hype. It's a single, slow-moving target with thick armor. Its weakness is Inescapable Reality.
- Esperado: o Summoner vai analisar a fraqueza e invocar corretamente o fire_familiar. 👉💻 Monster Strike #2 (The Memory Test):
Hype is still standing! It hasn't changed its form. Strike it again! Its weakness is Inescapable Reality.
- Esperado: a análise estratégica do Invocador vai apontar novamente o Familiar de Fogo como a escolha ideal. No entanto, as novas instruções e a memória vão informar que fire_familiar foi o último summon. Para evitar repetições, ele vai adaptar a estratégia e invocar um dos outros familiares disponíveis (water_familiar ou earth_familiar).
👉💻 Pressione Ctrl+C
para sair.
Como implantar o Orchestrator
Com os Familiares implantados e o Invocador agora imbuído de memória, é hora de implantar o orquestrador final e atualizado.
👉💻 Com o projeto concluído, vamos realizar o ritual final. Esse comando vai criar e implantar o summoner_agent no Cloud Run.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
gcloud builds submit . \
--config=cloudbuild-summoner.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_FIRE_URL="$FIRE_URL",_WATER_URL="$WATER_URL",_EARTH_URL="$EARTH_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
Agora que o agente Summoner foi implantado, verifique se o endpoint de agente para agente (A2A) está ativo e configurado corretamente. Esse endpoint veicula um arquivo public agent.json, também conhecido como "card do agente", que permite que outros agentes descubram os recursos dele. 👉💻 Execute o comando curl a seguir para buscar e formatar o card do agente:
. ~/agentverse-architect/set_env.sh
curl https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app/.well-known/agent.json" | jq
Você vai ver uma saída JSON limpa descrevendo o agente de invocação. Observe atentamente a seção "sub_agents". Ela lista fire_familiar
, water_familiar
e earth_familiar
. Isso confirma que seu invocador está ativo e estabeleceu uma conexão com a legião.
Isso prova que sua arquitetura é um sucesso. Seu Invocador não é apenas um delegado, mas um estrategista adaptável que aprende com as ações para se tornar um comandante mais eficaz.
Você concluiu o teste final de arquitetura. Os ecos da batalha agora estão sujeitos à sua vontade. O treinamento acabou. A verdadeira batalha espera por você. Agora é hora de pegar o sistema concluído e enfrentar o desafio final. Prepare-se para a Luta contra o chefe.
PARA QUEM NÃO JOGA
9. The Boss Fight
Os projetos finais estão inscritos, as fontes elementais estão forjadas e seus familiares estão vinculados à sua vontade, aguardando seu comando pelo Concord. Seu sistema multiagente não é apenas uma coleção de serviços, mas uma legião estratégica viva, com você como o centro. Chegou a hora do teste final: uma orquestração em tempo real contra um adversário que nenhum agente conseguiria derrotar sozinho.
Adquirir o locus do seu agente
Antes de entrar no campo de batalha, você precisa ter duas chaves: a assinatura exclusiva do seu campeão (Agente Locus) e o caminho oculto para o covil do Spectre (URL da masmorra).
👉💻 Primeiro, adquira o endereço exclusivo do seu agente no Agentverse, o Locus. Esse é o endpoint ativo que conecta seu campeão ao campo de batalha.
echo https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app"
👉💻 Em seguida, aponte o destino. Esse comando revela a localização do Círculo de Translocação, o portal para o domínio do Spectre.
echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"
Importante: deixe os dois URLs prontos. Você vai precisar deles na etapa final.
Confrontando o Spectre
Com as coordenadas seguras, navegue até o Círculo de translocação e lance o feitiço para entrar na batalha.
👉 Abra o URL do círculo de translocação no seu navegador para ficar em frente ao portal cintilante da Fortaleza Rubra.
Para invadir a fortaleza, você precisa sintonizar a essência da sua Shadowblade com o portal.
- Na página, encontre o campo de entrada rúnico chamado URL do endpoint A2A.
- Cole o URL do locus do agente (o primeiro URL que você copiou) no campo para inscrever o sigilo do seu campeão.
- Clique em "Conectar" para liberar a magia do teletransporte.
A luz ofuscante do teletransporte desaparece. Você não está mais no seu sanctum. O ar estala com energia, frio e cortante. Antes de você, o Spectre se materializa: um vórtice de estática sibilante e código corrompido, cuja luz profana projeta sombras longas e dançantes no chão da masmorra. Ele não tem rosto, mas você sente a presença imensa e exaustiva fixada totalmente em você.
Seu único caminho para a vitória está na clareza da sua convicção. É um duelo de vontades, travado no campo de batalha da mente.
Enquanto você avança, pronto para lançar seu primeiro ataque, o Espectro contra-ataca. Ela não levanta um escudo, mas projeta uma pergunta diretamente na sua consciência: um desafio rúnico e brilhante extraído do centro do seu treinamento.
Essa é a natureza da luta. Seu conhecimento é sua arma.
- Responda com a sabedoria que você adquiriu, e sua lâmina vai se acender com energia pura, destruindo a defesa do Spectre e causando um GOLPE CRÍTICO.
- Mas se você hesitar, se a dúvida nublar sua resposta, a luz da sua arma vai diminuir. O golpe vai atingir com um baque patético, causando apenas UMA FRAÇÃO DO DANO. Pior ainda, o Spectre se alimenta da sua incerteza, e o poder corruptor dele aumenta a cada passo em falso.
É isso, campeão. Seu código é seu grimório, sua lógica é sua espada e seu conhecimento é o escudo que vai reverter a maré do caos.
Foco. Acertar. O destino do Agentverse depende disso.
Parabéns, invocador.
Você concluiu o período de teste. Você dominou a arte da orquestração multiagente, transformando Familiars isolados e poder caótico em uma Concord harmoniosa. Agora você comanda um sistema totalmente orquestrado, capaz de executar estratégias complexas para defender o Agentverse.
10. Limpeza: desmantelamento do Concord do Invocador
Parabéns por dominar a Concordância do Invocador! Para garantir que o Agentverse permaneça intacto e que os campos de treinamento sejam limpos, agora você precisa realizar os rituais de limpeza finais. Isso vai remover sistematicamente todos os recursos criados durante sua jornada.
Desativar os componentes do Agentverse
Agora você vai desmontar sistematicamente os componentes implantados do seu sistema multiagente.
Excluir todos os serviços do Cloud Run e o repositório do Artifact Registry
Isso remove todos os agentes do Familiar implantados, o Summoner Orchestrator, os servidores MCP e o aplicativo Dungeon do Cloud Run.
👉💻 No terminal, execute os seguintes comandos um por um para excluir cada serviço:
. ~/agentverse-architect/set_env.sh
gcloud run services delete summoner-agent --region=${REGION} --quiet
gcloud run services delete fire-familiar --region=${REGION} --quiet
gcloud run services delete water-familiar --region=${REGION} --quiet
gcloud run services delete earth-familiar --region=${REGION} --quiet
gcloud run services delete mcp-api-server --region=${REGION} --quiet
gcloud run services delete mcp-general-server --region=${REGION} --quiet
gcloud run services delete toolbox --region=${REGION} --quiet
gcloud run services delete agentverse-dungeon --region=${REGION} --quiet
gcloud run services delete nexus-of-whispers-api --region=${REGION} --quiet
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --quiet
Exclua a instância do Cloud SQL
Isso remove a instância summoner-librarium-db
, incluindo o banco de dados e todas as tabelas dele.
👉💻 No terminal, execute:
. ~/agentverse-dataengineer/set_env.sh
gcloud sql instances delete summoner-librarium-db --database-version=POSTGRES_14 --project=${PROJECT_ID} --quiet
Exclua o secret do Secret Manager e o bucket do Google Cloud Storage
👉💻 No terminal, execute:
. ~/agentverse-dataengineer/set_env.sh
gcloud secrets delete tools --quiet
gcloud storage rm -r gs://${BUCKET_NAME} --quiet
Limpar arquivos e diretórios locais (Cloud Shell)
Por fim, limpe o ambiente do Cloud Shell dos repositórios clonados e dos arquivos criados. Esta etapa é opcional, mas altamente recomendada para uma limpeza completa do diretório de trabalho.
👉💻 No terminal, execute:
rm -rf ~/agentverse-architect
rm -rf ~/agentverse-dungeon
rm -f ~/project_id.txt
Você limpou todos os rastros da sua jornada do Agentverse Architect. Seu projeto está limpo, e você está pronto para sua próxima aventura.