Long decode lets Gemini 4 Argon generate past the single-request output limit for deep reasoning tasks, up to the unified 1M-token context window (1,048,576 tokens shared across input, thinking, and output).
Changing the model ID alone doesn't enable long decode. Without additional setup, output stops at 64K tokens for streaming calls and 32K tokens for non-streaming calls. The fastest way to turn on long decode is to upgrade the Google GenAI SDK and set max_output_tokens greater than 65,536. This guide explains how long decode works, when to use it, and how to turn it on with generateContent.
How long decode works
A single streaming or SDK request generates up to 64K tokens, and a non-streaming REST request generates up to 32K tokens. When a response needs more tokens, the model generates it across multiple request-and-response hops that each continue from where the previous hop stopped.
- Unified input and output token limit: Input, thinking, function calls, and the final response share one 1M-token window. Output can use up to 1,048,576 minus your input tokens.
- A cap on each hop: One hop returns up to 65,536 output tokens. Non-streaming REST requests return up to 32,768.
- A continuation signal: If the model reaches the cap and has tokens left, the response ends with
finish_reason: CONTINUATIONand acontinuation_token. - The next hop: The client sends the same request again with the token. The model continues from where it stopped.
- One total for all hops:
max_output_tokenssets the total thinking and output tokens for all hops together. - A stop signal: When the model uses all of
max_output_tokens, the response ends withfinish_reason: MAX_TOKENS.
On hard problems, a hop can spend all of its tokens on internal thinking and return empty text with a continuation_token. This is normal, and the final answer arrives in later hops.
Default output limits
Without long decode, a single request stops at these per-request limits:
- Streaming requests and non-streaming requests through the Google GenAI SDK (
generate_content): Default to 64K output tokens. - Direct non-streaming REST calls (
generateContent): Default to 32K output tokens. Settingmax_output_tokensgreater than 32,768 on a non-streaming REST call without acontinuation_tokenreturns a400error.
| How you call the model | Output limit without long decode | Long decode at launch | What to do |
|---|---|---|---|
| Google GenAI SDK, latest version | 64K | Yes, the SDK continues for you | Set max_output_tokens. |
| Google GenAI SDK, older version, non-streaming | 64K | No | Upgrade the SDK. |
REST streamGenerateContent |
64K | Yes, with your own loop | Write a loop. See Option 2. |
REST generateContent |
32K | Yes, with your own loop | Write a loop. See Option 2. |
When to use long decode
Most requests finish within the single-request limit (64K tokens for streaming and SDK calls, or 32K tokens for non-streaming REST calls). Use long decode when a response needs more combined thinking and output tokens than a single request allows. Raising max_output_tokens gives the model a higher ceiling to reason through hard problems, rather than making standard answers longer.
| Workload | Use long decode? | Why |
|---|---|---|
| Hard math, science, research, and formal proofs | Yes | The model can spend more than 64K tokens to explore and check its reasoning. |
| The hardest coding and agentic tasks | Yes | Some tasks need more than 64K tokens of thinking and code in one response. Most coding and agentic tasks finish under 64K. |
| Evaluation harnesses that stop at the output limit | Yes | Long decode prevents cut-off answers when the model spends a whole 64K or 32K request on thinking. |
| Chat, Q&A, summarization, classification, and extraction | No | These tasks finish well under 32K tokens. |
| Requests for a fixed length, such as "write a 700,000-word book" | No | The model does not follow length targets. |
| Agents that call tools in many short turns | No | Each turn is short. Large outputs on each turn fill the unified 1M input and output window fast. |
| Prompts near the 1M input limit | No | Output can use only 1M minus your input. |
| Latency-sensitive requests | No | Long decode can run for several minutes. |
Setting a high max_output_tokens gives the model room to think longer on hard problems, but the model still decides how much to write. To control how much reasoning effort the model uses, set thinking_level.
Turn on long decode
You can run long decode automatically with the Google GenAI SDK (Option 1, recommended for most apps) or write your own continuation loop (Option 2). Both options support the full 1M-token context window.
| Option 1: Google GenAI SDK (recommended) | Option 2: Your own streaming loop | Option 2: Your own non-streaming loop | |
|---|---|---|---|
| Who starts each hop | The SDK. You set max_output_tokens. |
Your code, at each checkpoint or after a dropped stream | Your code, every 32K tokens |
| Tokens per request | 64K per hop | 64K per stream, with a checkpoint every 5K tokens after 32K | 32K per request |
| Time limit per request | 20 minutes | 20 minutes | 20 minutes |
| Storage | No server storage | No server storage | No server storage |
| Best for | Most applications | REST callers and custom harnesses that stream | Simple evaluation harnesses |
The encrypted continuation_token carries the model's state between requests, so nothing is stored on the server.
Option 1: Use the Google GenAI SDK (recommended)
In the latest Google GenAI SDK, automatic_continuation is enabled by default for both streaming and non-streaming calls, so you do not need to set it. When you set max_output_tokens above the per-request cap, the SDK automatically runs the continuation hops and returns one combined response.
Upgrade the SDK.
Python
pip install -U "google-genai>=2.30.1"JavaScript
npm install "@google/genai@>=2.29.1"Set
max_output_tokensgreater than 65,536.Python
from google import genai from google.genai import types client = genai.Client() # Reads GEMINI_API_KEY response = client.models.generate_content( model="gemini-4-argon", contents="Write a complete, rigorous proof of the prime number theorem.", config=types.GenerateContentConfig( max_output_tokens=262_144, # Total thinking and output for all hops thinking_config=types.ThinkingConfig(thinking_level="high"), automatic_continuation=True, # Default. Shown for clarity. ), ) print(response.text) print("Finish reason:", response.candidates[0].finish_reason) print("Prompt size:", response.usage_metadata.initial_prompt_token_count) print("Billed tokens:", response.usage_metadata.total_token_count)JavaScript
import { GoogleGenAI, ThinkingLevel } from "@google/genai"; const ai = new GoogleGenAI({}); // Reads GEMINI_API_KEY const response = await ai.models.generateContent({ model: "gemini-4-argon", contents: "Write a complete, rigorous proof of the prime number theorem.", config: { maxOutputTokens: 262144, // Total thinking and output for all hops thinkingConfig: { thinkingLevel: ThinkingLevel.HIGH }, automaticContinuation: true, // Default. Shown for clarity. }, }); console.log(response.text); console.log("Finish reason:", response.candidates?.[0]?.finishReason); console.log("Prompt size:", response.usageMetadata?.initialPromptTokenCount); console.log("Billed tokens:", response.usageMetadata?.totalTokenCount);
Keep these points in mind:
- Streaming:
generate_content_stream(Python) andgenerateContentStream(JavaScript) also continue for you. If a stream drops after a checkpoint, the SDK resumes from that checkpoint. - Timeouts: Timeouts and retries apply to each hop, not to the full run.
- Manual control: To run the loop yourself, set
automatic_continuation=False(Python) orautomaticContinuation: false(JavaScript). Then follow Option 2. - Usage: The usage fields show the sum of all hops. To get the size of your prompt, read
initial_prompt_token_count. See Count tokens.
Option 2: Write your own loop
Write your own loop if you call REST directly, use a language without the latest SDK, or need full control. You can also refer to our Google GenAI SDK implementations in Python and JavaScript/TypeScript as a reference.
Follow these rules:
- Send the same request on every hop. Send the original
contents,system_instruction,tools, andgeneration_config. Keepmax_output_tokensthe same. - Do not add partial output to
contents. Thecontinuation_tokencarries the model's state, including its thinking. - Send only the latest token. Each token contains all earlier progress.
- Continue while
finish_reasonisCONTINUATION. Stop on any other finish reason. - Join the parts after the last hop. Combine the parts from all hops into one model turn for the conversation history.
Python
from google import genai
from google.genai import types
client = genai.Client() # Reads GEMINI_API_KEY
PROMPT = "Write a complete, rigorous proof of the prime number theorem."
parts = []
token = None
while True:
response = client.models.generate_content(
model="gemini-4-argon",
contents=PROMPT, # The original contents on every request
config=types.GenerateContentConfig(
max_output_tokens=262_144, # The same total on every request
thinking_config=types.ThinkingConfig(thinking_level="high"),
automatic_continuation=False, # You run the loop
continuation_token=token,
),
)
candidate = response.candidates[0]
if candidate.content and candidate.content.parts:
parts.extend(candidate.content.parts)
token = candidate.continuation_token
if candidate.finish_reason != types.FinishReason.CONTINUATION or not token:
break
print("".join(p.text for p in parts if p.text and not p.thought))
print("Finish reason:", candidate.finish_reason)
JavaScript
import { GoogleGenAI, ThinkingLevel } from "@google/genai";
const ai = new GoogleGenAI({}); // Reads GEMINI_API_KEY
const PROMPT = "Write a complete, rigorous proof of the prime number theorem.";
const parts = [];
let token = undefined;
let candidate = undefined;
while (true) {
const response = await ai.models.generateContent({
model: "gemini-4-argon",
contents: PROMPT, // The original contents on every request
config: {
maxOutputTokens: 262144, // The same total on every request
thinkingConfig: { thinkingLevel: ThinkingLevel.HIGH },
automaticContinuation: false, // You run the loop
continuationToken: token,
},
});
candidate = response.candidates?.[0];
if (candidate?.content?.parts) {
parts.push(...candidate.content.parts);
}
token = candidate?.continuationToken;
if (candidate?.finishReason !== "CONTINUATION" || !token) {
break;
}
}
console.log(parts.filter((p) => p.text && !p.thought).map((p) => p.text).join(""));
console.log("Finish reason:", candidate?.finishReason);
REST
# Hop 1: send the request with max_output_tokens.
curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-argon:generateContent" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"role": "user", "parts": [{"text": "Write a complete, rigorous proof of the prime number theorem."}]}],
"generationConfig": {
"maxOutputTokens": 262144,
"thinkingConfig": {"thinkingLevel": "high"}
}
}'
# Hop 2: if finishReason is CONTINUATION, send the same request plus the token.
curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-4-argon:generateContent" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"role": "user", "parts": [{"text": "Write a complete, rigorous proof of the prime number theorem."}]}],
"generationConfig": {
"maxOutputTokens": 262144,
"thinkingConfig": {"thinkingLevel": "high"}
},
"continuationToken": "TOKEN_FROM_HOP_1"
}'
A hop spent entirely on thinking returns empty text with finishReason: "CONTINUATION". Treat this as normal progress and request the next hop:
{
"candidates": [{
"content": {"role": "model", "parts": [{"text": ""}]},
"finishReason": "CONTINUATION",
"continuationToken": "CiQ4ZmQ3..."
}],
"usageMetadata": {
"promptTokenCount": 142,
"candidatesTokenCount": 0,
"thoughtsTokenCount": 32768,
"totalTokenCount": 32910
}
}
Streaming loops need one more rule. After the first 32,768 tokens, the stream sends a checkpoint token every 5,000 tokens. Keep new chunks in a pending list. When a chunk has a continuation_token, move the pending chunks to your committed output and save the token. If the stream drops, discard the pending chunks and resume from the last token. If the stream drops before the first checkpoint, send the original request again.
Set max_output_tokens
max_output_tokens sets the combined limit for thinking and output across all hops. Lowering it doesn't make the model think more concisely, and instead cuts the response off sooner.
| Your workload | Recommended max_output_tokens |
|---|---|
| Existing apps with a limit lower than 32K | Raise it to 32,768. |
| Long coding and agentic tasks | Start at 65,536. |
| Hard math, science, research, and proofs | Test values from 262,144 up to 1,048,576 minus your input tokens. |
To use fewer tokens, lower thinking_level. Use high for the hardest reasoning tasks. Use medium (the default) for most coding and agentic work. Use low for less complex tasks.
Handle long-running requests
Because Gemini 4 Argon thinks longer than Gemini 3.x models on hard problems, you should increase your client timeouts so long requests don't disconnect early.
- Non-streaming calls: The server closes the connection after 10 minutes.
- Streaming calls: The server closes the stream after 20 minutes.
- Client timeouts: Set your HTTP read timeout to 20 minutes. A 3-minute or 5-minute timeout stops the request early.
In Python, set the timeout on the client in milliseconds:
client = genai.Client(http_options=types.HttpOptions(timeout=1_200_000)) # 20 minutes
For jobs that your client polls, the Interactions API runs long decode on the server. See background execution.
Resume when the model uses all output tokens
When a response ends with MAX_TOKENS, it still includes a continuation_token. You have two choices:
- Continue: Send the same request with the token and a higher
max_output_tokens. The value must be above the tokens used so far. Otherwise, the API returns a 400 error. - Start again: Send the original request with a higher
max_output_tokensand no token. You pay for both runs.
Count tokens
With automatic continuation, usage_metadata reports the totals across all hops. The SDK adds up every count field: prompt_token_count, cached_content_token_count, candidates_token_count, thoughts_token_count, and total_token_count.
prompt_token_count adds up the input tokens of every hop. Each hop sends your prompt plus everything generated so far back to the model as input, so the same tokens are counted again in every later hop. For example, with the Google GenAI SDK, a 1,000-token prompt that produces 200,000 tokens of thinking and output takes four hops:
| Hop | Input sent to the model | Input tokens |
|---|---|---|
| 1 | Prompt | 1,000 |
| 2 | Prompt + hop 1 | 66,536 |
| 3 | Prompt + hops 1 and 2 | 132,072 |
| 4 | Prompt + hops 1 to 3 | 197,608 |
| Total | 397,216 |
prompt_token_count reports about 397,000 tokens (with repeated hop inputs automatically discounted 95% by implicit caching), and total_token_count reports about 597,000 tokens, even though the actual context size is only about 201,000 tokens: the 1,000-token prompt plus 200,000 tokens of thinking and output. A non-streaming REST loop uses 32K hops, so it takes seven hops for the same output and reports 695,128 input tokens.
| How you call the model | What usage_metadata shows |
For cost | For the prompt size |
|---|---|---|---|
| Google GenAI SDK, automatic continuation (the default) | Totals across all hops | Read the usage fields as is. | Read usage_metadata.initial_prompt_token_count (Python) or usageMetadata.initialPromptTokenCount (JavaScript). |
SDK with automatic_continuation=False, or REST |
One hop per response | Add each field across hops. | Read prompt_token_count from the first hop. |
prompt_token_count and total_token_count are the sum of every hop, not the size of your context. Don't use them to decide when to summarize or trim your conversation history (context compaction), or to enforce a context limit. To estimate the context size, add your prompt size from the table to candidates_token_count and thoughts_token_count.
Update your agent framework, evaluation tool, or proxy before you run long decode:
- Agents and evaluation tools: If your code compacts context or stops a run at a token limit, use
initial_prompt_token_count(or the first hop'sprompt_token_countin REST) instead of the summedprompt_token_count. Responses that finish in one hop report the same value in both fields, so short tests don't show the problem. - Proxies and gateways that call REST: Each REST response reports only its own hop. Add each field across hops for cost, and keep the first hop's
promptTokenCountas the prompt size. Otherwise, your users see different numbers than SDK users see for the same request. - Logs and serialized responses: The SDK calculates
initial_prompt_token_counton the client. It isn't in the REST response or in the SDK's JSON output, such asmodel_dump(). Save it as a separate value if you need it later.
If you stream in your own loop, usage_metadata is cumulative within each stream. Keep only the last value of each stream, then add the values across hops.
Understand billing
You pay for every token in every hop, including hops that contain only thinking.
- Cache discount: Implicit caching discounts the repeated input in each hop by 95%. Cached input costs $0.10 per 1M tokens instead of $2.00 during the introductory period.
- Cache expiry: The cache expires after 15 to 20 minutes without use. A long pause between hops charges the full input rate again.
- Failed non-streaming hops: You pay only when a response completes. A failed or dropped request costs $0.
- Dropped streams: A stream that drops before 32K tokens costs $0. After that, you pay up to the last checkpoint token, because you can resume from it.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
Output stops at 64K or 32K with CONTINUATION |
The model has tokens left, but nothing continued the request. Upgrade the SDK or add a loop. |
Output stops at 64K or 32K with MAX_TOKENS |
max_output_tokens is not set or is too low. Set it to more than 65,536. |
Empty text with MAX_TOKENS |
The model used all tokens on thinking. Raise max_output_tokens or lower thinking_level. |
| 400: "Continuation token has already used output tokens..." | max_output_tokens is not above the tokens used so far. Raise it. |
Error for thinking_level: "minimal", or for thinking_budget with thinking_level |
Gemini 4 Argon does not support minimal. Use low, medium, or high. Set thinking_level or thinking_budget, not both. |
Warning for thinking_budget, temperature, top_p, or top_k |
Gemini 4 Argon ignores or maps these fields. Use thinking_level, and remove the sampling parameters. |
| Request ends after 3 or 5 minutes | The client timeout is too short. Set it to 20 minutes. |
| Context compaction starts too early | The harness reads summed input. Read initial_prompt_token_count instead. |
Limitations
- OpenAI compatibility endpoint: Long decode is not available. Output stops at the per-request cap.
- Older SDKs: Versions below the minimums in the note do not continue automatically.
- Length: The model does not follow token-length or word-count targets.
Checklist
- Upgrade the Google GenAI SDK to the minimum version.
- Set
max_output_tokensgreater than 65,536. - Use
thinking_level(low,medium, orhigh), notthinking_budget. - Set HTTP read timeouts to 20 minutes.
- Use
initial_prompt_token_countfor context size and compaction. - Run one prompt as a test before a large evaluation.