Crea apps multimodales y agentes administrados personalizados con el SDK de Gemini Interactions para Java

1. Te damos la bienvenida, desarrollador de Gemini.

Notas visuales de aprendizaje para desarrolladores

En este codelab, aprenderás a compilar aplicaciones de IA de próxima generación en Java con el SDK de Gemini Interactions personalizado.

¿Qué es la API de Gemini Interactions?

Las APIs de LLM tradicionales no tienen estado y se basan en solicitudes y respuestas. Para compilar un asistente de chat de varias turnos o un bucle de agentes complejo, los desarrolladores históricamente tuvieron que administrar el estado de la conversación, el truncamiento del historial, la organización de llamadas a herramientas y los bucles de ejecución por completo en el código de la aplicación del cliente.

La API de Gemini Interactions traslada esta complejidad al servidor. Es una API con estado y basada en sesiones en la que la infraestructura de Google aloja y administra el gráfico de conversación. Una sola Interaction representa una sesión con estado. Cuando interactúas con ella, la API muestra una cronología estructurada y enriquecida compuesta por Steps polimórficos, como los siguientes:

  • ThoughtStep: Es el proceso de razonamiento interno del modelo.
  • ModelOutputStep: Es el contenido de texto, audio o imagen que genera el modelo.
  • ToolCallStep y ToolResultStep: Son invocaciones de herramientas iniciadas por el sistema o el modelo.
  • UserInteractionStep: Son puntos en los que el sistema se detiene para solicitar la aprobación o la entrada de datos de un usuario.

¿Qué son los agentes administrados?

La organización de agentes autónomos (el manejo de bucles, la lógica de reintento, los entornos de ejecución de herramientas y la administración de estados) es notoriamente difícil.

Los agentes administrados son una solución a nivel de la plataforma que proporciona la API de Gemini Interactions. En lugar de ejecutar bucles de agentes de forma local, puedes aprovisionar agentes especializados directamente en la infraestructura de Google:

  • Agentes integrados: Son agentes especializados listos para usar, como el agente de Deep Research, que realiza investigaciones web de varios pasos, agrega resultados y genera informes completos.
  • Agentes administrados personalizados: Son entidades autónomas que tú defines. Proporcionas instrucciones del sistema, adjuntas herramientas (como la Búsqueda de Google o un entorno de ejecución de Bash) y configuras un Cloud Sandbox, que es un entorno de ejecución seguro, aislado y en contenedores con reglas de salida de red personalizables (p.ej., que permiten el acceso solo a dominios específicos como GitHub).

Si usas el SDK de Gemini Interactions para Java, puedes inicializar, coordinar y colaborar fácilmente con estos agentes administrados en aplicaciones Java estándar.

Qué aprenderás

  • Cómo navegar por la nueva arquitectura polimórfica basada en Step
  • Cómo transmitir audio de TTS expresivo directamente a los altavoces
  • Cómo generar música (MP3 + letras) con Lyria
  • Cómo generar sketchnotes visuales con Gemini 3 Pro Image
  • Cómo dirigir el agente de Deep Research con la planificación colaborativa
  • Cómo aprovisionar un agente personalizado con herramientas y reglas de salida de red

Requisitos

  • Java 21 o una versión posterior
  • Apache Maven
  • Un editor de texto o IDE (IntelliJ IDEA, VS Code, etcétera)
  • Una clave de API de Gemini (de Google AI Studio)

2. Configuración: Proyecto y clave de API

Crea un proyecto de Maven

Inicializa un proyecto de Maven nuevo desde tu terminal con el siguiente comando:

mvn archetype:generate \
    -DgroupId=com.example \
    -DartifactId=gemini-interactions-demo \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-quickstart \
    -DarchetypeVersion=1.5 \
    -DinteractiveMode=false

Navega al directorio del proyecto recién creado:

cd gemini-interactions-demo

Abre el archivo pom.xml y configúralo:

  1. Actualiza las propiedades de la versión de Java para segmentar Java 21:
    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
    </properties>
    
  2. Agrega la dependencia del SDK dentro del bloque :
    <dependency>
        <groupId>io.github.glaforge</groupId>
        <artifactId>gemini-interactions-api-sdk</artifactId>
        <version>0.10.1</version>
    </dependency>
    

