Developer's guide to Gemini 4 Hydrogen

Gemini 4 Hydrogen brings cutting-edge intelligence with speed and efficiency to everyday coding and agentic enterprise workflows.

This document covers the key capabilities of Hydrogen, the API conventions it enforces, how to migrate to it from Gemini 3.8 Flash and earlier Gemini 3 Flash models, and a quickstart. For an overview of the Gemini 4 family, see Get started with Gemini 4.

Key capabilities in Gemini 4 Hydrogen

Gemini 4 Hydrogen includes the following capabilities:

  • Unified input and output token limit: Hydrogen has a unified 1,048,576-token limit that includes both input and output tokens (where output includes thinking, function calls, and the final response).
  • Long decodes up to 1,048,576 tokens: Hydrogen extends generation beyond a single 65,536-token foreground segment (streaming or non-streaming) up to 1,048,576 tokens (minus your input tokens) on both the Interactions API and GenerateContent (v1beta1). The Google Gen AI SDK handles continuation_token automatically across segments, or you can run asynchronous server-managed background decodes (background=true) or manage continuation_token in a custom continuation loop.
  • Thinking levels: Hydrogen supports LOW, MEDIUM, HIGH (default), and XHIGH.
  • Implicit caching with durable caching: Implicit caching applies automatically to shared prompt prefixes of 4,096 tokens or more, with durable caching enabled by default. Explicit context caching isn't supported.
  • Office and OpenDocument file inputs: In addition to PDF and plain text, Hydrogen accepts Microsoft Office (.docx, .dotx, .doc, .pptx, .ppt, .xlsx, .xls) and OpenDocument (.odt, .odp, .ods) files inline or from Cloud Storage on both GenerateContent and the Interactions API, including inside multimodal FunctionResponse parts.
  • Agentic video understanding: Agentic video understanding is generally available and off by default.
  • Short-term release lifecycle: Hydrogen is a short-term generally available (GA) release subject to a minimum 45-day retirement notice policy. For lifecycle details, see Model versions and lifecycle.

Quickstart

Before you begin, you must authenticate to Gemini Enterprise Agent Platform using Application Default Credentials (ADC) or an API key. See Get started with Agent Platform for more information.

In the following code blocks, replace PROJECT_ID with your project ID.

Try it in Agent Studio

To test prompts and configure gemini-4-hydrogen in the Agent Studio UI, do the following:

  1. Open Agent Studio in your Google Cloud project and select gemini-4-hydrogen under the Gemini group.
  2. In Model settings, configure the following options:
    • Thinking level: Choose Low, Medium, High (default), or Extra high.
    • Region: Select Global, us, or eu.
    • Output token limit: Set between 32,768 and 1,048,576 (1,048,576 default). Agent Studio handles continuation tokens automatically for responses over the single-request limit.

Installation

Upgrade to the latest Google Gen AI SDK. Automatic continuation on the Interactions API requires google-genai >= 2.34.0 for Python, @google/genai >= 2.32.0 for JavaScript/TypeScript, >= 1.77.0 for Go, or >= 1.80.0 for Java (on GenerateContent, automatic continuation requires >= 2.30.1 for Python, >= 2.29.1 for JavaScript/TypeScript, >= 1.74.0 for Go, >= 1.77.0 for Java, >= 1.26.0 for .NET, or >= 1.6.0 for Kotlin):

pip install --upgrade "google-genai>=2.34.0"

Basic request

Send a request to gemini-4-hydrogen using the Google Gen AI SDK or REST:

Python (GenerateContent)

from google import genai
from google.genai import types

client = genai.Client(enterprise=True, project="PROJECT_ID", location="global")

response = client.models.generate_content(
    model="gemini-4-hydrogen",
    contents="Design a lock-free ring buffer in Rust for multi-producer, single-consumer telemetry ingestion.",
    config=types.GenerateContentConfig(
        thinking_config=types.ThinkingConfig(
            thinking_level="HIGH",  # Default: "HIGH" (Valid: "LOW", "MEDIUM", "HIGH", "XHIGH")
        ),
    ),
)
print(response.text)

Python (Interactions API)

from google import genai

client = genai.Client(enterprise=True, project="PROJECT_ID", location="global")

# Turn 1: Initial request (stored server-side by default)
turn1 = client.interactions.create(
    model="gemini-4-hydrogen",
    input="Design a lock-free ring buffer in Rust for multi-producer, single-consumer telemetry ingestion.",
    store=True,
)
print(turn1.output_text)

# Turn 2: Continue the conversation using previous_interaction_id
turn2 = client.interactions.create(
    model="gemini-4-hydrogen",
    input="Add a bounded backpressure policy and unit tests for concurrent writers.",
    previous_interaction_id=turn1.id,
)
print(turn2.output_text)

REST

curl -X POST \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
"https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-4-hydrogen:generateContent" \
-d '{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Provide an architectural review of this Go interface."
        }
      ]
    }
  ],
  "generationConfig": {
    "thinkingConfig": {
      "thinkingLevel": "HIGH"
    }
  }
}'

Structured output

To generate JSON output that conforms to a schema, configure response_mime_type and response_schema:

from pydantic import BaseModel, Field
from google import genai
from google.genai import types

class ArchitectureReview(BaseModel):
    component: str = Field(description="Service or module name")
    bottlenecks: list[str] = Field(description="Throughput or latency bottlenecks")
    recommended_changes: list[str] = Field(description="Concrete refactoring steps")

client = genai.Client(enterprise=True, project="PROJECT_ID", location="global")

response = client.models.generate_content(
    model="gemini-4-hydrogen",
    contents="Review a synchronous order-processing pipeline backed by a single primary database at 15,000 writes/sec.",
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=ArchitectureReview,
        thinking_config=types.ThinkingConfig(thinking_level="HIGH"),
    ),
)
print(response.text)

Long decode examples

By default, a single foreground API segment generates up to 65,536 output tokens (streaming or non-streaming), where output includes thinking, function calls, and the final response. To generate completions up to 1,048,576 tokens (minus your input tokens), use long decodes on either the Interactions API or GenerateContent. For continuation options, status transitions, and validation rules, see Long decodes.

Use long decodes with the Interactions API

In google-genai >= 2.34.0 (Python), @google/genai >= 2.32.0 (JavaScript/TypeScript), Go >= 1.77.0, and Java >= 1.80.0, interactions.create() automatically follows continuation_token across segments whenever a segment returns status="requires_continuation". You can also opt out (automatic_continuation=False) to run a custom stored (store=True) or stateless (store=False) loop:

Python (SDK automatic)

from google import genai

client = genai.Client(
    enterprise=True,
    project="PROJECT_ID",
    location="global",
)

# Automatic continuation is enabled by default in google-genai >= 2.34.0.
# Unary calls merge all segments into one Interaction with summed usage.
interaction = client.interactions.create(
    model="gemini-4-hydrogen",
    input="Write a complete formal proof of the prime number theorem.",
    generation_config={
        "max_output_tokens": 256000,
        "thinking_level": "high",
    },
)
print(interaction.output_text)
print(f"Merged segment IDs: {interaction.continuation_ids}")
print(f"Initial input tokens: {interaction.usage.initial_input_tokens}")

# Streaming yields events across all segments in order. Intermediate segments
# emit interaction.completed with status="requires_continuation".
stream = client.interactions.create(
    model="gemini-4-hydrogen",
    input="Write a complete formal proof of the prime number theorem.",
    stream=True,
    generation_config={
        "max_output_tokens": 256000,
        "thinking_level": "high",
    },
)
for event in stream:
    if event.event_type == "step.delta" and getattr(event.delta, "text", None):
        print(event.delta.text, end="", flush=True)
    elif (
        event.event_type == "interaction.completed"
        and event.interaction.status != "requires_continuation"
    ):
        print(f"\nFinal status: {event.interaction.status}")

# Optional: Delete each stored server segment (last segment first) before its 7-day TTL expires.
for segment_id in reversed(interaction.continuation_ids or [interaction.id]):
    client.interactions.delete(id=segment_id)

# Set automatic_continuation=False to return after a single segment.
single_segment = client.interactions.create(
    model="gemini-4-hydrogen",
    input="Write a complete formal proof of the prime number theorem.",
    generation_config={"max_output_tokens": 256000, "thinking_level": "high"},
    automatic_continuation=False,
)

Python (Custom loop)

from google import genai

client = genai.Client(
    enterprise=True,
    project="PROJECT_ID",
    location="global",
)

prompt = "Write a complete formal proof of the prime number theorem."

# Stored loop (store=True, default): chain previous_interaction_id + continuation_token
# without resending input.
segment = client.interactions.create(
    model="gemini-4-hydrogen",
    input=prompt,
    store=True,
    generation_config={"max_output_tokens": 131072, "thinking_level": "high"},
    automatic_continuation=False,
)
full_text = segment.output_text or ""

while segment.status == "requires_continuation" and segment.continuation_token:
    segment = client.interactions.create(
        model="gemini-4-hydrogen",
        previous_interaction_id=segment.id,
        continuation_token=segment.continuation_token,
        generation_config={"max_output_tokens": 131072, "thinking_level": "high"},
        automatic_continuation=False,
    )
    full_text += segment.output_text or ""

# If status == "incomplete", max_output_tokens was exhausted; raise max_output_tokens to continue.
if segment.status == "incomplete" and segment.continuation_token:
    segment = client.interactions.create(
        model="gemini-4-hydrogen",
        previous_interaction_id=segment.id,
        continuation_token=segment.continuation_token,
        generation_config={"max_output_tokens": 256000, "thinking_level": "high"},
    )
    full_text += segment.output_text or ""

# Stateless loop (store=False): resend original input + continuation_token
# with no previous_interaction_id.
stateless_seg = client.interactions.create(
    model="gemini-4-hydrogen",
    input=prompt,
    store=False,
    generation_config={"max_output_tokens": 131072, "thinking_level": "high"},
    automatic_continuation=False,
)
stateless_text = stateless_seg.output_text or ""
while stateless_seg.status == "requires_continuation" and stateless_seg.continuation_token:
    stateless_seg = client.interactions.create(
        model="gemini-4-hydrogen",
        input=prompt,
        store=False,
        continuation_token=stateless_seg.continuation_token,
        generation_config={"max_output_tokens": 131072, "thinking_level": "high"},
        automatic_continuation=False,
    )
    stateless_text += stateless_seg.output_text or ""

REST (Stored)

# Segment 1: Start a stored interaction (store=true by default)
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "store": true,
    "input": "Write a complete formal proof of the prime number theorem.",
    "generation_config": {
      "max_output_tokens": 131072,
      "thinking_level": "high"
    }
  }'

# Segment 2: When status is "requires_continuation", pass previous_interaction_id
# and continuation_token without resending input
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "store": true,
    "previous_interaction_id": "SEGMENT_1_ID",
    "continuation_token": "CONTINUATION_TOKEN",
    "generation_config": {
      "max_output_tokens": 131072,
      "thinking_level": "high"
    }
  }'

REST (Stateless)

# Segment 1: Stateless interaction (store=false)
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "store": false,
    "input": "Write a complete formal proof of the prime number theorem.",
    "generation_config": {
      "max_output_tokens": 131072,
      "thinking_level": "high"
    }
  }'

# Segment 2: Resend the original input and continuation_token (no previous_interaction_id)
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "store": false,
    "input": "Write a complete formal proof of the prime number theorem.",
    "continuation_token": "CONTINUATION_TOKEN",
    "generation_config": {
      "max_output_tokens": 131072,
      "thinking_level": "high"
    }
  }'

For asynchronous server-managed execution (background=True with store=True) or recovery from streaming checkpoints (interaction.status_update events emitted starting at 65,536 output tokens and every 5,000 tokens thereafter), use the following patterns:

Python (Background)

import time
from google import genai

client = genai.Client(
    enterprise=True,
    project="PROJECT_ID",
    location="global",
)

# Start a server-managed background long decode (requires store=True)
interaction = client.interactions.create(
    model="gemini-4-hydrogen",
    input="Write a complete formal proof of the prime number theorem.",
    background=True,
    store=True,
    generation_config={"max_output_tokens": 256000, "thinking_level": "high"},
)

while interaction.status in ("queued", "in_progress"):
    time.sleep(10)
    interaction = client.interactions.get(id=interaction.id)

print(f"Status: {interaction.status}")
print(interaction.output_text)

# Optional: Cancel an in-progress background interaction and resume later
# from its persisted checkpoint continuation_token (if >= 65,536 tokens decoded).
# cancelled = client.interactions.cancel(id=interaction.id)
# if cancelled.continuation_token:
#     resumed = client.interactions.create(
#         model="gemini-4-hydrogen",
#         previous_interaction_id=cancelled.id,
#         continuation_token=cancelled.continuation_token,
#         background=True,
#         generation_config={"max_output_tokens": 256000, "thinking_level": "high"},
#     )

REST (Background)

# Start a server-managed background long decode (requires store=true)
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "background": true,
    "store": true,
    "input": "Write a complete formal proof of the prime number theorem.",
    "generation_config": {
      "max_output_tokens": 256000,
      "thinking_level": "high"
    }
  }'

# Poll the interaction until status reaches completed, incomplete, failed, or cancelled
curl -s -X GET \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions/INTERACTION_ID"

# Optional: Cancel an in-progress background decode
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions/INTERACTION_ID/cancel"

# Optional: Resume a cancelled background decode from its checkpoint continuation_token
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "background": true,
    "store": true,
    "previous_interaction_id": "INTERACTION_ID",
    "continuation_token": "CONTINUATION_TOKEN",
    "generation_config": {
      "max_output_tokens": 256000,
      "thinking_level": "high"
    }
  }'

Python (Streaming checkpoints)

from google import genai
from google.genai import errors

client = genai.Client(
    enterprise=True,
    project="PROJECT_ID",
    location="global",
)

# With default automatic_continuation=True, stream=True automatically
# reconnects from the latest interaction.status_update checkpoint (65,536
# output tokens, then every 5,000 tokens) if no output was yielded after the
# checkpoint. If a disconnect occurs after output was yielded since the last
# checkpoint, the SDK raises ContinuationInterruptedError so you can resume
# from err.continuation_token.
stream = client.interactions.create(
    model="gemini-4-hydrogen",
    input="Write a complete formal proof of the prime number theorem.",
    stream=True,
    store=True,
    generation_config={"max_output_tokens": 256000, "thinking_level": "high"},
)

try:
    for event in stream:
        if event.event_type == "step.delta" and getattr(event.delta, "text", None):
            print(event.delta.text, end="", flush=True)
except errors.ContinuationInterruptedError as err:
    # Resuming from a mid-segment checkpoint regenerates any output yielded
    # after that checkpoint.
    if err.interaction_id and err.continuation_token:
        resumed_stream = client.interactions.create(
            model="gemini-4-hydrogen",
            previous_interaction_id=err.interaction_id,
            continuation_token=err.continuation_token,
            stream=True,
            store=True,
            generation_config={"max_output_tokens": 256000, "thinking_level": "high"},
        )
        for event in resumed_stream:
            if event.event_type == "step.delta" and getattr(event.delta, "text", None):
                print(event.delta.text, end="", flush=True)

REST (Streaming checkpoints)

# Start a streaming interaction; save interaction.id from interaction.created
# and the latest continuation_token from interaction.status_update SSE events
curl -N -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "stream": true,
    "store": true,
    "input": "Write a complete formal proof of the prime number theorem.",
    "generation_config": {
      "max_output_tokens": 256000,
      "thinking_level": "high"
    }
  }'

# Resume a dropped stream from the last saved checkpoint continuation_token
# (for store=false, resend the original input instead of previous_interaction_id)
curl -N -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/interactions" \
  -d '{
    "model": "gemini-4-hydrogen",
    "stream": true,
    "store": true,
    "previous_interaction_id": "SEGMENT_ID",
    "continuation_token": "CHECKPOINT_CONTINUATION_TOKEN",
    "generation_config": {
      "max_output_tokens": 256000,
      "thinking_level": "high"
    }
  }'

Use long decodes with GenerateContent

On GenerateContent (v1beta1), set max_output_tokens greater than 65,536 (up to 1,048,576) for streaming or non-streaming requests. The Google Gen AI SDK automatically follows continuation_token across segments when finish_reason is CONTINUATION (set automatic_continuation=False in GenerateContentConfig to opt out), or you can pass continuation_token in a custom loop:

from google import genai
from google.genai import types

client = genai.Client(enterprise=True, project="PROJECT_ID", location="global")

# Automatic continuation is enabled by default in google-genai >= 2.30.1.
# Chunks across all continuation requests are yielded as a single stream.
for chunk in client.models.generate_content_stream(
    model="gemini-4-hydrogen",
    contents="Write a complete formal proof of the prime number theorem.",
    config=types.GenerateContentConfig(
        max_output_tokens=256000,
        thinking_config=types.ThinkingConfig(thinking_level="HIGH"),
    ),
):
    print(chunk.text, end="")

# Set automatic_continuation=False to disable automatic continuation.
for chunk in client.models.generate_content_stream(
    model="gemini-4-hydrogen",
    contents="Write a complete formal proof of the prime number theorem.",
    config=types.GenerateContentConfig(
        thinking_config=types.ThinkingConfig(thinking_level="HIGH"),
        automatic_continuation=False,
    ),
):
    print(chunk.text, end="")

REST (Custom continuation loop)

# Request 1: Initial request with maxOutputTokens > 65,536
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-4-hydrogen:generateContent" \
  -d '{
    "contents": [{
      "role": "user",
      "parts": [{"text": "Write a complete formal proof of the prime number theorem."}]
    }],
    "generationConfig": {
      "maxOutputTokens": 131072,
      "thinkingConfig": {"thinkingLevel": "HIGH"}
    }
  }'

# Request 2: Resend the original request with top-level continuationToken
# from Request 1 (candidates[0].continuationToken)
curl -s -X POST \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  "https://aiplatform.googleapis.com/v1beta1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-4-hydrogen:generateContent" \
  -d '{
    "contents": [{
      "role": "user",
      "parts": [{"text": "Write a complete formal proof of the prime number theorem."}]
    }],
    "continuationToken": "CONTINUATION_TOKEN",
    "generationConfig": {
      "maxOutputTokens": 131072,
      "thinkingConfig": {"thinkingLevel": "HIGH"}
    }
  }'

Mandatory API rules and behavioral conventions

Hydrogen enforces the conventions in the following sections for thinking levels, token limits, caching, generation parameters, and multi-turn tool execution.

Thinking levels

Hydrogen supports four thinking_level values (thinking_budget and MINIMAL return an HTTP 400 validation error). The following table lists each thinking level and its recommended workloads:

Thinking level Recommended workloads
XHIGH Deep reasoning, mathematical proofs, scientific analysis, and the most complex multi-file software engineering tasks.
HIGH (default on gemini-4-hydrogen) Multi-step agentic tool loops, code generation, architectural refactoring, and complex multimodal analysis.
MEDIUM General coding, tool use, document Q&A, and video understanding with balanced latency.
LOW High-throughput classification, routing, summarization, and structured metadata extraction.

Token limits, caching, and billing

Hydrogen applies the following token, caching, media, and billing rules:

  • Unified input and output token limit and single-request output limits: Token budgets and per-request limits work as follows:
    • The overall token limit of the model is 1,048,576 tokens and includes both input and output tokens (where output includes thinking, function calls, and the final response). max_output_tokens controls the output token cap for the generation (up to 1,048,576 minus your input tokens); setting max_output_tokens greater than 1,048,576 returns an HTTP 400 error.
    • To avoid unintended long completions, the default output budget and single-segment foreground limit (thinking, function calls, and model response) is 65,536 tokens for both streaming and non-streaming requests.
    • Reasoning tokens generated at HIGH (default) and XHIGH count toward max_output_tokens and accumulate in multi-turn context when you preserve thought signatures across turns. Set max_output_tokens high enough for both thinking and final output, avoid overly low context-compaction thresholds in multi-turn coding harnesses, or set thinking_level="MEDIUM" on latency-sensitive tool turns.
  • Long decodes: Single-segment foreground responses generate up to 65,536 output tokens (streaming or non-streaming). To extend single-turn output up to 1,048,576 tokens (minus input tokens) on the Interactions API or GenerateContent (v1beta1), see Long decodes.
  • Context caching: Explicit context caching isn't supported. Implicit caching (with durable caching enabled by default) applies automatically to shared prompt prefixes of 4,096 tokens or more, so put static content at the start of your prompt.
  • Office and OpenDocument inputs: Pass Word (application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.wordprocessingml.template, application/msword, application/vnd.oasis.opendocument.text), PowerPoint (application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.ms-powerpoint, application/vnd.oasis.opendocument.presentation), and Excel or OpenDocument spreadsheet (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, application/vnd.oasis.opendocument.spreadsheet) files inline or by Cloud Storage URI (gs://) using inlineData or fileData on GenerateContent (including inside FunctionResponse parts) and document inputs (including tool results) on the Interactions API.
  • Agentic video: Uploaded videos default to media_processing="static". Set media_processing="agentic" to enable agentic video processing.
  • Token counting and billing: Every token the model processes is counted and billed, including thinking tokens and internal tool system instructions and function declarations when using grounding. Grounding with Google Search also remains billed per query.

Parameters, function calling, and chat validation

Hydrogen enforces the following rules for generation parameters, tool calls, thought signatures, and chat history:

  • Ignored sampling parameters (temperature, top_k, top_p): The backend ignores custom values. Control reasoning depth with thinking_level, and output format with response_schema.
  • Unsupported parameters (frequency_penalty, presence_penalty, and candidate_count greater than 1): Passing frequency_penalty, presence_penalty, or candidate_count greater than 1 (candidateCount is fixed at 1) returns an HTTP 400 error. Remove these parameters from your requests.
  • Function calling and thought signatures: Tool declarations, parallel tool calls, and multi-turn thought_signature replay follow these rules:

    • Turn symmetry: Each FunctionResponse must match the id, name, and order of the preceding FunctionCall.
    • Multimodal FunctionResponse parts: Include Office documents, spreadsheets, presentations, PDFs, images, audio, and video inside multimodal FunctionResponse parts (or tool results on the Interactions API) rather than appending them as separate user-turn parts.
    • Parallel function call thought_signature placement: When the model emits multiple parallel functionCall parts in a single model turn, only the first functionCall part contains the thought_signature. Omitting thought_signature from the first functionCall part in the active user turn, duplicating it onto subsequent parallel functionCall parts, or interleaving functionCall and functionResponse turns returns an HTTP 400 error; keep all parallel functionCall parts in a single model turn followed by all matching functionResponse parts in a single user turn. For details, see Thought signatures.
    • Prompt-prefix binding (prefix_mismatch_behavior): Input thought_signature parts are cryptographically bound to the conversation prefix (system_instruction, tools, and prior contents). By default (prefix_mismatch_behavior="ERROR"), modifying earlier turns or system instructions on a same-model replay returns an HTTP 400 (INVALID_ARGUMENT) error (signatures generated by a different model, such as gemini-4-carbon or gemini-4-argon, are dropped automatically). If your agent harness compacts, prunes, or edits earlier conversation history, set prefix_mismatch_behavior="DROP" in ThinkingConfig (or generation_config.prefix_mismatch_behavior="drop" on the Interactions API) so the server drops prefix-mismatched thought_signature values while retaining visible text, function_call, and media parts.
    • Cross-turn thought_signature preservation: Pass back every thought_signature inside its original Part across all previous turns in multi-turn chat history (both functionCall and final text parts), not only within the active user turn. Although HTTP 400 signature validation applies only to functionCall steps within the active user turn, stripping thought_signature values from earlier turns or substituting bypass values such as skip_thought_signature_validator removes reasoning context, degrades output quality, and can cause MALFORMED_FUNCTION_CALL finish reasons.
    • Pre-tool formatting: Separate inline instructions with \n\n and avoid unstructured text before tool calls. To log intermediate state before a tool call, use a dedicated function declaration:

      {
        "name": "update",
        "description": "Update working notes before tool execution",
        "parameters": {
          "type": "OBJECT",
          "properties": {
            "previous_step": {"type": "STRING"},
            "plan": {"type": "STRING"},
            "next_step": {"type": "STRING"}
          },
          "required": ["previous_step", "plan", "next_step"]
        }
      }
      
  • Chat sequence validation: Multi-turn chat payloads enforce the following constraints:

    • History payloads can't end with a model role turn.
    • Prefilled model turns aren't supported.

Long decodes

Long decode splits a generation up to 1,048,576 tokens (minus your input tokens) across multiple segments on either the Interactions API or GenerateContent (v1beta1). On the Interactions API, each foreground segment (stream=true or stream=false) generates up to 65,536 output tokens and returns status="requires_continuation" with an encrypted continuation_token, or you can set background=true (store=true) so the server runs the continuation loop asynchronously and stores the merged output in one Interaction. On GenerateContent, each streaming or non-streaming segment generates up to 65,536 output tokens before emitting finish_reason=CONTINUATION with continuation_token, continuing until finish_reason=STOP. In Agent Studio, setting the output token limit greater than 65,536 up to 1,048,576 handles continuation tokens automatically. For runnable code samples, see the Long decode quickstart examples.

When to use long decode

Most requests finish within the 65,536-token per-segment output limit. Use long decode only when one response needs more output than that. Long decode gives the model more room to reason; it doesn't make answers longer (use thinking_level to control reasoning depth).

Workload Use long decode? Why
Hard math, science, research, and formal proofs Yes The model can spend more than 65,536 tokens to explore and check its reasoning.
The hardest coding and agentic tasks Yes Some tasks need more than 65,536 tokens of thinking and code in one response. Most coding and agentic tasks finish under 65,536 tokens.
Evaluation harnesses that stop at the output limit Yes Long decode prevents cut-off answers when the model spends an entire 65,536-token segment on thinking.
Chat, Q&A, summarization, classification, and extraction No These tasks finish well under 65,536 tokens.
Requests for a fixed length, such as "write a 700,000-word book" No The model doesn't follow length targets.
Agents that call tools in many short turns No Each turn is short. Large outputs on each turn fill the unified 1,048,576-token input and output limit quickly.
Prompts near the 1,048,576-token input limit No Output can use only 1,048,576 tokens minus your input.
Latency-sensitive requests No Long decode can run for several minutes.

Choose a continuation option

Select a continuation pattern based on your API surface, storage posture, and runtime environment. All options in the following table reach the same 1,048,576-token limit (minus input tokens) on gemini-4-hydrogen.

Continuation option API surface Who starts each segment Tokens per segment Time limit per request Server storage Best for
Google Gen AI SDK automatic continuation (recommended) Interactions API (v1beta1) Google Gen AI SDKs: Python (google-genai >= 2.34.0), JavaScript/TypeScript (@google/genai >= 2.32.0), Go (>= 1.77.0), and Java (>= 1.80.0) Up to 65,536 (stream=true or stream=false) 20 minutes per segment 7-day server storage by default (store=true), or none (store=false) Most stateful or stateless Interactions API applications
Background server-managed loop (background=true) Interactions API (v1beta1) Agent Platform server loop; your code polls get Managed server-side up to max_output_tokens Asynchronous (no open client stream required) 7-day server storage (store=true required) Asynchronous jobs, .NET/Kotlin callers, and single-record persistence
Custom foreground stored loop (store=true) Interactions API (v1beta1) Your code (previous_interaction_id + continuation_token, no input) Up to 65,536 (stream=true or stream=false; checkpoints starting at 65,536 and every 5,000 tokens thereafter) 20 minutes per segment 7-day server storage (store=true) REST callers and custom checkpoint recovery
Custom foreground stateless loop (store=false) Interactions API (v1beta1) Your code (original input + continuation_token, no previous_interaction_id) Up to 65,536 (stream=true or stream=false; checkpoints starting at 65,536 and every 5,000 tokens thereafter) 20 minutes per segment No server storage (Zero Data Retention workflows) Custom REST harnesses requiring stateless execution
Google Gen AI SDK automatic continuation (recommended) GenerateContent (v1beta1) Google Gen AI SDKs: Python (>= 2.30.1), JavaScript/TypeScript (>= 2.29.1), Go (>= 1.74.0), Java (>= 1.77.0), .NET (>= 1.26.0), and Kotlin (>= 1.6.0) Up to 65,536 (generate_content_stream or generate_content) 20 minutes per segment No server storage (Zero Data Retention workflows) Existing GenerateContent applications
Custom continuation loop GenerateContent (v1beta1) Your code (original contents + continuation_token) Up to 65,536 (streamGenerateContent or generateContent; checkpoints starting at 65,536 and every 5,000 tokens thereafter) 20 minutes per segment No server storage (Zero Data Retention workflows) Direct REST GenerateContent callers and evaluation harnesses

API version and SDK requirements

Long decodes require the following API version and minimum SDK versions:

  • v1beta1 API requirement (known issue): Long decoding (continuation_token) on both the Interactions API and GenerateContent (generateContent and streamGenerateContent) is supported only in the v1beta1 API (not v1) on Agent Platform. The Google Gen AI SDK uses v1beta1 by default unless api_version='v1' is specified in http_options (or api_version="v1" on interactions.create); for direct REST calls, use the /v1beta1/ endpoint path.
  • SDK versions and OpenAI compatibility: For automatic continuation on the Interactions API, upgrade to Python google-genai >= 2.34.0, JavaScript/TypeScript @google/genai >= 2.32.0, Go >= 1.77.0, or Java >= 1.80.0 (for .NET and Kotlin on the Interactions API, use background=true or a custom continuation loop). For automatic continuation on GenerateContent, upgrade to Python >= 2.30.1, JavaScript/TypeScript >= 2.29.1, Go >= 1.74.0, Java >= 1.77.0, .NET >= 1.26.0, or Kotlin >= 1.6.0. Earlier SDK versions and the OpenAI compatibility layer can't retrieve long completions using continuation tokens.

Interactions API continuation rules

The following status transitions, chaining rules, and storage behaviors apply to long decodes on the Interactions API.

Status values and output token budget

When generation_config.max_output_tokens is omitted on an Interactions API request, the total output budget defaults to 65,536 tokens (matching the 65,536-token single-segment foreground limit for both streaming and non-streaming requests). Set generation_config.max_output_tokens greater than 65,536 (up to 1,048,576 minus input tokens) for multi-segment long decodes in both foreground and background=true modes. The server returns the following status values:

  • requires_continuation: The 65,536-token per-segment output limit was reached before max_output_tokens; pass the returned continuation_token on the next request to continue decoding.
  • incomplete: The total max_output_tokens budget was exhausted; continuing with continuation_token without raising max_output_tokens returns an HTTP 400 error (max_output_tokens has already been exhausted). Increase max_output_tokens on the next request to resume decoding.
  • completed: Generation finished naturally and continuation_token is cleared.

Chaining, mode switching, and segment storage

Continuation requests on the Interactions API enforce the following rules:

  • Stored continuation (store=true, default): Pass previous_interaction_id set to the segment id that issued the continuation_token along with continuation_token, and omit input (the stored segment already holds the turn input). Always pair each continuation_token with the previous_interaction_id of the segment that issued it; passing a continuation_token on an already completed interaction returns an HTTP 400 error.
  • Stateless continuation (store=false): Omit previous_interaction_id and resend the original input alongside continuation_token on every segment.
  • Switching store modes across segments: You can switch from stored (store=true) to stateless (store=false) mid-decode by omitting previous_interaction_id and resending the original input with continuation_token. Switching from stateless (store=false) to stored (store=true) isn't supported because no stored parent interaction exists for previous_interaction_id.
  • Foreground and background=true mode switching and branching: Stored continuations (store=true) can switch between foreground (background=false) and background (background=true) execution across segments, including resuming a cancelled background=true interaction from its checkpoint continuation_token (persisted starting at 65,536 output tokens and every 5,000 tokens thereafter) in either background or foreground mode. Reusing the same previous_interaction_id and continuation_token creates independent branched continuations.
  • Turn-boundary enforcement: Starting a new user turn (previous_interaction_id with new input and no continuation_token) from a segment whose status is requires_continuation or incomplete returns an HTTP 400 error. Finish continuing the decode to completed, or branch your next turn from the most recent completed interaction. Once the final segment reaches completed, passing that final segment's id as previous_interaction_id reconstructs the full conversation history across all prior segments.
  • Parameter consistency across segments: Changing model, system_instruction, or function declarations (tools) on a continuation segment returns an HTTP 400 error. Keep thinking_level and built-in tools unchanged across segments as well (see Known issues).
  • Single-segment get, list, and delete behavior: In foreground mode (background=false), each segment is stored as a separate Interaction resource (interactions.get(id) returns only that segment, interactions.list() lists each segment separately, and interactions.delete(id) deletes only that segment; when deleting a chain of segments, delete in reverse order from the last segment backward). In the Google Gen AI SDK with automatic_continuation=True (stream=False), interactions.create() merges all segments on return and populates interaction.continuation_ids with the ordered segment IDs (ending with interaction.id). If a later segment fails, exceeds a numeric per-call timeout, or drops mid-stream after progress was made past a resumable checkpoint, the SDK raises ContinuationInterruptedError carrying partial_interaction, continuation_token, interaction_id, and continuation_ids so you can resume from continuation_token.

GenerateContent custom loop rules

In a custom GenerateContent continuation loop, follow these rules:

  • Set max_output_tokens greater than 65,536 (up to 1,048,576), and resend the original contents, system_instruction, and tools on every continuation request along with the latest continuation_token (a top-level field on GenerateContentRequest in REST, or in GenerateContentConfig in the Google Gen AI SDK).
  • Don't append partial model output into contents or send a follow-up prompt asking the model to continue.
  • Continue looping as long as finish_reason is CONTINUATION and continuation_token is present, even if a segment spent all 65,536 tokens on thinking (parts: [{"text": ""}]). If finish_reason is MAX_TOKENS when continuation_token is present, raise max_output_tokens in the next request.
  • Combine accumulated parts into a single model turn for multi-turn history only after STOP.

Token counting, compaction, and implicit caching

Token accounting and caching across continuation segments work as follows:

  • On the Interactions API, non-streaming interactions.create() calls with automatic_continuation=True and server-managed background=true interactions sum token counts across all segments in usage (total_input_tokens, total_cached_tokens, total_output_tokens, total_thought_tokens, total_tokens), preserving the first segment's prompt count in usage.initial_input_tokens. In custom foreground loops and streamed interaction.completed events, each segment's usage reports only that segment's delta, so sum usage fields across segments for total billed tokens.
  • On GenerateContent, the Python Google Gen AI SDK (generate_content and generate_content_stream) accumulates total billed tokens across segments in the final usage_metadata and preserves initial_prompt_token_count. In custom REST loops, sum the final prompt_token_count, cached_content_token_count, candidates_token_count, and thoughts_token_count across segments.
  • Because each foreground continuation segment re-prefills the conversation and previously generated tokens as input, usage.total_input_tokens (on the Interactions API) and prompt_token_count (on GenerateContent) increase across segments. Don't use cumulative input counts to trigger context compaction in agent harnesses; instead, check usage.initial_input_tokens (or initial_prompt_token_count on GenerateContent) and compact only after the turn finishes (status="completed" or no continuation_token).
  • Each continuation segment re-prefills the prompt plus previously decoded tokens and automatically qualifies for implicit context caching (4,096-token minimum, with durable caching enabled by default) when segments run back-to-back. Completed segments are billed at the end of each segment even if a later segment fails or is cancelled.

Migrate to Hydrogen from 3.8 Flash

The following behavior is different from gemini-3.8-flash and earlier Gemini 3 Flash models:

  • Hydrogen has a unified 1,048,576-token limit across input and output (where output includes thinking, function calls, and the final response), instead of separate input and output limits. Single-segment foreground output is capped at 65,536 tokens (streaming or non-streaming), and can be extended up to 1,048,576 tokens using long decodes on the Interactions API or GenerateContent (handled automatically in the Google Gen AI SDK, with background=true on the Interactions API, or using continuation_token in custom loops).
  • The default thinking_level is HIGH (changed from MEDIUM on gemini-3.8-flash), and XHIGH is supported for deep reasoning tasks (leave context-compaction headroom for HIGH and XHIGH reasoning traces in multi-turn coding harnesses, or set MEDIUM on latency-sensitive turns). thinking_budget and thinking_level="MINIMAL" return an HTTP 400 error.
  • Explicit context caching (cached_content) isn't supported. Implicit caching applies automatically at a 4,096-token minimum (reduced from 6,144 tokens on gemini-3.8-flash), with durable caching enabled by default.
  • Microsoft Office (.docx, .dotx, .doc, .pptx, .ppt, .xlsx, .xls) and OpenDocument (.odt, .odp, .ods) files are supported inline or by Cloud Storage URI (gs://), including inside multimodal FunctionResponse parts.
  • Parallel function-calling turns enforce strict thought_signature placement (only the first functionCall part in a parallel turn carries thought_signature; omitting it in the active turn or duplicating it onto subsequent sibling functionCall parts returns an HTTP 400 error), and same-model prompt-prefix edits fail with HTTP 400 by default unless prefix_mismatch_behavior="DROP" is set in ThinkingConfig. Preserve thought_signature parts across all previous turns as well (both functionCall and final text parts) to maintain reasoning quality and avoid MALFORMED_FUNCTION_CALL finish reasons.
  • Every token the model processes is billed, including internal tool system instructions and function declarations when using grounding.

For a side-by-side comparison, see Migrate from Gemini 3 models.

 client = genai.Client(
     enterprise=True,
     project="PROJECT_ID",
     location="global", # Supports "global", "us", and "eu"
 )

 response = client.models.generate_content(
-    model="gemini-3.8-flash",
+    model="gemini-4-hydrogen",
     contents=prompt,
     config=types.GenerateContentConfig(
-        temperature=0.0,
-        cached_content="projects/.../cachedContents/...", # Explicit caching unsupported
         thinking_config=types.ThinkingConfig(
-            thinking_budget=16384, # Returns HTTP 400 instead of mapping silently
-            thinking_level="MINIMAL", # MINIMAL unsupported on Gemini 4 Hydrogen
+            thinking_level="HIGH", # Valid: "LOW", "MEDIUM", "HIGH" (default), "XHIGH"
+            # prefix_mismatch_behavior="DROP", # Optional: set if compacting or editing prior history
         ),
     ),
 )

To migrate from gemini-3.8-flash or earlier Gemini 3 Flash models, do the following:

  1. Update the model ID to gemini-4-hydrogen.
  2. Upgrade to the latest Google Gen AI SDK and account for the unified input and output token limit: Upgrade to google-genai >= 2.34.0 (Python), @google/genai >= 2.32.0 (JavaScript/TypeScript), Go >= 1.77.0, or Java >= 1.80.0 for Interactions API automatic continuation (or >= 2.30.1 Python / >= 2.29.1 JavaScript on GenerateContent). Input and output tokens (including thinking and function calls) share the unified 1,048,576-token limit. For outputs exceeding 65,536 tokens (up to 1,048,576 tokens) on the Interactions API or GenerateContent, set max_output_tokens greater than 65,536 so the Google Gen AI SDK continues automatically across segments (or use background=true or a custom continuation_token loop).
  3. Update thinking_level configuration: Replace thinking_budget and MINIMAL with thinking_level set to LOW, MEDIUM, HIGH (default on gemini-4-hydrogen), or XHIGH (use lowercase "low", "medium", "high", or "xhigh" on the Interactions API). If your workload relied on MEDIUM as the default on gemini-3.8-flash, explicitly set thinking_level="MEDIUM" to keep equivalent reasoning latency.
  4. Remove explicit caching and front-load static prompt content (4,096 tokens or more) for automatic implicit caching.
  5. Verify multi-turn and parallel thought_signature preservation and prefix compaction: Preserve thought_signature across all previous turns (both functionCall and final text parts) rather than stripping signatures between turns, keep thought_signature only on the first functionCall part of a parallel tool-calling turn, and set prefix_mismatch_behavior="DROP" in ThinkingConfig if your application modifies or compacts earlier turns in multi-turn chat history.
  6. Remove parameters that have no effect or aren't supported: Remove ignored and rejected generation fields as follows:
    • Remove temperature, top_p, and top_k, which are ignored.
    • Remove frequency_penalty, presence_penalty, and any candidate_count value greater than 1.
    • Remove any prefilled model turns from conversation histories.

Summary checklist for developers

Use the following checklist to verify your Hydrogen integration:

Known issues

The following known issues apply to Hydrogen long decodes:

  • Long decodes require v1beta1: Long decoding (continuation_token) on both the Interactions API and the GenerateContent API (generateContent and streamGenerateContent) is supported only in the v1beta1 API (not v1) on Agent Platform. The Google Gen AI SDK uses v1beta1 by default unless api_version='v1' is set in http_options (or api_version="v1" on interactions.create); for direct REST calls, use the /v1beta1/ endpoint path.
  • Parameter changes across Interactions API continuation segments: Changing model, system_instruction, or function declarations across continuation segments returns an HTTP 400 error, whereas mid-decode changes to generation_config.thinking_level or built-in tools (google_search, code_execution, url_context) aren't rejected by server validation. Keep thinking_level and built-in tools unchanged across all segments of a continuation loop.

Additional resources

For more information about Hydrogen, see the following resources: