The Gemini Interactions API has become the recommended unified interface for new projects. It represents a generation, tool call, thinking process, tool result and final reply as observable execution steps, suitable for Agents, long tasks and applications that need to display intermediate states.
This also means that legacy code can no longer assume outputs in the response. Starting in May 2026, the new schema will become the default; the old schema was removed on June 8. If there are empty replies, tool calls are lost, SSE events are not triggered, or historical context is broken after migration, it is usually not a model problem, but that the data is still being read according to the old structure.
First confirm which layer you are migrating to
Before troubleshooting, categorize the problem first to avoid changing just one field:
| Hierarchy | Old way | New way |
|---|---|---|
| Final text | Traverse outputs to find text |
Simple scene reading interaction.output_text |
| Full response | Find content, tools, or search results in outputs |
Traverse interaction.steps, process as type |
| Tool call | Parse from old content type | Process steps such as function_call, function_result |
| Streaming events | content.start, content.delta, content.stop |
step.start, step.delta, step.stop |
| Multi-round history | Return old outputs |
Use previous_interaction_id on the server, or return steps on the client |
If the SDK is still Python 1.x or JavaScript 1.x, confirm the version first. The official migration instructions require using Python ≥2.0.0 or JavaScript ≥2.0.0 to automatically adopt the new schema; but upgrading the SDK will not automatically fix the outputs parser, SSE processor and front-end state machine you wrote yourself.
Easiest fix: read the final text with output_text
When processing only plain text questions and answers, there is no need to manually find the last text from steps. The new version of the SDK provides output_text, which extracts and splices consecutive text blocks at the end of the response:
|
|
If you leave interaction.outputs[-1].text as is after migration, common results are that the property does not exist, indexing fails, or the object is incorrectly serialized into an empty string. First replace it with interaction.output_text, and then add the step analysis of complex scenarios.
output_text is not suitable for all responses: when text is separated by thoughts, images, audio, or tool calls, it won’t restore all interleaving content for you. When you need to show the complete execution process, you should traverse steps.
How to properly traverse steps
The new schema represents processes as typed steps. At a minimum, user_input, model_output, function_call, and function_result will be recognized; if using server-side tools, you will also see google_search_call, google_search_result, or other tool-specific steps.
The following example only collects text from the final model output:
|
|
In real projects, don’t assume that content exists for every step, and don’t treat thought as the final answer. First branch according to step.type, and then read the fields allowed by this type. Record unknown steps as type, ID, and status to preserve forward compatibility; don’t let the entire request fail just because a new tool step appears.
Why does the tool call “disappear”?
Older schemas often wrap server-side tool operations in a specific content type called outputs. The new schema breaks these into independent steps, so scanning only model_output will not see the search, function calls, and function results.
For example, the function call would read like this:
|
|
Server-side Google Search should also handle the call and result steps separately, rather than guessing from the final text whether a search was performed or not. For client function tools, after receiving requires_action, submit the corresponding function_result and continue to use the status of the interaction to complete the subsequent process.
Streaming SSE events are migrated together
If you only change the REST response parsing and do not change the stream processor, the front end will usually behave as “the request is successful but the page is not updated.” The new event names are as follows:
| Old events | New events |
|---|---|
interaction.start |
interaction.created |
interaction.complete |
interaction.completed |
content.start |
step.start |
content.delta |
step.delta |
content.stop |
step.stop |
interaction.status_update |
interaction.in_progress, interaction.requires_action and other status events |
The parameters of the function call are no longer guaranteed to arrive completely at once. In the stream, step.start will first give the function name, and then multiple step.delta events will be delivered piece by piece with some JSON parameters. The client must accumulate parameters and parse the complete JSON after step.stop or a state requiring action; do not directly JSON.parse() for each delta.
|
|
Do not reply after multiple rounds of dialogue outputs
The old stateless implementation often collects the previous round of outputs and stuffs it back into the next round of input. There are two clearer options after migration:
- Continue the same session via
previous_interaction_idusing the default server-side state; - When you must manage the history by yourself, return the previous round of
stepsand add a newuser_inputstep.
Server-side status is more suitable for ordinary multi-round conversations; client-side status is used when strict control of saved content, cross-system migration, or offline playback is required. No matter which one you choose, do not splice the old outputs and the new steps at the same time, otherwise it is easy to produce duplicate contexts, tool result mismatches, or token proliferation.
response_format may also be the source of the error
This migration not only changes the output array. Structured output and multi-modal configuration are also unified into the top-level response_format:
- The original
response_mime_typehas been removed; specifymime_typein theresponse_formatentry. - The JSON schema needs to be put in a format object with
type: "text". - Picture configuration moved from
generation_configtoresponse_formatentry intype: "image". - Multimodal output requires an array of format entries.
If the interface returns 400, in addition to checking for steps, the code is also searched for response_mime_type, generation_config.image_config, and the legacy single object response_format. These old fields often appear together with the outputs problem after the same upgrade.
A practical troubleshooting procedure
- Upgrade the Google GenAI SDK and document the actual version.
- Verify
interaction.output_textwith a toolless, non-streaming minimal request. - Print the type and status of
interaction.stepsto confirm that the program has received the new schema. - Migrate the parsing logic of function calls, server-side searches, and tool results respectively.
- Modify SSE event subscription and parameter accumulation logic.
- Check if the multi-round history is changed to
previous_interaction_idorsteps. - Search and replace old
response_formatrelated fields. - Run regression tests one each with text, tool calls, streaming output, and failure retries.
Don’t rely on the old Api-Revision header to temporarily restore old code. The transition period for the old schema is over; migration should now be considered an official compatibility fix, rather than continuing to have two sets of inconsistent parsers.
Summary
The essence of changing outputs to steps is that the Interactions API no longer crams all processes into an output list, but explicitly exposes inputs, reflections, tools, results, and final outputs. Pure text scenes preferentially use interaction.output_text; Agent, tool, streaming and multi-modal scenes use step.type to establish explicit branches; multi-round sessions use previous_interaction_id or steps instead. By migrating according to these three principles, most of the “no output”, “tool missing” and “SSE does not refresh” problems can be located.
Official information: