1. Te damos la bienvenida, desarrollador de agentes de IA.
En este codelab, aprenderás a compilar agentes de IA en Java con el Kit de desarrollo de agentes (ADK) para Java. Iremos más allá de las simples llamadas a la API del modelo de lenguaje grande (LLM) para crear agentes autónomos de IA que puedan razonar, planificar, usar herramientas y trabajar en conjunto para resolver problemas complejos.
Comenzarás canjeando los créditos de Google Cloud, configurando tu entorno de Google Cloud y, luego, crearás tu primer agente simple y agregarás progresivamente capacidades más avanzadas, como herramientas personalizadas, búsqueda web y organización de varios agentes.
Qué aprenderás
- Cómo crear un agente de IA básico basado en arquetipos
- Cómo potenciar a los agentes con herramientas personalizadas y herramientas integradas (como la Búsqueda de Google)
- Cómo agregar tus propias herramientas implementadas en Java
- Cómo organizar varios agentes en flujos de trabajo potentes secuenciales, paralelos y de bucle
Requisitos
- Un navegador web que usaremos en modo Incógnito.
- Una cuenta personal de Gmail
- Un nuevo proyecto de Google Cloud asociado a tu cuenta personal de Gmail
- Una cuenta de facturación creada con los créditos de Google Cloud canjeados
- La herramienta de línea de comandos de Git para extraer el código fuente
- Java 17 (o versiones posteriores) y Apache Maven
- Un editor de texto o IDE, como IntelliJ IDEA o VS Code
Es posible usar el editor de VS Code integrado en Cloud Shell, en la consola de Google Cloud.
2. Configuración: Tu entorno
Cómo reclamar créditos de Google Cloud para el taller
En el caso de un taller dirigido por un instructor, habrás recibido un vínculo al sitio web en el que puedes reclamar créditos de Google Cloud para usar en el taller.
- Usa una Cuenta de Google personal: Es importante usar una Cuenta de Google personal (como una dirección de gmail.com), ya que las direcciones de correo electrónico corporativas o educativas no funcionarán.
- Usa Google Chrome en modo incógnito: Se recomienda para crear una sesión limpia y evitar conflictos con otras Cuentas de Google.
- Usa el vínculo del evento especial: Se debe usar un vínculo especial para el evento, que se ve como https://trygcp.dev/event/xxx seguido de un código de evento (aquí "xxx" en este ejemplo).
- Acepta las condiciones del servicio: Después de acceder, se te presentarán las condiciones del servicio de Google Cloud Platform, que debes aceptar para continuar.
- Crea un proyecto nuevo: Se debe crear un proyecto vacío nuevo desde la consola de Google Cloud.
- Vincular una cuenta de facturación: Vincula el proyecto recién creado a una cuenta de facturación.
- Confirma el crédito: En el siguiente video, se muestra cómo confirmar que el crédito se aplicó al proyecto. Para ello, revisa la sección "Créditos" en la página de facturación.
Puedes mirar este video para saber cómo canjear y aplicar los créditos.
Crea y configura tu clave de API
Para autenticar tus agentes de IA del ADK con la API de Gemini en este codelab, usarás una clave de API asociada a tu proyecto de Google Cloud.
- Genera una clave de API:
- Ve a Google AI Studio y haz clic en el vínculo "Obtener clave de API" que se encuentra en la parte inferior del panel lateral izquierdo.
- Selecciona Proyectos y, luego, haz clic en el botón Importar proyectos.
- Busca y selecciona el proyecto de Google Cloud que deseas importar y, luego, selecciona el botón Importar.
- Una vez que se importe el proyecto, ve a la página Claves de API del menú del panel y crea una clave de API en el proyecto que acabas de importar.
- Anota la clave de API.
- Configura la variable de entorno: Tu agente debe acceder a esta clave. La forma estándar es configurar una variable de entorno llamada
GOOGLE_API_KEY
.
- macOS o Linux: Abre la terminal y ejecuta el siguiente comando, reemplazando
"your-api-key"
por la clave que acabas de copiar. Para que esto sea permanente, agrega esta línea al archivo de inicio de tu shell (p.ej.,~/.bash_profile
,~/.zshrc
).
export GOOGLE_API_KEY="your-api-key"
- Windows (símbolo del sistema): Abre un símbolo del sistema nuevo y ejecuta el siguiente comando:
setx GOOGLE_API_KEY "your-api-key"
- Deberás reiniciar el símbolo del sistema para que se aplique este cambio.
- Windows (PowerShell): Abre una terminal de PowerShell y ejecuta lo siguiente:
$env:GOOGLE_API_KEY="your-api-key"
- Para que este cambio sea permanente en PowerShell, deberás agregarlo a la secuencia de comandos de tu perfil.
3. Primeros pasos: Tu primer agente
La mejor manera de comenzar un proyecto nuevo es usar la plantilla de GitHub del ADK para Java. Proporciona la estructura del proyecto y todas las dependencias necesarias.
Si tienes una cuenta de GitHub, puedes hacer lo siguiente: Use this template
> Create a new repository
y, luego, extraer el código de forma local con el comando git clone
.
Aquí tienes una captura de pantalla que muestra el menú de la esquina superior derecha para usar la plantilla.
El otro enfoque es clonar directamente ese repositorio con el siguiente comando:
git clone https://github.com/glaforge/adk-java-maven-template.git
Luego, cd
en adk-java-maven-template
.
Para verificar que todo esté listo para comenzar a programar tu primer agente de IA en Java, asegúrate de poder compilar el código de este proyecto con lo siguiente:
mvn compile
Paso de código: Un agente amigable de profesor de ciencias
El componente fundamental del ADK es la clase LlmAgent
. Piensa en él como una IA con una personalidad y un objetivo específicos, potenciada por un modelo de lenguaje grande. Más adelante, agregaremos más capacidades a través de herramientas y la potenciaremos con la colaboración de otros agentes similares.
Crearemos una nueva clase de Java en el paquete com.example.agent
y la llamaremos ScienceTeacher
.
Este es el "Hello, World!" de la creación de agentes. Definiremos un agente simple con el arquetipo de un profesor de ciencias.
// 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()
);
}
}
El agente de IA se configura a través del método LlmAgent.builder()
. Los parámetros name()
, description()
y model()
son obligatorios, y, para darle a tu agente una personalidad específica y un comportamiento adecuado, siempre debes proporcionar orientación detallada a través del método instruction()
.
Aquí elegimos usar el modelo Gemini 2.5 Flash, pero no dudes en probar Gemini 2.5 Pro también para tareas más complicadas.
Este agente se incluye en el método AdkWebServer.start()
. Esta es la interfaz de chat de la llamada IU de desarrollo del ADK. Te permite conversar con el agente a través de una interfaz de chat típica. Además, es de gran ayuda si quieres comprender qué sucede en segundo plano, como todos los eventos que fluyen a través del sistema, las solicitudes y las respuestas que se envían al LLM.
Para compilar y ejecutar este agente de forma local, ejecuta el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.ScienceTeacher
Luego, ve a tu navegador en http://localhost:8080. Deberías ver la IU como se muestra en la siguiente captura de pantalla. Hazle preguntas relacionadas con la ciencia a tu agente.
4. Potencia los agentes con herramientas
¿Por qué los agentes necesitan herramientas? Los LLM son potentes, pero su conocimiento se congela en el tiempo y no pueden interactuar con el mundo exterior. Las herramientas son el puente. Permiten que un agente acceda a información en tiempo real (como precios de acciones o noticias), consulte APIs privadas o realice cualquier acción que puedas codificar en Java.
Paso de código: Cómo crear una herramienta personalizada (StockTicker
)
Aquí, le damos a nuestro agente una herramienta para consultar los precios de las acciones. El agente razona que, cuando un usuario pregunta por un precio, debe llamar a nuestro método de 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 que los agentes sean más inteligentes y tengan la capacidad de interactuar con el mundo (o con tu propio código, APIs, servicios, etcétera), puedes configurar el agente para que use herramientas, en particular, herramientas de código personalizado, a través del método tools()
, pasándole un FunctionTool.create(...)
.
FunctionTool
necesita una clase y un nombre de método que apunten a tu propio método estático. También es posible pasar una instancia de una clase y el nombre de un método de instancia de ese objeto.
Es importante especificar el name
y el description
del método y sus parámetros a través de la anotación @Schema
, ya que el LLM subyacente usará esta información para determinar cuándo y cómo debe llamar a un método determinado.
Igualmente importante, es mejor ayudar al LLM con instrucciones claras sobre cómo y cuándo usar la herramienta. Es posible que el modelo pueda resolverlo por sí solo, pero si das explicaciones explícitas en el método instruction()
, es más probable que se llame a tu función de manera adecuada.
Este método debería devolver un objeto Map
. Por lo general, la idea es devolver un mapa con una clave que represente el resultado, como stock_price
, y asociar el valor del precio de las acciones a él. Con el tiempo, puedes agregar un par de claves adicional de éxito / verdadero para indicar el éxito de la operación. En caso de error, debes devolver un mapa con una clave llamada, por ejemplo, error
y asociar el mensaje de error en el valor asociado. Esto ayuda al LLM a comprender si la llamada se realizó correctamente o falló por algún motivo.
- Si se ejecuta de forma correcta, devuelve
{"stock_price": 123}
. - En caso de error, devuelve:
{"error": "Impossible to retrieve stock price for XYZ"}
Luego, ejecuta esta clase con el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.StockTicker
5. El poder de la Búsqueda de Google para obtener información actualizada
El ADK para Java incluye varias herramientas potentes, entre las que se encuentra GoogleSearchTool
. Con esta herramienta, tu agente puede solicitar el uso de la Búsqueda de Google para encontrar información pertinente y alcanzar su objetivo.
De hecho, el conocimiento de un LLM se congela en el tiempo: se entrena hasta una fecha determinada (la "fecha límite") con datos que también están tan actualizados como cuando se recopiló la información. Esto significa que los LLM no necesariamente conocen los eventos recientes, o bien su conocimiento puede ser limitado y superficial, y la ayuda de un motor de búsqueda podría refrescar su memoria o enseñarles más sobre el tema.
Veamos este agente de búsqueda de noticias simple:
// 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());
}
}
Observa cómo pasamos una instancia de la herramienta de búsqueda con tools(new GoogleSearchTool())
. Esto es lo que le da a nuestro agente la capacidad de ponerse al día con la información más reciente que se puede encontrar en la Web. Además, la instrucción especificó la fecha del día, ya que podría ayudar al LLM a comprender cuándo las preguntas son sobre información pasada y se requiere la búsqueda de información más reciente.
Luego, ejecuta esta clase con el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.LatestNews
Siéntete libre de jugar con la instrucción, de pedir diferentes resultados en términos de estilo, concisión o enfoque, etc.
Paso de código: El agente de búsqueda como herramienta
En lugar de pasar el GoogleSearchTool
a un agente directamente como una herramienta, puedes crear un agente de búsqueda dedicado que encapsule la funcionalidad de búsqueda y exponga ese agente como una herramienta para un agente de nivel superior.
Este es un concepto avanzado que te permite delegar comportamientos complejos (como buscar y resumir los resultados) en un subagente especializado. Este enfoque suele ser útil para flujos de trabajo más complejos, ya que las herramientas integradas no se pueden usar con herramientas personalizadas basadas en 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()
);
}
}
La línea AgentTool.create(searchAgent)
es el concepto clave aquí. Registra todo el searchAgent
(con su propia lógica interna, instrucciones y herramientas) como una sola herramienta invocable para el mainAgent
. Esto promueve la modularidad y la reutilización.
Ejecuta esta clase con el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SearchAgentAsTool
Para preguntas comunes, el agente responderá desde su propia base de conocimiento, pero, cuando se le pregunte sobre eventos recientes, delegará la búsqueda al agente de búsqueda especializado con la herramienta de la Búsqueda de Google.
6. Dominar los flujos de trabajo de agentes
Para problemas complejos, un solo agente no es suficiente. Cuando se les asigna un objetivo que consta de demasiadas subtareas, con una instrucción enorme que explica con demasiado detalle o con acceso a una gran cantidad de funciones, los LLM tienen dificultades y su rendimiento y precisión se degradan.
La clave es dividir y conquistar orquestando varios agentes especializados. Afortunadamente, el ADK incluye diferentes agentes especializados integrados:
- Agente normal con
subAgent()
para delegar tareas SequentialAgent
, para realizar tareas en secuenciaParallelAgent
, para ejecutar agentes en paraleloLoopAgent
, por lo general, para pasar por un proceso de perfeccionamiento tantas veces como sea necesario.
Consulta la siguiente tabla para conocer los casos de uso clave y las ventajas y desventajas de cada flujo de trabajo. Sin embargo, ten en cuenta que el verdadero poder provendrá de la combinación de varias de ellas.
Flujo de trabajo | Clase del ADK | Caso de uso | Ventajas | Desventajas |
Agentes secundarios |
| Tareas flexibles y controladas por el usuario en las que no siempre se conoce el siguiente paso. | Es muy flexible, conversacional y excelente para los bots orientados al usuario. | Es menos predecible y depende del razonamiento del LLM para el control de flujo. |
Secuencial |
| Procesos fijos de varios pasos en los que el orden es fundamental | Es predecible, confiable, fácil de depurar y garantiza el orden. | Es inflexible y puede ser más lento si las tareas se pudieran paralelizar. |
Paralelo |
| Recopilar datos de varias fuentes o ejecutar tareas independientes | Es muy eficiente y reduce significativamente la latencia de las tareas vinculadas a E/S. | Se ejecutan todas las tareas; no hay cortocircuitos. Es menos adecuado para tareas con dependencias. |
Bucle |
| Refinamiento iterativo, autocorrección o procesos que se repiten hasta que se cumple una condición. | Es potente para la resolución de problemas complejos y permite que los agentes mejoren su propio trabajo. | Puede generar bucles infinitos si no se diseña con cuidado (siempre usa maxIterations). |
7. Flujos de trabajo de agentes: Delegación con subagentes
Un agente supervisor puede delegar tareas particulares a agentes secundarios. Por ejemplo, imagina el agente de un sitio web de comercio electrónico que delegaría las preguntas relacionadas con los pedidos a un agente ("¿Cuál es el estado de mi pedido?") y las preguntas sobre el servicio posventa a otro agente ("¡No sé cómo encenderlo!"). Este es el caso de uso que analizaremos.
// 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()
);
}
}
La línea clave aquí es donde se llama al método subAgents()
, pasando los dos subagentes cuyo rol específico se controlará por separado entre sí.
Ejecuta el ejemplo anterior con el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SupportAgent
Este concepto de delegar tareas a subagentes refleja una administración humana eficaz, en la que un buen administrador (el agente supervisor) se basa en empleados especializados (los subagentes) para manejar tareas específicas para las que tienen mayor experiencia. El supervisor no necesita conocer los detalles de cada proceso, sino que dirige de forma inteligente la solicitud de un cliente (como una consulta sobre un pedido o un problema técnico) al "miembro del equipo" más calificado, lo que garantiza una respuesta de mayor calidad y más eficiente que la que podría proporcionar un generalista por sí solo. Además, estos subagentes pueden concentrarse por completo en sus tareas individuales sin necesidad de comprender la totalidad del proceso general complejo.
8. Flujos de trabajo de agentes: La línea de ensamblaje
Cuando el orden de las operaciones es importante, usa un SequentialAgent
. Es como una línea de ensamblaje, en la que se ejecutan subagentes en un orden fijo y cada paso puede depender del anterior.
Imaginemos que un poeta inglés colabora con un traductor de inglés y francés para crear poemas primero en inglés y, luego, traducirlos al 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());
}
}
Ejecuta el ejemplo para obtener un poema en inglés y, luego, traducirlo al francés con el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.PoetAndTranslator
Esta descomposición sistemática de tareas complejas en subtareas más pequeñas y ordenadas garantiza un proceso más determinístico y confiable, lo que mejora significativamente la probabilidad de un resultado exitoso en comparación con la dependencia de un solo agente de propósito amplio.
Descomponer una tarea de manera eficaz en una secuencia de subtareas (cuando sea posible y tenga sentido) es fundamental para lograr resultados más determinísticos y exitosos, ya que permite una progresión estructurada y una administración de dependencias entre los pasos.
9. Flujos de trabajo de agentes: Trabajo en paralelo
Cuando las tareas son independientes, un ParallelAgent
proporciona un gran aumento de eficiencia, ya que las ejecuta de forma simultánea. En el siguiente ejemplo, incluso combinaremos un SequentialAgent
con un ParallelAgent
: primero se ejecutan las tareas paralelas y, luego, un agente final resume el resultado de las tareas paralelas.
Creemos un detective de empresas cuyo trabajo será buscar información sobre lo siguiente:
- El perfil de la empresa (CEO, sede central, lema, etc.)
- Las noticias más recientes sobre la empresa
- Son los detalles sobre las finanzas de la 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 costumbre, puedes ejecutar el agente con el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CompanyDetective
Este agente demuestra una potente combinación de flujos de trabajo, con agentes paralelos y secuenciales que se utilizan de manera eficiente gracias a la paralelización de la investigación y la síntesis de información.
10. Flujos de trabajo de agentes: perfeccionamiento iterativo
Para las tareas que requieren un ciclo de "generar → revisar → perfeccionar", usa un LoopAgent
. Automatiza la mejora iterativa hasta que se alcanza un objetivo. De manera similar a SequentialAgent
, LoopAgent
llamará a los subagentes de forma serial, pero volverá al principio. El LLM que usa internamente el agente decidirá si solicitar o no la llamada a una herramienta especial, la herramienta integrada exit_loop
, para detener la ejecución del bucle.
En el siguiente ejemplo de perfeccionador de código, que usa un LoopAgent
, se automatiza el perfeccionamiento del código: generar, revisar y corregir. Esto imita el desarrollo humano. Primero, un generador de código genera el código solicitado y lo guarda en el estado del agente con la clave generated_code
. Luego, un revisor de código revisa el código generado y proporciona comentarios (en la clave feedback
) o llama a una herramienta de bucle de salida para finalizar la iteración antes de tiempo.
Veamos el 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());
}
}
Ejecuta este agente con el siguiente comando:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CodeRefiner
Los bucles de comentarios y perfeccionamiento, implementados con LoopAgent
, son indispensables para resolver problemas que requieren mejoras iterativas y autocorrección, ya que imitan de cerca los procesos cognitivos humanos. Este patrón de diseño es particularmente útil para tareas en las que el resultado inicial rara vez es perfecto, como la generación de código, la escritura creativa, la iteración de diseño o el análisis de datos complejos. Al pasar el resultado por un agente de revisión especializado que proporciona comentarios estructurados, el agente generador puede perfeccionar continuamente su trabajo hasta que se cumpla un criterio de finalización predefinido, lo que genera resultados finales de calidad demostrablemente superior y más confiables que un enfoque de una sola pasada.
11. ¡Felicitaciones!
Creaste y exploraste con éxito una variedad de agentes de IA, desde simples conversadores hasta complejos sistemas multiagente. Aprendiste los conceptos básicos del ADK para Java: definir agentes con instrucciones, potenciarlos con herramientas y coordinarlos en flujos de trabajo eficaces.
Próximos pasos
- Explora el repositorio oficial de GitHub del ADK para Java.
- Obtén más información sobre el framework en su documentación.
- Lee sobre los diversos flujos de trabajo basados en agentes en esta serie de blogs y sobre las diversas herramientas disponibles.
- Profundiza en las otras herramientas integradas y las devoluciones de llamada avanzadas.
- Maneja el contexto, el estado y los artefactos para interacciones más enriquecidas y multimodales.
- Implementa y aplica complementos que se conecten al ciclo de vida de tus agentes.
- Intenta crear tu propio agente que resuelva un problema del mundo real.