Home / Articles

Stateful Remote Sandboxes With Antigravity Managed Agents and the GenAI SDK

Antigravity managed agents with the GenAI SDK: keep a remote Ubuntu sandbox alive across turns, re-attach by environment ID and pull the workspace snapshot.

Publisher: REACTAPP.TOP8 min read1737 words

This article is published in English.

Sources: Orchestrating with Antigravity: A Crescendo of Agents (Part 1)

Some developers live in the terminal. If a tool can't be scripted from bash, they skip it, and their daily AI workflow rests on command-line agents such as gemini-cli and its newer sibling antigravity-cli (agy). It's the "BashOps" way of working, as opposed to the "ClickOps" crowd that prefers graphical tools.

That approach hits a wall when agent work grows. Running several coding agents at once, driving multi-turn stateful loops and tracking file changes can mean babysitting six to twelve terminal windows spread over as many virtual desktops, which quickly becomes a mental burden. The first piece of the answer is persistence: giving each agent a workspace that survives between calls. The second, running parallel local subagents safely with git worktrees, is a separate topic.

Here we look at how stateful remote sandboxes work with Google's Antigravity managed agents, using the Google GenAI SDK and the preview agent model antigravity-preview-05-2026. You'll see how to re-attach to a container environment and how to pull the agent's workspace back to your own machine from a local shell. The architecture and hosted side of managed agents is covered well elsewhere, for instance in Philipp Schmid's write-up of how managed agents work under the hood. The focus here is driving them programmatically to build automation loops.

Stateful agents in practice

In a traditional agent API call there's no memory. You send a prompt, the agent replies, and the workspace vanishes. If you want it to edit a file it made last turn, you have to send the whole file back in the prompt. That costs tokens, adds latency and makes multi-turn code generation slow and expensive.

Antigravity's answer is the stateful remote sandbox. Pass "remote" as the environment and the SDK takes care of the following:

  1. it creates a private, locked-down Ubuntu container in Google Cloud;
  2. the agent executes inside it;
  3. the container stays up after the call, and an environment_id comes back to identify it;
  4. any later call can attach to that same container and find the filesystem untouched.

The easiest way to believe it is to see the code.

Example: an IPO analyst driven from Python

To show the idea, here is a script that orchestrates a stateful, three-turn agent session. The agent plays the role of an IPO analyst. Turn one has it research a company's public listing and save a Markdown report. Turn two reconnects to the same container, opens that report and rebuilds it as an HTML dashboard with its own stylesheet, and produces a matching image. In the third turn the script downloads a snapshot of the whole workspace.

The stateful features are reached through the standard Google GenAI Python SDK, by calling the preview agent model with environment="remote".

import os
import requests
import tarfile
from google import genai

client = genai.Client()
print("🚀 Turn 1: Launching SRE/Financial Agent in remote Ubuntu Sandbox...")
# Turn 1: Launch agent to research and write a report in a remote sandbox
interaction_1 = client.interactions.create(
    agent="antigravity-preview-05-2026",
    input="Research SpaceX IPO and save report as spacex-report.md.",
    environment="remote"  # Launches a remote Ubuntu sandbox
)
env_id = interaction_1.environment_id
print(f"✅ Turn 1 Complete. Container Environment ID: {env_id}")

print("\n🔄 Turn 2: Re-attaching to same container and converting to HTML...")
# Turn 2: Re-attach to the SAME sandbox and preserve conversation memory
interaction_2 = client.interactions.create(
    agent="antigravity-preview-05-2026",
    environment=env_id,                              # ← Re-attaches to same sandbox
    previous_interaction_id=interaction_1.id,       # ← Preserves conversation memory
    input="Convert that spacex-report.md file into a clean index.html webpage" +
          " with styling and generate a custom nanobanana image."
)
print("✅ Turn 2 Complete.")

print("\n📦 Turn 3: Downloading the entire container snapshot (.tar) locally...")
# Turn 3: Download the entire sandbox environment state (.tar) locally
api_key = os.environ.get("GEMINI_API_KEY")
response = requests.get(
    f"https://generativelanguage.googleapis.com/v1beta/files/environment-{env_id}:download",
    params={"alt": "media"},
    headers={"x-goog-api-key": api_key},
)
tar_path = "snapshot_env.tar"
with open(tar_path, "wb") as f:
    f.write(response.content)
print(f"✅ Snapshot downloaded to {tar_path}. Extracting...")
with tarfile.open(tar_path) as tar:
    tar.extractall(path="./workspace_extract")
# Wow! We've dumped the remote agent workspace locally!
print("🎉 Workspace extracted successfully! Check ./workspace_extract/")