Configura la clave de API

Obtén una clave de API de Gemini en Google AI Studio.

Configura la clave como una variable de entorno en tu terminal:

macOS / Linux:

export GEMINI_API_KEY="your_actual_api_key"

Windows (símbolo del sistema):

set GEMINI_API_KEY="your_actual_api_key"

3. Hello World: Navega por la arquitectura de pasos

La API de Interactions introdujo una arquitectura de cronología polimórfica basada en pasos. En lugar de mostrar una lista plana de resultados, la API muestra una secuencia de objetos Step con tipo (p.ej., ModelOutputStep, ThoughtStep, FunctionCallStep).

En este paso, escribirás una interacción simple para comprender cómo extraer el resultado final del modelo de esta estructura.

Crea HelloInteractions.java

Crea el archivo src/main/java/com/example/HelloInteractions.java con el siguiente contenido:

package com.example;

import io.github.glaforge.gemini.interactions.GeminiInteractionsClient;
import io.github.glaforge.gemini.interactions.model.*;
import io.github.glaforge.gemini.interactions.model.InteractionParams.ModelInteractionParams;

public class HelloInteractions {
    public static void main(String[] args) {
        // 1. Initialize the client
        GeminiInteractionsClient client = GeminiInteractionsClient.builder()
            .apiKey(System.getenv("GEMINI_API_KEY"))
            .build();

        // 2. Build the request
        ModelInteractionParams request = ModelInteractionParams.builder()
            .model("gemini-3.5-flash")
            .input("Explain the difference between a library and a framework in one sentence.")
            .build();

        // 3. Send request
        Interaction response = client.create(request);
        
        // 4. Navigate the step-based architecture to get the output
        response.steps().stream()
            .filter(step -> step instanceof Step.ModelOutputStep)
            .map(step -> (Step.ModelOutputStep) step)
            .findFirst()
            .ifPresent(step -> System.out.println(step.content().get(0)));
    }
}

Ejecuta el código

Compila y ejecuta la clase:

mvn compile exec:java -Dexec.mainClass=com.example.HelloInteractions

4. Audio dirigible: Transmisión de TTS expresivo

Gemini 3.1 Flash presenta la función de texto a voz (TTS) dirigible. Puedes controlar el ritmo, el tono y el entorno de la voz con instrucciones, y usar etiquetas emocionales (como [excitedly] o [whispers]) en medio de la oración.

En este paso, generarás audio expresivo y lo transmitirás directamente a tus altavoces.

Crea StreamingDJ.java

Crea el archivo src/main/java/com/example/StreamingDJ.java con el siguiente contenido:

package com.example;

import io.github.glaforge.gemini.interactions.GeminiInteractionsClient;
import io.github.glaforge.gemini.interactions.model.*;
import io.github.glaforge.gemini.interactions.model.Config.SpeechConfig;
import io.github.glaforge.gemini.interactions.model.InteractionParams.ModelInteractionParams;
import javax.sound.sampled.*;
import java.util.Base64;
import java.util.stream.Stream;

public class StreamingDJ {
    public static void main(String[] args) throws Exception {
        GeminiInteractionsClient client = GeminiInteractionsClient.builder()
            .apiKey(System.getenv("GEMINI_API_KEY"))
            .build();

        // Prompt defining the voice profile and emotional tags
        String prompt = """
            # AUDIO PROFILE: Jaz R.
            ## THE SCENE: London Studio
            ### DIRECTOR'S NOTES
            Accent: Jaz is a DJ from Brixton, London.
            Style: Bouncy, energetic, high-speed delivery.
            
            #### TRANSCRIPT
            [excitedly] Yes, massive vibes in the studio! 
            [whispers] But keep it down, the boss is coming... 
            [shouting] Turn this up! Let's go!
            """;

        ModelInteractionParams request = ModelInteractionParams.builder()
            .model("gemini-3.1-flash-tts-preview")
            .input(prompt)
            .responseModalities(Interaction.Modality.AUDIO)
            .speechConfig(new SpeechConfig("Algenib", "en-GB"))
            .stream(true) // Enable streaming
            .build();

        System.out.println("Streaming audio from Gemini...");

        try (Stream<Events> eventStream = client.stream(request)) {
            // Configure the Java Audio System for 24kHz Mono 16-bit PCM
            AudioFormat format = new AudioFormat(24000, 16, 1, true, false);
            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

            try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) {
                line.open(format);
                line.start();

                // Process the stream and play audio chunks as they arrive
                eventStream.forEach(event -> {
                    if (event instanceof Events.StepDelta cd && cd.delta() instanceof Events.AudioDelta audioDelta) {
                        byte[] audioData = Base64.getDecoder().decode(audioDelta.data());
                        line.write(audioData, 0, audioData.length);
                    }
                });
                line.drain();
            }
        }
    }
}

Ejecuta el código

mvn compile exec:java -Dexec.mainClass=com.example.StreamingDJ

Escucha el resultado

Aquí hay un ejemplo de audio de lo que escucharás cuando ejecutes el código (con la voz Algenib con etiquetas emocionales):

Escucha el resultado de TTS generado (tts_output.wav)

5. Generación de música con Lyria 3

Con el modelo DeepMind Lyria 3, puedes generar música y jingles. Si solicitas modalidades de respuesta dual (AUDIO y TEXT), puedes recuperar el audio generado (MP3) y la letra de la canción.

Crea MusicGenerator.java

Crea el archivo src/main/java/com/example/MusicGenerator.java con el siguiente contenido:

package com.example;

import io.github.glaforge.gemini.interactions.GeminiInteractionsClient;
import io.github.glaforge.gemini.interactions.model.*;
import io.github.glaforge.gemini.interactions.model.InteractionParams.ModelInteractionParams;
import io.github.glaforge.gemini.interactions.model.Content.AudioContent;
import java.nio.file.Files;
import java.nio.file.Paths;

public class MusicGenerator {
    public static void main(String[] args) throws Exception {
        GeminiInteractionsClient client = GeminiInteractionsClient.builder()
            .apiKey(System.getenv("GEMINI_API_KEY"))
            .build();

        ModelInteractionParams request = ModelInteractionParams.builder()
            .model("models/lyria-3-clip-preview") // 30-second clip
            .input("An uplifting rock song with acoustic guitars about coding in Java.")
            .responseModalities(
                Interaction.Modality.AUDIO,
                Interaction.Modality.TEXT) // Request both MP3 and Lyrics
            .build();

        System.out.println("Generating music (this might take a moment)...");
        Interaction response = client.create(request);

        // 1. Print the lyrics (TEXT output)
        System.out.println("\n--- Generated Lyrics ---");
        response.steps().stream()
            .filter(step -> step instanceof Step.ModelOutputStep)
            .flatMap(step -> ((Step.ModelOutputStep) step).content().stream())
            .filter(content -> content instanceof Content.TextContent)
            .forEach(content -> System.out.println(((Content.TextContent) content).text()));

        // 2. Save the MP3 (AUDIO output)
        response.steps().stream()
            .filter(step -> step instanceof Step.ModelOutputStep)
            .flatMap(step -> ((Step.ModelOutputStep) step).content().stream())
            .filter(content -> content instanceof AudioContent)
            .map(content -> (AudioContent) content)
            .findFirst()
            .ifPresent(audio -> {
                try {
                    Files.write(Paths.get("coding_song.mp3"), audio.data());
                    System.out.println("\nSuccess: Song saved to coding_song.mp3");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
    }
}

Ejecuta el código

mvn compile exec:java -Dexec.mainClass=com.example.MusicGenerator

Escucha la canción generada

Aquí está el archivo MP3 generado (coding_song.mp3) que contiene la música y la letra:

Escucha la canción generada (coding_song.mp3)

6. Visualización con sketchnotes (Nano Banana Pro)

Gemini 3 Pro Image (también conocido como Nano Banana Pro) puede generar imágenes. Si solicitas la modalidad IMAGE, puedes generar infografías, diagramas o sketchnotes basados en la entrada de texto.

En este paso, generarás un resumen de sketchnote de un artículo sobre agentes administrados y lo guardarás como un archivo PNG.

Crea ImageGenerator.java

Crea el archivo src/main/java/com/example/ImageGenerator.java con el siguiente contenido:

package com.example;

import io.github.glaforge.gemini.interactions.GeminiInteractionsClient;
import io.github.glaforge.gemini.interactions.model.*;
import io.github.glaforge.gemini.interactions.model.InteractionParams.ModelInteractionParams;
import io.github.glaforge.gemini.interactions.model.Content.ImageContent;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ImageGenerator {
    public static void main(String[] args) throws Exception {
        GeminiInteractionsClient client = GeminiInteractionsClient.builder()
            .apiKey(System.getenv("GEMINI_API_KEY"))
            .build();

        String articleSummary = """
            Managed Agents in the Gemini API allow developers to run autonomous agents
            that reason, plan, use tools, and execute code inside isolated cloud sandboxes.
            The Gemini API handles the infrastructure (containers, network, runtime).
            It is powered by the Antigravity agent running on Gemini 3.5 Flash.
            The Java Interactions SDK supports these capabilities, utilizing a Step-based
            architecture to model the execution timeline.
            """;

        ModelInteractionParams request = ModelInteractionParams.builder()
            .model("gemini-3-pro-image-preview")
            .input(String.format("""
                Create a hand-drawn and hand-written sketchnote
                style summary infographic, with a pure white background,
                about the following information:
                
                %s
                """, articleSummary))
            .responseModalities(Interaction.Modality.IMAGE) // Request IMAGE modality
            .build();

        System.out.println("Generating sketchnote (this might take a moment)...");
        Interaction response = client.create(request);

        // Save the generated image
        response.steps().stream()
            .filter(step -> step instanceof Step.ModelOutputStep)
            .flatMap(step -> ((Step.ModelOutputStep) step).content().stream())
            .filter(content -> content instanceof ImageContent)
            .map(content -> (ImageContent) content)
            .findFirst()
            .ifPresent(image -> {
                try {
                    Files.write(Paths.get("sketchnote.png"), image.data());
                    System.out.println("Success: Sketchnote saved to sketchnote.png");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
    }
}

Ejecuta el código

mvn compile exec:java -Dexec.mainClass=com.example.ImageGenerator

Sketchnote generada

Aquí está la sketchnote generada (sketchnote.png) que creó el modelo:

Boceto generado

7. Agentes de dirección: Deep Research colaborativo

Deep Research es un agente potente que puede ejecutar tareas de investigación de varios pasos. Sin embargo, en lugar de ejecutarse de inmediato, puedes usar la planificación colaborativa para revisar, modificar y dirigir el plan de investigación antes de que el agente comience a recopilar datos.

Implementarás una conversación de varias turnos que usa el mismo estado del servidor (previousInteractionId) para refinar un plan.

Crea CollaborativeResearch.java

Crea el archivo src/main/java/com/example/CollaborativeResearch.java con el siguiente contenido:

package com.example;

import io.github.glaforge.gemini.interactions.GeminiInteractionsClient;
import io.github.glaforge.gemini.interactions.model.*;
import io.github.glaforge.gemini.interactions.model.InteractionParams.AgentInteractionParams;
import io.github.glaforge.gemini.interactions.model.Config.DeepResearchAgentConfig;
import io.github.glaforge.gemini.interactions.model.Config.ThinkingSummaries;
import io.github.glaforge.gemini.interactions.model.Config.Visualization;

public class CollaborativeResearch {
    public static void main(String[] args) throws Exception {
        GeminiInteractionsClient client = GeminiInteractionsClient.builder()
            .apiKey(System.getenv("GEMINI_API_KEY"))
            .build();

        String agentModel = "deep-research-preview-04-2026";

        // --- Phase 1: Request a Plan ---
        System.out.println("Phase 1: Requesting research plan...");
        AgentInteractionParams planParams = AgentInteractionParams.builder()
            .agent(agentModel)
            .input("Research the latest generations of Google Cloud TPUs (TPU7x and the 8th generation TPU 8t and TPU 8i).")
            .agentConfig(new DeepResearchAgentConfig(
                "deep-research", 
                ThinkingSummaries.AUTO, 
                Visualization.AUTO, 
                true // TRUE enables collaborative planning
            ))
            .background(true)
            .store(true)
            .build();

        Interaction planInteraction = client.create(planParams);
        planInteraction = waitForCompletion(client, planInteraction.id());
        
        System.out.println("\n--- Proposed Plan ---");
        printOutputText(planInteraction);

        // --- Phase 2: Refine the Plan ---
        System.out.println("\nPhase 2: Refining research plan...");
        AgentInteractionParams refineParams = AgentInteractionParams.builder()
            .agent(agentModel)
            .input("Focus on comparing the architectural, performance, and scaling differences between the TPU7x generation and the two flavors of the eighth generation: TPU 8t (optimized for training at scale) and TPU 8i (optimized for low-latency reasoning and inference).")
            .agentConfig(new DeepResearchAgentConfig(
                "deep-research", 
                ThinkingSummaries.AUTO, 
                Visualization.AUTO, 
                true // Keep collaborative planning TRUE to iterate
            ))
            .previousInteractionId(planInteraction.id()) // Resume session
            .background(true)
            .store(true)
            .build();

        Interaction refinedInteraction = client.create(refineParams);
        refinedInteraction = waitForCompletion(client, refinedInteraction.id());

        System.out.println("\n--- Refined Plan ---");
        printOutputText(refinedInteraction);

        // --- Phase 3: Approve and Execute ---
        System.out.println("\nPhase 3: Approving plan and starting deep research (this will take a few minutes)...");
        AgentInteractionParams executeParams = AgentInteractionParams.builder()
            .agent(agentModel)
            .input("Plan looks good, execute!")
            .agentConfig(new DeepResearchAgentConfig(
                "deep-research", 
                ThinkingSummaries.AUTO, 
                Visualization.AUTO, 
                false // FALSE approves the plan and executes the research
            ))
            .previousInteractionId(refinedInteraction.id()) // Resume session
            .background(true)
            .store(true)
            .build();

        Interaction finalReport = client.create(executeParams);
        finalReport = waitForCompletion(client, finalReport.id());

        System.out.println("\n--- Final Research Report ---");
        printOutputText(finalReport);
    }

    private static Interaction waitForCompletion(GeminiInteractionsClient client, String id) throws Exception {
        Interaction interaction = client.get(id);
        while (interaction.status() != Interaction.Status.COMPLETED && interaction.status() != Interaction.Status.FAILED) {
            Thread.sleep(5000);
            interaction = client.get(id);
        }
        if (interaction.status() == Interaction.Status.FAILED) {
            throw new RuntimeException("Interaction failed. Status: " + interaction.status());
        }
        return interaction;
    }

    private static void printOutputText(Interaction interaction) {
        interaction.steps().stream()
            .filter(step -> step instanceof Step.ModelOutputStep)
            .flatMap(step -> ((Step.ModelOutputStep) step).content().stream())
            .filter(content -> content instanceof Content.TextContent)
            .forEach(content -> System.out.println(((Content.TextContent) content).text()));
    }
}

Ejecuta el código

mvn compile exec:java -Dexec.mainClass=com.example.CollaborativeResearch

Resultado del informe generado

El agente de Deep Research producirá un informe integral y estructurado. Puedes ver el informe completo generado por la ejecución de ejemplo aquí:

Consulta el informe de Deep Research generado (tpu_history_report.md)

8. Agentes personalizados y Cloud Sandboxes

Para tareas complejas de desarrolladores, puedes aprovisionar agentes personalizados. Defines sus instrucciones del sistema, los equipas con herramientas (como Code Execution/Bash) y configuras su entorno remoto (como las reglas de salida de red).

En este paso, aprovisionarás un agente que tenga acceso seguro a Internet a github.com y le indicarás que clone un repositorio y analice sus archivos de configuración dentro de su zona de pruebas en la nube.

Crea GitHubAnalyzer.java

Crea el archivo src/main/java/com/example/GitHubAnalyzer.java con el siguiente contenido:

package com.example;

import io.github.glaforge.gemini.interactions.GeminiInteractionsClient;
import io.github.glaforge.gemini.interactions.model.*;
import io.github.glaforge.gemini.interactions.model.InteractionParams.AgentInteractionParams;
import java.util.List;

public class GitHubAnalyzer {
    public static void main(String[] args) throws Exception {
        GeminiInteractionsClient client = GeminiInteractionsClient.builder()
            .apiKey(System.getenv("GEMINI_API_KEY"))
            .build();

        String agentId = "github-analyzer-codelab";

        // 1. Define the Custom Agent with Network Egress and Tools
        Agent customAgent = Agent.builder()
            .id(agentId)
            .description("Clones and analyzes GitHub repos.")
            .baseAgent("antigravity-preview-05-2026")
            .baseEnvironment(new EnvironmentConfig(
                new EnvironmentNetworkEgressAllowlist(List.of(
                    new AllowlistEntry("github.com") // Allow git clone over HTTPS
                )),
                List.of()
            ))
            .systemInstruction("You are an architect. Clone the repo, inspect files, and write a summary.")
            .tools(List.of(
                new AgentTool.CodeExecution(), // Enables terminal bash execution in sandbox
                new AgentTool.GoogleSearch()
            ))
            .build();

        // 2. Provision the Agent
        System.out.println("Provisioning custom agent in the cloud...");
        client.createAgent(customAgent);

        try {
            // 3. Start the Interaction
            AgentInteractionParams params = AgentInteractionParams.builder()
                .agent(agentId)
                .input("Clone https://github.com/glaforge/gemini-interactions-api-sdk and explain its pom.xml structure.")
                .environment("remote") // Crucial: Run in cloud sandbox
                .build();

            System.out.println("Starting clone and analysis (polling status)...");
            Interaction interaction = client.create(params);

            // 4. Poll for completion
            while (interaction.status() != Interaction.Status.COMPLETED) {
                System.out.println("Agent working... Status: " + interaction.status());
                Thread.sleep(5000);
                interaction = client.get(interaction.id());
            }

            // 5. Output the results
            System.out.println("\n--- Architectural Analysis ---");
            interaction.steps().stream()
                .filter(step -> step instanceof Step.ModelOutputStep)
                .flatMap(step -> ((Step.ModelOutputStep) step).content().stream())
                .filter(content -> content instanceof Content.TextContent)
                .forEach(content -> System.out.println(((Content.TextContent) content).text()));

        } finally {
            // 6. Clean up resources
            client.deleteAgent(agentId);
            System.out.println("\nCustom agent resource deleted from cloud.");
        }
    }
}

Ejecuta el código

mvn compile exec:java -Dexec.mainClass=com.example.GitHubAnalyzer

Resultado del análisis generado

Puedes ver el informe completo de análisis arquitectónico que produjo el agente personalizado después de clonar el repositorio aquí:

Consulta el resultado del analizador de GitHub (github_analysis_report.md)

9. ¡Felicitaciones!

Completaste el codelab y aprendiste a compilar flujos de trabajo complejos, multimodales y de agentes en Java con el SDK de Gemini Interactions.

Objetivos logrados:

  1. Navegaste por la arquitectura de pasos: Usaste la nueva arquitectura de pasos polimórfica para consultar modelos estándar.
  2. Transmitiste TTS expresivo: Usaste las notas del director y las etiquetas emocionales intercaladas para transmitir audio en tiempo real.
  3. Generaste música: Generaste pistas y letras de MP3 con Lyria 3.
  4. Generaste sketchnotes: Creaste resúmenes visuales con Gemini 3 Pro Image (Nano Banana Pro).
  5. Dirigiste Deep Research: Utilizaste la planificación colaborativa para refinar los planes de investigación.
  6. Aprovisionaste agentes personalizados: Creaste entornos de zona de pruebas con control de salida de red personalizado para ejecutar código de forma segura.

Más información: