ANTIGRAVITY LABJP
Articles/Integrations
Integrations/2026-09-20Intermediate

antigravity-preview-05-2026 shuts down October 5: which setups need more than a string swap

The shutdown date for antigravity-preview-05-2026 is set for October 5, and the official page gives you the date and the successor name, nothing more. If you only read output_text, swapping the string is the whole migration. If you read steps, it is not.

Managed Agents5Gemini API5Antigravity374Migration8Python16

I reopened the deprecations page on a Sunday morning and found a date sitting in the Managed agents row. antigravity-preview-05-2026 shuts down on October 5, and the recommended successor is antigravity-preview-09-2026.

My first instinct was to open the successor's documentation. Read what changed, I thought, and the places I need to fix will become obvious.

An hour later I still could not point at a single line of my own code. I had the order backwards. Count what you depend on before you read what they changed. Once I flipped the order, the work took about fifteen minutes.

The official page gives you two rows and nothing else

Here is what the Managed agents section of the Gemini API deprecations page actually says.

AgentRelease dateShutdown dateRecommended replacement
antigravity-preview-09-2026September 17, 2026No shutdown date announced
antigravity-preview-05-2026May 19, 2026October 5, 2026antigravity-preview-09-2026

A note on the same page explains that the listed date is the earliest possible shutdown date, and that the exact date will be communicated with advance notice. In practice: it will not come sooner.

That is the end of what the table tells you. A side-by-side of how built-in tool names or argument keys differ between the old and new harness is not on any official page I could find. Plenty of secondary write-ups quote specifics, and some of them may well be right — but copying an unverified detail into your own runbook means you are the one holding the bag on migration day.

So this piece covers the one thing you can decide without that table.

If you only read output_text, the string swap is the whole job

An Interactions API response puts the final text in interaction.output_text. Separately, interaction.steps lists what the agent did along the way.

Which one your code reads is the entire fork in the road.

# The shallow side. Nothing but the final output.
interaction = client.interactions.create(
    agent="antigravity-preview-05-2026",
    input="Summarize this week's changes in three lines",
    environment="remote",
)
print(interaction.output_text)

If this is your shape, change the agent string and you are done. Whatever happened to tool names or argument spellings stayed inside the sandbox; none of it reaches you.

One thing worth adding while you are in there. The successor's default model is gemini-3.8-flash, and that default applies whenever you omit agent_config. If you care which model runs, this is a good moment to say so out loud.

interaction = client.interactions.create(
    agent="antigravity-preview-09-2026",
    input="Summarize this week's changes in three lines",
    environment="remote",
    agent_config={
        "type": "antigravity",
        "model": "gemini-3.8-flash",  # This is the default anyway — writing it down helps the next reader
    },
)

If you read steps, count the names you lean on first

The other shape interprets the intermediate steps yourself. Most people who wrote this did it for a good reason: they wanted an audit trail, or a notification when a particular tool ran.

# The deep side. This reaches into the step contents.
for step in interaction.steps:
    if step.type == "function_call" and step.name == "write_to_file":
        notify("a file was written: " + str(step.arguments))

The literal in step.name, and the spelling of the keys in step.arguments. Every place that leans on those two is a place that can go quiet after the switch. Nothing raises. The condition simply stops matching, and you find out days later through the vague feeling that the notifications stopped.

Start by counting what you actually depend on. This function takes a response object and returns the set of tool names that appeared, along with the argument keys each one used.

def collect_tool_surface(interaction):
    """Collect the tool names seen in steps, plus the argument keys each one used.
 
    Shape of the return value: a key like write_to_file mapping to a set of
    argument names. Call it on the same input before and after the switch and
    diff the two results.
    """
    surface = {}
    for step in getattr(interaction, "steps", []) or []:
        if getattr(step, "type", None) != "function_call":
            continue
        name = getattr(step, "name", None)
        if not name:
            continue
        args = getattr(step, "arguments", None) or {}
        if not isinstance(args, dict):
            args = {}
        surface.setdefault(name, set()).update(args.keys())
    return surface

The getattr calls are deliberate. SDK versions add and drop step attributes, and a migration-checking tool that breaks because of a migration is not much use.

Run the same request through both agents before you switch

With no published diff table, the most reliable move is to run your own input through both agents and lay the responses side by side. Both are alive until the shutdown date, which makes this a check with an expiry on it.

from google import genai
 
client = genai.Client(api_key="YOUR_API_KEY")
 
PROMPT = "Read one Markdown file under docs, pull out its headings, and write them to summary.txt"
 
 
def run(agent_name):
    interaction = client.interactions.create(
        agent=agent_name,
        input=PROMPT,
        environment="remote",
    )
    return collect_tool_surface(interaction)
 
 
old = run("antigravity-preview-05-2026")
new = run("antigravity-preview-09-2026")
 
for name in sorted(set(old) | set(new)):
    if name not in new:
        print("[gone] " + name + " args: " + str(sorted(old[name])))
    elif name not in old:
        print("[new] " + name + " args: " + str(sorted(new[name])))
    else:
        dropped = sorted(old[name] - new[name])
        added = sorted(new[name] - old[name])
        if dropped or added:
            print("[args changed] " + name + " dropped: " + str(dropped) + " added: " + str(added))
 
# Sample output — which tools appear depends on what you ask for
# [gone] write_to_file args: ['content', 'path']
# [new] WriteToFile args: ['CodeContent', 'TargetFile']

Do not draw conclusions from a single run. Agents do not take identical paths every time, so vary the request two or three ways, then pay attention only to names that disappear consistently. If one of those names is a literal your code branches on, you have found your fix.

One more thing that catches people. Filesystem tools are enabled automatically once you set environment, and they execute inside the sandbox. They still show up as function_call steps, but you are not expected to return results for them. If you hand-rolled your own polling loop, confusing those two will leave you waiting forever — so give your requires_action handling a second look before the switch, not after.

A few constraints worth confirming while you are in there

Even without a diff table, the successor's own documentation states several constraints plainly. Reading them now costs a few minutes and saves the particular kind of afternoon where nothing works and nothing explains why.

AreaHow the successor handles it
Default modelgemini-3.8-flash, with 3.7, 3.6, 3.5-flash and 3.5-flash-lite selectable through agent_config.model
Generation parameterstemperature, top_p, top_k, stop_sequences and max_output_tokens return a 400
Structured outputsNot supported. If something downstream expects JSON, that is the part to revisit
Function callingStateful only. You continue a turn with previous_interaction_id; hand-assembled history is not accepted
Budget exhaustionExceeding agent_config.max_total_tokens leaves the interaction at status: incomplete
Context compactionHappens automatically around the 135k-token mark
MCP serversSSE transport is not supported, and server names must match lowercase letters, digits, hyphens and underscores

The generation-parameter row is the one that caught me. An old call site still carrying temperature fails the moment you point it at the successor. As failures go, that one is generous: it happens while you are watching, rather than at 3 a.m. on shutdown day.

The stateful-only rule deserves a second look too, particularly if you built your loop to be restartable. Anything that reconstructs the conversation from stored messages rather than carrying previous_interaction_id forward is going to need rework, and that rework is larger than a string swap. Better to know now, while the old agent is still there to compare against.

If you register MCP servers, read that last row carefully. A server name that worked as a label elsewhere in your stack can be rejected here on a character you never thought about, and the failure arrives at registration time rather than as something obvious in the response. I now keep MCP server names deliberately boring across every project for exactly this reason: lowercase, hyphens, nothing clever. It is a small rule that has paid for itself several times over.

None of the above is a migration step on its own. Taken together, though, these six rows are the difference between a switch that lands in an afternoon and one that leaks into the following week.

Do it on a calm day, well before October 5

For a long time my habit with any upstream change was to start on their side: read the release notes, read the migration guide, then go looking for my own code afterwards. It never worked. I would finish reading with nothing to act on and end up grepping my repository anyway.

These days the order is fixed. Count the names I lean on, then read what they changed — the same order I use for the automation behind the Lab sites and for plugin updates on the client sites I maintain. As an indie developer with more things running than I can hold in my head, that ordering has quietly saved me more time than any checklist.

If you do one thing today, search your repository for the word steps. No hits means you change the agent string and move on. Hits mean you should put the comparison script above on your calendar for some point this week.

The quietest way to avoid a scramble on shutdown day is to look at both responses side by side while both still answer.

I wrote about where to stop a session that started without the tools it needed in When a session starts with MCP tools missing, where do you stop?, and the model-ID equivalent of this inventory is in The October 16 date I could not find — taking stock of Gemini model shutdown dates yourself.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Agents & Manager2026-06-12
Running Gemini's Managed Agents API: Where Cloud Execution Ends and My Local Agents Begin
A hands-on record of launching Gemini's Managed Agents (public preview) from Python — polling, artifact retrieval, and a cost guard — plus five criteria I use to decide what stays on my local CLI agents.
Integrations2026-05-14
Antigravity × Gemma 4 API Implementation Guide — Build from Zero with Python & TypeScript
Call Gemma 4 API from Antigravity IDE. Python & TypeScript code examples, streaming, error handling, and Next.js integration — production-ready guide.
Integrations2026-04-24
Antigravity × Gemini File API: A Production Guide to Feeding Long-Form Media (Video, Audio, PDF) into Your Agents
Feed hour-long videos, podcasts, and book-length PDFs into your Antigravity agents with the Gemini File API. A practical, production-oriented pipeline with timestamped highlight extraction, idempotent uploads, cost accounting, and failure recovery.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links