What the script does, step by step:

  1. Spin up and investigate. Google starts a container on an Ubuntu machine, a real instance with a real disk, and the agent begins its research.
  2. Continue and convert. The second turn changes the Markdown to HTML. That's a silly split, since the first turn could have produced HTML directly, but it proves you can park the work today and resume tomorrow with the session intact, perhaps even from a chat app.
  3. Pull results locally. This is the part that makes it feel real. The container holds an actual workspace, possibly with a cloned repository and added unit tests. In this run it contained the Markdown report from turn one, an index.html, an image file and a stylesheet from turn two.

Opening index.html in a browser shows the generated dashboard, including a bull-versus-bear section for the investment case.

Example: prototyping a small kids' game

The same pattern works for building software. Consider a clock-reading game for children. The problem it solves is concrete: a child who is strong at arithmetic can still stumble on mapping an analog clock face, say one pointing at 19:45, to the digital string for that time. Once the digital form is in hand, calculating differences like 08:45 plus or minus 20 minutes is easy. The obstacle is purely visual, so a game that bridges the two is useful.

The ambition was a cross-platform mobile game in Flutter, partly because frequent travel makes an app that works offline on a phone during a flight valuable. To start, a single stateful agent script produced the first prototype. It was given a detailed multi-step prompt telling it to read a product requirements file, implement the game, start a local server, take a screenshot and open a pull request on GitHub.

The core of that script uses the google-genai SDK to provision the remote sandbox, mount the git repository, and then download and extract the final workspace snapshot:

from google import genai
import requests, os

client = genai.Client()
api_key    = os.environ["GEMINI_API_KEY"]
gh_token   = os.environ.get("GITHUB_TOKEN")  # optional: enables the agent to push a PR

# Mount the git repo AND inject the GitHub token as a file into the sandbox
sources = [
    {"type": "repository",
     "source": "https://github.com/palladius/orologia.io",
     "target": "/workspace"},

    {"type": "inline",
     "target": "/workspace/.github_token",
     "content": gh_token},  # ← secret injection!
]
# The prompt tells the agent exactly what to build
prompt = """
You are an expert full-stack developer agent.

The repo orologia.io is mounted at /workspace.
1. Read docs/PRD.md and implement a beautiful clock-learning game...
2. Make it stunning: analog clock with rotating hands, digital display, ..
3. Optionally screenshot it, then commit and open a PR using the token
   at /workspace/.github_token.
"""  # Full prompt: https://github.com/palladius/orologia.io/blob/main/solutions/20260615-antigravity-managed-agents/run-agent-prototype.py
# Launch remote stateful sandbox agent
interaction = client.interactions.create(
    agent="antigravity-preview-05-2026",
    input=prompt,
    environment={"type": "remote", "sources": sources}
)
# Download final snapshot locally
url = ...
response = requests.get(url, headers={"x-goog-api-key": api_key}, params={"alt": "media"})

Instead of jumping straight to a complex Flutter app, the agent wrote a fast throwaway prototype in vanilla HTML, CSS and JavaScript. Given a description of the clock behaviour and its feedback loop in a single turn, the agent produced a responsive clock app in about a minute. It also designed interactive options that match an analog time to several digital answer buttons.

That demonstrated the value of single-agent rapid prototyping. Scaling beyond one prototype is a different problem, because implementing the full Flutter game with several subagents at once is where a plain CLI loop starts to struggle. Handling that safely calls for isolated git worktrees and a dedicated orchestration setup.

What remote agents are good for

The natural question is what these remote agents are actually good for. You could argue that everything is more comfortable on localhost. A more interesting reading treats them as the first step toward "Dockerfiles for agents". You begin by experimenting locally, then gradually build an agent container with your own scripts, a tool configuration folder and perhaps a cloud service-account key. Before long you have a repeatable, self-contained, secure sandbox where an agent can reach the internet, with git clone and API keys as a powerful combination.

Practical guidance:

  • Skip it for a one-off investigation. The web interface or a local CLI is much faster.
  • Use it for repeatable workflows where the setup is far bigger than the final prompt. If you run five prompts and the first four never change while the fifth always does, that is the sweet spot.
  • Try the Gemini API command-line tooling too, which Philipp Schmid describes in his managed agents developer guide.

An example of the repeatable case is a containerised family travel planner where you only state the destination, the dates and the constraints. It behaves a bit like a fine-tuned model, except that the whole filesystem is observable and adjustable, so you can download the generated index.html afterwards. In one run, an agent built a full island travel plan, with an itinerary map and verifiable booking links, from three prompts of which the first two stayed constant.

Cautions before you adopt it

A few sensible checks apply to any setup like this:

  • A snapshot may contain everything the agent saw, including cloned repositories and any credentials you mounted. Treat the tar file as sensitive and keep service-account keys out of sandboxes unless they are strictly needed.
  • The model name here is a dated preview. Pin it deliberately and expect behaviour and endpoints to change.
  • Keep the environment ID somewhere durable. Losing it means losing the ability to re-attach.
  • Check what a stateful sandbox costs and how long it lives before relying on "come back tomorrow" workflows.