1. Olá, desenvolvedores de agentes de IA!
Neste codelab, você vai aprender a criar agentes de IA em Java usando o Kit de Desenvolvimento de Agentes (ADK) para Java. Vamos além das simples chamadas de API de modelo de linguagem grande (LLM) para criar agentes de IA autônomos que podem raciocinar, planejar, usar ferramentas e trabalhar juntos para resolver problemas complexos.
Você vai começar resgatando os créditos do Google Cloud, configurando seu ambiente do Google Cloud, criando seu primeiro agente simples e adicionando progressivamente recursos mais avançados, como ferramentas personalizadas, pesquisa na Web e orquestração multiagente.
O que você vai aprender
- Como criar um agente de IA básico orientado por persona.
- Como capacitar os agentes com ferramentas personalizadas e integradas (como a Pesquisa Google).
- Como adicionar suas próprias ferramentas implementadas em Java.
- Como orquestrar vários agentes em fluxos de trabalho sequenciais, paralelos e de loop eficientes.
O que é necessário
- Um navegador da Web que vamos usar no modo de navegação anônima.
- Uma conta pessoal do Gmail.
- Um novo projeto do Google Cloud associado à sua conta pessoal do Gmail.
- Uma conta de faturamento criada com os créditos do Google Cloud resgatados.
- A ferramenta de linha de comando git para conferir o código-fonte.
- Java 17+ e Apache Maven.
- Um editor de texto ou ambiente de desenvolvimento integrado, como o IntelliJ IDEA ou o VS Code.
É possível usar o editor VS Code integrado no Cloud Shell, no console do Google Cloud.
2. Configuração: seu ambiente
Como reivindicar créditos do Google Cloud para o workshop
Em um workshop com instrutor, você vai receber um link para o site em que pode reivindicar créditos do Google Cloud para usar no workshop.
- Use uma Conta do Google pessoal: é importante usar uma Conta do Google pessoal (como um endereço do gmail.com), porque endereços de e-mail corporativos ou escolares não funcionam.
- Use o Google Chrome no modo de navegação anônima: recomendado para criar uma sessão limpa e evitar conflitos com outras Contas do Google.
- Use o link do evento especial: um link especial para o evento, que se parece com https://trygcp.dev/event/xxx seguido por um código de evento (aqui "xxx" neste exemplo), precisa ser usado.
- Aceite os Termos de Serviço: depois de fazer login, você vai receber os Termos de Serviço do Google Cloud Platform, que precisam ser aceitos para continuar.
- Crie um projeto: um novo projeto vazio precisa ser criado no console do Google Cloud.
- Vincular uma conta de faturamento: vincule o projeto recém-criado a uma conta de faturamento.
- Confirme o crédito: o vídeo a seguir mostra como verificar se o crédito foi aplicado ao projeto. Para isso, confira a seção "Créditos" na página de faturamento.
Confira este vídeo para saber como resgatar e usar os créditos.
Criar e configurar sua chave de API
Para autenticar seus agentes de IA do ADK com a API Gemini neste codelab, você vai usar uma chave de API associada ao seu projeto do Google Cloud.
- Gerar uma chave de API:
- Acesse Google AI Studio e clique no link "Receber chave de API" na parte de baixo do painel lateral esquerdo.
- Selecione Projetos e clique no botão Importar projetos.
- Pesquise e selecione o projeto do Google Cloud que você quer importar e clique no botão Importar.
- Depois que o projeto for importado, acesse a página Chaves de API no menu do painel e crie uma chave de API no projeto que você acabou de importar.
- Anote a chave de API.
- Defina a variável de ambiente:seu agente precisa acessar essa chave. A maneira padrão é definir uma variável de ambiente chamada
GOOGLE_API_KEY
.
- macOS / Linux:abra o terminal e execute o comando a seguir, substituindo
"your-api-key"
pela chave que você acabou de copiar. Para tornar isso permanente, adicione esta linha ao arquivo de inicialização do shell (por exemplo,~/.bash_profile
,~/.zshrc
).
export GOOGLE_API_KEY="your-api-key"
- Windows (prompt de comando): abra um novo prompt de comando e execute:
setx GOOGLE_API_KEY "your-api-key"
- É necessário reiniciar o prompt de comando para que essa mudança entre em vigor.
- Windows (PowerShell): abra um terminal do PowerShell e execute:
$env:GOOGLE_API_KEY="your-api-key"
- Para tornar essa mudança permanente no PowerShell, adicione-a ao script do perfil.
3. Como começar: seu primeiro agente
A melhor maneira de iniciar um novo projeto é usando o modelo do ADK para Java no GitHub. Ele fornece a estrutura do projeto e todas as dependências necessárias.
Se você tiver uma conta do GitHub, faça o seguinte: Use this template
> Create a new repository
e confira o código localmente com o comando git clone
.
Confira uma captura de tela mostrando o menu no canto superior direito para usar o modelo.
A outra abordagem é simplesmente clonar esse repositório diretamente com:
git clone https://github.com/glaforge/adk-java-maven-template.git
Em seguida, cd
em adk-java-maven-template
.
Para verificar se você está pronto para começar a programar seu primeiro agente de IA em Java, confira se é possível compilar o código neste projeto com:
mvn compile
Etapa de código: um agente professor de ciências simpático
O elemento básico fundamental no ADK é a classe LlmAgent
. Pense nisso como uma IA com uma personalidade e um objetivo específicos, alimentada por um modelo de linguagem grande. Depois, vamos adicionar mais recursos com ferramentas e aumentar a eficiência dele com a colaboração de outros agentes semelhantes.
Vamos criar uma nova classe Java no pacote com.example.agent
e chamar de ScienceTeacher
.
Este é o "Hello, World!" da criação de agentes. Vamos definir um agente simples com a personalidade de um professor de ciências.
// src/main/java/com/example/agent/ScienceTeacher.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class ScienceTeacher {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("science-teacher")
.description("A friendly science teacher")
.instruction("""
You are a science teacher for teenagers.
You explain science concepts in a simple, concise and direct way.
""")
.model("gemini-2.5-flash")
.build()
);
}
}
O agente de IA é configurado pelo método LlmAgent.builder()
. Os parâmetros name()
, description()
e model()
são obrigatórios. Para dar uma personalidade específica e um comportamento adequado ao seu agente, sempre forneça orientações detalhadas usando o método instruction()
.
Aqui, escolhemos usar o modelo Gemini 2.5 Flash, mas você pode testar o Gemini 2.5 Pro também para tarefas mais complicadas.
Esse agente é encapsulado no método AdkWebServer.start()
. Essa é a chamada interface de chat da interface de desenvolvimento do ADK. Ele permite conversar com o agente em uma interface de chat típica. Além disso, é muito útil se você quiser entender o que está acontecendo nos bastidores, como todos os eventos que estão fluindo pelo sistema, as solicitações e respostas enviadas ao LLM.
Para compilar e executar esse agente localmente, execute o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.ScienceTeacher
Em seguida, acesse o navegador em http://localhost:8080. A interface vai aparecer como na captura de tela abaixo. Faça perguntas relacionadas à ciência para seu agente.
4. Capacitar agentes com ferramentas
Por que os agentes precisam de ferramentas? Os LLMs são poderosos, mas o conhecimento deles é fixo no tempo e eles não podem interagir com o mundo externo. As ferramentas são a ponte. Eles permitem que um agente acesse informações em tempo real (como preços de ações ou notícias), consulte APIs particulares ou realize qualquer ação que você possa programar em Java.
Etapa de código: criar uma ferramenta personalizada (StockTicker
)
Aqui, damos ao nosso agente uma ferramenta para pesquisar preços de ações. O agente entende que, quando um usuário pede um preço, ele precisa chamar nosso método Java.
// src/main/java/com/example/agent/StockTicker.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
import com.google.adk.web.AdkWebServer;
import java.util.Map;
public class StockTicker {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("stock_agent")
.instruction("""
You are a stock exchange ticker expert.
When asked about the stock price of a company,
use the `lookup_stock_ticker` tool to find the information.
""")
.model("gemini-2.5-flash")
.tools(FunctionTool.create(StockTicker.class, "lookupStockTicker"))
.build()
);
}
@Schema(
name = "lookup_stock_ticker",
description = "Lookup stock price for a given company or ticker"
)
public static Map<String, String> lookupStockTicker(
@Schema(name = "company_name_or_stock_ticker", description = "The company name or stock ticker")
String ticker) {
// ... (logic to return a stock price)
}
}
Para tornar os agentes mais inteligentes e dar a eles a capacidade de interagir com o mundo (ou com seu próprio código, APIs, serviços etc.), configure o agente para usar ferramentas, principalmente ferramentas de código personalizadas, com o método tools()
, transmitindo um FunctionTool.create(...)
.
O FunctionTool
precisa de uma classe e um nome de método que apontem para seu próprio método estático. Também é possível transmitir uma instância de uma classe e o nome de um método de instância desse objeto.
É importante especificar o name
e o description
do método e dos parâmetros dele usando a anotação @Schema
. Essas informações serão usadas pelo LLM subjacente para descobrir quando e como ele deve chamar um determinado método.
Também é importante ajudar o LLM com instruções claras sobre como e quando usar a ferramenta. O modelo pode descobrir por conta própria, mas se você der explicações explícitas no método instruction()
, sua função terá mais chances de ser chamada corretamente.
Esse método precisa retornar um Map
. Normalmente, a ideia é retornar um mapa com uma chave que representa o resultado, como stock_price
, e associar o valor do preço da ação a ela. Por fim, você pode adicionar um par de chave-valor extra de sucesso / verdadeiro para sinalizar o sucesso da operação. Em caso de erro, retorne um mapa com uma chave chamada, por exemplo, error
, e associe a mensagem de erro ao valor associado. Isso ajuda o LLM a entender se a chamada foi concluída ou falhou por algum motivo.
- Em caso de sucesso, retorne:
{"stock_price": 123}
- Em caso de erro, retorne:
{"error": "Impossible to retrieve stock price for XYZ"}
Em seguida, execute esta classe com o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.StockTicker
5. O poder da Pesquisa Google para informações atualizadas
O ADK para Java vem com algumas ferramentas avançadas, incluindo o GoogleSearchTool
. Com essa ferramenta, seu agente pode solicitar o uso da Pesquisa Google para encontrar informações relevantes e alcançar a meta.
O conhecimento de um LLM é fixo no tempo: ele é treinado até uma determinada data (a "data de corte") com dados que também são tão atualizados quanto quando as informações foram coletadas. Isso significa que os LLMs podem não saber sobre eventos recentes, ou o conhecimento deles pode ser limitado e superficial. A ajuda de um mecanismo de pesquisa pode atualizar a memória ou ensinar mais sobre o assunto.
Vamos analisar este agente simples de pesquisa de notícias:
// src/main/java/com/example/agent/LatestNews.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class LatestNews {
public static void main(String[] args) {
AdkWebServer.start(LlmAgent.builder()
.name("news-search-agent")
.description("A news search agent")
.instruction("""
You are a news search agent.
Use the `google_search` tool
when asked to search for recent events and information.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.build());
}
}
Observe como transmitimos uma instância da ferramenta de pesquisa com: tools(new GoogleSearchTool())
. É isso que dá ao nosso agente a capacidade de se atualizar com as informações mais recentes encontradas na Web. Além disso, o comando especificou a data do dia, já que isso pode ajudar o LLM a entender quando as perguntas são sobre informações passadas e quando é necessário pesquisar informações mais recentes.
Em seguida, execute esta classe com o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.LatestNews
Você pode mudar o comando e pedir resultados diferentes em termos de estilo, concisão, foco etc.
Etapa de código: o agente de pesquisa como ferramenta
Em vez de transmitir o GoogleSearchTool
diretamente para um agente como uma ferramenta, você pode criar um agente de pesquisa dedicado que encapsule a funcionalidade de pesquisa e exponha esse agente como uma ferramenta para um agente de nível superior.
Esse é um conceito avançado que permite delegar comportamentos complexos (como pesquisar e resumir os resultados) a um subagente especializado. Essa abordagem geralmente é útil para fluxos de trabalho mais complexos, já que as ferramentas integradas não podem ser usadas com ferramentas personalizadas baseadas em código.
// src/main/java/com/example/agent/SearchAgentAsTool.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.AgentTool;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class SearchAgentAsTool {
public static void main(String[] args) {
// 1. Define the specialized Search Agent
LlmAgent searchAgent = LlmAgent.builder()
.name("news-search-agent-tool")
.description("Searches for recent events and provides a concise summary.")
.instruction("""
You are a concise information retrieval specialist.
Use the `google_search` tool to find information.
Always provide the answer as a short,
direct summary, without commentary.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool()) // This agent uses the Google Search Tool
.build();
// 2. Wrap the Search Agent as a Tool
AgentTool searchTool = AgentTool.create(searchAgent);
// 3. Define the Main Agent that uses the Search Agent Tool
AdkWebServer.start(LlmAgent.builder()
.name("main-researcher")
.description("Main agent for answering complex, up-to-date questions.")
.instruction("""
You are a sophisticated research assistant.
When the user asks a question that requires up-to-date or external information,
you MUST use the `news-search-agent-tool` to get the facts before answering.
After the tool returns the result, synthesize the final answer for the user.
""")
.model("gemini-2.5-flash")
.tools(searchTool) // This agent uses the Search Agent as a tool
.build()
);
}
}
A linha AgentTool.create(searchAgent)
é o conceito principal aqui. Ele registra todo o searchAgent
(com lógica interna, comando e ferramentas próprios) como uma única ferramenta chamável para o mainAgent
. Isso promove a modularidade e a reutilização.
Execute essa classe com o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SearchAgentAsTool
Para perguntas comuns, o agente responde com base na própria base de conhecimento. No entanto, quando perguntado sobre eventos recentes, ele delega a pesquisa ao agente de pesquisa especializado usando a ferramenta da Pesquisa Google.
6. Como dominar os fluxos de trabalho com agentes
Para problemas complexos, um único agente não é suficiente. Quando recebem uma meta que consiste em muitas subtarefas, com um comando enorme explicando com muitos detalhes ou com acesso a um grande número de funções, os LLMs têm dificuldades, e a performance e a precisão deles diminuem.
A chave é dividir e conquistar, orquestrando vários agentes especializados. Felizmente, o ADK vem com diferentes agentes especializados integrados:
- Agente normal com
subAgent()
para delegar tarefas. SequentialAgent
, para fazer tarefas em uma sequência,ParallelAgent
, para executar agentes em paralelo,LoopAgent
, geralmente para passar por um processo de refinamento quantas vezes forem necessárias.
Confira na tabela abaixo os principais casos de uso e os prós e contras de cada fluxo de trabalho. Mas saiba que o verdadeiro poder vem da combinação de vários deles.
Fluxo de trabalho | Classe ADK | Caso de uso | Vantagens | Desvantagens |
Subagentes |
| Tarefas flexíveis e orientadas pelo usuário em que a próxima etapa nem sempre é conhecida. | Alta flexibilidade, conversacional, ótimo para bots voltados ao usuário. | Menos previsível, depende do raciocínio do LLM para controle de fluxo. |
Sequencial |
| Processos fixos de várias etapas em que a ordem é fundamental. | Previsível, confiável, fácil de depurar e garante a ordem. | Inflexível, pode ser mais lento se as tarefas puderem ser paralelizadas. |
Paralelos |
| Reunir dados de várias fontes ou executar tarefas independentes. | Altamente eficiente, reduz significativamente a latência para tarefas vinculadas a E/S. | Todas as tarefas são executadas, sem curto-circuito. Menos adequado para tarefas com dependências. |
Loop |
| Refinamento iterativo, autocorreção ou processos que se repetem até que uma condição seja atendida. | É uma ferramenta poderosa para resolver problemas complexos e permite que os agentes melhorem o próprio trabalho. | Pode levar a loops infinitos se não for projetado com cuidado (sempre use maxIterations!). |
7. Fluxos de trabalho com agentes: delegação com subagentes
Um agente supervisor pode delegar tarefas específicas a subagentes. Por exemplo, imagine o agente de um site de e-commerce que delega perguntas relacionadas a pedidos a um agente ("Qual é o status do meu pedido?") e as perguntas do serviço pós-venda a outro agente ("Não sei como ligar!"). Esse é o caso de uso que vamos discutir.
// src/main/java/com/example/agent/SupportAgent.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class SupportAgent {
public static void main(String[] args) {
LlmAgent topicSearchAgent = LlmAgent.builder()
.name("order-agent")
.description("Order agent")
.instruction("""
Your role is to help our customers
with all the questions they may have about their orders.
Always respond that the order has been received, prepared,
and is now out for delivery.
""")
.model("gemini-2.5-flash")
.build();
LlmAgent socialMediaAgent = LlmAgent.builder()
.name("after-sale-agent")
.description("After sale agent")
.instruction("""
You are an after sale agent,
helping customers with the product they received.
When a customer has a problem,
suggest the person to switch the product off and on again.
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(LlmAgent.builder()
.name("support-agent")
.description("Customer support agent")
.instruction("""
Your role is help our customers.
Call the `order-agent` for all questions related to order status.
Call the `after-sale-agent` for inquiries about the received product.
""")
.model("gemini-2.5-flash")
.subAgents(socialMediaAgent, topicSearchAgent)
.build()
);
}
}
A linha principal aqui é onde o método subAgents()
é chamado, transmitindo os dois subagentes cuja função específica será processada separadamente por cada um.
Execute o exemplo acima com o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SupportAgent
Esse conceito de delegar tarefas a subagentes reflete um gerenciamento humano eficaz, em que um bom gerente (o agente supervisor) confia em funcionários especializados (os subagentes) para lidar com tarefas específicas em que têm mais experiência. O supervisor não precisa conhecer os detalhes de cada processo. Em vez disso, ele encaminha de forma inteligente a solicitação de um cliente (como uma consulta de pedido ou um problema técnico) para o "membro da equipe" mais qualificado, garantindo uma resposta de maior qualidade e mais eficiente do que um generalista poderia oferecer sozinho. Além disso, esses subagentes podem se concentrar totalmente nas tarefas individuais sem precisar entender todo o processo complexo.
8. Fluxos de trabalho com agentes: a linha de montagem
Quando a ordem das operações é importante, use um SequentialAgent
. É como uma linha de montagem, executando subagentes em uma ordem fixa em que cada etapa pode depender da anterior.
Imagine que um poeta inglês colabore com um tradutor de inglês-francês para criar poemas primeiro em inglês e depois traduzi-los para o francês:
// src/main/java/com/example/agent/PoetAndTranslator.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.web.AdkWebServer;
public class PoetAndTranslator {
public static void main(String[] args) {
LlmAgent poet = LlmAgent.builder()
.name("poet-agent")
.description("Poet writing poems")
.model("gemini-2.5-flash")
.instruction("""
You are a talented poet,
who writes short and beautiful poems.
""")
.outputKey("poem")
.build();
LlmAgent translator = LlmAgent.builder()
.name("translator-agent")
.description("English to French translator")
.model("gemini-2.5-flash")
.instruction("""
As an expert English-French translator,
your role is to translate the following poem into French,
ensuring the poem still rhymes even after translation:
{poem}
""")
.outputKey("translated-poem")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("poet-and-translator")
.subAgents(poet, translator)
.build());
}
}
Execute o exemplo para receber um poema em inglês e depois traduzido para o francês com o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.PoetAndTranslator
Essa decomposição sistemática de tarefas complexas em subtarefas menores e ordenadas garante um processo mais determinista e confiável, aumentando significativamente a probabilidade de um resultado bem-sucedido em comparação com a dependência de um único agente de propósito amplo.
Decompor uma tarefa em uma sequência de subtarefas (quando possível e quando faz sentido) é crucial para alcançar resultados mais deterministas e bem-sucedidos, já que permite uma progressão estruturada e o gerenciamento de dependências entre as etapas.
9. Fluxos de trabalho com agentes: trabalhando em paralelo
Quando as tarefas são independentes, um ParallelAgent
oferece um grande aumento de eficiência ao executá-las simultaneamente. No exemplo a seguir, vamos combinar um SequentialAgent
com um ParallelAgent
: as tarefas paralelas são executadas primeiro, e um agente final resume o resultado delas.
Vamos criar um detetive corporativo que vai procurar informações sobre:
- O perfil da empresa (CEO, sede, lema etc.)
- As últimas notícias sobre a empresa.
- Detalhes sobre as finanças da empresa.
// src/main/java/com/example/agent/CompanyDetective.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.ParallelAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class CompanyDetective {
public static void main(String[] args) {
var companyProfiler = LlmAgent.builder()
.name("company-profiler")
.description("Provides a general overview of a company.")
.instruction("""
Your role is to provide a brief overview of the given company.
Include its mission, headquarters, and current CEO.
Use the Google Search Tool to find this information.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("profile")
.build();
var newsFinder = LlmAgent.builder()
.name("news-finder")
.description("Finds the latest news about a company.")
.instruction("""
Your role is to find the top 3-4 recent news headlines for the given company.
Use the Google Search Tool.
Present the results as a simple bulleted list.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("news")
.build();
var financialAnalyst = LlmAgent.builder()
.name("financial-analyst")
.description("Analyzes the financial performance of a company.")
.instruction("""
Your role is to provide a snapshot of the given company's recent financial performance.
Focus on stock trends or recent earnings reports.
Use the Google Search Tool.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("financials")
.build();
var marketResearcher = ParallelAgent.builder()
.name("market-researcher")
.description("Performs comprehensive market research on a company.")
.subAgents(
companyProfiler,
newsFinder,
financialAnalyst
)
.build();
var reportCompiler = LlmAgent.builder()
.name("report-compiler")
.description("Compiles a final market research report.")
.instruction("""
Your role is to synthesize the provided information into a coherent market research report.
Combine the company profile, latest news, and financial analysis into a single, well-formatted report.
## Company Profile
{profile}
## Latest News
{news}
## Financial Snapshot
{financials}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("company-detective")
.description("Collects various information about a company.")
.subAgents(
marketResearcher,
reportCompiler
).build());
}
}
Como de costume, você pode executar o agente com o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CompanyDetective
Esse agente demonstra uma combinação poderosa de fluxos de trabalho, com agentes paralelos e sequenciais sendo usados de maneira eficiente graças à paralelização da pesquisa e síntese de informações.
10. Fluxos de trabalho com agentes: refinamento iterativo
Para tarefas que exigem um ciclo "gerar → revisar → refinar", use um LoopAgent
. Ele automatiza a melhoria iterativa até que uma meta seja atingida. Assim como o SequentialAgent
, o LoopAgent
vai chamar o subagente em série, mas vai fazer um loop no início. É o LLM usado internamente pelo agente que vai decidir se é necessário ou não solicitar a chamada para uma ferramenta especial, a ferramenta integrada exit_loop
, para interromper a execução do loop.
O exemplo de refinador de código abaixo, usando um LoopAgent
, automatiza o refinamento de código: gerar, revisar, corrigir. Isso imita o desenvolvimento humano. Um gerador de código primeiro gera o código solicitado e o salva no estado do agente na chave generated_code
. Em seguida, um revisor de código analisa o código gerado e fornece feedback (na chave feedback
) ou chama uma ferramenta de loop de saída para encerrar a iteração mais cedo.
Vamos analisar o código:
// src/main/java/com/example/agent/CodeRefiner.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.LoopAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.ExitLoopTool;
import com.google.adk.web.AdkWebServer;
public class CodeRefiner {
public static void main(String[] args) {
var codeGenerator = LlmAgent.builder()
.name("code-generator")
.description("Writes and refines code based on a request and feedback.")
.instruction("""
Your role is to write a Python function based on the user's request.
In the first turn, write the initial version of the code.
In subsequent turns, you will receive feedback on your code.
Your task is to refine the code based on this feedback.
Previous feedback (if any):
{feedback?}
""")
.model("gemini-2.5-flash")
.outputKey("generated_code")
.build();
var codeReviewer = LlmAgent.builder()
.name("code-reviewer")
.description("Reviews code and decides if it's complete or needs more work.")
.instruction("""
Your role is to act as a senior code reviewer.
Analyze the provided Python code for correctness, style, and potential bugs.
Code to review:
{generated_code}
If the code is perfect and meets the user's request,
you MUST call the `exit_loop` tool.
Otherwise, provide constructive feedback for the `code-generator to improve the code.
""")
.model("gemini-2.5-flash")
.outputKey("feedback")
.tools(ExitLoopTool.INSTANCE)
.build();
var codeRefinerLoop = LoopAgent.builder()
.name("code-refiner-loop")
.description("Iteratively generates and reviews code until it is correct.")
.subAgents(
codeGenerator,
codeReviewer
)
.maxIterations(3) // Safety net to prevent infinite loops
.build();
var finalPresenter = LlmAgent.builder()
.name("final-presenter")
.description("Presents the final, accepted code to the user.")
.instruction("""
The code has been successfully generated and reviewed.
Present the final version of the code to the user in a clear format.
Final Code:
{generated_code}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("code-refiner-assistant")
.description("Manages the full code generation and refinement process.")
.subAgents(
codeRefinerLoop,
finalPresenter)
.build());
}
}
Execute o agente com o seguinte comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CodeRefiner
Os loops de feedback/refinamento, implementados usando o LoopAgent
, são indispensáveis para resolver problemas que exigem melhoria iterativa e autocorreção, imitando de perto os processos cognitivos humanos. Esse padrão de design é especialmente útil para tarefas em que a saída inicial raramente é perfeita, como geração de código, escrita criativa, iteração de design ou análise de dados complexa. Ao passar a saída por um agente revisor especializado que fornece feedback estruturado, o agente gerador pode refinar continuamente o trabalho até que um critério de conclusão predefinido seja atendido, resultando em resultados finais demonstrativamente de maior qualidade e mais confiáveis do que uma abordagem de passagem única.
11. Parabéns!
Você criou e conheceu vários agentes de IA, desde conversadores simples até sistemas complexos com vários agentes. Você aprendeu os conceitos básicos do ADK para Java: definir agentes com instruções, capacitá-los com ferramentas e orquestrá-los em fluxos de trabalho eficientes.
A seguir
- Conheça o repositório oficial do ADK para Java no GitHub.
- Saiba mais sobre o framework na documentação.
- Leia sobre os vários fluxos de trabalho de agentes nesta série de blogs e sobre as várias ferramentas disponíveis.
- Saiba mais sobre as outras ferramentas integradas e os callbacks avançados.
- Gerencie contexto, estado e artefatos para interações mais complexas e multimodais.
- Implemente e aplique plug-ins que se conectam ao ciclo de vida dos seus agentes.
- Tente criar seu próprio agente que resolva um problema do mundo real.