> ## AI Agent Context > Get the complete documentation index at: https://aistudio.google.com/docs/llms.txt > Use this file to discover all available pages. > For the full documentation in a single file, fetch: https://aistudio.google.com/docs/llms-full.txt # Streaming interactions When creating an Interaction, you can set `stream: true` to incrementally stream the response using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) (SSE). {% tabs %} {% tab label="Python" %} ```python from google import genai client = genai.Client() stream = client.interactions.create( model="gemini-3.8-flash", input="Count from 1 to 25.", stream=True, ) for event in stream: if event.event_type == "step.delta": if event.delta.type == "text": print(event.delta.text, end="", flush=True) ``` {% /tab %} {% tab label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const stream = await client.interactions.create({ model: "gemini-3.8-flash", input: "Count from 1 to 25.", stream: true, }); for await (const event of stream) { if (event.event_type === "step.delta") { if (event.delta.type === "text") { process.stdout.write(event.delta.text); } } } ``` {% /tab %} {% tab label="Java" %} ```java import com.google.genai.Client; import com.google.genai.gaos.models.interactions.CreateModelInteraction; import com.google.genai.gaos.models.interactions.InteractionSSEEvent; import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent; import com.google.genai.gaos.models.interactions.InteractionsInput; import com.google.genai.gaos.models.interactions.Model; import com.google.genai.gaos.models.interactions.StepDelta; import com.google.genai.gaos.models.interactions.StepDeltaData; import com.google.genai.gaos.models.interactions.TextDelta; import com.google.genai.gaos.models.operations.CreateInteractionRequestBody; import com.google.genai.gaos.models.operations.CreateInteractionResponse; import com.google.genai.gaos.utils.EventStream; Client client = new Client(); CreateModelInteraction params = CreateModelInteraction.builder() .model(Model.of("gemini-3.8-flash")) .input(InteractionsInput.of("Count from 1 to 25.")) .stream(true) .build(); CreateInteractionResponse response = client.interactions.create(CreateInteractionRequestBody.of(params)); try (EventStream events = response.events()) { for (InteractionSSEStreamEvent streamEvent : events) { InteractionSSEEvent event = streamEvent.data().orElse(null); if (event instanceof StepDelta stepDelta) { StepDeltaData data = stepDelta.delta().orElse(null); if (data instanceof TextDelta textDelta) { textDelta.text().ifPresent(System.out::print); } } } } ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{ Model: interactions.Model("gemini-3.8-flash"), Input: interactions.NewInteractionsInput("Explain quantum computing in simple terms."), Stream: genai.Ptr(true), }), }) if err != nil { log.Fatal(err) } stream := res.InteractionSSEStreamEvent defer stream.Close() for stream.Next() { event := stream.Value() if stepDelta := event.GetDataStepDelta(); stepDelta != nil { if textDelta := stepDelta.GetDeltaText(); textDelta != nil { fmt.Print(textDelta.GetText()) } } } if err := stream.Err(); err != nil { log.Fatal(err) } } ``` {% /tab %} {% tab label="REST" %} ```bash curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "model": "gemini-3.8-flash", "input": "Count from 1 to 25.", "stream": true }' ``` {% /tab %} {% /tabs %} ```none event: interaction.created data: {"interaction":{"id":"v1_...","status":"in_progress","object":"interaction","model":"gemini-3.8-flash"},"event_type":"interaction.created"} event: interaction.status_update data: {"interaction_id":"v1_...","status":"in_progress","event_type":"interaction.status_update"} event: step.start data: {"index":0,"step":{"type":"thought"},"event_type":"step.start"} event: step.delta data: {"index":0,"delta":{"signature":"...","type":"thought_signature"},"event_type":"step.delta"} event: step.stop data: {"index":0,"event_type":"step.stop"} event: step.start data: {"index":1,"step":{"type":"model_output"},"event_type":"step.start"} event: step.delta data: {"index":1,"delta":{"text":"1, 2, 3, 4, 5, 6, ","type":"text"},"event_type":"step.delta"} event: step.delta data: {"index":1,"delta":{"text":"7, 8, 9, 10, 11, 12, 13,","type":"text"},"event_type":"step.delta"} ... event: step.stop data: {"index":1,"event_type":"step.stop"} event: interaction.completed data: {"interaction":{"id":"v1_...","status":"completed","usage":{"total_tokens":346,"total_input_tokens":11,"input_tokens_by_modality":[{"modality":"text","tokens":11}],"total_cached_tokens":0,"total_output_tokens":90,"total_tool_use_tokens":0,"total_thought_tokens":245},"created":"2026-05-12T18:44:51Z","updated":"2026-05-12T18:44:51Z","service_tier":"standard","object":"interaction","model":"gemini-3.8-flash"},"event_type":"interaction.completed"} event: done data: [DONE] ``` ## Event types {% id="event-types" %} Each server-sent event includes a named `event_type` and associated JSON data. The Interactions API uses a symmetric streaming model where all content—text, tool calls, thinking—flows through a consistent **step-based** event. Each stream follows this event flow: 1. `interaction.created`: The interaction is created, includes metadata (ID, model, status). 2. A series of **steps**, each consisting of: - A `step.start` event, indicating the step type (e.g., `model_output`, `thought`, `function_call`). - One or more `step.delta` events with incremental data for that step. - A `step.stop` event marking the step as complete. 3. An `interaction.completed` event with final `usage` statistics. When you set `stream: false`, the API returns a single `interaction` object with a `steps` array. Each element in `steps` is the fully assembled version of one `step.start` → `step.delta`(s) → `step.stop` cycle. ### `interaction.created` {% id="event-interaction-created" %} Sent when the interaction is first created. Contains the interaction ID, model, and initial status. ```none event: interaction.created data: {"interaction": {"id": "...", "model": "gemini-3.8-flash", "status": "in_progress", "object": "interaction"}, "event_type": "interaction.created"} ``` ### `interaction.status_update` {% id="event-interaction-status-update" %} Signals an interaction-level status transition. May appear between steps. ```none event: interaction.status_update data: {"interaction_id": "...", "status": "in_progress", "event_type": "interaction.status_update"} ``` ### `step.start` {% id="event-step-start" %} Marks the beginning of a new step. Contains the step `type` and `index`. The step type determines which delta types to expect and how the step appears in a non-streaming response: | Step Type | Expected Delta Types | Description | | | --- | --- | --- | --- | | `model_output` | `text`, `image`, `audio` | The model's final response content. | | | `thought` | `thought_signature`, `thought_summary` | Chain-of-thought reasoning. `summary` is only present when `thinking_summaries` is enabled. | | | `function_call` | `arguments_delta` | A request for the client to execute a function. Sets interaction status to `requires_action`. | | | Server-side tools | Varies by tool | Tools executed by the API (e.g., `google_search_call`, `google_search_result`, `code_execution_call`, `code_execution_result`). | | See the [Interactions API reference](https://ai.google.dev/api/interactions-api) for the full list. ```none event: step.start data: {"index": 0, "step": {"type": "model_output"}, "event_type": "step.start"} ``` For function calls, the step includes the function name, id and empty arguments `{}`. ```none event: step.start data: {"index": 0, "step": {"type": "function_call", "id":"un6k8t18", "name": "get_weather", "arguments":{}}, "event_type": "step.start"} ``` ### `step.delta` {% id="event-step-delta" %} Incremental data for the current step. The `delta` object contains a `type` field that determines its shape. **Examples:** **`text`:** Incremental text token from a `model_output` step: ```none event: step.delta data: {"index": 0, "delta": {"type": "text", "text": "Hello, my name is Phil"}, "event_type": "step.delta"} event: step.delta data: {"index": 0, "delta": {"type": "text", "text": ", and I live in Germany." }, "event_type": "step.delta"} ``` **`image`:** Base64-encoded image data from a `model_output` step: ```none event: step.delta data: {"index": 0, "delta": {"type": "image", "mime_type": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCg..."}, "event_type": "step.delta"} ``` **`thought_summary`:** Thinking summary content from a `thought` step: ```none event: step.delta data: {"index": 0, "delta": {"type": "thought_summary", "content": {"type": "text", "text": "I need to find the GCD..."}}, "event_type": "step.delta"} ``` **`arguments_delta`:** (Partial) JSON string for function call arguments. Must be accumulated across deltas: ```none event: step.delta data: {"index": 0, "delta": {"type": "arguments_delta", "arguments": "{\"location\": \"San Francisco, CA\"}"}, "event_type": "step.delta"} ``` These are some of the most common delta types. For the complete list of all delta types, see the [Interactions API reference](https://ai.google.dev/api/interactions-api). ### `step.stop` {% id="event-step-stop" %} Marks the end of a step. Contains the step `index`. ```none event: step.stop data: {"index": 0, "event_type": "step.stop"} ``` When using the [Antigravity Agent](/docs/antigravity-agent), the `step.stop` event may also include usage statistics: * **`usage`**: The accumulated usage (running total) since the start of the interaction. * **`step_usage`**: The usage of this specific step. ```none event: step.stop data: {"index": 2, "event_type": "step.stop", "usage": {"total_tokens": 4650, "total_input_tokens": 3577, "total_output_tokens": 305, "total_cached_tokens": 0}, "step_usage": {"total_tokens": 303, "total_input_tokens": 31, "total_output_tokens": 3, "total_cached_tokens": 0}} ``` ### `interaction.completed` {% id="event-interaction-completed" %} Sent when the interaction is finished. Contains the final interaction object with `usage` statistics. In non-streaming mode, this is the top-level response object itself. Does not include `steps` in the response. ```none event: interaction.completed data: {"interaction": {"id": "v1_abc123", "status": "completed", "usage": {"total_input_tokens": 7, "total_output_tokens": 12, "total_tokens": 19}}, "event_type": "interaction.completed"} ``` ### `error` {% id="event-error" %} Sent when an error occurs during the interaction. Contains an error object with a message and code. ```none event: error data: {"error":{"message":"Deadline expired before operation could complete.","code":"gateway_timeout"},"event_type":"error"} ``` ## Streaming with tools {% id="streaming-with-tools" %} The Interactions API supports streaming with both client-side tools (function calling) and server-side tools (Google Search, Code Execution, etc.) in a single request. During streaming, tool invocations appear as typed steps in the event stream. For function calls, the `step.start` event delivers the function name, and `step.delta` events stream the arguments as JSON strings (`arguments_delta`). You must accumulate these deltas to get the full arguments. Server-side tools like Google Search are executed automatically by the API, producing `google_search_call` and `google_search_result` steps. ### Streaming with function calling {% id="streaming-with-function-calling" %} To perform function calling with streaming, the client must handle a multi-turn conversation: 1. **Turn 1 (Function Request):** Call `interactions.create` with `stream: true` and your defined `tools`. The API will stream a `function_call` step. You must accumulate the incremental argument JSON strings (`arguments_delta`) from `step.delta` events until the interaction completes with the status `requires_action`. 2. **Turn 2 (Sending Result):** Call `interactions.create` again, passing the `previous_interaction_id` (matching the ID of the first interaction) and sending a `function_result` block within the `input` array. This resumes the stream, allowing the model to generate its final response. {% tabs %} {% tab label="Python" %} ```python from google import genai client = genai.Client() weather_tool = { "type": "function", "name": "get_weather", "description": "Get the current weather in a given location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA" } }, "required": ["location"] } } # Turn 1: Request function call stream = client.interactions.create( model="gemini-3.8-flash", tools=[weather_tool], input="What is the weather in Paris right now?", stream=True, ) first_interaction_id = None func_call_id = None func_call_name = None func_args_accumulated = "" for event in stream: if event.event_type == "interaction.created": first_interaction_id = event.interaction.id elif event.event_type == "step.start": step = event.step if step.type == "function_call": func_call_id = step.id func_call_name = step.name elif event.event_type == "step.delta": if event.delta.type == "arguments_delta": func_args_accumulated += event.delta.arguments # Turn 2: Execute tool and send the result back to resume stream if func_call_id: # Execute weather_tool using accumulated arguments dummy_result = { "content": [{"type": "text", "text": '{"weather": "Sunny and 22°C"}'}] } stream2 = client.interactions.create( model="gemini-3.8-flash", previous_interaction_id=first_interaction_id, input=[{ "type": "function_result", "name": func_call_name, "call_id": func_call_id, "result": dummy_result }], stream=True, ) for event in stream2: if event.event_type == "step.delta": if event.delta.type == "text": print(event.delta.text, end="", flush=True) ``` {% /tab %} {% tab label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const weatherTool = { type: "function", name: "get_weather", description: "Get the current weather in a given location", parameters: { type: "object", properties: { location: { type: "string", description: "The city and state, e.g. San Francisco, CA" } }, required: ["location"] } }; // Turn 1: Request function call const stream = await client.interactions.create({ model: "gemini-3.8-flash", tools: [ { type: "function", name: "get_current_weather", description: "Get the current weather for a given location", parameters: { type: "object", properties: { location: { type: "string" }, }, required: ["location"], }, }, ], input: "What is the weather in Paris right now?", stream: true, }); let firstInteractionId = null; let funcCallId = null; let funcCallName = null; let funcArgsAccumulated = ""; for await (const event of stream) { if (event.event_type === "interaction.created") { firstInteractionId = event.interaction.id; } else if (event.event_type === "step.start") { const step = event.step; if (step.type === "function_call") { funcCallId = step.id; funcCallName = step.name; } } else if (event.event_type === "step.delta") { if (event.delta.type === "arguments_delta") { funcArgsAccumulated += event.delta.arguments; } } } // Turn 2: Execute tool and send the result back to resume stream if (funcCallId && firstInteractionId && funcCallName) { const dummyResult = { content: [{ type: "text", text: '{"weather": "Sunny and 22°C"}' }] }; const stream2 = await client.interactions.create({ model: "gemini-3.8-flash", previous_interaction_id: firstInteractionId, input: [{ type: "function_result", name: funcCallName, call_id: funcCallId, result: dummyResult }], stream: true, }); for await (const event of stream2) { if (event.event_type === "step.delta") { if (event.delta.type === "text") { process.stdout.write(event.delta.text); } } } } ``` {% /tab %} {% tab label="Java" %} ```java import com.google.genai.Client; import com.google.genai.gaos.models.interactions.ArgumentsDelta; import com.google.genai.gaos.models.interactions.CreateModelInteraction; import com.google.genai.gaos.models.interactions.Function; import com.google.genai.gaos.models.interactions.FunctionCallStep; import com.google.genai.gaos.models.interactions.FunctionResultStep; import com.google.genai.gaos.models.interactions.FunctionResultStepResultUnion; import com.google.genai.gaos.models.interactions.InteractionCreatedEvent; import com.google.genai.gaos.models.interactions.InteractionSSEEvent; import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent; import com.google.genai.gaos.models.interactions.InteractionSseEventInteraction; import com.google.genai.gaos.models.interactions.InteractionsInput; import com.google.genai.gaos.models.interactions.Model; import com.google.genai.gaos.models.interactions.Step; import com.google.genai.gaos.models.interactions.StepDelta; import com.google.genai.gaos.models.interactions.StepDeltaData; import com.google.genai.gaos.models.interactions.StepStart; import com.google.genai.gaos.models.interactions.TextContent; import com.google.genai.gaos.models.interactions.TextDelta; import com.google.genai.gaos.models.operations.CreateInteractionRequestBody; import com.google.genai.gaos.models.operations.CreateInteractionResponse; import com.google.genai.gaos.utils.EventStream; import java.util.Arrays; import java.util.HashMap; import java.util.Map; Client client = new Client(); Map locationProp = new HashMap<>(); locationProp.put("type", "string"); locationProp.put("description", "The city and state, e.g. San Francisco, CA"); Map properties = new HashMap<>(); properties.put("location", locationProp); Map parameters = new HashMap<>(); parameters.put("type", "object"); parameters.put("properties", properties); parameters.put("required", Arrays.asList("location")); Function weatherTool = Function.builder() .name("get_weather") .description("Get the current weather in a given location") .parameters(parameters) .build(); // Turn 1: Request function call CreateModelInteraction params = CreateModelInteraction.builder() .model(Model.of("gemini-3.8-flash")) .tools(Arrays.asList(weatherTool)) .input(InteractionsInput.of("What is the weather in Paris right now?")) .stream(true) .build(); CreateInteractionResponse response = client.interactions.create(CreateInteractionRequestBody.of(params)); String firstInteractionId = null; String funcCallId = null; String funcCallName = null; StringBuilder funcArgsAccumulated = new StringBuilder(); try (EventStream stream = response.events()) { for (InteractionSSEStreamEvent streamEvent : stream) { InteractionSSEEvent event = streamEvent.data().orElse(null); if (event instanceof InteractionCreatedEvent createdEvent) { firstInteractionId = createdEvent.interaction().flatMap(InteractionSseEventInteraction::id).orElse(null); } else if (event instanceof StepStart stepStart) { Step step = stepStart.step().orElse(null); if (step instanceof FunctionCallStep fcStep) { funcCallId = fcStep.id().orElse(null); funcCallName = fcStep.name().orElse(null); } } else if (event instanceof StepDelta stepDelta) { StepDeltaData delta = stepDelta.delta().orElse(null); if (delta instanceof ArgumentsDelta argsDelta) { funcArgsAccumulated.append(argsDelta.arguments().orElse("")); } } } } // Turn 2: Execute tool and send the result back to resume stream if (funcCallId != null && firstInteractionId != null && funcCallName != null) { FunctionResultStep resultStep = FunctionResultStep.builder() .name(funcCallName) .callId(funcCallId) .result( FunctionResultStepResultUnion.of( Arrays.asList(TextContent.builder().text("{\"weather\": \"Sunny and 22°C\"}").build()))) .build(); CreateModelInteraction params2 = CreateModelInteraction.builder() .model(Model.of("gemini-3.8-flash")) .previousInteractionId(firstInteractionId) .input(InteractionsInput.ofStep(Arrays.asList(resultStep))) .stream(true) .build(); CreateInteractionResponse response2 = client.interactions.create(CreateInteractionRequestBody.of(params2)); try (EventStream stream2 = response2.events()) { for (InteractionSSEStreamEvent streamEvent : stream2) { InteractionSSEEvent event = streamEvent.data().orElse(null); if (event instanceof StepDelta stepDelta) { StepDeltaData delta = stepDelta.delta().orElse(null); if (delta instanceof TextDelta textDelta) { textDelta.text().ifPresent(System.out::print); } } } } } ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{ Model: interactions.Model("gemini-3.8-pro"), Input: interactions.NewInteractionsInput("Solve the Monty Hall problem step-by-step."), GenerationConfig: &interactions.GenerationConfig{ ThinkingLevel: interactions.ThinkingLevelHigh.ToPointer(), ThinkingSummaries: interactions.ThinkingSummariesAuto.ToPointer(), }, Stream: genai.Ptr(true), }), }) if err != nil { log.Fatal(err) } stream := res.InteractionSSEStreamEvent defer stream.Close() for stream.Next() { event := stream.Value() if stepDelta := event.GetDataStepDelta(); stepDelta != nil { if thoughtDelta := stepDelta.GetDeltaThoughtSummary(); thoughtDelta != nil { if textContent := thoughtDelta.GetContentText(); textContent != nil { fmt.Printf("[Thought] %s\n", textContent.Text) } } if textDelta := stepDelta.GetDeltaText(); textDelta != nil { fmt.Print(textDelta.GetText()) } } } if err := stream.Err(); err != nil { log.Fatal(err) } } ``` {% /tab %} {% tab label="REST" %} ``` **Turn 1:** Request function call ```bash curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "model": "gemini-3.8-flash", "input": "What is the weather in Paris right now?", "stream": true, "tools": [ { "type": "function", "name": "get_weather", "description": "Get the current weather in a given location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA" } }, "required": ["location"] } } ] }' ``` **Turn 2:** Send the function result using the `previous_interaction_id` and `call_id` from Turn 1 ```bash curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "model": "gemini-3.8-flash", "previous_interaction_id": "v1_ChdGUVFJYXBXVUdLVEF4TjhQ...", "stream": true, "input": [ { "type": "function_result", "name": "get_weather", "call_id": "CALL_ID", "result": { "content": [ { "type": "text", "text": "{\"weather\": \"Sunny and 22°C\"}" } ] } } ] }' ``` ``` {% /tab %} {% /tabs %} ### Streaming with multiple tools {% id="streaming-with-multiple-tools" %} The following example uses both a `function` tool and `google_search` in one request: {% tabs %} {% tab label="Python" %} ```python from google import genai client = genai.Client() tools = [ {"type": "google_search"}, { "type": "function", "name": "get_weather", "description": "Get the current weather in a given location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA" } }, "required": ["location"] } } ] stream = client.interactions.create( model="gemini-3.8-flash", tools=tools, input="Search what is the largest mountain in Europe and what the weather is there right now?", stream=True, ) for event in stream: if event.event_type == "step.start": step = event.step print(f"\n--- Step {event.index}: {step.type} ---") # Show details for tool steps if step.type == "google_search_call": print(f" Search ID: {step.id}") elif step.type == "google_search_result": print(f" Result for: {step.call_id}") elif step.type == "function_call": print(f" Function: {step.name}({step.arguments})") elif event.event_type == "step.delta": if event.delta.type == "text": print(event.delta.text, end="", flush=True) elif event.delta.type == "google_search_call": print(f" Queries: {event.delta.arguments}") elif event.delta.type == "arguments_delta": print(f" Args chunk: {event.delta.arguments}", end="", flush=True) elif event.event_type == "interaction.completed": print(f"\n\nStatus: {event.interaction.status}") if event.interaction.status == "requires_action": print("Action required: provide function call results to continue.") ``` {% /tab %} {% tab label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const stream = await client.interactions.create({ model: "gemini-3.8-flash", tools: [ { type: "google_search" }, { type: "function", name: "get_weather", description: "Get the current weather in a given location", parameters: { type: "object", properties: { location: { type: "string", description: "The city and state, e.g. San Francisco, CA" } }, required: ["location"] } } ], input: "Search what is the largest mountain in Europe and what the weather is there right now?", stream: true, }); for await (const event of stream) { if (event.event_type === "step.start") { const step = event.step; console.log(`\n--- Step ${event.index}: ${step.type} ---`); // Show details for tool steps if (step.type === "google_search_call") { console.log(` Search ID: ${step.id}`); } else if (step.type === "google_search_result") { console.log(` Result for: ${step.call_id}`); } else if (step.type === "function_call") { console.log(` Function: ${step.name}(${JSON.stringify(step.arguments)})`); } } else if (event.event_type === "step.delta") { if (event.delta.type === "text") { process.stdout.write(event.delta.text); } else if (event.delta.type === "google_search_call") { console.log(` Queries: ${JSON.stringify(event.delta.arguments?.queries)}`); } else if (event.delta.type === "arguments_delta") { process.stdout.write(` Args chunk: ${event.delta.arguments}`); } } else if (event.event_type === "interaction.completed") { console.log(`\n\nStatus: ${event.interaction.status}`); if (event.interaction.status === "requires_action") { console.log("Action required: provide function call results to continue."); } } } ``` {% /tab %} {% tab label="Java" %} ```java import com.google.genai.Client; import com.google.genai.gaos.models.interactions.ArgumentsDelta; import com.google.genai.gaos.models.interactions.CreateModelInteraction; import com.google.genai.gaos.models.interactions.Function; import com.google.genai.gaos.models.interactions.FunctionCallStep; import com.google.genai.gaos.models.interactions.GoogleSearch; import com.google.genai.gaos.models.interactions.GoogleSearchCallDelta; import com.google.genai.gaos.models.interactions.GoogleSearchCallStep; import com.google.genai.gaos.models.interactions.GoogleSearchResultStep; import com.google.genai.gaos.models.interactions.InteractionCompletedEvent; import com.google.genai.gaos.models.interactions.InteractionSSEEvent; import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent; import com.google.genai.gaos.models.interactions.InteractionSseEventInteractionStatus; import com.google.genai.gaos.models.interactions.InteractionsInput; import com.google.genai.gaos.models.interactions.Model; import com.google.genai.gaos.models.interactions.Step; import com.google.genai.gaos.models.interactions.StepDelta; import com.google.genai.gaos.models.interactions.StepDeltaData; import com.google.genai.gaos.models.interactions.StepStart; import com.google.genai.gaos.models.interactions.TextDelta; import com.google.genai.gaos.models.interactions.Tool; import com.google.genai.gaos.models.operations.CreateInteractionRequestBody; import com.google.genai.gaos.models.operations.CreateInteractionResponse; import com.google.genai.gaos.utils.EventStream; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; Client client = new Client(); Map locationProp = new HashMap<>(); locationProp.put("type", "string"); locationProp.put("description", "The city and state, e.g. San Francisco, CA"); Map properties = new HashMap<>(); properties.put("location", locationProp); Map parameters = new HashMap<>(); parameters.put("type", "object"); parameters.put("properties", properties); parameters.put("required", Arrays.asList("location")); List tools = Arrays.asList( new GoogleSearch(), Function.builder() .name("get_weather") .description("Get the current weather in a given location") .parameters(parameters) .build()); CreateModelInteraction params = CreateModelInteraction.builder() .model(Model.of("gemini-3.8-flash")) .tools(tools) .input( InteractionsInput.of( "Search what is the largest mountain in Europe and what the weather is there right now?")) .stream(true) .build(); CreateInteractionResponse response = client.interactions.create(CreateInteractionRequestBody.of(params)); try (EventStream stream = response.events()) { for (InteractionSSEStreamEvent streamEvent : stream) { InteractionSSEEvent event = streamEvent.data().orElse(null); if (event instanceof StepStart stepStart) { Step step = stepStart.step().orElse(null); if (step != null) { System.out.printf("%n--- Step %d: %s ---%n", stepStart.index().orElse(0), step.type()); if (step instanceof GoogleSearchCallStep searchCall) { System.out.println(" Search ID: " + searchCall.id().orElse("")); } else if (step instanceof GoogleSearchResultStep searchResult) { System.out.println(" Result for: " + searchResult.callId().orElse("")); } else if (step instanceof FunctionCallStep fcStep) { System.out.printf( " Function: %s(%s)%n", fcStep.name().orElse(""), fcStep.arguments().orElse(Collections.emptyMap())); } } } else if (event instanceof StepDelta stepDelta) { StepDeltaData delta = stepDelta.delta().orElse(null); if (delta instanceof TextDelta textDelta) { textDelta.text().ifPresent(System.out::print); } else if (delta instanceof GoogleSearchCallDelta searchDelta) { System.out.println(" Queries: " + searchDelta.arguments().orElse(null)); } else if (delta instanceof ArgumentsDelta argsDelta) { System.out.print(" Args chunk: " + argsDelta.arguments().orElse("")); } } else if (event instanceof InteractionCompletedEvent completedEvent) { completedEvent .interaction() .ifPresent( interaction -> { String status = interaction .status() .map(InteractionSseEventInteractionStatus::value) .orElse(""); System.out.println("\n\nStatus: " + status); if ("requires_action".equals(status)) { System.out.println("Action required: provide function call results to continue."); } }); } } } ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } weatherTool := interactions.NewTool(interactions.Function{ Name: genai.Ptr("get_weather"), Description: genai.Ptr("Gets the current weather for a given location."), Parameters: map[string]any{ "type": "object", "properties": map[string]any{ "location": map[string]any{"type": "string"}, }, "required": []string{"location"}, }, }) res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{ Model: interactions.Model("gemini-3.8-flash"), Input: interactions.NewInteractionsInput("What is the weather in Tokyo and Paris?"), Tools: []interactions.Tool{weatherTool}, Stream: genai.Ptr(true), }), }) if err != nil { log.Fatal(err) } stream := res.InteractionSSEStreamEvent defer stream.Close() for stream.Next() { event := stream.Value() if stepStart := event.GetDataStepStart(); stepStart != nil { if call := stepStart.GetStepFunctionCall(); call != nil { fmt.Printf("\n[Function Call Started] %s (id: %s)\n", call.Name, call.ID) } } if stepDelta := event.GetDataStepDelta(); stepDelta != nil { if argsDelta := stepDelta.GetDeltaArgumentsDelta(); argsDelta != nil && argsDelta.Arguments != nil { fmt.Printf("[Args Delta] %s\n", *argsDelta.Arguments) } if textDelta := stepDelta.GetDeltaText(); textDelta != nil { fmt.Print(textDelta.GetText()) } } if completed := event.GetDataInteractionCompleted(); completed != nil { interaction := completed.Interaction if interaction.Status == interactions.InteractionSseEventInteractionStatusRequiresAction { fmt.Printf("\nStream paused: Waiting for tool outputs for interaction %s\n", interaction.ID) } } } if err := stream.Err(); err != nil { log.Fatal(err) } } ``` {% /tab %} {% tab label="REST" %} ```bash curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "model": "gemini-3.8-flash", "input": "Search what is the largest mountain in Europe and what the weather is there right now?", "stream": true, "tools": [ { "type": "google_search" }, { "type": "function", "name": "get_weather", "description": "Get the current weather in a given location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA" } }, "required": ["location"] } } ] }' ``` {% /tab %} {% /tabs %} ```none event: interaction.created data: {"interaction":{"id":"v1_...","status":"in_progress","object":"interaction","model":"gemini-3.8-flash"},"event_type":"interaction.created"} event: interaction.status_update data: {"interaction_id":"v1_...","status":"in_progress","event_type":"interaction.status_update"} event: step.start data: {"index":0,"step":{"id":"mkutnkgn","signature":"","type":"google_search_call"},"event_type":"step.start"} event: step.delta data: {"index":0,"delta":{"signature":"...","type":"google_search_call","arguments":{"queries":["largest mountain in Europe"]}},"event_type":"step.delta"} event: step.stop data: {"index":0,"event_type":"step.stop"} event: step.start data: {"index":1,"step":{"call_id":"mkutnkgn","signature":"","type":"google_search_result"},"event_type":"step.start"} event: step.delta data: {"index":1,"delta":{"signature":"...","type":"google_search_result","is_error":false},"event_type":"step.delta"} event: step.stop data: {"index":1,"event_type":"step.stop"} event: step.start data: {"index":2,"step":{"type":"thought"},"event_type":"step.start"} event: step.delta data: {"index":2,"delta":{"signature":"...","type":"thought_signature"},"event_type":"step.delta"} event: step.stop data: {"index":2,"event_type":"step.stop"} event: step.start data: {"index":3,"step":{"id":"ktr5aysg","type":"function_call","name":"get_weather","arguments":{}},"event_type":"step.start"} event: step.delta data: {"index":3,"delta":{"arguments":"{\"location\":\"Mount Elbrus, Russia\"}","type":"arguments_delta"},"event_type":"step.delta"} event: step.stop data: {"index":3,"event_type":"step.stop"} event: interaction.completed data: {"interaction":{"id":"v1_...","status":"requires_action","usage":{"total_tokens":299,"total_input_tokens":138,"input_tokens_by_modality":[{"modality":"text","tokens":138}],"total_cached_tokens":0,"total_output_tokens":20,"total_tool_use_tokens":0,"total_thought_tokens":141},"created":"2026-05-12T17:24:26Z","updated":"2026-05-12T17:24:26Z","service_tier":"standard","object":"interaction","model":"gemini-3.8-flash"},"event_type":"interaction.completed"} event: done data: [DONE] ``` ## Streaming with thinking {% id="streaming-with-thinking" %} When the model uses thinking, you'll receive `thought` steps with two distinct delta types: `thought_summary` (incremental text or image summary content), and `thought_signature` (an encrypted representation of the model's internal reasoning, sent as the last delta before `step.stop`). If `thinking_summaries` is enabled, `thought_summary` deltas stream a summary of the model's reasoning. For more details on thinking, see the [Thinking guide](/docs/thinking). {% tabs %} {% tab label="Python" %} ```python from google import genai client = genai.Client() stream = client.interactions.create( model="gemini-3.8-flash", input="What is the greatest common divisor of 1071 and 462?", generation_config={ "thinking_summaries": "auto" }, stream=True, ) for event in stream: if event.event_type == "step.start": print(f"\n--- Step: {event.step.type} ---") elif event.event_type == "step.delta": if event.delta.type == "thought_summary": if event.delta.content.type == "text": print(event.delta.content.text, end="", flush=True) elif event.delta.type == "text": print(event.delta.text, end="", flush=True) ``` {% /tab %} {% tab label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const stream = await client.interactions.create({ model: "gemini-3.8-flash", input: "What is the greatest common divisor of 1071 and 462?", generation_config: { thinking_summaries: "auto", }, stream: true, }); for await (const event of stream) { if (event.event_type === "step.start") { console.log(`\n--- Step: ${event.step.type} ---`); } else if (event.event_type === "step.delta") { if (event.delta.type === "thought_summary") { if (event.delta.content?.type === "text") { process.stdout.write(event.delta.content.text); } } else if (event.delta.type === "text") { process.stdout.write(event.delta.text); } } } ``` {% /tab %} {% tab label="Java" %} ```java import com.google.genai.Client; import com.google.genai.gaos.models.interactions.Content; import com.google.genai.gaos.models.interactions.CreateModelInteraction; import com.google.genai.gaos.models.interactions.GenerationConfig; import com.google.genai.gaos.models.interactions.InteractionSSEEvent; import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent; import com.google.genai.gaos.models.interactions.InteractionsInput; import com.google.genai.gaos.models.interactions.Model; import com.google.genai.gaos.models.interactions.Step; import com.google.genai.gaos.models.interactions.StepDelta; import com.google.genai.gaos.models.interactions.StepDeltaData; import com.google.genai.gaos.models.interactions.StepStart; import com.google.genai.gaos.models.interactions.TextContent; import com.google.genai.gaos.models.interactions.TextDelta; import com.google.genai.gaos.models.interactions.ThinkingSummaries; import com.google.genai.gaos.models.interactions.ThoughtSummaryDelta; import com.google.genai.gaos.models.operations.CreateInteractionRequestBody; import com.google.genai.gaos.models.operations.CreateInteractionResponse; import com.google.genai.gaos.utils.EventStream; Client client = new Client(); CreateModelInteraction params = CreateModelInteraction.builder() .model(Model.of("gemini-3.8-flash")) .input(InteractionsInput.of("What is the greatest common divisor of 1071 and 462?")) .generationConfig( GenerationConfig.builder().thinkingSummaries(ThinkingSummaries.AUTO).build()) .stream(true) .build(); CreateInteractionResponse response = client.interactions.create(CreateInteractionRequestBody.of(params)); try (EventStream stream = response.events()) { for (InteractionSSEStreamEvent streamEvent : stream) { InteractionSSEEvent event = streamEvent.data().orElse(null); if (event instanceof StepStart stepStart) { Step step = stepStart.step().orElse(null); if (step != null) { System.out.printf("%n--- Step: %s ---%n", step.type()); } } else if (event instanceof StepDelta stepDelta) { StepDeltaData delta = stepDelta.delta().orElse(null); if (delta instanceof ThoughtSummaryDelta thoughtDelta) { Content content = thoughtDelta.content().orElse(null); if (content instanceof TextContent textContent) { textContent.text().ifPresent(System.out::print); } } else if (delta instanceof TextDelta textDelta) { textDelta.text().ifPresent(System.out::print); } } } } ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{ Model: interactions.Model("gemini-3.8-flash"), Input: interactions.NewInteractionsInput("What are the top news stories in AI today, and calculate 2^64 - 1?"), Tools: []interactions.Tool{ interactions.NewTool(interactions.GoogleSearch{}), interactions.NewTool(interactions.CodeExecution{}), }, Stream: genai.Ptr(true), }), }) if err != nil { log.Fatal(err) } stream := res.InteractionSSEStreamEvent defer stream.Close() for stream.Next() { event := stream.Value() if stepStart := event.GetDataStepStart(); stepStart != nil { step := stepStart.Step if searchCall := step.GoogleSearchCallStep; searchCall != nil { fmt.Printf("[Google Search Started] id: %s\n", searchCall.ID) } else if searchRes := step.GoogleSearchResultStep; searchRes != nil { fmt.Printf("[Google Search Results Received] for call_id: %s\n", searchRes.CallID) } else if codeCall := step.CodeExecutionCallStep; codeCall != nil { fmt.Printf("[Code Execution Started] id: %s\n", codeCall.ID) } else if codeRes := step.CodeExecutionResultStep; codeRes != nil { fmt.Printf("[Code Execution Finished] output: %s\n", codeRes.Result) } } if stepDelta := event.GetDataStepDelta(); stepDelta != nil { if searchDelta := stepDelta.GetDeltaGoogleSearchCall(); searchDelta != nil { fmt.Printf("[Search Queries] %v\n", searchDelta.Arguments.Queries) } if codeDelta := stepDelta.GetDeltaCodeExecutionCall(); codeDelta != nil { fmt.Printf("[Code Delta] %s\n", codeDelta.Arguments.Code) } if textDelta := stepDelta.GetDeltaText(); textDelta != nil { fmt.Print(textDelta.GetText()) } } } if err := stream.Err(); err != nil { log.Fatal(err) } } ``` {% /tab %} {% tab label="REST" %} ```bash curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "model": "gemini-3.8-flash", "input": "What is the greatest common divisor of 1071 and 462?", "stream": true, "generation_config": { "thinking_summaries": "auto" } }' ``` {% /tab %} {% /tabs %} ```none event: interaction.created data: {"interaction":{"id":"v1_...","status":"in_progress","object":"interaction","model":"gemini-3.8-flash"},"event_type":"interaction.created"} event: interaction.status_update data: {"interaction_id":"v1_...","status":"in_progress","event_type":"interaction.status_update"} event: step.start data: {"index":0,"step":{"type":"thought"},"event_type":"step.start"} event: step.delta data: {"index":0,"delta":{"content":{"text":"**Implementing Euclidean Algorithm**\n\nI've just worked through a detailed example applying the Euclidean algorithm to find the GCD of 1071 and 462, confirming its step-by-step nature. The calculations went smoothly, tracking the remainders until zero. My focus is now solidifying the implementation logic, ensuring accuracy and considering potential edge cases. I'll translate this example into code.\n\n\n","type":"text"},"type":"thought_summary"},"event_type":"step.delta"} event: step.delta data: {"index":0,"delta":{"signature":"...","type":"thought_signature"},"event_type":"step.delta"} event: step.stop data: {"index":0,"event_type":"step.stop"} event: step.start data: {"index":1,"step":{"type":"model_output"},"event_type":"step.start"} ... ``` ## Streaming with agents {% id="streaming-with-agents" %} The Interactions API supports agents like Deep Research. Agents use `background=True` and return results asynchronously, but you can also stream agent interactions to receive progress updates and intermediate steps as they happen. For more details, see the [Background execution guide](/docs/background-execution) and the [Deep Research guide](/docs/deep-research). {% tabs %} {% tab label="Python" %} ```python from google import genai client = genai.Client() stream = client.interactions.create( agent="deep-research-preview-04-2026", input="Research the latest advances in quantum computing.", stream=True, background=True, agent_config={ "type": "deep-research", "thinking_summaries": "auto" } ) for event in stream: if event.event_type == "step.start": print(f"\n--- Step: {event.step.type} ---") elif event.event_type == "step.delta": if event.delta.type == "text": print(event.delta.text, end="", flush=True) elif event.delta.type == "thought_summary": if event.delta.content.type == "text": print(event.delta.content.text, end="", flush=True) elif event.event_type == "interaction.completed": print(f"\n\nTotal Tokens: {event.interaction.usage.total_tokens}") ``` {% /tab %} {% tab label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const stream = await client.interactions.create({ agent: "deep-research-preview-04-2026", input: "Research the latest advances in quantum computing.", stream: true, background: true, agent_config: { type: "deep-research", thinking_summaries: "auto" } }); for await (const event of stream) { if (event.event_type === "step.start") { console.log(`\n--- Step: ${event.step.type} ---`); } else if (event.event_type === "step.delta") { if (event.delta.type === "text") { process.stdout.write(event.delta.text); } else if (event.delta.type === "thought_summary") { if (event.delta.content?.type === "text") { process.stdout.write(event.delta.content.text); } } } else if (event.event_type === "interaction.completed") { if (event.interaction?.usage?.total_tokens) { console.log(`\n\nTotal Tokens: ${event.interaction.usage.total_tokens}`); } } } ``` {% /tab %} {% tab label="Java" %} ```java import com.google.genai.Client; import com.google.genai.gaos.models.interactions.Content; import com.google.genai.gaos.models.interactions.CreateAgentInteraction; import com.google.genai.gaos.models.interactions.DeepResearchAgentConfig; import com.google.genai.gaos.models.interactions.InteractionCompletedEvent; import com.google.genai.gaos.models.interactions.InteractionSSEEvent; import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent; import com.google.genai.gaos.models.interactions.InteractionSseEventInteraction; import com.google.genai.gaos.models.interactions.InteractionsInput; import com.google.genai.gaos.models.interactions.Step; import com.google.genai.gaos.models.interactions.StepDelta; import com.google.genai.gaos.models.interactions.StepDeltaData; import com.google.genai.gaos.models.interactions.StepStart; import com.google.genai.gaos.models.interactions.TextContent; import com.google.genai.gaos.models.interactions.TextDelta; import com.google.genai.gaos.models.interactions.ThinkingSummaries; import com.google.genai.gaos.models.interactions.ThoughtSummaryDelta; import com.google.genai.gaos.models.interactions.Usage; import com.google.genai.gaos.models.operations.CreateInteractionRequestBody; import com.google.genai.gaos.models.operations.CreateInteractionResponse; import com.google.genai.gaos.utils.EventStream; Client client = new Client(); CreateAgentInteraction params = CreateAgentInteraction.builder() .agent("deep-research-preview-04-2026") .input(InteractionsInput.of("Research the latest advances in quantum computing.")) .stream(true) .background(true) .agentConfig( DeepResearchAgentConfig.builder() .thinkingSummaries(ThinkingSummaries.AUTO) .build()) .build(); CreateInteractionResponse response = client.interactions.create(CreateInteractionRequestBody.of(params)); try (EventStream stream = response.events()) { for (InteractionSSEStreamEvent streamEvent : stream) { InteractionSSEEvent event = streamEvent.data().orElse(null); if (event instanceof StepStart stepStart) { Step step = stepStart.step().orElse(null); if (step != null) { System.out.printf("%n--- Step: %s ---%n", step.type()); } } else if (event instanceof StepDelta stepDelta) { StepDeltaData delta = stepDelta.delta().orElse(null); if (delta instanceof TextDelta textDelta) { textDelta.text().ifPresent(System.out::print); } else if (delta instanceof ThoughtSummaryDelta thoughtDelta) { Content content = thoughtDelta.content().orElse(null); if (content instanceof TextContent textContent) { textContent.text().ifPresent(System.out::print); } } } else if (event instanceof InteractionCompletedEvent completedEvent) { completedEvent .interaction() .flatMap(InteractionSseEventInteraction::usage) .flatMap(Usage::totalTokens) .ifPresent(tokens -> System.out.println("\n\nTotal Tokens: " + tokens)); } } } ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "encoding/base64" "fmt" "log" "os" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{ Model: interactions.Model("gemini-3.1-flash-image-preview"), Input: interactions.NewInteractionsInput("Generate a watercolor illustration of a lighthouse at sunset and describe the scene."), ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat([]interactions.ResponseFormat{ interactions.NewResponseFormat(interactions.TextResponseFormat{}), interactions.NewResponseFormat(interactions.ImageResponseFormat{}), })), Stream: genai.Ptr(true), }), }) if err != nil { log.Fatal(err) } stream := res.InteractionSSEStreamEvent defer stream.Close() for stream.Next() { event := stream.Value() if stepDelta := event.GetDataStepDelta(); stepDelta != nil { if textDelta := stepDelta.GetDeltaText(); textDelta != nil { fmt.Print(textDelta.GetText()) } if imgDelta := stepDelta.GetDeltaImage(); imgDelta != nil && imgDelta.Data != nil { imageBytes, err := base64.StdEncoding.DecodeString(*imgDelta.Data) if err != nil { log.Fatal(err) } if err := os.WriteFile("lighthouse.png", imageBytes, 0644); err != nil { log.Fatal(err) } fmt.Println("\n[Saved lighthouse.png]") } } if completed := event.GetDataInteractionCompleted(); completed != nil { // You can also access the final image using interaction.GetOutputImage() on a non-streamed or retrieved interaction fmt.Println("\nGeneration complete!") } } if err := stream.Err(); err != nil { log.Fatal(err) } } ``` {% /tab %} {% tab label="REST" %} ```bash curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "agent": "deep-research-preview-04-2026", "input": "Research the latest advances in quantum computing.", "stream": true, "background": true, "agent_config": { "type": "deep-research", "thinking_summaries": "auto" } }' ``` {% /tab %} {% /tabs %} ```none event: interaction.created data: {"interaction":{"id":"v1_...","status":"in_progress","object":"interaction","agent":"deep-research-preview-04-2026"},"event_type":"interaction.created"} event: interaction.status_update data: {"interaction_id":"v1_...","status":"in_progress","event_type":"interaction.status_update"} event: step.start data: {"index":0,"step":{"type":"thought"},"event_type":"step.start"} event: step.delta data: {"index":0,"delta":{"content":{"text":"***Generating research plan***\n\nTo best answer your request, I'm starting by constructing a comprehensive research plan. This will outline the key areas I need to investigate and the strategy I'll use to connect them."},"type":"thought_summary"},"event_type":"step.delta"} ... (additional thought steps) ... event: step.stop data: {"index":0,"event_type":"step.stop"} event: step.start data: {"index":1,"step":{"type":"model_output"},"event_type":"step.start"} event: step.delta data: {"index":1,"delta":{"text":"# The Quantum Inflection Point: Exhaustive Analysis of Hardware, Algorithms, and Market Dynamics in 2026\n\n## Executive Summary\n\n..."},"event_type":"step.delta"} event: step.stop data: {"index":1,"event_type":"step.stop"} event: interaction.completed data: {"interaction":{"id":"v1_...","status":"completed","usage":{"total_tokens":1117031,"total_input_tokens":428865,"total_output_tokens":22294,"total_thought_tokens":26213},"created":"2026-05-12T17:24:27Z","updated":"2026-05-12T17:24:27Z","object":"interaction","agent":"deep-research-preview-04-2026"},"event_type":"interaction.completed"} event: done data: [DONE] ``` ## Streaming image generation {% id="streaming-image-generation" %} The Interactions API supports streaming multiple output modalities simultaneously. By requesting both `text` and `image` in the `response_format`, you can receive interleaved text and generated images in the same stream. The following example uses `gemini-3.1-flash-image` (Nano Banana 2) to search for information and generate a story with interleaved illustrations. {% tabs %} {% tab label="Python" %} ```python from google import genai client = genai.Client() stream = client.interactions.create( model="gemini-3.1-flash-image", tools=[{"type": "google_search", "search_types": ["web_search", "image_search"]}], input="Search for the history of the Colosseum and write a short illustrated story about a gladiator named Marcus. Interleave text and generated images.", response_format=[ {"type": "text"}, {"type": "image"} ], stream=True, ) for event in stream: if event.event_type == "step.delta": if event.delta.type == "text": print(event.delta.text, end="", flush=True) elif event.delta.type == "image": print(f"\n[Image chunk: {len(event.delta.data)} bytes]", end="", flush=True) ``` {% /tab %} {% tab label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const stream = await client.interactions.create({ model: "gemini-3.1-flash-image", tools: [{ type: "google_search", search_types: ["web_search", "image_search"] }], input: "Search for the history of the Colosseum and write a short illustrated story about a gladiator named Marcus. Interleave text and generated images.", response_format: [ { type: "text" }, { type: "image" } ], stream: true, }); for await (const event of stream) { if (event.event_type === "step.delta") { if (event.delta.type === "text") { process.stdout.write(event.delta.text); } else if (event.delta.type === "image") { if (event.delta?.data) { console.log(`\n[Image chunk: ${event.delta.data.length} bytes]`); } } } } ``` {% /tab %} {% tab label="Java" %} ```java import com.google.genai.Client; import com.google.genai.gaos.models.interactions.CreateModelInteraction; import com.google.genai.gaos.models.interactions.CreateModelInteractionResponseFormat; import com.google.genai.gaos.models.interactions.GoogleSearch; import com.google.genai.gaos.models.interactions.GoogleSearchSearchType; import com.google.genai.gaos.models.interactions.ImageDelta; import com.google.genai.gaos.models.interactions.ImageResponseFormat; import com.google.genai.gaos.models.interactions.InteractionSSEEvent; import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent; import com.google.genai.gaos.models.interactions.InteractionsInput; import com.google.genai.gaos.models.interactions.Model; import com.google.genai.gaos.models.interactions.ResponseFormat; import com.google.genai.gaos.models.interactions.StepDelta; import com.google.genai.gaos.models.interactions.StepDeltaData; import com.google.genai.gaos.models.interactions.TextDelta; import com.google.genai.gaos.models.interactions.TextResponseFormat; import com.google.genai.gaos.models.operations.CreateInteractionRequestBody; import com.google.genai.gaos.models.operations.CreateInteractionResponse; import com.google.genai.gaos.utils.EventStream; import java.util.Arrays; Client client = new Client(); CreateModelInteraction params = CreateModelInteraction.builder() .model(Model.of("gemini-3.1-flash-image")) .tools( Arrays.asList( GoogleSearch.builder() .searchTypes( Arrays.asList( GoogleSearchSearchType.of("web_search"), GoogleSearchSearchType.of("image_search"))) .build())) .input( InteractionsInput.of( "Search for the history of the Colosseum and write a short illustrated story about a gladiator named Marcus. Interleave text and generated images.")) .responseFormat( CreateModelInteractionResponseFormat.of( Arrays.asList( ResponseFormat.of(TextResponseFormat.builder().build()), ResponseFormat.of(ImageResponseFormat.builder().build())))) .stream(true) .build(); CreateInteractionResponse response = client.interactions.create(CreateInteractionRequestBody.of(params)); try (EventStream stream = response.events()) { for (InteractionSSEStreamEvent streamEvent : stream) { InteractionSSEEvent event = streamEvent.data().orElse(null); if (event instanceof StepDelta stepDelta) { StepDeltaData delta = stepDelta.delta().orElse(null); if (delta instanceof TextDelta textDelta) { textDelta.text().ifPresent(System.out::print); } else if (delta instanceof ImageDelta imageDelta) { imageDelta .data() .ifPresent(data -> System.out.printf("%n[Image chunk: %d bytes]", data.length())); } } } } ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } var interactionID string var lastEventID *string res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{ Model: interactions.Model("gemini-3.8-pro"), Input: interactions.NewInteractionsInput("Write a detailed 5-section guide to distributed consensus algorithms."), Stream: genai.Ptr(true), }), }) if err != nil { log.Fatal(err) } stream := res.InteractionSSEStreamEvent defer stream.Close() for stream.Next() { event := stream.Value() if created := event.GetDataInteractionCreated(); created != nil { interactionID = created.Interaction.ID if created.EventID != nil { lastEventID = created.EventID } } if stepDelta := event.GetDataStepDelta(); stepDelta != nil { if stepDelta.EventID != nil { lastEventID = stepDelta.EventID } if textDelta := stepDelta.GetDeltaText(); textDelta != nil { fmt.Print(textDelta.GetText()) } } } if err := stream.Err(); err != nil { fmt.Printf("\nStream interrupted (%v). Resuming...\n", err) if interactionID != "" && lastEventID != nil { resumedRes, err := client.Interactions.Get(ctx, operations.GetInteractionByIDRequest{ ID: interactionID, Stream: genai.Ptr(true), LastEventID: lastEventID, }) if err != nil { log.Fatal(err) } resumedStream := resumedRes.InteractionSSEStreamEvent defer resumedStream.Close() for resumedStream.Next() { event := resumedStream.Value() if stepDelta := event.GetDataStepDelta(); stepDelta != nil { if textDelta := stepDelta.GetDeltaText(); textDelta != nil { fmt.Print(textDelta.GetText()) } } } if err := resumedStream.Err(); err != nil { log.Fatal(err) } } } } ``` {% /tab %} {% tab label="REST" %} ```bash curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -H "Content-Type: application/json" \ --no-buffer \ -d '{ "model": "gemini-3.1-flash-image", "input": "Search for the history of the Colosseum and write a short illustrated story about a gladiator named Marcus. Interleave text and generated images.", "stream": true, "tools": [ { "type": "google_search", "search_types": ["web_search", "image_search"] } ], "generation_config": { "thinking_summaries": "auto" }, "response_format": [ { "type": "text" }, { "type": "image"} ] }' ``` {% /tab %} {% /tabs %} ```none event: interaction.created data: {"interaction":{"id":"v1_...","status":"in_progress","object":"interaction","model":"gemini-3.1-flash-image"},"event_type":"interaction.created"} event: interaction.status_update data: {"interaction_id":"v1_...","status":"in_progress","event_type":"interaction.status_update"} event: step.start data: {"index":0,"step":{"type":"model_output"},"event_type":"step.start"} event: step.delta data: {"index":0,"delta":{"text":"Here is a short illustrated story about the Colosseum...\n\n### Part 1: The New Flavian Amphitheater\n\n...","type":"text"},"event_type":"step.delta"} ... event: step.stop data: {"index":0,"event_type":"step.stop"} event: step.start data: {"index":1,"step":{"type":"thought"},"event_type":"step.start"} event: step.delta data: {"index":1,"delta":{"signature":"...","type":"thought_signature"},"event_type":"step.delta"} event: step.stop data: {"index":1,"event_type":"step.stop"} event: step.start data: {"index":2,"step":{"type":"model_output"},"event_type":"step.start"} event: step.delta data: {"index":2,"delta":{"mime_type":"image/jpeg","data":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCg...","type":"image"},"event_type":"step.delta"} event: step.delta data: {"index":2,"delta":{"text":"### Part 2: The Hypogeum and the Wait\n\n...","type":"text"},"event_type":"step.delta"} ... event: step.stop data: {"index":2,"event_type":"step.stop"} event: step.start data: {"index":3,"step":{"type":"thought"},"event_type":"step.start"} event: step.delta data: {"index":3,"delta":{"signature":"...","type":"thought_signature"},"event_type":"step.delta"} event: step.stop data: {"index":3,"event_type":"step.stop"} event: step.start data: {"index":4,"step":{"type":"model_output"},"event_type":"step.start"} event: step.delta data: {"index":4,"delta":{"mime_type":"image/jpeg","data":"/9j/4AAQSkZJRgABAQAAAQABAAD/...","type":"image"},"event_type":"step.delta"} event: step.delta data: {"index":4,"delta":{"text":"### Part 3: The Moment of Spectacle\n\n...","type":"text"},"event_type":"step.delta"} ... event: step.stop data: {"index":4,"event_type":"step.stop"} event: interaction.completed data: {"interaction":{"id":"v1_...","status":"completed","usage":{"total_tokens":6128,"total_input_tokens":29,"total_output_tokens":6099,"output_tokens_by_modality":[{"modality":"image","tokens":4480}]}},"event_type":"interaction.completed"} event: done data: [DONE] ``` ## Handling unknown events {% id="handling-unknown-events" %} In accordance with the API's versioning policy, new event types and delta types may be added over time. Your code should handle unknown event types gracefully—log and skip any events you don't recognize rather than throwing an error. ## What's next {% id="whats-next" %} * Learn more about the [Interactions API](/docs/interactions-overview). * Explore [Function calling](/docs/function-calling) with tools. * Learn about [Thinking](/docs/thinking) for enhanced reasoning. * Try the [Deep Research agent](/docs/deep-research) for long-running tasks. * See the [Interactions API reference](https://ai.google.dev/api/interactions-api) for all event types and delta types.