Environments are managed Linux sandboxes that give agents an isolated place to execute code and persist files. They are decoupled from interaction context, so you can reuse the same environment across multiple interactions or start fresh at any time.
The following example demonstrates how to create an interaction with a fresh remote environment and retrieve its ID:
Python
from google import genai
client = genai.Client()
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Install pandas and matplotlib, verify the imports, and print the versions.",
environment="remote",
)
print(f"Environment ID: {interaction.environment_id}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Install pandas and matplotlib, verify the imports, and print the versions.",
environment: "remote",
});
console.log(`Environment ID: ${interaction.environment_id}`);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Install pandas and matplotlib, verify the imports, and print the versions."))
.environment(CreateAgentInteractionEnvironment.of("remote"))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println("Environment ID: " + interaction.environmentId().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "Install pandas and matplotlib, verify the imports, and print the versions.",
"environment": "remote"
}'
The environment parameter
The environment parameter accepts three forms:
| Form | Example | When to use |
|---|---|---|
"remote" |
environment="remote" |
Provision a fresh sandbox. |
| Environment ID | environment="env_abc123" |
Reuse an existing sandbox with all its files and packages. |
| Config object | environment={...} |
Provision a new sandbox with sources, network rules, or both. |
The following examples demonstrate the three ways of using the environment
parameter.
Python
from google import genai
client = genai.Client()
# Fresh sandbox
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Write a hello world script.",
environment="remote",
)
# Reuse an existing sandbox
interaction_2 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Modify the script to accept a name argument.",
environment=interaction.environment_id,
previous_interaction_id=interaction.id,
)
# New sandbox with sources
interaction_3 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="List all files and summarize the project.",
environment={
"type": "remote",
"sources": [
{
"type": "repository",
"source": "https://github.com/octocat/Spoon-Knife",
"target": "/workspace/spoon-knife",
}
],
},
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
// Fresh sandbox
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Write a hello world script.",
environment: "remote",
});
// Reuse an existing sandbox
const interaction2 = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Modify the script to accept a name argument.",
environment: interaction.environment_id,
previous_interaction_id: interaction.id,
});
// New sandbox with sources
const interaction3 = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "List all files and summarize the project.",
environment: {
type: "remote",
sources: [
{
type: "repository",
source: "https://github.com/octocat/Spoon-Knife",
target: "/workspace/spoon-knife",
},
],
},
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
Client client = new Client();
// Fresh sandbox
CreateAgentInteraction params1 = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Write a hello world script."))
.environment(CreateAgentInteractionEnvironment.of("remote"))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params1)).interaction().get();
// Reuse an existing sandbox
CreateAgentInteraction params2 = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Modify the script to accept a name argument."))
.environment(CreateAgentInteractionEnvironment.of(interaction.environmentId().orElse("")))
.previousInteractionId(interaction.id().orElse(""))
.build();
Interaction interaction2 = client.interactions.create(CreateInteractionRequestBody.of(params2)).interaction().get();
// New sandbox with sources
Environment env3 = Environment.builder()
.sources(List.of(
Source.builder()
.type(SourceType.REPOSITORY)
.source("https://github.com/octocat/Spoon-Knife")
.target("/workspace/spoon-knife")
.build()
))
.build();
CreateAgentInteraction params3 = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("List all files and summarize the project."))
.environment(CreateAgentInteractionEnvironment.of(env3))
.build();
Interaction interaction3 = client.interactions.create(CreateInteractionRequestBody.of(params3)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
# Fresh sandbox
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": [{"type": "text", "text": "Write a hello world script."}],
"environment": "remote"
}'
# Reuse an existing sandbox (replace $ENV_ID and $INTERACTION_ID with values from the previous response)
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d "{
\"agent\": \"antigravity-preview-05-2026\",
\"input\": [{\"type\": \"text\", \"text\": \"Modify the script to accept a name argument.\"}],
\"environment\": \"$ENV_ID\",
\"previous_interaction_id\": \"$INTERACTION_ID\"
}"
# New sandbox with sources
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": [{"type": "text", "text": "List all files and summarize the project."}],
"environment": {
"type": "remote",
"sources": [
{
"type": "repository",
"source": "https://github.com/octocat/Spoon-Knife",
"target": "/workspace/spoon-knife"
}
]
}
}'
Configure an environment
One way to set up an environment is to tell the agent what you need installed.
It handles dependency resolution and troubleshooting. Once the environment is
ready, save the environment_id and reuse it.
Python
from google import genai
client = genai.Client()
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Install pandas, matplotlib, and seaborn. Verify all imports work and print the installed versions.",
environment="remote",
)
# Reuse the configured environment
interaction_2 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Clone https://github.com/octocat/Spoon-Knife into /workspace/tools. Run the test suite and fix any missing dependencies.",
environment=interaction.environment_id,
previous_interaction_id=interaction.id,
)
# Reuse the configured environment
interaction_3 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Using the tools in /workspace/tools, list the files.",
environment=interaction.environment_id,
previous_interaction_id=interaction_2.id,
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Install pandas, matplotlib, and seaborn. Verify all imports work and print the installed versions.",
environment: "remote",
});
const interaction2 = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Clone https://github.com/octocat/Spoon-Knife into /workspace/tools. Run the test suite and fix any missing dependencies.",
environment: interaction.environment_id,
previous_interaction_id: interaction.id,
});
const interaction3 = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Using the tools in /workspace/tools, list the files.",
environment: interaction.environment_id,
previous_interaction_id: interaction2.id,
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
CreateAgentInteraction params1 = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Install pandas, matplotlib, and seaborn. Verify all imports work and print the installed versions."))
.environment(CreateAgentInteractionEnvironment.of("remote"))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params1)).interaction().get();
// Reuse the configured environment
CreateAgentInteraction params2 = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Clone https://github.com/octocat/Spoon-Knife into /workspace/tools. Run the test suite and fix any missing dependencies."))
.environment(CreateAgentInteractionEnvironment.of(interaction.environmentId().orElse("")))
.previousInteractionId(interaction.id().orElse(""))
.build();
Interaction interaction2 = client.interactions.create(CreateInteractionRequestBody.of(params2)).interaction().get();
// Reuse the configured environment
CreateAgentInteraction params3 = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Using the tools in /workspace/tools, list the files."))
.environment(CreateAgentInteractionEnvironment.of(interaction.environmentId().orElse("")))
.previousInteractionId(interaction2.id().orElse(""))
.build();
Interaction interaction3 = client.interactions.create(CreateInteractionRequestBody.of(params3)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
# Create interaction
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "Install pandas, matplotlib, and seaborn. Verify all imports work and print the installed versions.",
"environment": "remote"
}'
Mount from a source
If you know exactly what files the agent needs, mount them in a single call
instead of iterating. The environment config object accepts a sources array
with three types:
| Source type | type value |
Description | Limit |
|---|---|---|---|
| Git repository | repository |
Clones a repository from a URL into the sandbox at target. |
500 MB |
| Cloud Storage | gcs |
Copies a file or directory from Cloud Storage into the sandbox at target. |
2 GB |
| Inline content | inline |
Writes raw text content to a file in the sandbox at target. |
1 MB per file, 2 MB total |
Python
from google import genai
client = genai.Client()
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="List all files under /workspace and describe what you find.",
environment={
"type": "remote",
"sources": [
{
"type": "repository",
"source": "https://github.com/octocat/Spoon-Knife",
"target": "/workspace/spoon-knife",
},
{
"type": "gcs",
"source": "gs://cloud-samples-data/bigquery/us-states/",
"target": "/workspace/gcs-data",
},
{
"type": "inline",
"content": "# Project Notes\n\n- Analyze state population data\n- Create visualizations\n",
"target": "/workspace/notes/readme.md",
},
],
},
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "List all files under /workspace and describe what you find.",
environment: {
type: "remote",
sources: [
{
type: "repository",
source: "https://github.com/octocat/Spoon-Knife",
target: "/workspace/spoon-knife",
},
{
type: "gcs",
source: "gs://cloud-samples-data/bigquery/us-states/",
target: "/workspace/gcs-data",
},
{
type: "inline",
content: "# Project Notes\n\n- Analyze state population data\n- Create visualizations\n",
target: "/workspace/notes/readme.md",
},
],
},
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
Client client = new Client();
Environment env = Environment.builder()
.sources(List.of(
Source.builder()
.type(SourceType.REPOSITORY)
.source("https://github.com/octocat/Spoon-Knife")
.target("/workspace/spoon-knife")
.build(),
Source.builder()
.type(SourceType.GCS)
.source("gs://cloud-samples-data/bigquery/us-states/")
.target("/workspace/gcs-data")
.build(),
Source.builder()
.type(SourceType.INLINE)
.content("# Project Notes\n\n- Analyze state population data\n- Create visualizations\n")
.target("/workspace/notes/readme.md")
.build()
))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("List all files under /workspace and describe what you find."))
.environment(CreateAgentInteractionEnvironment.of(env))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
# Create interaction with sources
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "List all files under /workspace and describe what you find.",
"environment": {
"type": "remote",
"sources": [
{
"type": "repository",
"source": "https://github.com/octocat/Spoon-Knife",
"target": "/workspace/spoon-knife"
},
{
"type": "gcs",
"source": "gs://cloud-samples-data/bigquery/us-states/",
"target": "/workspace/gcs-data"
},
{
"type": "inline",
"content": "# Project Notes\n\n- Analyze state population data\n- Create visualizations\n",
"target": "/workspace/notes/readme.md"
}
]
}
}'
You can combine both approaches: mount known sources declaratively, then iterate
with follow-up interactions to install packages or run setup scripts. You can't
set root (/) as target when adding a custom source, you must always specify a
sub-directory.
Hooks
You can also mount a .agents/hooks.json configuration file and custom interception scripts into the sandbox to enforce security guardrails or run automated validations whenever tools execute. For schema definitions and code examples, see Hooks.
Private sources
You can also download from private GitHub repositories or private Cloud Storage buckets by adding the credentials in the network configuration:
For private Git repositories, use Basic authentication with your
GitHub Personal Access Token
(PAT).
Encode the token using x-oauth-basic as the username:
echo -n "x-oauth-basic:ghp_YourPATHere" | base64
Python
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Run the test for my backend app and fix any issue.",
environment={
"type": "remote",
"sources": [
{
"type": "repository",
"source": "https://github.com/your-org/backend",
"target": "/backend-app"
}
],
"network": {
"allowlist": [
{
"domain": "github.com",
"transform": {
"Authorization": "Basic YOUR_BASE64_TOKEN"
}
},
{
"domain": "*"
}
]
}
}
)
JavaScript
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Run the test for my backend app and fix any issue.",
environment: {
type: "remote",
sources: [
{
type: "repository",
source: "https://github.com/your-org/backend",
target: "/backend-app"
}
],
network: {
allowlist: [
{
domain: "github.com",
transform: {
"Authorization": "Basic YOUR_BASE64_TOKEN"
}
},
{
domain: "*"
}
]
}
},
});
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
Environment env = Environment.builder()
.sources(List.of(
Source.builder()
.type(SourceType.REPOSITORY)
.source("https://github.com/your-org/backend")
.target("/backend-app")
.build()
))
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("github.com")
.transform(Transform.of(Map.of(
"Authorization", "Basic YOUR_BASE64_TOKEN"
)))
.build(),
AllowlistEntry.builder()
.domain("*")
.build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Run the test for my backend app and fix any issue."))
.environment(CreateAgentInteractionEnvironment.of(env))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "Run the test for my backend app and fix any issue.",
"environment": {
"type": "remote",
"sources": [
{
"type": "repository",
"source": "https://github.com/your-org/backend",
"target": "/backend-app"
}
],
"network": {
"allowlist": [
{
"domain": "github.com",
"transform": {
"Authorization": "Basic YOUR_BASE64_TOKEN"
}
},
{
"domain": "*"
}
]
}
}
}'
For private Cloud Storage buckets, use a standard OAuth 2.0 Bearer token:
gcloud auth print-access-token
Python
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Analyze the discrepancies across the data in workspace",
environment={
"type": "remote",
"sources": [
{
"type": "gcs",
"source": "gs://my-private-bucket/data",
"target": "/workspace",
}
],
"network": {
"allowlist": [
{
"domain": "*.googleapis.com",
"transform": {
"Authorization": "Bearer YOUR_GCS_TOKEN"
}
},
{
"domain": "*"
}
]
}
},
)
JavaScript
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Analyze the discrepancies across the data in workspace",
environment: {
type: "remote",
sources: [
{
type: "gcs",
source: "gs://my-private-bucket/data",
target: "/workspace",
}
],
network: {
allowlist: [
{
domain: "storage.googleapis.com",
transform: {
"Authorization": "Bearer YOUR_GCS_TOKEN"
}
},
{
domain: "*"
}
]
}
},
});
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
Environment env = Environment.builder()
.sources(List.of(
Source.builder()
.type(SourceType.GCS)
.source("gs://my-private-bucket/data")
.target("/workspace")
.build()
))
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("*.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer YOUR_GCS_TOKEN"
)))
.build(),
AllowlistEntry.builder()
.domain("*")
.build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Analyze the discrepancies across the data in workspace"))
.environment(CreateAgentInteractionEnvironment.of(env))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "Analyze the discrepancies across the data in workspace",
"environment": {
"type": "remote",
"sources": [
{
"type": "gcs",
"source": "gs://my-private-bucket/data",
"target": "/workspace"
}
],
"network": {
"allowlist": [
{
"domain": "storage.googleapis.com",
"transform": {
"Authorization": "Bearer YOUR_GCS_TOKEN"
}
},
{
"domain": "*"
}
]
}
}
}'
Pre-installed software
The sandbox runs on Ubuntu and comes with runtimes and common packages
pre-installed. The agent can install additional packages at runtime using pip
install or npm install. Packages installed during an interaction persist when
you reuse the same environment_id.
| Category | Pre-installed packages |
|---|---|
| UNIX tools | curl, wget, git, rsync, unzip, ripgrep, fd-find, gawk, bc, tree, which, lsof, htop, jq, iproute2, procps, gcloud CLI |
| Python 3.12 | numpy, pandas, requests, google-genai, beautifulsoup4, pyyaml, ast-grep-cli |
| Node.js 22 | create-next-app, create-vite, typescript |
Network configuration
By default, environments have unrestricted outbound network access. Use the
network field to restrict outbound traffic to specific domains. Each rule
specifies a domain and an optional transform object to inject headers into
matching requests. These headers can be unique per interaction, and you can update them for the same environment.
| Field | Type | Description |
|---|---|---|
domain |
string |
Domain to match. Use an exact hostname or * for all domains. |
transform |
object |
Object containing flat key-value pairs representing headers to inject into matching requests, e.g. {"Authorization": "Bearer ..."}. |
Python
from google import genai
client = genai.Client()
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Fetch the latest issues from the GitHub API for my-org/my-repo.",
environment={
"type": "remote",
"network": {
"allowlist": [
{
"domain": "api.github.com",
"transform": {
"Authorization": "Bearer ghp_your_github_token"
},
},
{"domain": "pypi.org"},
{"domain": "*"},
]
},
},
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Fetch the latest issues from the GitHub API for my-org/my-repo.",
environment: {
type: "remote",
network: {
allowlist: [
{
domain: "api.github.com",
transform: {
"Authorization": "Bearer ghp_your_github_token"
},
},
{ domain: "pypi.org" },
{ domain: "*" },
]
}
},
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
Environment env = Environment.builder()
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("api.github.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer ghp_your_github_token"
)))
.build(),
AllowlistEntry.builder().domain("pypi.org").build(),
AllowlistEntry.builder().domain("*").build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Fetch the latest issues from the GitHub API for my-org/my-repo."))
.environment(CreateAgentInteractionEnvironment.of(env))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": [{"type": "text", "text": "Fetch the latest issues from the GitHub API for my-org/my-repo."}],
"environment": {
"type": "remote",
"network": {
"allowlist": [
{
"domain": "api.github.com",
"transform": {
"Authorization": "Bearer ghp_your_github_token"
}
},
{"domain": "pypi.org"},
{"domain": "*"}
]
}
}
}'
When an allowlist is set, only requests to explicitly listed domains are
permitted. You can use wildcards to match subdomains (e.g., {"domain":
"*.example.com"}), but note that this does not match the root domain
example.com, which must be added separately. To permit all other traffic, such
as routing unlisted domains without injected headers, add {"domain": "*"} as a
catch-all entry.
Credentials
You can add credentials for your agent to use by adding header transformations. The credentials are injected in the respective HTTP headers by an egress proxy, they are never exposed inside the sandbox as environment variables or files.
Python
import subprocess
from google import genai
# Fetch a short-lived access token from your local gcloud CLI
gcloud_token = subprocess.check_output(
["gcloud", "auth", "print-access-token"], text=True
).strip()
client = genai.Client()
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="List the files in gs://my-bucket/reports/ using the GCS JSON API.",
environment={
"type": "remote",
"network": {
"allowlist": [
{
"domain": "storage.googleapis.com",
"transform": {
"Authorization": f"Bearer {gcloud_token}"
},
}
]
},
},
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
import { execSync } from "child_process";
const gcloudToken = execSync("gcloud auth print-access-token").toString().trim();
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "List the files in gs://my-bucket/reports/ using the GCS JSON API.",
environment: {
type: "remote",
network: {
allowlist: [
{
domain: "storage.googleapis.com",
transform: {
"Authorization": `Bearer ${gcloudToken}`
},
}
]
}
},
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
// Fetch a short-lived access token from your local gcloud CLI
Process process = new ProcessBuilder("gcloud", "auth", "print-access-token").start();
String gcloudToken = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8).trim();
Client client = new Client();
Environment env = Environment.builder()
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("storage.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer " + gcloudToken
)))
.build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("List the files in gs://my-bucket/reports/ using the GCS JSON API."))
.environment(CreateAgentInteractionEnvironment.of(env))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "List the files in gs://my-bucket/reports/ using the GCS JSON API.",
"environment": {
"type": "remote",
"network": {
"allowlist": [
{
"domain": "storage.googleapis.com",
"transform": {
"Authorization": "Bearer <YOUR_GCLOUD_TOKEN>"
}
}
]
}
}
}'
Disable network access
To block all outbound network access, set network to disabled:
Python
from google import genai
client = genai.Client()
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Analyze the local files only.",
environment={
"type": "remote",
"network": "disabled",
},
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Analyze the local files only.",
environment: {
type: "remote",
network: "disabled",
},
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.NetworkEnum;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
Environment env = Environment.builder()
.network(Network.of(NetworkEnum.DISABLED))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Analyze the local files only."))
.environment(CreateAgentInteractionEnvironment.of(env))
.build();
Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "Analyze the local files only.",
"environment": {
"type": "remote",
"network": "disabled"
}
}'
Refresh credentials
Credentials such as access tokens and short-lived API keys expire.
You can refresh them by passing the existing environment_id together with a
new network configuration on the next interaction. The new network rules
fully replace the previous ones, while the environment's file system state
(installed packages, files, repositories) is preserved.
Python
from google import genai
client = genai.Client()
# First interaction: use an initial token
first = client.interactions.create(
agent="antigravity-preview-05-2026",
input="List the files in gs://my-bucket/reports/ using the GCS JSON API.",
environment={
"type": "remote",
"network": {
"allowlist": [
{
"domain": "storage.googleapis.com",
"transform": {
"Authorization": "Bearer INITIAL_TOKEN"
},
}
]
},
},
)
# Later: refresh the token on the same environment
result = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Now download the file reports/q1.csv from the same bucket.",
environment={
"type": "remote",
"environment_id": first.environment_id,
"network": {
"allowlist": [
{
"domain": "storage.googleapis.com",
"transform": {
"Authorization": "Bearer REFRESHED_TOKEN"
},
}
]
},
},
)
print(result.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
// First interaction: use an initial token
const first = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "List the files in gs://my-bucket/reports/ using the GCS JSON API.",
environment: {
type: "remote",
network: {
allowlist: [
{
domain: "storage.googleapis.com",
transform: {
"Authorization": "Bearer INITIAL_TOKEN"
},
}
]
}
},
});
// Later: refresh the token on the same environment
const result = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Now download the file reports/q1.csv from the same bucket.",
environment: {
type: "remote",
environment_id: first.environment_id,
network: {
allowlist: [
{
domain: "storage.googleapis.com",
transform: {
"Authorization": "Bearer REFRESHED_TOKEN"
},
}
]
}
},
});
console.log(result.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
// First interaction: use an initial token
Environment initialEnv = Environment.builder()
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("storage.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer INITIAL_TOKEN"
)))
.build()
))
.build()
)))
.build();
CreateAgentInteraction firstParams = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("List the files in gs://my-bucket/reports/ using the GCS JSON API."))
.environment(CreateAgentInteractionEnvironment.of(initialEnv))
.build();
Interaction first = client.interactions.create(CreateInteractionRequestBody.of(firstParams)).interaction().get();
// Later: refresh the token on the same environment
Environment refreshedEnv = Environment.builder()
.environmentId(first.environmentId().orElse(""))
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("storage.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer REFRESHED_TOKEN"
)))
.build()
))
.build()
)))
.build();
CreateAgentInteraction secondParams = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Now download the file reports/q1.csv from the same bucket."))
.environment(CreateAgentInteractionEnvironment.of(refreshedEnv))
.build();
Interaction result = client.interactions.create(CreateInteractionRequestBody.of(secondParams)).interaction().get();
System.out.println(result.outputText().orElse(""));
REST
# Use the environment_id from a previous interaction
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "Now download the file reports/q1.csv from the same bucket.",
"environment": {
"type": "remote",
"environment_id": "<ENVIRONMENT_ID_FROM_PREVIOUS_INTERACTION>",
"network": {
"allowlist": [
{
"domain": "storage.googleapis.com",
"transform": {
"Authorization": "Bearer REFRESHED_TOKEN"
}
}
]
}
}
}'
Environment lifecycle
Environments follow this lifecycle:
| State | Behavior |
|---|---|
| Created | Provisioned when an interaction specifies environment: "remote" or a config object. |
| Active | Running while an interaction is in progress. |
| Idle | Auto-snapshot and stopped after 15 minutes of inactivity. |
| Offline | Retained for 7 days since last active. Can be resumed by passing its ID. |
| Deleted | Removed from the system automatically after 7-day TTL retention expires or upon manual deletion. |
Environments API
You can use the Environments API to programmatically manage sandbox sessions. Enumerating environments lets you discover active session IDs and recover state if a client connection terminates during a long-running task. You can also inspect session metadata and explicitly delete environments when workflows conclude rather than waiting for automatic TTL expiration.
List environments
List active environments belonging to your project. Use pagination parameters to control the response batch size.
Python
from google import genai
client = genai.Client()
response = client.environments.list(page_size=10)
for env in response.environments:
print(f"Environment ID: {env.id}, Status: {env.status}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const response = await client.environments.list({ page_size: 10 });
for (const env of response.environments) {
console.log(`Environment ID: ${env.id}, Status: ${env.status}`);
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.environments.Environment;
import com.google.genai.gaos.models.environments.ListEnvironmentsResponse;
import java.util.List;
Client client = new Client();
ListEnvironmentsResponse response = client.environments.listEnvironments()
.pageSize(10)
.call()
.listEnvironmentsResponse()
.get();
for (Environment env : response.environments().orElse(List.of())) {
System.out.println("Environment ID: " + env.id().orElse("") + ", Status: " + env.status().orElse(null));
}
REST
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments?pageSize=10" \
-H "x-goog-api-key: $GEMINI_API_KEY"
The response looks similar to the following:
{
"environments": [
{
"id": "140128b2a13c12c00a5a0d8cf7af9469",
"status": "active"
},
{
"id": "362b738275a1d74af6f1c62bc050da73",
"status": "active"
}
],
"next_page_token": "Cj...5aE="
}
Get an environment
Retrieve metadata and configuration details for a specific environment by its resource name.
Python
from google import genai
client = genai.Client()
env = client.environments.get(id="YOUR_ENVIRONMENT_ID")
print(f"Environment ID: {env.id}, Status: {env.status}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const env = await client.environments.get("YOUR_ENVIRONMENT_ID");
console.log(`Environment ID: ${env.id}, Status: ${env.status}`);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.environments.Environment;
Client client = new Client();
Environment env = client.environments.getEnvironment("YOUR_ENVIRONMENT_ID").environment().get();
System.out.println("Environment ID: " + env.id().orElse("") + ", Status: " + env.status().orElse(null));
REST
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/YOUR_ENVIRONMENT_ID" \
-H "x-goog-api-key: $GEMINI_API_KEY"
The response looks similar to the following:
{
"id": "140128b2a13c12c00a5a0d8cf7af9469",
"status": "active",
"sources": [
{
"type": "repository",
"source": "https://github.com/octocat/Spoon-Knife",
"target": "/workspace/spoon-knife"
}
],
"network": {
"allowlist": [
{
"domain": "api.github.com"
},
{
"domain": "github.com"
}
]
}
}
Delete an environment
Explicitly terminate and delete an environment to clean up sandbox resources when your tasks or pipelines finish.
Python
from google import genai
client = genai.Client()
client.environments.delete(id="YOUR_ENVIRONMENT_ID")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
await client.environments.delete("YOUR_ENVIRONMENT_ID");
Java
import com.google.genai.Client;
Client client = new Client();
client.environments.deleteEnvironment("YOUR_ENVIRONMENT_ID");
REST
curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/environments/YOUR_ENVIRONMENT_ID" \
-H "x-goog-api-key: $GEMINI_API_KEY"
Manage files in the environment
The agent creates and modifies files inside the sandbox during execution. You can browse directory contents, get file metadata, download individual files or entire directories as tar archives, and upload files or extract archives directly into the environment. Storage in sandbox environments is subject to fair usage limits.
List files in a directory
List the contents of a directory in the environment. By default, lists the root directory.
Query parameters
| Parameter | Type | Description |
|---|---|---|
recursive |
boolean | When true, lists all files and directories recursively. Default: false. |
Python
from google import genai
client = genai.Client()
# List root directory
response = client.environments.files.list(
environment="YOUR_ENVIRONMENT_ID",
path="",
)
for file in response.files:
print(f"{file.name} ({file.type}) - {file.path}")
# List a subdirectory recursively
response = client.environments.files.list(
environment="YOUR_ENVIRONMENT_ID",
path="src",
recursive=True,
)
for file in response.files:
print(f"{file.name} ({file.type}) - {file.path}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
// List root directory
const response = await client.environments.files.list({
environment: "YOUR_ENVIRONMENT_ID",
path: "",
});
for (const file of response.files) {
console.log(`${file.name} (${file.type}) - ${file.path}`);
}
// List a subdirectory recursively
const srcResponse = await client.environments.files.list({
environment: "YOUR_ENVIRONMENT_ID",
path: "src",
recursive: true,
});
for (const file of srcResponse.files) {
console.log(`${file.name} (${file.type}) - ${file.path}`);
}
REST
# List root directory
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files" \
-H "x-goog-api-key: $GEMINI_API_KEY"
# List a subdirectory
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src" \
-H "x-goog-api-key: $GEMINI_API_KEY"
# List all files recursively
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files?recursive=true" \
-H "x-goog-api-key: $GEMINI_API_KEY"
The response returns a files array with metadata for each entry:
{
"files": [
{
"name": "config",
"path": "config",
"type": "DIRECTORY",
"created": "2026-08-12T07:44:18Z",
"modified": "2026-08-12T07:44:18Z"
},
{
"name": "main.py",
"path": "src/main.py",
"type": "FILE",
"size_bytes": "15",
"mime_type": "text/x-python; charset=utf-8",
"created": "2026-08-12T07:44:20Z",
"modified": "2026-08-12T07:44:20Z"
}
]
}
File entry fields
| Field | Type | Description |
|---|---|---|
name |
string | The file or directory name. |
path |
string | The full path relative to the environment root. |
type |
string | Either FILE or DIRECTORY. |
size_bytes |
string | File size in bytes (files only). |
mime_type |
string | MIME type (files only). |
created |
string | ISO 8601 creation timestamp. |
modified |
string | ISO 8601 last-modified timestamp. |
Get file metadata
Get metadata for a specific file by path.
Python
from google import genai
client = genai.Client()
response = client.environments.files.list(
environment="YOUR_ENVIRONMENT_ID",
path="src/main.py",
)
file = response.files[0]
print(f"Name: {file.name}, Size: {file.size_bytes} bytes, Type: {file.mime_type}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const response = await client.environments.files.list({
environment: "YOUR_ENVIRONMENT_ID",
path: "src/main.py",
});
const file = response.files[0];
console.log(`Name: ${file.name}, Size: ${file.size_bytes} bytes, Type: ${file.mime_type}`);
REST
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src/main.py" \
-H "x-goog-api-key: $GEMINI_API_KEY"
The response returns the file metadata wrapped in a files array:
{
"files": [
{
"name": "main.py",
"path": "src/main.py",
"type": "FILE",
"size_bytes": "15",
"mime_type": "text/x-python; charset=utf-8",
"created": "2026-08-12T07:44:20Z",
"modified": "2026-08-12T07:44:20Z"
}
]
}
If the file doesn't exist, the API returns a 404 error:
{
"error": {
"message": "Path 'nonexistent.txt' not found in environment 'ENV_ID'.",
"code": "not_found"
}
}
Download a single file
Download the contents of a specific file. In the SDKs, use the download()
method. In REST requests, append the ?alt=media query parameter to the file
path. The server responds with 200 OK and streams the raw file content.
Python
from google import genai
client = genai.Client()
content = client.environments.files.download(
environment="YOUR_ENVIRONMENT_ID",
path="src/main.py",
)
with open("main.py", "wb") as f:
f.write(content)
JavaScript
import { GoogleGenAI } from "@google/genai";
import * as fs from "fs";
const client = new GoogleGenAI({});
const bytes = await client.environments.files.download({
environment: "YOUR_ENVIRONMENT_ID",
path: "src/main.py",
});
fs.writeFileSync("main.py", Buffer.from(bytes));
REST
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src/main.py?alt=media" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o main.py
Download a directory as a tar archive
Download an entire directory as a tar archive by requesting the directory path
with ?alt=media. This returns a POSIX tar file (not gzipped). Use
recursive=true to include nested subdirectories.
Python
import tarfile
from google import genai
client = genai.Client()
# Download a subdirectory archive
archive = client.environments.files.download(
environment="YOUR_ENVIRONMENT_ID",
path="src",
)
with open("src.tar", "wb") as f:
f.write(archive)
with tarfile.open("src.tar") as tar:
tar.extractall(path="./extracted")
JavaScript
import { GoogleGenAI } from "@google/genai";
import { execSync } from "child_process";
import * as fs from "fs";
const client = new GoogleGenAI({});
// Download a subdirectory archive
const bytes = await client.environments.files.download({
environment: "YOUR_ENVIRONMENT_ID",
path: "src",
});
fs.writeFileSync("src.tar", Buffer.from(bytes));
execSync("tar -xf src.tar -C ./extracted");
REST
# Download a subdirectory (top-level files only)
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src?alt=media" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o src.tar
# Download a subdirectory recursively (includes nested directories)
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/config?alt=media&recursive=true" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o config.tar
# Download root directory
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files?alt=media" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o snapshot.tar
# Extract the archive
tar xf snapshot.tar -C ./extracted
Behavior matrix
The following behavior matrix summarizes the expected response and archive behavior across file and directory endpoints, HTTP methods, and query parameters:
| Request | alt |
recursive |
extract |
overwrite |
Response |
|---|---|---|---|---|---|
GET /files |
(none) | (none) | - | - | JSON listing of root directory |
GET /files/{path} (file) |
(none) | - | - | - | JSON metadata for the file |
GET /files/{path} (dir) |
(none) | false |
- | - | JSON listing of immediate children |
GET /files/{path} (dir) |
(none) | true |
- | - | JSON listing of all descendants |
GET /files/{path}?alt=media (file) |
media |
- | - | - | Raw file content |
GET /files/{path}?alt=media (dir) |
media |
false |
- | - | Tar archive of immediate files in directory |
GET /files/{path}?alt=media (dir) |
media |
true |
- | - | Tar archive of all files recursively |
GET /files?alt=media |
media |
false |
- | - | Tar archive of root-level files only |
PUT /files/{path} (file) |
- | - | false |
false |
Writes the file at path. Returns 409 Conflict if it already exists |
PUT /files/{path}?overwrite=true |
- | - | false |
true |
Writes or overwrites the file at path |
PUT /files/{path}?extract=true |
- | - | true |
false |
Unpacks archive into destination directory. Returns 409 Conflict if any target file exists |
PUT /files/{path}?extract=true&overwrite=true |
- | - | true |
true |
Unpacks archive, replacing any existing files |
Upload files to the environment
Upload individual files or directory archives directly to an existing environment
sandbox using HTTP PUT. Parent directories are created automatically if they
do not exist. Storage in environments is subject to fair usage limits.
Upload a single file
Python
from google import genai
client = genai.Client()
with open("local_file.txt", "rb") as f:
result = client.environments.files.upload(
environment="YOUR_ENVIRONMENT_ID",
path="workspace/data/file.txt",
file=f,
mime_type="text/plain",
overwrite=True,
)
file = result.files[0]
print(f"Uploaded: {file.name} ({file.size_bytes} bytes)")
JavaScript
import { GoogleGenAI } from "@google/genai";
import * as fs from "fs";
const client = new GoogleGenAI({});
const content = fs.readFileSync("local_file.txt");
const result = await client.environments.files.upload({
environment: "YOUR_ENVIRONMENT_ID",
path: "workspace/data/file.txt",
file: content,
mime_type: "text/plain",
overwrite: true,
});
const file = result.files[0];
console.log(`Uploaded: ${file.name} (${file.size_bytes} bytes)`);
REST
curl -X PUT "https://generativelanguage.googleapis.com/upload/v1beta/environments/$ENV_ID/files/workspace/data/file.txt" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: text/plain" \
--data-binary @local_file.txt
The response returns metadata for the uploaded file, wrapped in a files array
for consistency with the list and get endpoints:
{
"files": [
{
"name": "file.txt",
"path": "workspace/data/file.txt",
"type": "FILE",
"size_bytes": "1024",
"mime_type": "text/plain"
}
]
}
Upload and extract a directory archive
To seed an entire codebase or directory structure in a single request, upload a
.tar or .tar.gz archive with extract=true.
Python
from google import genai
client = genai.Client()
with open("source.tar.gz", "rb") as f:
result = client.environments.files.upload(
environment="YOUR_ENVIRONMENT_ID",
path="workspace/src/",
file=f,
extract=True,
)
for entry in result.files:
print(f"Extracted: {entry.path}")
JavaScript
import { GoogleGenAI } from "@google/genai";
import * as fs from "fs";
const client = new GoogleGenAI({});
const archive = fs.readFileSync("source.tar.gz");
const result = await client.environments.files.upload({
environment: "YOUR_ENVIRONMENT_ID",
path: "workspace/src/",
file: archive,
extract: true,
});
for (const entry of result.files) {
console.log(`Extracted: ${entry.path}`);
}
REST
curl -X PUT "https://generativelanguage.googleapis.com/upload/v1beta/environments/$ENV_ID/files/workspace/src/?extract=true" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/x-tar" \
--data-binary @source.tar.gz
The response lists every file written by the archive:
{
"files": [
{
"name": "app.py",
"path": "workspace/src/app.py",
"type": "FILE",
"size_bytes": "15",
"mime_type": "text/x-python"
},
{
"name": "requirements.txt",
"path": "workspace/src/requirements.txt",
"type": "FILE",
"size_bytes": "17",
"mime_type": "text/plain"
}
]
}
Upload large files with a resumable session
For large payloads, or when uploading over an unreliable connection, use a resumable session instead of sending the whole body in one request. A resumable upload splits the transfer into chunks that can be retried individually, so a failure part way through does not force you to start over.
Start by initiating the session with uploadType=resumable. Send an empty body
and use the X-Upload-Content-Type and X-Upload-Content-Length headers to
declare the media type and total size of the payload you intend to upload:
PUT /upload/v1beta/environments/$ENV_ID/files/workspace/data/large_dataset.bin?uploadType=resumable HTTP/1.1
Host: generativelanguage.googleapis.com
X-Upload-Content-Type: application/octet-stream
X-Upload-Content-Length: 20971520
Content-Length: 0
x-goog-api-key: $GEMINI_API_KEY
The response carries the session URL in the Location header. This URL already
contains an upload_id, so it does not need the API key again:
HTTP/1.1 200 OK
Location: https://generativelanguage.googleapis.com/upload/v1beta/environments/$ENV_ID/files/workspace/data/large_dataset.bin?uploadType=resumable&upload_id=AJjja9bfHjiYlGi60pUazCaTuPY
Content-Length: 0
Upload the payload to that URL in chunks. Each chunk declares its byte range and
the total size with a Content-Range header:
PUT /upload/v1beta/environments/$ENV_ID/files/workspace/data/large_dataset.bin?uploadType=resumable&upload_id=AJjja9bfHjiYlGi60pUazCaTuPY HTTP/1.1
Host: generativelanguage.googleapis.com
Content-Type: application/octet-stream
Content-Range: bytes 0-10485759/20971520
Content-Length: 10485760
<10 MB binary payload>
Every chunk except the last returns 308 Resume Incomplete. The Range header
tells you how many bytes the server has committed, which is where you resume
from if a chunk fails:
HTTP/1.1 308 Resume Incomplete
Range: bytes=0-10485759
Content-Length: 0
Send the remaining chunks the same way:
PUT /upload/v1beta/environments/$ENV_ID/files/workspace/data/large_dataset.bin?uploadType=resumable&upload_id=AJjja9bfHjiYlGi60pUazCaTuPY HTTP/1.1
Host: generativelanguage.googleapis.com
Content-Type: application/octet-stream
Content-Range: bytes 10485760-20971519/20971520
Content-Length: 10485760
<remaining 10 MB binary payload>
The final chunk completes the upload and returns the file metadata, in the same
files envelope as a single-shot upload:
{
"files": [
{
"name": "large_dataset.bin",
"path": "workspace/data/large_dataset.bin",
"type": "FILE",
"size_bytes": "20971520",
"mime_type": "application/octet-stream"
}
]
}
Resumable sessions work with extract and overwrite as well. Set those query
parameters on the initiating request, not on the individual chunks.
Overwrite protection
By default, overwrite is false. If the destination path already exists, the
request returns a 409 Conflict error and nothing is written:
{
"error": {
"message": "Requested entity already exists",
"code": "aborted"
}
}
To replace an existing file or directory, set overwrite=true (or append
?overwrite=true in REST). With extract=true, the conflict check applies to
every file in the archive, so the request fails if any target file exists.
Download full snapshot (deprecated)
To migrate existing code to the environment files API:
Python: Replace legacy file download requests with:
archive = client.environments.files.download( environment="YOUR_ENVIRONMENT_ID", path="workspace", ) with open("snapshot.tar", "wb") as f: f.write(archive)JavaScript: Replace legacy file download requests with:
const bytes = await client.environments.files.download({ environment: "YOUR_ENVIRONMENT_ID", path: "workspace", }); fs.writeFileSync("snapshot.tar", Buffer.from(bytes));REST: Replace
GET /v1beta/files/environment-$ENV_ID:download?alt=mediawith:curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files?alt=media" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -o snapshot.tar
Pricing & resources
Each environment runs with fixed resource allocations:
| Resource | Value |
|---|---|
| CPU | 4 cores |
| Memory | 16 GB |
Environment compute (CPU, memory, sandbox execution) is not billed during the preview period. See Pricing for agent token costs.
Limitations
- Preview status: Environments and managed agents are in preview. Features and schemas may change.
- Inline source size: Inline sources are limited to 1 MB per file, and 2 MB total across all files.
- Source size: Git repositories are limited to 500 MB and Cloud Storage repositories to 2 GB.
- Environment startup: Provisioning a new environment takes up to ~5 seconds. Large source repositories may increase this time.
- Environment expiration: Inactive offline environments are retained for 7
days before expiring using automatic TTL cleanup. Passing an expired or
invalid environment ID returns a
404 Not Founderror. - File support: The agent is currently constrained to reading text and image files. Binary file support is not yet available.
- No mounting from root: You can't set root (
/) as target when adding a custom source, you must always specify a sub-directory.
What's next
- Agents Overview: Learn about the core concepts of managed agents.
- Quickstart: Start building with multi-turn conversations and streaming.
- Antigravity Agent: Explore capabilities, tools, model selection, and pricing for the default agent.
- Building Custom Agents: Define your own agents using
AGENTS.mdandSKILL.md. - Hooks: Enforce security guardrails and run side-effect validations inside the sandbox.