SPB Git

Repository Public

migrate-to-interactions.md 74.3 KB 2,348 lines markdown

1This guide helps you migrate from the `generateContent` API to the Interactions API.23The Interactions API is our simplest and best way to build with Gemini models and agents. While `generateContent` remains fully supported, we recommend the Interactions API for all new development.45> [!NOTE]6> **Automate this migration with a coding agent.** If you use7> a coding agent that supports skills (like Gemini CLI or Jules), install the8> [Gemini9> API development skill](https://ai.google.dev/gemini-api/docs/coding-agents#gemini-api-dev) and run:10>11> ```12> /gemini-api-dev migrate my app to the interactions api13> ```14>15> The skill applies the API changes described in this guide.1617### Why migrate?1819The Interactions API is our simplest and best way to build with Gemini models and agents:2021- **Server-side history management** : Simplified multi-turn flows via `previous_interaction_id`. The server enables state by default (`store=true`), but you can opt into stateless behavior by setting `store=false`.22- **Observable execution steps**: Typed steps make it easy to debug complex flows and render UI for intermediate events (like thoughts or search widgets).23- **Tool use and agentic workflows**: Native support for multi-step tool use, orchestration, and complex reasoning flows through typed execution steps.24- **Long-running and background tasks** : Supports offloading time-intensive operations like Deep Think and Deep Research to background processes using `background=true`.2526## Basic input/output2728This section shows how to migrate a simple text generation request.2930### Before (`generateContent`)3132The `generateContent` API is stateless and returns the response directly. The response structure wraps the output in a list of `candidates`, each containing `content` with a list of `parts` to parse.3334### Python3536    from google import genai3738    client = genai.Client()3940    response = client.models.generate_content(41        model="gemini-2.5-flash-lite", contents="Tell me a joke."42    )43    print(response.text)4445### JavaScript4647    import { GoogleGenAI } from '@google/genai';4849    const ai = new GoogleGenAI({});5051    const response = await ai.models.generateContent({52      model: "gemini-2.5-flash-lite",53      contents: "Tell me a joke.",54    });55    console.log(response.text);5657### Java5859    import com.google.genai.Client;60    import com.google.genai.types.GenerateContentResponse;6162    Client client = new Client();6364    GenerateContentResponse response =65        client.models.generateContent("gemini-2.5-flash-lite", "Tell me a joke.", null);66    System.out.println(response.text());6768### REST6970    # Request71    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent" \72    -H "Content-Type: application/json" \73    -H "x-goog-api-key: $GEMINI_API_KEY" \74    -d '{75        "contents": \[{76    "parts": \[{77    "text": "Tell me a joke."78    }\]79    }\]80    }'8182    # Response83    {84      "candidates": \[85    {86    "content": {87    "parts": \[88    {89    "text": "Why did the chicken cross the road? To get to the other side!"90    }91    \],92    "role": "model"93    },94    "finishReason": "STOP",95    "index": 096    }97    \],98      "usageMetadata": {99        "promptTokenCount": 4,100        "candidatesTokenCount": 12,101        "totalTokenCount": 16102      }103    }104105The Interactions API returns a stored interaction resource with a `steps`106timeline. While you can inspect the `steps` array manually to find intermediate107events, the Google GenAI SDKs provide convenience properties108directly on the returned `Interaction` object to access the final output.109110The most common convenience property is **`.output_text`** (String), which111automatically extracts and joins consecutive `TextContent` blocks at the112end of the model's response. While this works perfectly for simple responses,113it does not include earlier text blocks separated by non-text content (such114as thoughts, images, audio, or tool calls). For complex or interleaved115multimodal responses, you must manually iterate over `steps` instead.116117> [!NOTE]118> **Note:** For details on other SDK convenience properties (including `.output_image` and `.output_audio`), see [Access outputs with SDK convenience properties](https://ai.google.dev/gemini-api/docs/interactions-overview#sdk-sugar) in the overview.119120### Python121122    from google import genai123124    client = genai.Client()125126    interaction = client.interactions.create(127        model="gemini-3.8-flash", input="Tell me a joke."128    )129130    print(interaction.output_text)131132### JavaScript133134    import { GoogleGenAI } from '@google/genai';135136    const client = new GoogleGenAI({});137138    let interaction = await client.interactions.create({139        model: 'gemini-3.8-flash',140        input: 'Tell me a joke.'141    });142143    console.log(interaction.output_text);144145### Java146147    import com.google.genai.Client;148    import com.google.genai.gaos.models.interactions.CreateModelInteraction;149    import com.google.genai.gaos.models.interactions.Interaction;150    import com.google.genai.gaos.models.interactions.InteractionsInput;151    import com.google.genai.gaos.models.interactions.Model;152    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;153154    Client client = new Client();155156    CreateModelInteraction request =157        CreateModelInteraction.builder()158            .model(Model.of("gemini-3.8-flash"))159            .input(InteractionsInput.of("Tell me a joke."))160            .build();161162    Interaction interaction =163        client.interactions.create(CreateInteractionRequestBody.of(request)).interaction().get();164165    System.out.println(interaction.outputText().orElse(""));166167### REST168169    # Request170    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \171    -H "Content-Type: application/json" \172    -H "x-goog-api-key: $GEMINI_API_KEY" \173    -d '{174        "model": "gemini-3.8-flash",175        "input": "Tell me a joke."176    }'177178    # Response179    {180      "id": "int_123",181      "status": "completed",182      "steps": \[183    {184    "type": "user_input",185    "status": "done",186    "content": \[187    {188    "type": "text",189    "text": "Tell me a joke."190    }191    \]192    },193    {194    "type": "model_output",195    "status": "done",196    "content": \[197    {198    "type": "text",199    "text": "Why did the chicken cross the road?"200    }201    \]202    }203    \]204    }205206## Multi-turn conversations207208The Interactions API stores interactions by default, enabling server-side state management for multi-turn conversations.209210### Before (`generateContent`)211212In `generateContent`, you must manually manage conversation history using the `contents` array or a client-side chat helper.213214### Python215216**Using the chat helper (recommended)**217218    from google import genai219220    client = genai.Client()221222    chat = client.chats.create(model="gemini-2.5-flash-lite")223    response1 = chat.send_message("Hi, my name is Phil.")224    print(response1.text)225226    response2 = chat.send_message("What is my name?")227    print(response2.text)228229**Manually managing history**230231    from google import genai232    from google.genai import types233234    client = genai.Client()235236    response = client.models.generate_content(237        model="gemini-2.5-flash-lite",238        contents=[239            types.Content(240                role="user", parts=[types.Part.from_text(text="Hi, my name is Phil.")]241            ),242            types.Content(243                role="model",244                parts=[types.Part.from_text(text="Hi Phil, how can I help you?")],245            ),246            types.Content(247                role="user", parts=[types.Part.from_text(text="What is my name?")]248            ),249        ],250    )251    print(response.text)252253### JavaScript254255**Using the chat helper (recommended)**256257    import { GoogleGenAI } from '@google/genai';258259    const client = new GoogleGenAI({});260261    const chat = client.chats.create({ model: 'gemini-2.5-flash-lite' });262    let response = await chat.sendMessage({ message: 'Hi, my name is Phil.' });263    console.log(response.text);264265    response = await chat.sendMessage({ message: 'What is my name?' });266    console.log(response.text);267268**Manually managing history**269270    import { GoogleGenAI } from '@google/genai';271272    const client = new GoogleGenAI({});273274    const response = await client.models.generateContent({275        model: 'gemini-2.5-flash-lite',276        contents: [277            { role: 'user', parts: [{ text: 'Hi, my name is Phil.' }] },278            { role: 'model', parts: [{ text: 'Hi Phil, how can I help you?' }] },279            { role: 'user', parts: [{ text: 'What is my name?' }] }280        ]281    });282    console.log(response.text);283284### Java285286    import com.google.genai.Chat;287    import com.google.genai.Client;288    import com.google.genai.types.Content;289    import com.google.genai.types.GenerateContentResponse;290    import com.google.genai.types.Part;291    import java.util.Arrays;292293    Client client = new Client();294295    // Using the chat helper (recommended)296    Chat chat = client.chats.create("gemini-2.5-flash-lite");297    GenerateContentResponse response1 = chat.sendMessage("Hi, my name is Phil.");298    System.out.println(response1.text());299300    GenerateContentResponse response2 = chat.sendMessage("What is my name?");301    System.out.println(response2.text());302303    // Manually managing history304    GenerateContentResponse manualResponse =305        client.models.generateContent(306            "gemini-2.5-flash-lite",307            Arrays.asList(308                Content.builder()309                    .role("user")310                    .parts(Arrays.asList(Part.fromText("Hi, my name is Phil.")))311                    .build(),312                Content.builder()313                    .role("model")314                    .parts(Arrays.asList(Part.fromText("Hi Phil, how can I help you?")))315                    .build(),316                Content.builder()317                    .role("user")318                    .parts(Arrays.asList(Part.fromText("What is my name?")))319                    .build()),320            null);321    System.out.println(manualResponse.text());322323### REST324325    # Request (the second turn requires sending the entire history)326    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent" \327    -H "Content-Type: application/json" \328    -H "x-goog-api-key: $GEMINI_API_KEY" \329    -d '{330        "contents": \[331    {"role": "user", "parts": \[{"text": "Hi, my name is Phil."}\]},332    {"role": "model", "parts": \[{"text": "Hi Phil, how can I help you?"}\]},333    {"role": "user", "parts": \[{"text": "What is my name?"}\]}334    \]335    }'336337    # Response338    {339      "candidates": \[340    {341    "content": {342    "parts": \[343    {344    "text": "Your name is Phil."345    }346    \],347    "role": "model"348    },349    "finishReason": "STOP",350    "index": 0351    }352    \]353    }354355### After (Interactions API)356357The Interactions API manages state on the server. You continue a conversation by referencing the `previous_interaction_id`.358359### Python360361    from google import genai362363    client = genai.Client()364365    interaction1 = client.interactions.create(366        model="gemini-3.8-flash", input="Hi, my name is Phil."367    )368    print("Response 1:", interaction1.output_text)369370    interaction2 = client.interactions.create(371        model="gemini-3.8-flash",372        previous_interaction_id=interaction1.id,373        input="What is my name?",374    )375    print("Response 2:", interaction2.output_text)376377### JavaScript378379    import { GoogleGenAI } from '@google/genai';380381    const client = new GoogleGenAI({});382383    let interaction = await client.interactions.create({384        model: 'gemini-3.8-flash',385        input: 'Hi, my name is Phil.'386    });387    console.log("Response 1:", interaction.output_text);388389    interaction = await client.interactions.create({390        model: 'gemini-3.8-flash',391        previous_interaction_id: interaction.id,392        input: 'What is my name?'393    });394    console.log("Response 2:", interaction.output_text);395396### Java397398    import com.google.genai.Client;399    import com.google.genai.gaos.models.interactions.CreateModelInteraction;400    import com.google.genai.gaos.models.interactions.Interaction;401    import com.google.genai.gaos.models.interactions.InteractionsInput;402    import com.google.genai.gaos.models.interactions.Model;403    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;404405    Client client = new Client();406407    CreateModelInteraction req1 =408        CreateModelInteraction.builder()409            .model(Model.of("gemini-3.8-flash"))410            .input(InteractionsInput.of("Hi, my name is Phil."))411            .build();412413    Interaction interaction1 =414        client.interactions.create(CreateInteractionRequestBody.of(req1)).interaction().get();415    System.out.println("Response 1: " + interaction1.outputText().orElse(""));416417    CreateModelInteraction req2 =418        CreateModelInteraction.builder()419            .model(Model.of("gemini-3.8-flash"))420            .previousInteractionId(interaction1.id().orElse(""))421            .input(InteractionsInput.of("What is my name?"))422            .build();423424    Interaction interaction2 =425        client.interactions.create(CreateInteractionRequestBody.of(req2)).interaction().get();426    System.out.println("Response 2: " + interaction2.outputText().orElse(""));427428### REST429430    # First Request431    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \432    -H "Content-Type: application/json" \433    -H "x-goog-api-key: $GEMINI_API_KEY" \434    -d '{435        "model": "gemini-3.8-flash",436        "input": "Hi, my name is Phil."437    }'438439    # Second Request (using ID from first response)440    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \441    -H "Content-Type: application/json" \442    -H "x-goog-api-key: $GEMINI_API_KEY" \443    -d '{444        "model": "gemini-3.8-flash",445        "previous_interaction_id": "int_123",446    "input": "What is my name?"447    }'448449    # Response to Second Request450    {451      "id": "int_123",452      "steps": \[453    {454    "type": "user_input",455    "status": "done",456    "content": \[{ "type": "text", "text": "Hi, my name is Phil." }\]457    },458    {459    "type": "model_output",460    "status": "done",461    "content": \[{ "type": "text", "text": "Hello Phil! How can I help you today?" }\]462    },463    {464    "type": "user_input",465    "status": "done",466    "content": \[{ "type": "text", "text": "What is my name?" }\]467    },468    {469    "type": "model_output",470    "status": "done",471    "content": \[{ "type": "text", "text": "Your name is Phil." }\]472    }473    \]474    }475476## Multimodal inputs477478Both APIs support multimodal inputs (text, images, video, etc.).479480### Before (`generateContent`)481482In `generateContent`, you pass a list of `parts` within the `contents` array. The response returns output in the `parts` of the first candidate.483484### Python485486    from google import genai487    from google.genai import types488489    client = genai.Client()490491    with open("sample.jpg", "rb") as f:492        image_bytes = f.read()493494    response = client.models.generate_content(495        model="gemini-2.5-flash-lite",496        contents=[497            types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"),498            "Describe this image.",499        ],500    )501    print(response.text)502503### JavaScript504505    import { GoogleGenAI } from '@google/genai';506    import * as fs from 'fs';507508    const client = new GoogleGenAI({});509510    const imageBytes = fs.readFileSync('sample.jpg').toString('base64');511512    const response = await client.models.generateContent({513        model: 'gemini-2.5-flash-lite',514        contents: [515            {516                inlineData: {517                    data: imageBytes,518                    mimeType: 'image/jpeg',519                },520            },521            'Describe this image.',522        ],523    });524    console.log(response.text);525526### Java527528    import com.google.genai.Client;529    import com.google.genai.types.Content;530    import com.google.genai.types.GenerateContentResponse;531    import com.google.genai.types.Part;532    import java.nio.file.Files;533    import java.nio.file.Paths;534535    Client client = new Client();536537    byte[] imageBytes = Files.readAllBytes(Paths.get("sample.jpg"));538539    GenerateContentResponse response =540        client.models.generateContent(541            "gemini-2.5-flash-lite",542            Content.fromParts(543                Part.fromBytes(imageBytes, "image/jpeg"), Part.fromText("Describe this image.")),544            null);545    System.out.println(response.text());546547### REST548549    # Request550    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent" \551    -H "Content-Type: application/json" \552    -H "x-goog-api-key: $GEMINI_API_KEY" \553    -d '{554        "contents": \[{555    "parts": \[556    {557    "inlineData": {558    "mimeType": "image/jpeg",559    "data": "..."560    }561    },562    {563    "text": "Describe this image."564    }565    \]566    }\]567    }'568569    # Response570    {571      "candidates": \[572    {573    "content": {574    "parts": \[575    {576    "text": "This is a picture of a beautiful sunset."577    }578    \],579    "role": "model"580    }581    }582    \]583    }584585### After (Interactions API)586587In the Interactions API, you pass an array to the `input` field. You retrieve output content by finding the `model_output` step in the timeline.588589### Python590591    import base64592    from google import genai593594    client = genai.Client()595596    with open("sample.jpg", "rb") as f:597        image_bytes = f.read()598    image_b64 = base64.b64encode(image_bytes).decode("utf-8")599600    interaction = client.interactions.create(601        model="gemini-3.8-flash",602        input=[603            {604                "type": "image",605                "mime_type": "image/jpeg",606                "data": image_b64,607            },608            {"type": "text", "text": "Describe this image."},609        ],610    )611    print(interaction.output_text)612613### JavaScript614615    import { GoogleGenAI } from '@google/genai';616    import * as fs from 'fs';617618    const client = new GoogleGenAI({});619620    const imageBytes = fs.readFileSync('sample.jpg').toString('base64');621622    const interaction = await client.interactions.create({623        model: 'gemini-3.8-flash',624        input: [625            {626                type: 'image',627                mime_type: 'image/jpeg',628                data: imageBytes629            },630            {631                type: 'text',632                text: 'Describe this image.'633            }634        ]635    });636    console.log(interaction.output_text);637638### Java639640    import com.google.genai.Client;641    import com.google.genai.gaos.models.interactions.CreateModelInteraction;642    import com.google.genai.gaos.models.interactions.ImageContent;643    import com.google.genai.gaos.models.interactions.ImageContentMimeType;644    import com.google.genai.gaos.models.interactions.Interaction;645    import com.google.genai.gaos.models.interactions.InteractionsInput;646    import com.google.genai.gaos.models.interactions.Model;647    import com.google.genai.gaos.models.interactions.TextContent;648    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;649    import java.nio.file.Files;650    import java.nio.file.Paths;651    import java.util.Arrays;652    import java.util.Base64;653654    Client client = new Client();655656    byte[] imageBytes = Files.readAllBytes(Paths.get("sample.jpg"));657    String base64ImageData = Base64.getEncoder().encodeToString(imageBytes);658659    CreateModelInteraction request =660        CreateModelInteraction.builder()661            .model(Model.of("gemini-3.8-flash"))662            .input(663                InteractionsInput.ofContent(664                    Arrays.asList(665                        ImageContent.builder()666                            .mimeType(ImageContentMimeType.IMAGE_JPEG)667                            .data(base64ImageData)668                            .build(),669                        TextContent.builder().text("Describe this image.").build())))670            .build();671672    Interaction interaction =673        client.interactions.create(CreateInteractionRequestBody.of(request)).interaction().get();674    System.out.println(interaction.outputText().orElse(""));675676### REST677678    # Request679    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \680    -H "Content-Type: application/json" \681    -H "x-goog-api-key: $GEMINI_API_KEY" \682    -d '{683        "model": "gemini-3.8-flash",684        "input": \[685    {686    "type": "image",687    "mime_type": "image/jpeg",688    "data": "..."689    },690    {691    "type": "text",692    "text": "Describe this image."693    }694    \]695    }'696697    # Response698    {699      "id": "int_multimodal",700      "steps": \[701    {702    "type": "user_input",703    "status": "done",704    "content": \[705    {706    "type": "image",707    "mime_type": "image/jpeg",708    "data": "..."709    },710    {711    "type": "text",712    "text": "Describe this image."713    }714    \]715    },716    {717    "type": "model_output",718    "status": "done",719    "content": \[720    {721    "type": "text",722    "text": "This is a picture of a beautiful sunset over the mountains."723    }724    \]725    }726    \]727    }728729## Structured output730731To make the model return JSON matching a specific schema, configure the response format.732733### Before (`generateContent`)734735In `generateContent`, you configure output format using the `response_mime_type` and `response_schema` fields nested inside the `config` (or `generationConfig`) object.736737### Python738739    from google import genai740    from google.genai import types741    from pydantic import BaseModel742743    client = genai.Client()744745    class Recipe(BaseModel):746        recipe_name: str747        ingredients: list[str]748749    response = client.models.generate_content(750        model="gemini-2.5-flash-lite",751        contents="Give me a recipe for chocolate chip cookies.",752        config=types.GenerateContentConfig(753            response_mime_type="application/json",754            response_schema=Recipe,755        ),756    )757    print(response.text)758759### JavaScript760761    import { GoogleGenAI, Type } from '@google/genai';762763    const ai = new GoogleGenAI({});764765    const response = await ai.models.generateContent({766        model: 'gemini-2.5-flash-lite',767        contents: 'Give me a recipe for chocolate chip cookies.',768        config: {769            responseMimeType: 'application/json',770            responseSchema: {771                type: Type.OBJECT,772                properties: {773                    recipe_name: { type: Type.STRING },774                    ingredients: {775                        type: Type.ARRAY,776                        items: { type: Type.STRING },777                    },778                },779                required: ['recipe_name', 'ingredients'],780            },781        },782    });783    console.log(response.text);784785### Java786787    import com.google.genai.Client;788    import com.google.genai.types.GenerateContentConfig;789    import com.google.genai.types.GenerateContentResponse;790    import com.google.genai.types.Schema;791    import com.google.genai.types.Type;792    import java.util.Arrays;793    import java.util.Map;794795    Client client = new Client();796797    Schema recipeSchema =798        Schema.builder()799            .type(Type.Known.OBJECT)800            .properties(801                Map.of(802                    "recipe_name", Schema.builder().type(Type.Known.STRING).build(),803                    "ingredients",804                        Schema.builder()805                            .type(Type.Known.ARRAY)806                            .items(Schema.builder().type(Type.Known.STRING).build())807                            .build()))808            .required(Arrays.asList("recipe_name", "ingredients"))809            .build();810811    GenerateContentResponse response =812        client.models.generateContent(813            "gemini-2.5-flash-lite",814            "Give me a recipe for chocolate chip cookies.",815            GenerateContentConfig.builder()816                .responseMimeType("application/json")817                .responseSchema(recipeSchema)818                .build());819    System.out.println(response.text());820821### REST822823    # Request824    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent" \825    -H "Content-Type: application/json" \826    -H "x-goog-api-key: $GEMINI_API_KEY" \827    -d '{828        "contents": \[{829    "parts": \[{830    "text": "Give me a recipe for chocolate chip cookies."831    }\]832    }\],833    "generationConfig": {834    "responseMimeType": "application/json",835    "responseSchema": {836    "type": "OBJECT",837    "properties": {838    "recipe_name": { "type": "STRING" },839    "ingredients": {840    "type": "ARRAY",841    "items": { "type": "STRING" }842    }843    },844    "required": \["recipe_name", "ingredients"\]845    }846    }847    }'848849    # Response850    {851      "candidates": \[852    {853    "content": {854    "parts": \[855    {856    "text": "{\\n \\"recipe_name\\": \\"Chocolate Chip Cookies\\",\\n \\"ingredients\\": \[\\n \\"1 cup butter\\",\\n \\"1 cup sugar\\",\\n \\"2 cups flour\\",\\n \\"1 cup chocolate chips\\"\\n \]\\n}"857    }858    \],859    "role": "model"860    }861    }862    \]863    }864865### After (Interactions API)866867In the Interactions API, output format controls move to a top-level `response_format` array.868869### Python870871    from google import genai872    from pydantic import BaseModel873874    client = genai.Client()875876    class Recipe(BaseModel):877        recipe_name: str878        ingredients: list[str]879880    interaction = client.interactions.create(881        model="gemini-3.8-flash",882        input="Give me a recipe for chocolate chip cookies.",883        response_format=[884            {885                "type": "text",886                "mime_type": "application/json",887                "schema": Recipe.model_json_schema(),888            }889        ],890    )891892    print(interaction.output_text)893894### JavaScript895896    import { GoogleGenAI } from '@google/genai';897898    const client = new GoogleGenAI({});899900    const interaction = await client.interactions.create({901        model: 'gemini-3.8-flash',902        input: 'Give me a recipe for chocolate chip cookies.',903        response_format: [904            {905                type: 'text',906                mime_type: 'application/json',907                schema: {908                    type: 'object',909                    properties: {910                        recipe_name: { type: 'string' },911                        ingredients: {912                            type: 'array',913                            items: { type: 'string' }914                        }915                    },916                    required: ['recipe_name', 'ingredients']917                }918            }919        ]920    });921    console.log(interaction.output_text);922923### Java924925    import com.google.genai.Client;926    import com.google.genai.gaos.models.interactions.CreateModelInteraction;927    import com.google.genai.gaos.models.interactions.CreateModelInteractionResponseFormat;928    import com.google.genai.gaos.models.interactions.Interaction;929    import com.google.genai.gaos.models.interactions.InteractionsInput;930    import com.google.genai.gaos.models.interactions.Model;931    import com.google.genai.gaos.models.interactions.ResponseFormat;932    import com.google.genai.gaos.models.interactions.TextResponseFormat;933    import com.google.genai.gaos.models.interactions.TextResponseFormatMimeType;934    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;935    import java.util.Arrays;936    import java.util.HashMap;937    import java.util.Map;938939    Client client = new Client();940941    Map<String, Object> properties = new HashMap<>();942    properties.put("recipe_name", Map.of("type", "string"));943    properties.put("ingredients", Map.of("type", "array", "items", Map.of("type", "string")));944945    Map<String, Object> schema = new HashMap<>();946    schema.put("type", "object");947    schema.put("properties", properties);948    schema.put("required", Arrays.asList("recipe_name", "ingredients"));949950    CreateModelInteraction request =951        CreateModelInteraction.builder()952            .model(Model.of("gemini-3.8-flash"))953            .input(InteractionsInput.of("Give me a recipe for chocolate chip cookies."))954            .responseFormat(955                CreateModelInteractionResponseFormat.of(956                    Arrays.asList(957                        ResponseFormat.of(958                            TextResponseFormat.builder()959                                .mimeType(TextResponseFormatMimeType.APPLICATION_JSON)960                                .schema(schema)961                                .build()))))962            .build();963964    Interaction interaction =965        client.interactions.create(CreateInteractionRequestBody.of(request)).interaction().get();966    System.out.println(interaction.outputText().orElse(""));967968### REST969970    # Request971    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \972    -H "Content-Type: application/json" \973    -H "x-goog-api-key: $GEMINI_API_KEY" \974    -d '{975        "model": "gemini-3.8-flash",976        "input": "Give me a recipe for chocolate chip cookies.",977    "response_format": \[978    {979    "type": "text",980    "mime_type": "application/json",981    "schema": {982    "type": "OBJECT",983    "properties": {984    "recipe_name": { "type": "STRING" },985    "ingredients": {986    "type": "ARRAY",987    "items": { "type": "STRING" }988    }989    },990    "required": \["recipe_name", "ingredients"\]991    }992    }993    \]994    }'995996    # Response997    {998      "id": "int_structured",999      "steps": \[1000    {1001    "type": "user_input",1002    "status": "done",1003    "content": \[{ "type": "text", "text": "Give me a recipe for chocolate chip cookies." }\]1004    },1005    {1006    "type": "model_output",1007    "status": "done",1008    "content": \[1009    {1010    "type": "text",1011    "text": "{\\n \\"recipe_name\\": \\"Chocolate Chip Cookies\\",\\n \\"ingredients\\": \[\\n \\"1 cup butter\\",\\n \\"1 cup sugar\\",\\n \\"2 cups flour\\",\\n \\"1 cup chocolate chips\\"\\n \]\\n}"1012    }1013    \]1014    }1015    \]1016    }10171018## Multimodal generation10191020When generating content in modalities beyond text (such as images or audio), the primary difference is how the response structures the generated media.10211022### Before (`generateContent`)10231024In `generateContent`, the response returns generated media directly in the `parts` of the candidate, typically as base64 data in `inlineData`.10251026    # Response structure concept1027    {1028      "candidates": \[1029    {1030    "content": {1031    "parts": \[1032    {1033    "text": "Here is your generated image:"1034    },1035    {1036    "inlineData": {1037    "mimeType": "image/jpeg",1038    "data": "...base64..."1039    }1040    }1041    \]1042    }1043    }1044    \]1045    }10461047### After (Interactions API)10481049In the Interactions API, generated media appears as distinct items within the `content` array of a `model_output` step in the timeline, maintaining the chronological flow of the interaction.10501051    # Response structure concept1052    {1053      "id": "int_123",1054      "steps": \[1055    {1056    "type": "model_output",1057    "status": "done",1058    "content": \[1059    {1060    "type": "text",1061    "text": "Here is your generated image:"1062    },1063    {1064    "type": "image",1065    "mime_type": "image/jpeg",1066    "data": "...base64..." // Or a reference URL in future1067    }1068    \]1069    }1070    \]1071    }10721073This keeps the response parsing consistent with how inputs and text outputs are handled---everything is a step in the timeline.10741075## Server-side tools10761077Gemini supports built-in server-side tools like Google Search grounding. The primary difference is how the response represents tool execution.10781079### Before (`generateContent`)10801081In `generateContent`, server-side tools are largely opaque. You enable the tool and get a final answer with a separate `groundingMetadata` object. Crucially, citations are not inline; `groundingSupports` use character indices to map text segments back to web sources in `groundingChunks`.10821083### Python10841085    from google import genai1086    from google.genai import types10871088    client = genai.Client()10891090    response = client.models.generate_content(1091        model="gemini-2.5-flash-lite",1092        contents="Who won Euro 2024?",1093        config=types.GenerateContentConfig(1094            tools=[{"google_search": {}}]1095        ),1096    )10971098    metadata = response.candidates[0].grounding_metadata1099    if metadata.search_entry_point:1100        print(f"Search Entry Point: {metadata.search_entry_point.rendered_content}")11011102    for support in metadata.grounding_supports:1103        print(f"Citation: {support.segment.text}")11041105### JavaScript11061107    import { GoogleGenAI } from '@google/genai';11081109    const client = new GoogleGenAI({});11101111    const response = await client.models.generateContent({1112        model: 'gemini-2.5-flash-lite',1113        contents: 'Who won Euro 2024?',1114        config: {1115            tools: [{ google_search: {} }]1116        }1117    });11181119    const metadata = response.candidates[0].groundingMetadata;1120    if (metadata.searchEntryPoint) {1121        console.log(`Search Entry Point: ${metadata.searchEntryPoint.renderedContent}`);1122    }1123    for (const support of metadata.groundingSupports) {1124        console.log(`Citation: ${support.segment.text}`);1125    }11261127### Java11281129    import com.google.genai.Client;1130    import com.google.genai.types.Candidate;1131    import com.google.genai.types.GenerateContentConfig;1132    import com.google.genai.types.GenerateContentResponse;1133    import com.google.genai.types.GoogleSearch;1134    import com.google.genai.types.GroundingMetadata;1135    import com.google.genai.types.GroundingSupport;1136    import com.google.genai.types.Tool;1137    import java.util.Arrays;1138    import java.util.Collections;1139    import java.util.List;1140    import java.util.Optional;11411142    Client client = new Client();11431144    GenerateContentResponse response =1145        client.models.generateContent(1146            "gemini-2.5-flash-lite",1147            "Who won Euro 2024?",1148            GenerateContentConfig.builder()1149                .tools(1150                    Arrays.asList(1151                        Tool.builder().googleSearch(GoogleSearch.builder().build()).build()))1152                .build());11531154    List<Candidate> candidates = response.candidates().orElse(Collections.emptyList());1155    if (!candidates.isEmpty() && candidates.get(0).groundingMetadata().isPresent()) {1156      GroundingMetadata metadata = candidates.get(0).groundingMetadata().get();1157      if (metadata.searchEntryPoint().isPresent()) {1158        System.out.println(1159            "Search Entry Point: " + metadata.searchEntryPoint().get().renderedContent().orElse(""));1160      }1161      for (GroundingSupport support : metadata.groundingSupports().orElse(Collections.emptyList())) {1162        Optional<String> segmentText = support.segment().flatMap(s -> s.text());1163        segmentText.ifPresent(text -> System.out.println("Citation: " + text));1164      }1165    }11661167### REST11681169    # Request1170    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent" \1171    -H "Content-Type: application/json" \1172    -H "x-goog-api-key: $GEMINI_API_KEY" \1173    -d '{1174        "contents": \[{1175    "parts": \[{1176    "text": "Who won Euro 2024?"1177    }\]1178    }\],1179    "tools": \[{1180    "googleSearchRetrieval": {}1181    }\]1182    }'11831184    # Response1185    {1186      "candidates": \[1187    {1188    "content": {1189    "parts": \[1190    {1191    "text": "Spain won Euro 2024, defeating England 2-1 in the final. This victory marks Spain's record fourth European Championship title."1192    }1193    \],1194    "role": "model"1195    },1196    "groundingMetadata": {1197    "webSearchQueries": \[1198    "UEFA Euro 2024 winner",1199    "who won euro 2024"1200    \],1201    "searchEntryPoint": {1202    "renderedContent": "\<!-- HTML and CSS for the search widget --\>"1203    },1204    "groundingChunks": \[1205    {"web": {"uri": "https://vertexaisearch.cloud.google.com.....", "title": "aljazeera.com"}},1206    {"web": {"uri": "https://vertexaisearch.cloud.google.com.....", "title": "uefa.com"}}1207    \],1208    "groundingSupports": \[1209    {1210    "segment": {"startIndex": 0, "endIndex": 85, "text": "Spain won Euro 2024, defeatin..."},1211    "groundingChunkIndices": \[0\]1212    },1213    {1214    "segment": {"startIndex": 86, "endIndex": 210, "text": "This victory marks Spain's..."},1215    "groundingChunkIndices": \[0, 1\]1216    }1217    \]1218    }1219    }1220    \]1221    }12221223### After (Interactions API)12241225In the Interactions API, server-side tools provide full timeline transparency. The API records the call and result as distinct execution `steps` (`google_search_call` and `google_search_result`), exposing exactly what data the model retrieved.12261227Furthermore, the API returns citations **inline** . Instead of mapping indices from a separate metadata object, the text item within the `model_output` step contains its own `annotations` array linking directly to the source.12281229### Python12301231    from google import genai12321233    client = genai.Client()12341235    interaction = client.interactions.create(1236        model="gemini-3.8-flash",1237        input="Who won Euro 2024?",1238        tools=[{"type": "google_search"}],1239    )12401241    for step in interaction.steps:1242        if step.type == "google_search_result":1243            print(f"Search Suggestions: {step.result[0].search_suggestions}")1244        elif step.type == "model_output":1245            print(f"Answer: {step.content[0].text}")1246            if step.content[0].annotations:1247                for anno in step.content[0].annotations:1248                    print(f"Citation: {anno.title} ({anno.uri})")12491250### JavaScript12511252    import { GoogleGenAI } from '@google/genai';12531254    const client = new GoogleGenAI({});12551256    const interaction = await client.interactions.create({1257        model: 'gemini-3.8-flash',1258        input: 'Who won Euro 2024?',1259        tools: [{ type: 'google_search' }]1260    });12611262    for (const step of interaction.steps) {1263        if (step.type === 'google_search_result') {1264            console.log(`Search Suggestions: ${step.result[0].search_suggestions}`);1265        } else if (step.type === 'model_output') {1266            console.log(`Answer: ${step.content[0].text}`);1267            if (step.content[0].annotations) {1268                for (const anno of step.content[0].annotations) {1269                    console.log(`Citation: ${anno.title} (${anno.uri})`);1270                }1271            }1272        }1273    }12741275### Java12761277    import com.google.genai.Client;1278    import com.google.genai.gaos.models.interactions.Annotation;1279    import com.google.genai.gaos.models.interactions.Content;1280    import com.google.genai.gaos.models.interactions.CreateModelInteraction;1281    import com.google.genai.gaos.models.interactions.GoogleSearch;1282    import com.google.genai.gaos.models.interactions.GoogleSearchResult;1283    import com.google.genai.gaos.models.interactions.GoogleSearchResultStep;1284    import com.google.genai.gaos.models.interactions.Interaction;1285    import com.google.genai.gaos.models.interactions.InteractionsInput;1286    import com.google.genai.gaos.models.interactions.Model;1287    import com.google.genai.gaos.models.interactions.ModelOutputStep;1288    import com.google.genai.gaos.models.interactions.Step;1289    import com.google.genai.gaos.models.interactions.TextContent;1290    import com.google.genai.gaos.models.interactions.URLCitation;1291    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;1292    import java.util.Arrays;1293    import java.util.Collections;12941295    Client client = new Client();12961297    CreateModelInteraction request =1298        CreateModelInteraction.builder()1299            .model(Model.of("gemini-3.8-flash"))1300            .input(InteractionsInput.of("Who won Euro 2024?"))1301            .tools(Arrays.asList(GoogleSearch.builder().build()))1302            .build();13031304    Interaction interaction =1305        client.interactions.create(CreateInteractionRequestBody.of(request)).interaction().get();13061307    for (Step step : interaction.steps().orElse(Collections.emptyList())) {1308      if (step instanceof GoogleSearchResultStep) {1309        GoogleSearchResultStep searchStep = (GoogleSearchResultStep) step;1310        for (GoogleSearchResult res : searchStep.result().orElse(Collections.emptyList())) {1311          System.out.println("Search Suggestions: " + res.searchSuggestions().orElse(""));1312        }1313      } else if (step instanceof ModelOutputStep) {1314        ModelOutputStep modelOutput = (ModelOutputStep) step;1315        for (Content contentBlock : modelOutput.content().orElse(Collections.emptyList())) {1316          if (contentBlock instanceof TextContent) {1317            TextContent textContent = (TextContent) contentBlock;1318            System.out.println("Answer: " + textContent.text().orElse(""));1319            for (Annotation anno : textContent.annotations().orElse(Collections.emptyList())) {1320              if (anno instanceof URLCitation) {1321                URLCitation cit = (URLCitation) anno;1322                System.out.println(1323                    "Citation: " + cit.title().orElse("") + " (" + cit.url().orElse("") + ")");1324              }1325            }1326          }1327        }1328      }1329    }13301331### REST13321333    # Request1334    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \1335    -H "Content-Type: application/json" \1336    -H "x-goog-api-key: $GEMINI_API_KEY" \1337    -d '{1338        "model": "gemini-3.8-flash",1339        "input": "Who won Euro 2024?",1340    "tools": \[{"type": "google_search"}\]1341    }'13421343    # Response (showing grounding)1344    {1345      "id": "int_grounded",1346      "steps": \[1347    {1348    "type": "user_input",1349    "status": "done",1350    "content": \[{ "type": "text", "text": "Who won Euro 2024?" }\]1351    },1352    {1353    "type": "google_search_call",1354    "status": "done",1355    "content": \[{ "type": "text", "text": "UEFA Euro 2024 winner" }\]1356    },1357    {1358    "type": "google_search_result",1359    "status": "done",1360    "content": \[1361    {1362    "type": "text",1363    "text": "Spain won Euro 2024..."1364    }1365    \]1366    },1367    {1368    "type": "model_output",1369    "status": "done",1370    "content": \[1371    {1372    "type": "text",1373    "text": "Spain won Euro 2024, defeating England 2-1.",1374    "annotations": \[1375    {1376    "start_index": 0,1377    "end_index": 42,1378    "uri": "https://vertexaisearch...",1379    "title": "aljazeera.com"1380    }1381    \]1382    }1383    \]1384    }1385    \]1386    }13871388## Function calling13891390The structure of function calls and results has also changed to fit the Steps schema.13911392### Before (`generateContent`)13931394In `generateContent`, the response returns function calls within the candidates.\* {Python}13951396    ```python1397    from google import genai1398    from google.genai import types13991400    client = genai.Client()14011402    response = client.models.generate_content(1403        model="gemini-2.5-flash-lite",1404        contents="What's the weather in Boston?",1405        config=types.GenerateContentConfig(tools=[weather_tool]),1406    )14071408    function_call = response.candidates[0].content.parts[0].function_call1409    print(f"Requested tool: {function_call.name}")14101411    result = "52°F and rain"14121413    response = client.models.generate_content(1414        model="gemini-2.5-flash-lite",1415        contents=[1416            types.Content(1417                role="user",1418                parts=[1419                    types.Part.from_text(text="What's the weather in Boston?")1420                ],1421            ),1422            response.candidates[0].content,1423            types.Content(1424                role="user",1425                parts=[1426                    types.Part.from_function_response(1427                        name=function_call.name,1428                        response={"result": result},1429                    )1430                ],1431            ),1432        ],1433        config=types.GenerateContentConfig(tools=[weather_tool]),1434    )1435    print(response.text)1436    ```14371438### JavaScript14391440    import { GoogleGenAI } from '@google/genai';14411442    const client = new GoogleGenAI({});14431444    let response = await client.models.generateContent({1445        model: 'gemini-2.5-flash-lite',1446        contents: "What's the weather in Boston?",1447        config: { tools: [weatherTool] }1448    });14491450    const functionCall = response.candidates[0].content.parts[0].functionCall;1451    console.log(`Requested tool: ${functionCall.name}`);14521453    const result = "52°F and rain";14541455    response = await client.models.generateContent({1456        model: 'gemini-2.5-flash-lite',1457        contents: [1458            { role: 'user', parts: [{ text: "What's the weather in Boston?" }] },1459            response.candidates[0].content,1460            {1461                role: 'user',1462                parts: [{1463                    functionResponse: {1464                        name: functionCall.name,1465                        response: { result: result }1466                    }1467                }]1468            }1469        ],1470        config: { tools: [weatherTool] }1471    });1472    console.log(response.text);14731474### Java14751476    import com.google.genai.Client;1477    import com.google.genai.types.Content;1478    import com.google.genai.types.FunctionCall;1479    import com.google.genai.types.FunctionDeclaration;1480    import com.google.genai.types.GenerateContentConfig;1481    import com.google.genai.types.GenerateContentResponse;1482    import com.google.genai.types.Part;1483    import com.google.genai.types.Schema;1484    import com.google.genai.types.Tool;1485    import com.google.genai.types.Type;1486    import java.util.Arrays;1487    import java.util.Map;14881489    Client client = new Client();14901491    FunctionDeclaration weatherFunc =1492        FunctionDeclaration.builder()1493            .name("get_weather")1494            .description("Gets weather")1495            .parameters(1496                Schema.builder()1497                    .type(Type.Known.OBJECT)1498                    .properties(Map.of("location", Schema.builder().type(Type.Known.STRING).build()))1499                    .build())1500            .build();15011502    Tool weatherTool = Tool.builder().functionDeclarations(Arrays.asList(weatherFunc)).build();15031504    GenerateContentResponse response =1505        client.models.generateContent(1506            "gemini-2.5-flash-lite",1507            "What's the weather in Boston?",1508            GenerateContentConfig.builder().tools(Arrays.asList(weatherTool)).build());15091510    FunctionCall functionCall = response.functionCalls().get(0);1511    System.out.println("Requested tool: " + functionCall.name().orElse(""));15121513    String result = "52°F and rain";15141515    GenerateContentResponse finalResponse =1516        client.models.generateContent(1517            "gemini-2.5-flash-lite",1518            Arrays.asList(1519                Content.builder()1520                    .role("user")1521                    .parts(Arrays.asList(Part.fromText("What's the weather in Boston?")))1522                    .build(),1523                response.candidates().get().get(0).content().get(),1524                Content.builder()1525                    .role("user")1526                    .parts(1527                        Arrays.asList(1528                            Part.fromFunctionResponse(1529                                functionCall.name().orElse(""), Map.of("result", result))))1530                    .build()),1531            GenerateContentConfig.builder().tools(Arrays.asList(weatherTool)).build());1532    System.out.println(finalResponse.text());15331534### REST15351536    # Request1537    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent" \1538    -H "Content-Type: application/json" \1539    -H "x-goog-api-key: $GEMINI_API_KEY" \1540    -d '{1541        "contents": \[{1542    "parts": \[{1543    "text": "What is the weather like in Boston, MA?"1544    }\]1545    }\],1546    "tools": \[{1547    "functionDeclarations": \[{1548    "name": "get_weather",1549    "description": "Get the current weather",1550    "parameters": {1551    "type": "OBJECT",1552    "properties": {1553    "location": {"type": "STRING"}1554    },1555    "required": \["location"\]1556    }1557    }\]1558    }\]1559    }'15601561    # Response1562    {1563      "candidates": \[1564    {1565    "content": {1566    "parts": \[1567    {1568    "functionCall": {1569    "name": "get_weather",1570    "args": { "location": "Boston, MA" }1571    }1572    }1573    \],1574    "role": "model"1575    },1576    "finishReason": "STOP",1577    "index": 01578    }1579    \]1580    }15811582### After (Interactions API)15831584Tool calls and results are now distinct steps in the timeline.15851586### Python15871588    from google import genai15891590    client = genai.Client()15911592    weather_tool = {1593        "type": "function",1594        "name": "get_weather",1595        "description": "Gets weather",1596        "parameters": {1597            "type": "object",1598            "properties": {1599                "location": {"type": "string"}1600            },1601        },1602    }16031604    interaction = client.interactions.create(1605        model="gemini-3.8-flash",1606        input="What's the weather in Boston?",1607        tools=[weather_tool],1608    )16091610    for step in interaction.steps:1611        if step.type == "function_call":1612            print(f"Executing {step.name} for {step.arguments}")16131614            result = "52°F and rain"16151616            interaction = client.interactions.create(1617                model="gemini-3.8-flash",1618                previous_interaction_id=interaction.id,1619                input=[1620                    {1621                        "type": "function_result",1622                        "call_id": step.id,1623                        "name": step.name,1624                        "result": [{"type": "text", "text": result}],1625                    }1626                ],1627            )1628            print(interaction.output_text)16291630### JavaScript16311632    import { GoogleGenAI } from '@google/genai';16331634    const client = new GoogleGenAI({});16351636    const weatherTool = {1637        type: "function",1638        name: "get_weather",1639        description: "Get weather for a location",1640        parameters: {1641            type: "object",1642            properties: {1643                location: { type: "string" }1644            },1645            required: ["location"]1646        }1647    };16481649    const interaction = await client.interactions.create({1650        model: 'gemini-3.8-flash',1651        input: "What's the weather in Boston?",1652        tools: [weatherTool]1653    });16541655    for (const step of interaction.steps) {1656        if (step.type === 'function_call') {1657            console.log(`Executing ${step.name} for ${JSON.stringify(step.arguments)}`);16581659            const result = "52°F and rain";16601661            const nextInteraction = await client.interactions.create({1662                model: 'gemini-3.8-flash',1663                previous_interaction_id: interaction.id,1664                input: [1665                    {1666                        type: 'function_result',1667                        call_id: step.id,1668                        name: step.name,1669                        result: [{ type: 'text', text: result }]1670                    }1671                ]1672            });16731674            console.log(nextInteraction.output_text);1675        }1676    }16771678### Java16791680    import com.google.genai.Client;1681    import com.google.genai.gaos.models.interactions.CreateModelInteraction;1682    import com.google.genai.gaos.models.interactions.Function;1683    import com.google.genai.gaos.models.interactions.FunctionCallStep;1684    import com.google.genai.gaos.models.interactions.FunctionResultStep;1685    import com.google.genai.gaos.models.interactions.FunctionResultStepResultUnion;1686    import com.google.genai.gaos.models.interactions.Interaction;1687    import com.google.genai.gaos.models.interactions.InteractionsInput;1688    import com.google.genai.gaos.models.interactions.Model;1689    import com.google.genai.gaos.models.interactions.Step;1690    import com.google.genai.gaos.models.interactions.TextContent;1691    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;1692    import java.util.Arrays;1693    import java.util.Collections;1694    import java.util.HashMap;1695    import java.util.Map;16961697    Client client = new Client();16981699    Map<String, Object> properties = new HashMap<>();1700    properties.put("location", Map.of("type", "string"));17011702    Map<String, Object> parameters = new HashMap<>();1703    parameters.put("type", "object");1704    parameters.put("properties", properties);1705    parameters.put("required", Arrays.asList("location"));17061707    Function weatherTool =1708        Function.builder()1709            .name("get_weather")1710            .description("Gets weather")1711            .parameters(parameters)1712            .build();17131714    CreateModelInteraction request =1715        CreateModelInteraction.builder()1716            .model(Model.of("gemini-3.8-flash"))1717            .input(InteractionsInput.of("What's the weather in Boston?"))1718            .tools(Arrays.asList(weatherTool))1719            .build();17201721    Interaction interaction =1722        client.interactions.create(CreateInteractionRequestBody.of(request)).interaction().get();17231724    for (Step step : interaction.steps().orElse(Collections.emptyList())) {1725      if (step instanceof FunctionCallStep) {1726        FunctionCallStep fcStep = (FunctionCallStep) step;1727        System.out.println(1728            "Executing "1729                + fcStep.name().orElse("")1730                + " for "1731                + fcStep.arguments().orElse(Collections.emptyMap()));17321733        String result = "52°F and rain";17341735        FunctionResultStep funcResult =1736            FunctionResultStep.builder()1737                .callId(fcStep.id().orElse(""))1738                .name(fcStep.name().orElse(""))1739                .result(1740                    FunctionResultStepResultUnion.of(1741                        Arrays.asList(TextContent.builder().text(result).build())))1742                .build();17431744        CreateModelInteraction nextRequest =1745            CreateModelInteraction.builder()1746                .model(Model.of("gemini-3.8-flash"))1747                .previousInteractionId(interaction.id().orElse(""))1748                .input(InteractionsInput.ofStep(Arrays.asList(funcResult)))1749                .build();17501751        Interaction nextInteraction =1752            client.interactions.create(CreateInteractionRequestBody.of(nextRequest)).interaction().get();1753        System.out.println(nextInteraction.outputText().orElse(""));1754      }1755    }17561757### REST17581759    # Initial Request1760    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \1761    -H "Content-Type: application/json" \1762    -H "x-goog-api-key: $GEMINI_API_KEY" \1763    -d '{1764        "model": "gemini-3.8-flash",1765        "input": "What's the weather in Boston?",1766    "tools": \[{1767    "type": "function",1768    "name": "get_weather",1769    "description": "Get weather for a location",1770    "parameters": {1771    "type": "object",1772    "properties": {1773    "location": { "type": "string" }1774    },1775    "required": \["location"\]1776    }1777    }\]1778    }'17791780    # Response (requires action)1781    {1782      "id": "int_001",1783      "status": "requires_action",1784      "steps": \[1785    {1786    "type": "user_input",1787    "status": "done",1788    "content": \[1789    { "type": "text", "text": "What's the weather in Boston?" }1790    \]1791    },1792    {1793    "type": "function_call",1794    "status": "waiting",1795    "id": "fc_1",1796    "name": "get_weather",1797    "arguments": { "location": "Boston, MA" }1798    }1799    \]1800    }18011802    # Submit Tool Result Request1803    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \1804    -H "Content-Type: application/json" \1805    -H "x-goog-api-key: $GEMINI_API_KEY" \1806    -d '{1807        "model": "gemini-3.8-flash",1808        "previous_interaction_id": "int_001",1809    "input": {1810    "type": "function_result",1811    "call_id": "fc_1",1812    "name": "get_weather",1813    "result": \[1814    { "type": "text", "text": "52°F with rain" }1815    \]1816    }1817    }'18181819    # Final Response1820    {1821      "id": "int_002",1822      "status": "completed",1823      "steps": \[1824    {1825    "type": "function_result",1826    "call_id": "fc_1",1827    "name": "get_weather",1828    "result": \[1829    { "type": "text", "text": "52°F with rain" }1830    \]1831    },1832    {1833    "type": "model_output",1834    "status": "done",1835    "content": \[1836    { "type": "text", "text": "It's 52°F with rain in Boston." }1837    \]1838    }1839    \]1840    }18411842## Streaming18431844A key difference in streaming is that the Interactions API uses the same endpoint with `"stream": true` in the request body, whereas the `generateContent` API required calling a dedicated endpoint (`:streamGenerateContent`).18451846Additionally, streaming events now use specialized types to monitor the interaction lifecycle and track execution steps along the timeline.18471848### Before (`generateContentStream`)18491850With `generateContent`, you consume a stream of response chunks.18511852### Python18531854    from google import genai18551856    client = genai.Client()18571858    response = client.models.generate_content_stream(1859        model="gemini-2.5-flash-lite", contents="Tell me a story"1860    )1861    for chunk in response:1862        print(chunk.text, end="")18631864### JavaScript18651866    const responseStream = await client.models.generateContentStream({1867        model: 'gemini-2.5-flash-lite',1868        contents: 'Tell me a story',1869    });1870    for await (const chunk of responseStream) {1871        process.stdout.write(chunk.text);1872    }18731874### Java18751876    import com.google.genai.Client;1877    import com.google.genai.ResponseStream;1878    import com.google.genai.types.GenerateContentResponse;18791880    Client client = new Client();18811882    try (ResponseStream<GenerateContentResponse> responseStream =1883        client.models.generateContentStream("gemini-2.5-flash-lite", "Tell me a story", null)) {1884      for (GenerateContentResponse chunk : responseStream) {1885        System.out.print(chunk.text());1886      }1887    }18881889### REST18901891    # Request1892    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:streamGenerateContent" \1893    -H "Content-Type: application/json" \1894    -H "x-goog-api-key: $GEMINI_API_KEY" \1895    -d '{1896        "contents": \[{1897    "parts": \[{1898    "text": "Tell me a story"1899    }\]1900    }\]1901    }'19021903    # Response stream1904    event: content.start1905    data: {"event_type": "content.start", "index": 0, "content": {"type": "thought"}}1906    event: content.delta1907    data: {"event_type": "content.delta", "index": 0, "delta": {"type": "thought_summary", "text": "User wants an explanation."}}1908    event: content.stop1909    data: {"event_type": "content.stop", "index": 0}1910    event: content.start1911    data: {"event_type": "content.start", "index": 1, "content": {"type": "text"}}1912    event: content.delta1913    data: {"event_type": "content.delta", "index": 1, "delta": {"type": "text", "text": "Hello"}}1914    event: content.stop1915    data: {"event_type": "content.stop", "index": 1}19161917### After (Interactions API)19181919In the Interactions API, streaming uses Server-Sent Events (SSE) and specialized delta types to represent execution steps as they happen.19201921### Python19221923    from google import genai19241925    client = genai.Client()19261927    stream = client.interactions.create(1928        model="gemini-3.8-flash",1929        input="Tell me a story",1930        stream=True,1931    )19321933    for event in stream:1934        if event.event_type == "step.delta" and event.delta:1935            if getattr(event.delta, "type", None) == "text" and getattr(event.delta, "text", None):1936                print(event.delta.text, end="", flush=True)1937        elif event.event_type == "interaction.completed":1938            print(f"\n\n--- Stream Finished ---")19391940### JavaScript19411942    import { GoogleGenAI } from '@google/genai';19431944    const client = new GoogleGenAI({});19451946    const stream = await client.interactions.create({1947        model: 'gemini-3.8-flash',1948        input: 'Tell me a story',1949        stream: true,1950    });19511952    for await (const event of stream) {1953        if (event.event_type === 'step.delta' && event.delta) {1954            if (event.delta.type === 'text' && event.delta.text) {1955                process.stdout.write(event.delta.text);1956            }1957        } else if (event.event_type === 'interaction.completed') {1958            console.log('\n\n--- Stream Finished ---');1959        }1960    }19611962### Java19631964    import com.google.genai.Client;1965    import com.google.genai.gaos.models.interactions.CreateModelInteraction;1966    import com.google.genai.gaos.models.interactions.InteractionCompletedEvent;1967    import com.google.genai.gaos.models.interactions.InteractionSSEEvent;1968    import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent;1969    import com.google.genai.gaos.models.interactions.InteractionsInput;1970    import com.google.genai.gaos.models.interactions.Model;1971    import com.google.genai.gaos.models.interactions.StepDelta;1972    import com.google.genai.gaos.models.interactions.TextDelta;1973    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;1974    import com.google.genai.gaos.utils.EventStream;19751976    Client client = new Client();19771978    CreateModelInteraction request =1979        CreateModelInteraction.builder()1980            .model(Model.of("gemini-3.8-flash"))1981            .input(InteractionsInput.of("Tell me a story"))1982            .stream(true)1983            .build();19841985    try (EventStream<InteractionSSEStreamEvent> stream =1986        client.interactions.create(CreateInteractionRequestBody.of(request)).events()) {1987      for (InteractionSSEStreamEvent streamEvent : stream) {1988        if (streamEvent.data().isPresent()) {1989          InteractionSSEEvent event = streamEvent.data().get();1990          if (event instanceof StepDelta) {1991            StepDelta stepDelta = (StepDelta) event;1992            if (stepDelta.delta().isPresent() && stepDelta.delta().get() instanceof TextDelta) {1993              TextDelta textDelta = (TextDelta) stepDelta.delta().get();1994              System.out.print(textDelta.text().orElse(""));1995            }1996          } else if (event instanceof InteractionCompletedEvent) {1997            System.out.println("\n\n--- Stream Finished ---");1998          }1999        }2000      }2001    }20022003### REST20042005# Example SSE stream output2006**event: interaction.created2007data: {"type": "interaction.created", "interaction": {"id": "int_xyz", "status": "created"}}2008event: interaction.in_progress2009data: {"type": "interaction.in_progress", "interaction": {"id": "int_xyz", "status": "in_progress"}}2010event: step.start2011data: {"type": "step.start", "index": 0, "step": {"type": "thought"}}2012event: step.delta2013data: {"type": "step.delta", "index": 0, "delta": {"type": "thought", "text": "User wants an explanation."}}2014event: step.stop2015data: {"type": "step.stop", "index": 0, "status": "done"}2016event: step.start2017data: {"type": "step.start", "index": 1, "step": {"type": "model_output"}}2018event: step.delta2019data: {"type": "step.delta", "index": 1, "delta": {"type": "text", "text": "Hello"}}2020event: step.stop2021data: {"type": "step.stop", "index": 1, "status": "done"}2022event: interaction.completed2023data: {"type": "interaction.completed", "interaction": {"id": "int_xyz", "status": "completed", "usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15}}}**2024\`\`\`20252026### Streaming tools and function calls20272028The way tools behave in the stream has shifted significantly from `generateContent` to provide more granular control and visibility.20292030#### Before (`generateContent`)20312032With `generateContent`, streaming function calls arrived complete in a single chunk. You could not see the arguments being generated in real-time, so the handler simply checked for a complete `functionCall` object.20332034### Python20352036    from google import genai2037    from google.genai import types20382039    client = genai.Client()20402041    stream = client.models.generate_content_stream(2042        model="gemini-2.5-flash-lite",2043        contents="What's the weather in Boston?",2044        config=types.GenerateContentConfig(tools=[weather_tool]),2045    )20462047    for chunk in stream:2048        # Function calls arrived complete --- no partial arguments2049        if chunk.candidates[0].content.parts[0].function_call:2050            fc = chunk.candidates[0].content.parts[0].function_call2051            print(f"Call: {fc.name}({fc.args})")2052        elif chunk.text:2053            print(chunk.text, end="")20542055### JavaScript20562057    import { GoogleGenAI } from '@google/genai';20582059    const client = new GoogleGenAI({});20602061    const stream = await client.models.generateContentStream({2062        model: 'gemini-2.5-flash-lite',2063        contents: "What's the weather in Boston?",2064        config: { tools: [weatherTool] }2065    });20662067    for await (const chunk of stream) {2068        const part = chunk.candidates[0].content.parts[0];2069        if (part.functionCall) {2070            console.log(`Call: ${part.functionCall.name}(${JSON.stringify(part.functionCall.args)})`);2071        } else if (part.text) {2072            process.stdout.write(part.text);2073        }2074    }20752076### Java20772078    import com.google.genai.Client;2079    import com.google.genai.ResponseStream;2080    import com.google.genai.types.FunctionCall;2081    import com.google.genai.types.FunctionDeclaration;2082    import com.google.genai.types.GenerateContentConfig;2083    import com.google.genai.types.GenerateContentResponse;2084    import com.google.genai.types.Schema;2085    import com.google.genai.types.Tool;2086    import com.google.genai.types.Type;2087    import java.util.Arrays;2088    import java.util.Map;20892090    Client client = new Client();20912092    FunctionDeclaration weatherFunc =2093        FunctionDeclaration.builder()2094            .name("get_weather")2095            .description("Gets weather")2096            .parameters(2097                Schema.builder()2098                    .type(Type.Known.OBJECT)2099                    .properties(Map.of("location", Schema.builder().type(Type.Known.STRING).build()))2100                    .build())2101            .build();21022103    Tool weatherTool = Tool.builder().functionDeclarations(Arrays.asList(weatherFunc)).build();21042105    try (ResponseStream<GenerateContentResponse> stream =2106        client.models.generateContentStream(2107            "gemini-2.5-flash-lite",2108            "What's the weather in Boston?",2109            GenerateContentConfig.builder().tools(Arrays.asList(weatherTool)).build())) {2110      for (GenerateContentResponse chunk : stream) {2111        if (chunk.functionCalls() != null && !chunk.functionCalls().isEmpty()) {2112          FunctionCall fc = chunk.functionCalls().get(0);2113          System.out.println("Call: " + fc.name().orElse("") + "(" + fc.args().orElse(Map.of()) + ")");2114        } else if (chunk.text() != null) {2115          System.out.print(chunk.text());2116        }2117      }2118    }21192120### REST21212122    # Request2123    curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:streamGenerateContent" \2124    -H "Content-Type: application/json" \2125    -H "x-goog-api-key: $GEMINI_API_KEY" \2126    -d '{2127        "contents": \[{"parts": \[{"text": "What is the weather in Boston?"}\]}\],2128    "tools": \[{"functionDeclarations": \[{"name": "get_weather", "parameters": {"type": "OBJECT", "properties": {"location": {"type": "STRING"}}}}\]}\]2129    }'21302131    # Response stream --- function call arrives complete in one chunk2132    {"candidates": \[{"content": {"parts": \[{"functionCall": {"name": "get_weather", "args": {"location": "Boston, MA"}}}\]}}\]}21332134#### After (Interactions API)21352136The Interactions API streams function call arguments character-by-character as `arguments` events. The entire tool lifecycle --- thought, call, result, and output --- plays out as a series of distinct steps.21372138### Python21392140    from google import genai21412142    client = genai.Client()21432144    stream = client.interactions.create(2145        model="gemini-3.8-flash",2146        input="What's the weather in Boston?",2147        tools=[get_weather_tool],2148        stream=True,2149    )21502151    for event in stream:2152        if event.event_type == "step.start" and event.step:2153            if getattr(event.step, "type", None) == "function_call":2154                print(f"Calling: {event.step.name}")2155        elif event.event_type == "step.delta" and event.delta:2156            if getattr(event.delta, "type", None) == "arguments":2157                print(f"  args: {event.delta.partial_arguments}")2158            elif getattr(event.delta, "type", None) == "text" and getattr(event.delta, "text", None):2159                print(event.delta.text, end="")2160        elif event.event_type == "interaction.completed":2161            print("\n--- Done ---")21622163### JavaScript21642165    import { GoogleGenAI } from '@google/genai';21662167    const client = new GoogleGenAI({});21682169    const stream = await client.interactions.create({2170        model: 'gemini-3.8-flash',2171        input: "What's the weather in Boston?",2172        tools: [getWeatherTool],2173        stream: true,2174    });21752176    for await (const event of stream) {2177        if (event.event_type === 'step.start' && event.step) {2178            if (event.step.type === 'function_call') {2179                console.log(`Calling: ${event.step.name}`);2180            }2181        } else if (event.event_type === 'step.delta' && event.delta) {2182            if (event.delta.type === 'arguments' && event.delta.partial_arguments) {2183                console.log(`  args: ${event.delta.partial_arguments}`);2184            } else if (event.delta.type === 'text' && event.delta.text) {2185                process.stdout.write(event.delta.text);2186            }2187        } else if (event.event_type === 'interaction.completed') {2188            console.log('\n--- Done ---');2189        }2190    }21912192### Java21932194    import com.google.genai.Client;2195    import com.google.genai.gaos.models.interactions.ArgumentsDelta;2196    import com.google.genai.gaos.models.interactions.CreateModelInteraction;2197    import com.google.genai.gaos.models.interactions.Function;2198    import com.google.genai.gaos.models.interactions.FunctionCallStep;2199    import com.google.genai.gaos.models.interactions.InteractionCompletedEvent;2200    import com.google.genai.gaos.models.interactions.InteractionSSEEvent;2201    import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent;2202    import com.google.genai.gaos.models.interactions.InteractionsInput;2203    import com.google.genai.gaos.models.interactions.Model;2204    import com.google.genai.gaos.models.interactions.StepDelta;2205    import com.google.genai.gaos.models.interactions.StepDeltaData;2206    import com.google.genai.gaos.models.interactions.StepStart;2207    import com.google.genai.gaos.models.interactions.TextDelta;2208    import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;2209    import com.google.genai.gaos.utils.EventStream;2210    import java.util.Arrays;2211    import java.util.HashMap;2212    import java.util.Map;22132214    Client client = new Client();22152216    Map<String, Object> properties = new HashMap<>();2217    properties.put("location", Map.of("type", "string"));22182219    Map<String, Object> parameters = new HashMap<>();2220    parameters.put("type", "object");2221    parameters.put("properties", properties);2222    parameters.put("required", Arrays.asList("location"));22232224    Function getWeatherTool =2225        Function.builder()2226            .name("get_weather")2227            .description("Gets weather")2228            .parameters(parameters)2229            .build();22302231    CreateModelInteraction request =2232        CreateModelInteraction.builder()2233            .model(Model.of("gemini-3.8-flash"))2234            .input(InteractionsInput.of("What's the weather in Boston?"))2235            .tools(Arrays.asList(getWeatherTool))2236            .stream(true)2237            .build();22382239    try (EventStream<InteractionSSEStreamEvent> stream =2240        client.interactions.create(CreateInteractionRequestBody.of(request)).events()) {2241      for (InteractionSSEStreamEvent streamEvent : stream) {2242        if (streamEvent.data().isPresent()) {2243          InteractionSSEEvent event = streamEvent.data().get();2244          if (event instanceof StepStart) {2245            StepStart stepStart = (StepStart) event;2246            if (stepStart.step().isPresent() && stepStart.step().get() instanceof FunctionCallStep) {2247              FunctionCallStep fcStep = (FunctionCallStep) stepStart.step().get();2248              System.out.println("Calling: " + fcStep.name().orElse(""));2249            }2250          } else if (event instanceof StepDelta) {2251            StepDelta stepDelta = (StepDelta) event;2252            if (stepDelta.delta().isPresent()) {2253              StepDeltaData delta = stepDelta.delta().get();2254              if (delta instanceof ArgumentsDelta) {2255                System.out.println("  args: " + ((ArgumentsDelta) delta).arguments().orElse(""));2256              } else if (delta instanceof TextDelta) {2257                System.out.print(((TextDelta) delta).text().orElse(""));2258              }2259            }2260          } else if (event instanceof InteractionCompletedEvent) {2261            System.out.println("\n--- Done ---");2262          }2263        }2264      }2265    }22662267### REST22682269    # Request2270    curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \2271    -H "Content-Type: application/json" \2272    -H "x-goog-api-key: $GEMINI_API_KEY" \2273    -d '{2274        "model": "gemini-3.8-flash",2275        "input": "What is the weather in Boston?",2276    "tools": \[{"type": "function", "name": "get_weather", "parameters": {"type": "object", "properties": {"location": {"type": "string"}}}}\],2277    "stream": true2278    }'22792280    # Response stream2281    // Interaction created2282    event: interaction.created2283    data: {"type": "interaction.created", "interaction": {"id": "int_xyz", "status": "created"}}22842285    event: interaction.in_progress2286    data: {"type": "interaction.in_progress", "interaction": {"id": "int_xyz", "status": "in_progress"}}22872288    // ── Step 0: Thought ──────────────────────────────────2289    event: step.start2290    data: {"type": "step.start", "index": 0, "step": {"type": "thought"}}22912292    event: step.delta2293    data: {"type": "step.delta", "index": 0, "delta": {"type": "thought", "text": "The user wants weather data for Boston. I'll call the get_weather tool."}}22942295    event: step.stop2296    data: {"type": "step.stop", "index": 0, "status": "done"}22972298    // ── Step 1: Function Call (arguments streamed) ───────2299    event: step.start2300    data: {"type": "step.start", "index": 1, "step": {"type": "function_call", "id": "fc_1", "name": "get_weather"}}23012302    event: step.delta2303    data: {"type": "step.delta", "index": 1, "delta": {"type": "arguments", "partial_arguments": "{\"location\": \"Boston, MA\"}"}}23042305    event: step.stop2306    data: {"type": "step.stop", "index": 1, "status": "waiting"}23072308    // The interaction pauses --- the model needs the tool result before continuing.2309    event: interaction.requires_action2310    data: {"type": "interaction.requires_action", "interaction": {"id": "int_xyz", "status": "requires_action"}}23112312    // ── (Client submits the tool result) ──────────────────2313    // The client calls interactions.create with the function_result as input2314    // and the previous interaction's ID, then resumes consuming the stream.23152316    event: interaction.in_progress2317    data: {"type": "interaction.in_progress", "interaction": {"id": "int_xyz", "status": "in_progress"}}23182319    // ── Step 2: Function Result (echoed back, no deltas) ─2320    event: step.start2321    data: {"type": "step.start", "index": 2, "step": {"type": "function_result", "call_id": "fc_1", "name": "get_weather", "result": [{"type": "text", "text": "52°F, rain"}]}}23222323    event: step.stop2324    data: {"type": "step.stop", "index": 2, "status": "done"}23252326    // ── Step 3: Thought ──────────────────────────────────2327    event: step.start2328    data: {"type": "step.start", "index": 3, "step": {"type": "thought"}}23292330    event: step.delta2331    data: {"type": "step.delta", "index": 3, "delta": {"type": "thought", "text": "Got weather data. Composing the final response."}}23322333    event: step.stop2334    data: {"type": "step.stop", "index": 3, "status": "done"}23352336    // ── Step 4: Model Output (text streamed) ─────────────2337    event: step.start2338    data: {"type": "step.start", "index": 4, "step": {"type": "model_output"}}23392340    event: step.delta2341    data: {"type": "step.delta", "index": 4, "delta": {"type": "text", "text": "It's currently 52°F and rainy in Boston."}}23422343    event: step.stop2344    data: {"type": "step.stop", "index": 4, "status": "done"}23452346    // ── Interaction complete ─────────────────────────────2347    event: interaction.completed2348    data: {"type": "interaction.completed", "interaction": {"id": "int_xyz", "status": "completed", "usage": {"prompt_tokens": 256, "completion_tokens": 128, "total_tokens": 384}}}
Files main
Menu

Theme