How to Migrate Gemini Deep Research Before October 23
Your Deep Research agent has an expiry date, and it is Friday, October 23, 2026. Google's deprecations page lists deep-research-pro-preview-12-2025 for shutdown that day, with deep-research-preview-04-2026 as the replacement.
This guide shows how to migrate Gemini Deep Research in four steps: pick an agent, swap the agent ID, fix your output parsing, and prove the new reports are good enough in a one-sprint spike.
1. Choose between the speed and Max agents
Both new agents are in preview and run only through the Interactions API, not generate_content. The Deep Research docs describe them like this:
deep-research-preview-04-2026: built for speed, suited to streaming into a client UI. The docs estimate about $1 to $3 per task.deep-research-max-preview-04-2026: aims for maximum comprehensiveness. About $3 to $7 per task.
Treat those preview-rate estimates as a budget guide, not a quote. If a person is watching a spinner, start with the speed agent. If the report lands in an inbox overnight, try Max. Step 4 settles it with your own prompts.
2. Swap the agent ID in your Interactions API call
The migration is one parameter. Find every reference first:
git grep -n "deep-research-pro-preview-12-2025"
Then move the ID into configuration, so a rollback is an environment variable and not a deploy:
import os
from google import genai
client = genai.Client() # reads your API key from the environment
AGENT = os.environ.get("DEEP_RESEARCH_AGENT", "deep-research-preview-04-2026")
job = client.interactions.create(
input="Research the history of Google TPUs.",
agent=AGENT,
background=True,
)
print(job.id)
The call returns right away with an interaction ID. background=True is required for agents, and the work happens server side. Collaborative planning, MCP servers and File Search are new in the 04-2026 agents but opt-in, so ignore them for a like-for-like swap.
3. Poll the interaction and read the steps array
Polling is easy. The part that bites is the response shape. The Interactions API replaced its flat outputs array with a steps array, and the migration guide says the legacy schema was removed on June 8, 2026, with Python and JavaScript SDKs 2.0.0 and later on the new one. Any code still reading outputs[-1].text needs to change.
import time
def wait_for_report(interaction_id, timeout_s=3900, every_s=10):
deadline = time.time() + timeout_s
while time.time() < deadline:
job = client.interactions.get(interaction_id)
if job.status == "completed":
# the last step is the final model output; keep only text items
return "\n".join(
item.text for item in job.steps[-1].content if item.type == "text"
)
if job.status == "failed":
raise RuntimeError(f"Deep Research failed: {job.error}")
time.sleep(every_s)
raise TimeoutError(f"No result after {timeout_s}s")
The 65-minute timeout allows for the docs' 60-minute cap. Filtering by type matters: the final step can also carry image items when your prompt asks for charts. If your parser wants text only, set visualization to "off" in agent_config.
The same flow over REST:
curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{"input": "Research the history of Google TPUs.", "agent": "deep-research-preview-04-2026", "background": true}'
curl -s "https://generativelanguage.googleapis.com/v1beta/interactions/<interaction-id>" \
-H "x-goog-api-key: $GEMINI_API_KEY"
4. Compare old and new reports side by side
The code change is small; what you don't know is whether the new reports are good enough and affordable. This script starts every prompt on every agent in the background, then polls them all:
import json
import re
import time
from google import genai
client = genai.Client()
AGENTS = {
"speed": "deep-research-preview-04-2026",
"max": "deep-research-max-preview-04-2026",
"legacy": "deep-research-pro-preview-12-2025", # baseline, gone after Oct 23
}
PROMPTS = {
"q1": "<a real prompt from production>",
"q2": "<a real prompt from production>",
"q3": "<a real prompt from production>",
}
jobs = {}
for pid, prompt in PROMPTS.items():
for label, agent in AGENTS.items():
job = client.interactions.create(input=prompt, agent=agent, background=True)
jobs[f"{pid}/{label}"] = {"id": job.id, "t0": time.time()}
results = {}
deadline = time.time() + 3900
while len(results) < len(jobs) and time.time() < deadline:
for key, meta in jobs.items():
if key in results:
continue
job = client.interactions.get(meta["id"])
if job.status == "completed":
text = "\n".join(i.text for i in job.steps[-1].content if i.type == "text")
results[key] = {
"seconds": round(time.time() - meta["t0"]),
"words": len(text.split()),
"distinct_urls": len(set(re.findall(r"https?://\S+", text))),
"text": text,
}
elif job.status == "failed":
results[key] = {"error": str(job.error)}
time.sleep(15)
with open("deep_research_compare.json", "w") as f:
json.dump(results, f, indent=2)
Three prompts on the two new agents is six tasks, roughly $12 to $30 at the docs' estimates. The pages I checked give no figure for the legacy agent, so if you store old production reports, reuse them as the baseline.
The numbers only explain; a human decides. Have a reviewer check that claims match their citations, that no section went missing, and that the length suits your readers.
Scope the migration as a one-sprint spike
The unknown here is quality and cost, which is what a spike is for.
- Spike: choose and verify the Deep Research replacement agent.
- Timebox: three working days, finished by Friday, October 16.
- Done when: parsing reads
stepsand passes one completed and one failed run; at least three real prompts are compared on both new agents with a named reviewer's sign-off; the agent ID comes from config; the speed-or-Max decision is recorded.
Ship by Wednesday, October 21, and keep Thursday and Friday free for a rollback. If your sprint ends after the 23rd, pull the spike in now.
Gotchas
- No structured output. The docs say the agent doesn't support structured outputs or custom function-calling tools (remote MCP servers are allowed). If downstream code expects JSON, add a separate extraction step.
- Storage is required.
background=Truerequiresstore=True, so don't switch storage off. - Long runs. Tasks can take up to 60 minutes, though most finish within 20. Check any gateway or job timeout shorter than that.
- Check the citations. The docs warn the agent can hit malicious pages, so review sources before reports reach customers.
A dated preview agent will vanish again, so the habit worth keeping is an agent ID in config, a comparison set you can rerun, and a rollback ready before the deadline.