> ## AI Agent Context > Get the complete documentation index at: https://aistudio.google.com/docs/llms.txt > Use this file to discover all available pages. > For the full documentation in a single file, fetch: https://aistudio.google.com/docs/llms-full.txt # Environments in managed agents 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: {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() interaction = client.interactions.create( agent="antigravity-preview-09-2026", input="Install pandas and matplotlib, verify the imports, and print the versions.", environment="remote", ) print(f"Environment ID: {interaction.environment_id}") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const interaction = await client.interactions.create({ agent: "antigravity-preview-09-2026", input: "Install pandas and matplotlib, verify the imports, and print the versions.", environment: "remote", }); console.log(`Environment ID: ${interaction.environment_id}`); ``` {% /tab %} {% tab label="REST" %} ```shell 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-09-2026", "input": "Install pandas and matplotlib, verify the imports, and print the versions.", "environment": "remote" }' ``` {% /tab %} {% tab label="Java" %} ```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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Install pandas and matplotlib, verify the imports, and print the versions."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment("remote")), }), }) if err != nil { log.Fatal(err) } if res.Interaction.EnvironmentID != nil { fmt.Printf("Environment ID: %s\n", *res.Interaction.EnvironmentID) } } ``` {% /tab %} {% /tabs %} ## The `environment` parameter {% id="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, environment variables, or a combination. | The following examples demonstrate the three ways of using the `environment` parameter. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() # Fresh sandbox interaction = client.interactions.create( agent="antigravity-preview-09-2026", input="Write a hello world script.", environment="remote", ) # Reuse an existing sandbox interaction_2 = client.interactions.create( agent="antigravity-preview-09-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-09-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) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); // Fresh sandbox const interaction = await client.interactions.create({ agent: "antigravity-preview-09-2026", input: "Write a hello world script.", environment: "remote", }); // Reuse an existing sandbox const interaction2 = await client.interactions.create({ agent: "antigravity-preview-09-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-09-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); ``` {% /tab %} {% tab label="REST" %} ```shell # 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-09-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-09-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-09-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" } ] } }' ``` {% /tab %} {% tab label="Java" %} ```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-09-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-09-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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } // Fresh sandbox res1, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Write a hello world script."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment("remote")), }), }) if err != nil { log.Fatal(err) } interaction := res1.Interaction // Reuse an existing sandbox res2, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Modify the script to accept a name argument."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(*interaction.EnvironmentID)), PreviousInteractionID: interaction.ID, }), }) if err != nil { log.Fatal(err) } _ = res2 // New sandbox with sources env3 := interactions.Environment{ Sources: []interactions.Source{ { Type: interactions.SourceTypeRepository.ToPointer(), Source: genai.Ptr("https://github.com/octocat/Spoon-Knife"), Target: genai.Ptr("/workspace/spoon-knife"), }, }, } res3, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("List all files and summarize the project."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env3)), }), }) if err != nil { log.Fatal(err) } _ = res3 if interaction.OutputText != nil { fmt.Println(*interaction.OutputText) } } ``` {% /tab %} {% /tabs %} ## Configure an environment {% id="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. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() interaction = client.interactions.create( agent="antigravity-preview-09-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-09-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-09-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) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const interaction = await client.interactions.create({ agent: "antigravity-preview-09-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-09-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-09-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); ``` {% /tab %} {% tab label="REST" %} ```shell # 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-09-2026", "input": "Install pandas, matplotlib, and seaborn. Verify all imports work and print the installed versions.", "environment": "remote" }' ``` {% /tab %} {% tab label="Java" %} ```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-09-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-09-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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } res1, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Install pandas, matplotlib, and seaborn. Verify all imports work and print the installed versions."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment("remote")), }), }) if err != nil { log.Fatal(err) } interaction := res1.Interaction // Reuse the configured environment res2, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Clone https://github.com/octocat/Spoon-Knife into /workspace/tools. Run the test suite and fix any missing dependencies."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(*interaction.EnvironmentID)), PreviousInteractionID: interaction.ID, }), }) if err != nil { log.Fatal(err) } interaction2 := res2.Interaction // Reuse the configured environment res3, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Using the tools in /workspace/tools, list the files."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(*interaction.EnvironmentID)), PreviousInteractionID: interaction2.ID, }), }) if err != nil { log.Fatal(err) } _ = res3 if interaction.OutputText != nil { fmt.Println(*interaction.OutputText) } } ``` {% /tab %} {% /tabs %} ### Mount from a source {% id="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 | {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() interaction = client.interactions.create( agent="antigravity-preview-09-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) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const interaction = await client.interactions.create({ agent: "antigravity-preview-09-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); ``` {% /tab %} {% tab label="REST" %} ```shell # 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-09-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" } ] } }' ``` {% /tab %} {% tab label="Java" %} ```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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } env := interactions.Environment{ Sources: []interactions.Source{ { Type: interactions.SourceTypeRepository.ToPointer(), Source: genai.Ptr("https://github.com/octocat/Spoon-Knife"), Target: genai.Ptr("/workspace/spoon-knife"), }, { Type: interactions.SourceTypeGcs.ToPointer(), Source: genai.Ptr("gs://cloud-samples-data/bigquery/us-states/"), Target: genai.Ptr("/workspace/gcs-data"), }, { Type: interactions.SourceTypeInline.ToPointer(), Content: genai.Ptr("# Project Notes\n\n- Analyze state population data\n- Create visualizations\n"), Target: genai.Ptr("/workspace/notes/readme.md"), }, }, } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("List all files under /workspace and describe what you find."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)), }), }) if err != nil { log.Fatal(err) } if res.Interaction.OutputText != nil { fmt.Println(*res.Interaction.OutputText) } } ``` {% /tab %} {% /tabs %} 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 {% id="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](/docs/agent-hooks). ### Private sources {% id="private-sources" %} You can also download from private GitHub repositories or private Cloud Storage buckets by authenticating the source domain in the network configuration. One option is a stored [credential](/docs/agent-credentials) referenced by ID, so you store the secret once and every environment that needs that source can reference it: ```json "network": { "allowlist": [ { "domain": "github.com", "credential": "github-production" }, { "domain": "*" } ] } ``` You can also set the header inline with `transform`, as the following examples do. The egress proxy applies both forms the same way, and in neither case does the secret land inside the sandbox. For **private Git repositories**, use `Basic` authentication with your [GitHub Personal Access Token (PAT)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). Encode the token using `x-oauth-basic` as the username: ```shell echo -n "x-oauth-basic:ghp_YourPATHere" | base64 ``` {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py interaction = client.interactions.create( agent="antigravity-preview-09-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": "*" } ] } } ) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript const interaction = await client.interactions.create({ agent: "antigravity-preview-09-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: "*" } ] } }, }); ``` {% /tab %} {% tab label="REST" %} ```shell 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-09-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": "*" } ] } } }' ``` {% /tab %} {% tab label="Java" %} ```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.builder() .allowlist(Allowlist.of(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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } env := interactions.Environment{ Sources: []interactions.Source{ { Type: interactions.SourceTypeRepository.ToPointer(), Source: genai.Ptr("https://github.com/your-org/backend"), Target: genai.Ptr("/backend-app"), }, }, Network: genai.Ptr(interactions.NewNetwork(interactions.EnvironmentNetworkEgressAllowlist{ Allowlist: genai.Ptr(interactions.NewAllowlist([]interactions.AllowlistEntry{ { Domain: "github.com", Transform: genai.Ptr(interactions.NewTransform(map[string]string{ "Authorization": "Basic YOUR_BASE64_TOKEN", })), }, { Domain: "*", }, })), })), } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Run the test for my backend app and fix any issue."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)), }), }) if err != nil { log.Fatal(err) } if res.Interaction.OutputText != nil { fmt.Println(*res.Interaction.OutputText) } } ``` {% /tab %} {% /tabs %} For **private Cloud Storage buckets**, use a standard OAuth 2.0 Bearer token: ```shell gcloud auth print-access-token ``` {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py interaction = client.interactions.create( agent="antigravity-preview-09-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": "*" } ] } }, ) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript const interaction = await client.interactions.create({ agent: "antigravity-preview-09-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: "*" } ] } }, }); ``` {% /tab %} {% tab label="REST" %} ```shell 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-09-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": "*" } ] } } }' ``` {% /tab %} {% tab label="Java" %} ```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.builder() .allowlist(Allowlist.of(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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } env := interactions.Environment{ Sources: []interactions.Source{ { Type: interactions.SourceTypeGcs.ToPointer(), Source: genai.Ptr("gs://my-private-bucket/data"), Target: genai.Ptr("/workspace"), }, }, Network: genai.Ptr(interactions.NewNetwork(interactions.EnvironmentNetworkEgressAllowlist{ Allowlist: genai.Ptr(interactions.NewAllowlist([]interactions.AllowlistEntry{ { Domain: "*.googleapis.com", Transform: genai.Ptr(interactions.NewTransform(map[string]string{ "Authorization": "Bearer YOUR_GCS_TOKEN", })), }, { Domain: "*", }, })), })), } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Analyze the discrepancies across the data in workspace"), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)), }), }) if err != nil { log.Fatal(err) } if res.Interaction.OutputText != nil { fmt.Println(*res.Interaction.OutputText) } } ``` {% /tab %} {% /tabs %} ## Pre-installed software {% id="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` | ## Environment variables {% id="environment-variables" %} Use the `env` field to set environment variables inside the sandbox. Each entry maps a variable name to either a literal string for configuration or a reference to a stored [credential](/docs/agent-credentials) for a secret. The agent sees them the way it would in any shell, so tools and scripts that read from the process environment pick them up without extra wiring. | Field | Type | Description | | :--- | :--- | :--- | | `env` | `object` | Map of variable name to value. A value is either a literal `string` or a credential reference of the form `{"credential": "credential-id"}`. | {% tabs %} {% tab filename="env_vars.py" label="Python" %} ```py from google import genai client = genai.Client() interaction = client.interactions.create( agent="antigravity-preview-09-2026", input="Build the project and run the test suite.", environment={ "type": "remote", "env": { "NODE_ENV": "production", "LOG_LEVEL": "debug", "API_TOKEN": {"credential": "my-api-token"}, }, }, ) print(interaction.output_text) ``` {% /tab %} {% tab filename="env_vars.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const interaction = await client.interactions.create({ agent: "antigravity-preview-09-2026", input: "Build the project and run the test suite.", environment: { type: "remote", env: { NODE_ENV: "production", LOG_LEVEL: "debug", API_TOKEN: { credential: "my-api-token" }, }, }, }); console.log(interaction.output_text); ``` {% /tab %} {% tab label="REST" %} ```shell 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-09-2026", "input": [{"type": "text", "text": "Build the project and run the test suite."}], "environment": { "type": "remote", "env": { "NODE_ENV": "production", "LOG_LEVEL": "debug", "API_TOKEN": {"credential": "my-api-token"} } } }' ``` {% /tab %} {% /tabs %} Variables apply to every command the agent runs in that interaction, including shell commands, build steps, and any process it starts. The two value types behave differently. A literal string is written into the container as plain text. A credential reference is not: the variable receives a placeholder, and the egress proxy substitutes the real secret only on outbound requests to that credential's trusted domains. See [Use credentials as environment variables](/docs/agent-credentials#environment-variables) for how that works. Caution: Literal values are readable by anything running in the sandbox, including the agent itself. Use them for configuration like `NODE_ENV`, not for secrets. Every secret belongs in a credential. ## Network configuration {% id="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`, plus an optional `credential` to inject a stored secret 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. | | `credential` | `string` | ID of a stored [credential](/docs/agent-credentials). The egress proxy resolves it and injects the auth header at request time. | | `transform` | `object` | Object containing flat key-value pairs representing headers to inject into matching requests, e.g. `{"Authorization": "Bearer ..."}`. | {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() interaction = client.interactions.create( agent="antigravity-preview-09-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) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const interaction = await client.interactions.create({ agent: "antigravity-preview-09-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); ``` {% /tab %} {% tab label="REST" %} ```shell 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-09-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": "*"} ] } } }' ``` {% /tab %} {% tab label="Java" %} ```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.builder() .allowlist(Allowlist.of(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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } env := interactions.Environment{ Network: genai.Ptr(interactions.NewNetwork(interactions.EnvironmentNetworkEgressAllowlist{ Allowlist: genai.Ptr(interactions.NewAllowlist([]interactions.AllowlistEntry{ { Domain: "api.github.com", Transform: genai.Ptr(interactions.NewTransform(map[string]string{ "Authorization": "Bearer ghp_your_github_token", })), }, { Domain: "pypi.org", }, { Domain: "*", }, })), })), } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Fetch the latest issues from the GitHub API for my-org/my-repo."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)), }), }) if err != nil { log.Fatal(err) } if res.Interaction.OutputText != nil { fmt.Println(*res.Interaction.OutputText) } } ``` {% /tab %} {% /tabs %} 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 {% id="credentials" %} There are two ways to authenticate outbound traffic, a stored credential referenced by ID and an inline `transform` on the allowlist rule. The egress proxy applies both on the wire, so in both cases the secret never enters the sandbox and never appears in your interaction payloads. A [managed credential](/docs/agent-credentials) is the one to reach for when you want to store the secret once and reuse it. Every environment, agent, and trigger in your project can reference the same ID, and you rotate it in one place. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() # Store the secret once client.credentials.create( id="github-production", type="bearer_token", token="ghp_your_github_token", ) interaction = client.interactions.create( agent="antigravity-preview-09-2026", input="Fetch the latest issues from the GitHub API for my-org/my-repo.", environment={ "type": "remote", "network": { "allowlist": [ {"domain": "api.github.com", "credential": "github-production"}, {"domain": "*"}, ] }, }, ) print(interaction.output_text) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); // Store the secret once await client.credentials.create({ id: "github-production", type: "bearer_token", token: "ghp_your_github_token", }); const interaction = await client.interactions.create({ agent: "antigravity-preview-09-2026", input: "Fetch the latest issues from the GitHub API for my-org/my-repo.", environment: { type: "remote", network: { allowlist: [ { domain: "api.github.com", credential: "github-production" }, { domain: "*" }, ] } }, }); console.log(interaction.output_text); ``` {% /tab %} {% tab label="REST" %} ```shell # Store the secret once curl -X POST "https://generativelanguage.googleapis.com/v1beta/credentials" \ -H "Content-Type: application/json" \ -H "x-goog-api-key: $GEMINI_API_KEY" \ -d '{ "id": "github-production", "type": "bearer_token", "token": "ghp_your_github_token" }' 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-09-2026", "input": "Fetch the latest issues from the GitHub API for my-org/my-repo.", "environment": { "type": "remote", "network": { "allowlist": [ { "domain": "api.github.com", "credential": "github-production" }, { "domain": "*" } ] } } }' ``` {% /tab %} {% /tabs %} An `oauth2` credential also refreshes its access token on its own, so a long-running interaction does not break when the token expires. See [Credentials](/docs/agent-credentials) for the full list of credential types and management operations. You can also set headers inline with `transform`. This fits when the value belongs to a single call, for example a token you generate right before creating the interaction. Headers set this way are injected by the same egress proxy, they are never exposed inside the sandbox as environment variables or files. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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-09-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) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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-09-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); ``` {% /tab %} {% tab label="REST" %} ```shell 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-09-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 " } } ] } } }' ``` {% /tab %} {% tab label="Java" %} ```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.builder() .allowlist(Allowlist.of(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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "os/exec" "strings" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() // Fetch a short-lived access token from your local gcloud CLI out, err := exec.Command("gcloud", "auth", "print-access-token").Output() if err != nil { log.Fatal(err) } gcloudToken := strings.TrimSpace(string(out)) client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } env := interactions.Environment{ Network: genai.Ptr(interactions.NewNetwork(interactions.EnvironmentNetworkEgressAllowlist{ Allowlist: genai.Ptr(interactions.NewAllowlist([]interactions.AllowlistEntry{ { Domain: "storage.googleapis.com", Transform: genai.Ptr(interactions.NewTransform(map[string]string{ "Authorization": "Bearer " + gcloudToken, })), }, })), })), } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("List the files in gs://my-bucket/reports/ using the GCS JSON API."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)), }), }) if err != nil { log.Fatal(err) } if res.Interaction.OutputText != nil { fmt.Println(*res.Interaction.OutputText) } } ``` {% /tab %} {% /tabs %} `credential` and `transform` can appear on the same rule. The credential is applied first and `transform` merges on top, so an explicit `transform` header wins if both set the same key. A common pattern is a credential for the authentication header plus a `transform` for the extra headers the service expects alongside it. ### Disable network access {% id="disable-network-access" %} To block all outbound network access, set `network` to `disabled`: {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() interaction = client.interactions.create( agent="antigravity-preview-09-2026", input="Analyze the local files only.", environment={ "type": "remote", "network": "disabled", }, ) print(interaction.output_text) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); const interaction = await client.interactions.create({ agent: "antigravity-preview-09-2026", input: "Analyze the local files only.", environment: { type: "remote", network: "disabled", }, }); console.log(interaction.output_text); ``` {% /tab %} {% tab label="REST" %} ```shell 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-09-2026", "input": "Analyze the local files only.", "environment": { "type": "remote", "network": "disabled" } }' ``` {% /tab %} {% tab label="Java" %} ```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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } env := interactions.Environment{ Network: genai.Ptr(interactions.NewNetwork(interactions.NetworkEnumDisabled)), } res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Analyze the local files only."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)), }), }) if err != nil { log.Fatal(err) } if res.Interaction.OutputText != nil { fmt.Println(*res.Interaction.OutputText) } } ``` {% /tab %} {% /tabs %} ### Refresh credentials {% id="refresh-credentials" %} Inline tokens 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. If you use a stored [credential](/docs/agent-credentials) instead, you don't need this. An `oauth2` credential refreshes itself, and rotating any credential is a `PATCH` on the credential that leaves every allowlist rule referencing it untouched. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() # First interaction: use an initial token first = client.interactions.create( agent="antigravity-preview-09-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-09-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) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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-09-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-09-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); ``` {% /tab %} {% tab label="REST" %} ```shell # 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-09-2026", "input": "Now download the file reports/q1.csv from the same bucket.", "environment": { "type": "remote", "environment_id": "", "network": { "allowlist": [ { "domain": "storage.googleapis.com", "transform": { "Authorization": "Bearer REFRESHED_TOKEN" } } ] } } }' ``` {% /tab %} {% tab label="Java" %} ```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.builder() .allowlist(Allowlist.of(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-09-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.builder() .allowlist(Allowlist.of(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-09-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("")); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "google.golang.org/genai" "google.golang.org/genai/interactions/models/interactions" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() client, err := genai.NewClient(ctx, nil) if err != nil { log.Fatal(err) } // First interaction: use an initial token initialEnv := interactions.Environment{ Network: genai.Ptr(interactions.NewNetwork(interactions.EnvironmentNetworkEgressAllowlist{ Allowlist: genai.Ptr(interactions.NewAllowlist([]interactions.AllowlistEntry{ { Domain: "storage.googleapis.com", Transform: genai.Ptr(interactions.NewTransform(map[string]string{ "Authorization": "Bearer INITIAL_TOKEN", })), }, })), })), } firstRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("List the files in gs://my-bucket/reports/ using the GCS JSON API."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(initialEnv)), }), }) if err != nil { log.Fatal(err) } first := firstRes.Interaction // Later: refresh the token on the same environment refreshedEnv := interactions.Environment{ EnvironmentID: first.EnvironmentID, Network: genai.Ptr(interactions.NewNetwork(interactions.EnvironmentNetworkEgressAllowlist{ Allowlist: genai.Ptr(interactions.NewAllowlist([]interactions.AllowlistEntry{ { Domain: "storage.googleapis.com", Transform: genai.Ptr(interactions.NewTransform(map[string]string{ "Authorization": "Bearer REFRESHED_TOKEN", })), }, })), })), } secondRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{ Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{ Agent: interactions.AgentOption("antigravity-preview-09-2026"), Input: interactions.NewInteractionsInput("Now download the file reports/q1.csv from the same bucket."), Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(refreshedEnv)), }), }) if err != nil { log.Fatal(err) } if secondRes.Interaction.OutputText != nil { fmt.Println(*secondRes.Interaction.OutputText) } } ``` {% /tab %} {% /tabs %} ## Environment lifecycle {% id="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 {% id="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 {% id="list-environments" %} List active environments belonging to your project. Use pagination parameters to control the response batch size. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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}") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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}`); } ``` {% /tab %} {% tab label="REST" %} ```shell curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments?pageSize=10" \ -H "x-goog-api-key: $GEMINI_API_KEY" ``` {% /tab %} {% tab label="Java" %} ```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)); } ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "os" "google.golang.org/genai" interactionssdk "google.golang.org/genai/interactions" "google.golang.org/genai/interactions/models/components" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() sdk := interactionssdk.New(interactionssdk.WithSecurity(components.Security{ APIKey: genai.Ptr(os.Getenv("GEMINI_API_KEY")), })) res, err := sdk.Environments.ListEnvironments(ctx, operations.ListEnvironmentsRequest{ PageSize: genai.Ptr(10), }) if err != nil { log.Fatal(err) } if res.ListEnvironmentsResponse != nil { for _, env := range res.ListEnvironmentsResponse.Environments { fmt.Printf("Environment ID: %s, Status: %v\n", env.ID, env.Status) } } } ``` {% /tab %} {% /tabs %} The response looks similar to the following: ```json { "environments": [ { "id": "140128b2a13c12c00a5a0d8cf7af9469", "status": "active" }, { "id": "362b738275a1d74af6f1c62bc050da73", "status": "active" } ], "next_page_token": "Cj...5aE=" } ``` ### Get an environment {% id="get-an-environment" %} Retrieve metadata and configuration details for a specific environment by its resource name. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() env = client.environments.get(id="YOUR_ENVIRONMENT_ID") print(f"Environment ID: {env.id}, Status: {env.status}") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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}`); ``` {% /tab %} {% tab label="REST" %} ```shell curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/YOUR_ENVIRONMENT_ID" \ -H "x-goog-api-key: $GEMINI_API_KEY" ``` {% /tab %} {% tab label="Java" %} ```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)); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "fmt" "log" "os" "google.golang.org/genai" interactionssdk "google.golang.org/genai/interactions" "google.golang.org/genai/interactions/models/components" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() sdk := interactionssdk.New(interactionssdk.WithSecurity(components.Security{ APIKey: genai.Ptr(os.Getenv("GEMINI_API_KEY")), })) res, err := sdk.Environments.GetEnvironment(ctx, operations.GetEnvironmentRequest{ ID: "YOUR_ENVIRONMENT_ID", }) if err != nil { log.Fatal(err) } env := res.Environment fmt.Printf("Environment ID: %s, Status: %v\n", env.ID, env.Status) } ``` {% /tab %} {% /tabs %} The response looks similar to the following: ```json { "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 {% id="delete-an-environment" %} Explicitly terminate and delete an environment to clean up sandbox resources when your tasks or pipelines finish. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py from google import genai client = genai.Client() client.environments.delete(id="YOUR_ENVIRONMENT_ID") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```javascript import { GoogleGenAI } from "@google/genai"; const client = new GoogleGenAI({}); await client.environments.delete("YOUR_ENVIRONMENT_ID"); ``` {% /tab %} {% tab label="REST" %} ```shell curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/environments/YOUR_ENVIRONMENT_ID" \ -H "x-goog-api-key: $GEMINI_API_KEY" ``` {% /tab %} {% tab label="Java" %} ```java import com.google.genai.Client; Client client = new Client(); client.environments.deleteEnvironment("YOUR_ENVIRONMENT_ID"); ``` {% /tab %} {% tab label="Go" %} ```go package main import ( "context" "log" "os" "google.golang.org/genai" interactionssdk "google.golang.org/genai/interactions" "google.golang.org/genai/interactions/models/components" "google.golang.org/genai/interactions/models/operations" ) func main() { ctx := context.Background() sdk := interactionssdk.New(interactionssdk.WithSecurity(components.Security{ APIKey: genai.Ptr(os.Getenv("GEMINI_API_KEY")), })) _, err := sdk.Environments.DeleteEnvironment(ctx, operations.DeleteEnvironmentRequest{ ID: "YOUR_ENVIRONMENT_ID", }) if err != nil { log.Fatal(err) } } ``` {% /tab %} {% /tabs %} ## Manage files in the environment {% id="download-files-from-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 {% id="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`. | {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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}") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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}`); } ``` {% /tab %} {% tab label="REST" %} ```shell # 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" ``` {% /tab %} {% /tabs %} The response returns a `files` array with metadata for each entry: ```json { "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 {% id="get-file-metadata" %} Get metadata for a specific file by path. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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}") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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]; if (file) { console.log(`Name: ${file.name}, Size: ${file.size_bytes} bytes, Type: ${file.mime_type}`); } ``` {% /tab %} {% tab label="REST" %} ```shell curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src/main.py" \ -H "x-goog-api-key: $GEMINI_API_KEY" ``` {% /tab %} {% /tabs %} The response returns the file metadata wrapped in a `files` array: ```json { "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: ```json { "error": { "message": "Path 'nonexistent.txt' not found in environment 'ENV_ID'.", "code": "not_found" } } ``` ### Download a single file {% id="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. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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) ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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)); ``` {% /tab %} {% tab label="REST" %} ```shell 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 ``` {% /tab %} {% /tabs %} ### Download a directory as a tar archive {% id="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. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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"); ``` {% /tab %} {% tab label="REST" %} ```shell # 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 ``` {% /tab %} {% /tabs %} #### 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 {% id="upload-a-file" %} 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. Note: REST uploads use the `/upload/` path prefix, for example `https://generativelanguage.googleapis.com/upload/v1beta/environments/{environment_id}/files/{path}`. A `PUT` sent without the prefix returns a `400` error. The Python and JavaScript clients add the prefix for you. #### Upload a single file {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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)") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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)`); ``` {% /tab %} {% tab label="REST" %} ```shell 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 ``` {% /tab %} {% /tabs %} The response returns metadata for the uploaded file, wrapped in a `files` array for consistency with the list and get endpoints: ```json { "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`. {% tabs %} {% tab filename="env_setup.py" label="Python" %} ```py 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}") ``` {% /tab %} {% tab filename="env_setup.js" label="JavaScript" %} ```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}`); } ``` {% /tab %} {% tab label="REST" %} ```shell 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 ``` {% /tab %} {% /tabs %} The response lists every file written by the archive: ```json { "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" } ] } ``` Note: The archive format is detected from the payload itself, so `.tar` and `.tar.gz` both work regardless of the `Content-Type` you send. #### 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: ```http 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 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: ```http 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 HTTP/1.1 308 Resume Incomplete Range: bytes=0-10485759 Content-Length: 0 ``` Send the remaining chunks the same way: ```http 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 ``` The final chunk completes the upload and returns the file metadata, in the same `files` envelope as a single-shot upload: ```json { "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: ```json { "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) {% id="download-full-snapshot-deprecated" %} Caution: The legacy `/files/environment-{id}:download` endpoint is deprecated. Use the [environment files endpoint](/docs/agent-environment#download-a-directory-as-a-tar-archive) to download directories or individual files instead. To migrate existing code to the environment files API: * **Python**: Replace legacy file download requests with: ```py 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: ```javascript 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=media` with: ```shell 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 {% id="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](/docs/pricing#pricing-for-agents) for agent token costs. ## Limitations {% id="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 Found` error. - **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 {% id="whats-next" %} * [Agents Overview](/docs/agents): Learn about the core concepts of managed agents. * [Quickstart](/docs/managed-agents-quickstart): Start building with multi-turn conversations and streaming. * [Antigravity Agent](/docs/antigravity-agent): Explore capabilities, tools, model selection, and pricing for the default agent. * [Building Custom Agents](/docs/custom-agents): Define your own agents using `AGENTS.md` and `SKILL.md`. * [Hooks](/docs/agent-hooks): Enforce security guardrails and run side-effect validations inside the sandbox.