관리형 에이전트의 환경(Environments)
관리형 에이전트의 환경(Environments)
환경(Environments)은 관리형 Linux 샌드박스로, 에이전트에게 코드를 실행하고 파일을 보관할 수 있는 격리된 공간을 제공해요. 상호작용 컨텍스트와 분리되어 있어서 같은 환경을 여러 상호작용에서 재사용하거나, 언제든 새로 시작할 수도 있답니다.
출처: 문서
본문
다음 예시는 새로운 원격 환경으로 상호작용을 만들고 그 ID를 가져오는 방법을 보여줘요.
Python
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}")
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}`);
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(""));
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)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-09-2026",
"input": "Install pandas and matplotlib, verify the imports, and print the versions.",
"environment": "remote"
}'
environment 매개변수
environment 매개변수는 세 가지 형태를 받아들일 수 있어요.
| 형태 | 예시 | 사용 시점 |
|---|---|---|
"remote" |
environment="remote" |
새 샌드박스를 프로비저닝할 때 |
| 환경 ID | environment="env_abc123" |
파일과 패키지를 모두 갖춘 기존 샌드박스를 재사용할 때 |
| 구성 객체 | environment={...} |
소스, 네트워크 규칙, 환경 변수 또는 이들의 조합으로 새 샌드박스를 프로비저닝할 때 |
다음 예시들은 environment 매개변수를 사용하는 세 가지 방법을 보여줘요.
Python
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)
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);
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(""));
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)
}
}
REST
# Fresh sandbox
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-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"
}
]
}
}'
환경 구성하기
환경을 설정하는 한 가지 방법은 에이전트에게 설치가 필요한 것을 알려주는 것이에요. 에이전트가 의존성 해결과 문제 해결을 처리해 줘요. 환경이 준비되면 environment_id를 저장해 두고 재사용하세요.
Python
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)
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);
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(""));
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)
}
}
REST
# Create interaction
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-09-2026",
"input": "Install pandas, matplotlib, and seaborn. Verify all imports work and print the installed versions.",
"environment": "remote"
}'
소스에서 마운트하기
에이전트가 필요로 하는 파일이 정확히 무엇인지 안다면, 반복해서 시도하는 대신 한 번의 호출로 마운트할 수 있어요. environment 구성 객체는 세 가지 유형을 가진 sources 배열을 받아요.
| 소스 유형 | type 값 |
설명 | 제한 |
|---|---|---|---|
| Git 저장소 | repository |
URL에서 샌드박스의 target 위치로 저장소를 클론해요. |
500 MB |
| Cloud Storage | gcs |
Cloud Storage의 파일이나 디렉터리를 샌드박스의 target 위치로 복사해요. |
2 GB |
| 인라인 콘텐츠 | inline |
원시 텍스트 콘텐츠를 샌드박스의 target 위치에 있는 파일로 작성해요. |
파일당 1 MB, 총 2 MB |
Python
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)
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);
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(""));
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)
}
}
REST
# Create interaction with sources
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-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"
}
]
}
}'
두 접근 방식을 조합할 수도 있어요. 알려진 소스를 선언적으로 마운트한 다음, 후속 상호작용을 통해 패키지를 설치하거나 설정 스크립트를 실행하는 식으로 반복할 수 있어요. 사용자 정의 소스를 추가할 때는 루트(/)를 target으로 설정할 수 없고, 항상 하위 디렉터리를 지정해야 해요.
Hooks
.agents/hooks.json 구성 파일과 사용자 정의 인터셉션(interception) 스크립트를 샌드박스에 마운트해서, 도구가 실행될 때마다 보안 가드레일을 강제하거나 자동 검증을 실행할 수도 있어요. 스키마 정의와 코드 예시는 Hooks 문서를 참고하세요.
비공개 소스
네트워크 구성에서 소스 도메인을 인증함으로써 비공개 GitHub 저장소나 비공개 Cloud Storage 버킷에서도 다운로드할 수 있어요.
한 가지 방법은 ID로 참조되는 저장된 credential을 사용하는 것이에요. 시크릿을 한 번 저장해 두면 그 소스가 필요한 모든 환경에서 참조할 수 있답니다.
"network": {
"allowlist": [
{ "domain": "github.com", "credential": "github-production" },
{ "domain": "*" }
]
}
또한 다음 예시들처럼 transform으로 헤더를 인라인으로 설정할 수도 있어요. 이그레스 프록시(egress proxy)는 두 형태 모두 동일하게 적용하며, 어느 쪽이든 시크릿이 샌드박스 안에 들어가지 않아요.
비공개 Git 저장소의 경우, GitHub Personal Access Token(PAT)과 함께 Basic 인증을 사용하세요. x-oauth-basic을 사용자 이름으로 사용해 토큰을 인코딩해요.
echo -n "x-oauth-basic:ghp_YourPATHere" | base64
Python
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": "*"
}
]
}
}
)
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: "*"
}
]
}
},
});
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
Environment env = Environment.builder()
.sources(List.of(
Source.builder()
.type(SourceType.REPOSITORY)
.source("https://github.com/your-org/backend")
.target("/backend-app")
.build()
))
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("github.com")
.transform(Transform.of(Map.of(
"Authorization", "Basic YOUR_BASE64_TOKEN"
)))
.build(),
AllowlistEntry.builder()
.domain("*")
.build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-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(""));
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.NewEnvironmentNetworkEgressAllowlist(interactions.Allowlist{
Allowlist: []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)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-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": "*"
}
]
}
}
}'
비공개 Cloud Storage 버킷의 경우, 표준 OAuth 2.0 Bearer 토큰을 사용하세요.
gcloud auth print-access-token
Python
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": "*"
}
]
}
},
)
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: "*"
}
]
}
},
});
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
Environment env = Environment.builder()
.sources(List.of(
Source.builder()
.type(SourceType.GCS)
.source("gs://my-private-bucket/data")
.target("/workspace")
.build()
))
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("*.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer YOUR_GCS_TOKEN"
)))
.build(),
AllowlistEntry.builder()
.domain("*")
.build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-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(""));
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.NewEnvironmentNetworkEgressAllowlist(interactions.Allowlist{
Allowlist: []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)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-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": "*"
}
]
}
}
}'
사전 설치된 소프트웨어
샌드박스는 Ubuntu에서 실행되며 런타임과 공용 패키지가 사전 설치되어 있어요. 에이전트는 pip install이나 npm install을 이용해 런타임 중 추가 패키지를 설치할 수 있어요. 상호작용 중 설치된 패키지는 같은 environment_id를 재사용하면 유지됩니다.
| 카테고리 | 사전 설치된 패키지 |
|---|---|
| UNIX 도구 | 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 |
환경 변수
env 필드를 사용해 샌드박스 안에 환경 변수를 설정할 수 있어요. 각 항목은 변수 이름을 구성용 리터럴 문자열 또는 시크릿용 저장된 credential 참조 중 하나로 매핑해요. 에이전트는 어떤 셸에서든 변수를 보게 되므로, 프로세스 환경에서 읽는 도구와 스크립트는 추가 배선 없이도 값을 가져올 수 있어요.
| 필드 | 타입 | 설명 |
|---|---|---|
env |
object |
변수 이름을 값으로 매핑한 맵. 값은 리터럴 string이거나 {"credential": "credential-id"} 형태의 자격 증명 참조예요. |
Python
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)
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);
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-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"}
}
}
}'
변수는 셸 명령, 빌드 단계, 시작되는 모든 프로세스를 포함해 그 상호작용에서 에이전트가 실행하는 모든 명령에 적용돼요.
두 값 유형은 다르게 동작해요. 리터럴 문자열은 컨테이너에 일반 텍스트로 작성돼요. 반면 자격 증명 참조는 그렇지 않아요. 변수에는 플레이스홀더가 들어가고, 이그레스 프록시가 해당 자격 증명의 신뢰된 도메인으로 가는 아웃바운드 요청에서만 실제 시크릿으로 치환해 줘요. 자세한 내용은 자격 증명을 환경 변수로 사용 문서를 참고하세요.
주의: 리터럴 값은 에이전트 자신을 포함해 샌드박스에서 실행되는 모든 것에 읽힐 수 있어요. NODE_ENV 같은 구성용으로만 사용하고 시크릿용으로는 사용하지 마세요. 모든 시크릿은 자격 증명에 넣어야 해요.
네트워크 구성
기본적으로 환경은 제한 없는 아웃바운드 네트워크 접근을 가져요. network 필드를 사용해 아웃바운드 트래픽을 특정 도메인으로 제한할 수 있어요. 각 규칙은 domain을 지정하고, 선택적으로 저장된 시크릿을 주입할 credential과 일치하는 요청에 헤더를 주입할 선택적 transform 객체를 포함해요. 이러한 헤더는 상호작용마다 다를 수 있으며, 같은 환경에 대해 업데이트할 수도 있어요.
| 필드 | 타입 | 설명 |
|---|---|---|
domain |
string |
일치시킬 도메인. 정확한 호스트 이름 또는 모든 도메인에 대한 *를 사용해요. |
credential |
string |
저장된 credential의 ID. 이그레스 프록시가 이를 해석해 요청 시점에 인증 헤더를 주입해요. |
transform |
object |
일치하는 요청에 주입할 헤더를 나타내는 평평한 key-value 쌍 객체, 예: {"Authorization": "Bearer ..."} |
Python
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)
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);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
Environment env = Environment.builder()
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("api.github.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer ghp_your_github_token"
)))
.build(),
AllowlistEntry.builder().domain("pypi.org").build(),
AllowlistEntry.builder().domain("*").build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-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(""));
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.NewEnvironmentNetworkEgressAllowlist(interactions.Allowlist{
Allowlist: []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)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-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": "*"}
]
}
}
}'
허용 목록이 설정되면 명시적으로 나열된 도메인에 대한 요청만 허용돼요. 와일드카드를 사용해 서브도메인을 일치시킬 수 있지만(예: {"domain": "*.example.com"}), 이것은 루트 도메인 example.com과 일치하지 않으므로 별도로 추가해야 해요. 나열되지 않은 도메인을 헤더 주입 없이 라우팅하는 등 다른 모든 트래픽을 허용하려면 catch-all 항목으로 {"domain": "*"}을 추가하세요.
자격 증명(Credentials)
아웃바운드 트래픽을 인증하는 두 가지 방법이 있어요. ID로 참조되는 저장된 자격 증명과 허용 목록 규칙의 인라인 transform이에요. 이그레스 프록시는 둘 다 와이어 상에서 적용하므로, 두 경우 모두 시크릿이 샌드박스에 들어가지 않고 상호작용 페이로드에도 나타나지 않아요.
관리형 자격 증명은 시크릿을 한 번 저장하고 재사용하고 싶을 때 찾게 되는 것이에요. 프로젝트의 모든 환경, 에이전트, 트리거가 같은 ID를 참조할 수 있고, 한 곳에서 회전(rotation)시킬 수 있어요.
Python
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)
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);
REST
# 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": "*" }
]
}
}
}'
oauth2 자격 증명은 액세스 토큰을 스스로 갱신하기도 해서, 장기 실행 상호작용이 토큰 만료로 끊기지 않아요. 자격 증명 유형과 관리 작업 전체 목록은 자격 증명 문서를 참고하세요.
transform으로 헤더를 인라인 설정할 수도 있어요. 값이 단일 호출에 속할 때, 예를 들어 상호작용을 만들기 바로 직전에 생성한 토큰 같은 경우에 적합해요. 이렇게 설정된 헤더는 같은 이그레스 프록시에 의해 주입되며, 샌드박스 안에서 환경 변수나 파일로 노출되지 않아요.
Python
import subprocess
from google import genai
# Fetch a short-lived access token from your local gcloud CLI
gcloud_token = subprocess.check_output(
["gcloud", "auth", "print-access-token"], text=True
).strip()
client = genai.Client()
interaction = client.interactions.create(
agent="antigravity-preview-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)
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);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
// Fetch a short-lived access token from your local gcloud CLI
Process process = new ProcessBuilder("gcloud", "auth", "print-access-token").start();
String gcloudToken = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8).trim();
Client client = new Client();
Environment env = Environment.builder()
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("storage.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer " + gcloudToken
)))
.build()
))
.build()
)))
.build();
CreateAgentInteraction params = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-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(""));
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.NewEnvironmentNetworkEgressAllowlist(interactions.Allowlist{
Allowlist: []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)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-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 <YOUR_GCLOUD_TOKEN>"
}
}
]
}
}
}'
credential과 transform은 같은 규칙에 나타날 수 있어요. credential이 먼저 적용되고 transform이 그 위에 병합되므로, 둘 다 같은 키를 설정하면 명시적인 transform 헤더가 우선해요. 흔한 패턴은 인증 헤더용 자격 증명에 서비스가 함께 기대하는 추가 헤더용 transform을 더하는 것이에요.
네트워크 접근 비활성화
모든 아웃바운드 네트워크 접근을 차단하려면 network를 disabled로 설정하세요.
Python
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)
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);
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(""));
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)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-09-2026",
"input": "Analyze the local files only.",
"environment": {
"type": "remote",
"network": "disabled"
}
}'
자격 증명 갱신
액세스 토큰이나 수명이 짧은 API 키 같은 인라인 토큰은 만료돼요. 다음 상호작용에서 기존 environment_id를 새 network 구성과 함께 전달하면 갱신할 수 있어요. 새 네트워크 규칙은 이전 규칙을 완전히 대체하지만, 환경의 파일 시스템 상태(설치된 패키지, 파일, 저장소)는 보존돼요.
대신 저장된 credential을 사용한다면 이 작업이 필요 없어요. oauth2 자격 증명은 스스로 갱신되고, 어떤 자격 증명이든 회전은 credential에 대한 PATCH로 처리되며 이를 참조하는 모든 허용 목록 규칙은 그대로 남아요.
Python
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)
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);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AgentOption;
import com.google.genai.gaos.models.interactions.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;
Client client = new Client();
// First interaction: use an initial token
Environment initialEnv = Environment.builder()
.network(Network.of(EnvironmentNetworkEgressAllowlist.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("storage.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer INITIAL_TOKEN"
)))
.build()
))
.build()
)))
.build();
CreateAgentInteraction firstParams = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-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.of(
Allowlist.builder()
.allowlist(List.of(
AllowlistEntry.builder()
.domain("storage.googleapis.com")
.transform(Transform.of(Map.of(
"Authorization", "Bearer REFRESHED_TOKEN"
)))
.build()
))
.build()
)))
.build();
CreateAgentInteraction secondParams = CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-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(""));
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.NewEnvironmentNetworkEgressAllowlist(interactions.Allowlist{
Allowlist: []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.NewEnvironmentNetworkEgressAllowlist(interactions.Allowlist{
Allowlist: []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)
}
}
REST
# Use the environment_id from a previous interaction
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-09-2026",
"input": "Now download the file reports/q1.csv from the same bucket.",
"environment": {
"type": "remote",
"environment_id": "<ENVIRONMENT_ID_FROM_PREVIOUS_INTERACTION>",
"network": {
"allowlist": [
{
"domain": "storage.googleapis.com",
"transform": {
"Authorization": "Bearer REFRESHED_TOKEN"
}
}
]
}
}
}'
환경 수명 주기(Environment lifecycle)
환경은 다음과 같은 수명 주기를 따라요.
| 상태 | 동작 |
|---|---|
| Created | 상호작용이 environment: "remote" 또는 구성 객체를 지정하면 프로비저닝돼요. |
| Active | 상호작용이 진행되는 동안 실행 중이에요. |
| Idle | 15분간 비활성이면 자동 스냅샷 후 중지돼요. |
| Offline | 마지막 활성 이후 7일간 보관돼요. ID를 전달하면 재개할 수 있어요. |
| Deleted | 7일 TTL 보존 기간이 만료되거나 수동 삭제 시 시스템에서 자동으로 제거돼요. |
Environments API
Environments API를 사용해 샌드박스 세션을 프로그래밍 방식으로 관리할 수 있어요. 환경을 열거하면 활성 세션 ID를 발견하고, 장기 실행 작업 중 클라이언트 연결이 끊어져도 상태를 복구할 수 있어요. 또한 세션 메타데이터를 검사하고, 자동 TTL 만료를 기다리는 대신 워크플로가 끝나면 환경을 명시적으로 삭제할 수도 있어요.
환경 나열(List environments)
프로젝트에 속한 활성 환경을 나열해요. 페이징 매개변수를 사용해 응답 배치 크기를 제어할 수 있어요.
Python
from google import genai
client = genai.Client()
response = client.environments.list(page_size=10)
for env in response.environments:
print(f"Environment ID: {env.id}, Status: {env.status}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const response = await client.environments.list({ page_size: 10 });
for (const env of response.environments) {
console.log(`Environment ID: ${env.id}, Status: ${env.status}`);
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.environments.Environment;
import com.google.genai.gaos.models.environments.ListEnvironmentsResponse;
import java.util.List;
Client client = new Client();
ListEnvironmentsResponse response = client.environments.listEnvironments()
.pageSize(10)
.call()
.listEnvironmentsResponse()
.get();
for (Environment env : response.environments().orElse(List.of())) {
System.out.println("Environment ID: " + env.id().orElse("") + ", Status: " + env.status().orElse(null));
}
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)
}
}
}
REST
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments?pageSize=10" \
-H "x-goog-api-key: $GEMINI_API_KEY"
응답은 다음과 비슷하게 보여요.
{
"environments": [
{
"id": "140128b2a13c12c00a5a0d8cf7af9469",
"status": "active"
},
{
"id": "362b738275a1d74af6f1c62bc050da73",
"status": "active"
}
],
"next_page_token": "Cj...5aE="
}
환경 가져오기(Get an environment)
리소스 이름으로 특정 환경의 메타데이터와 구성 세부 정보를 가져와요.
Python
from google import genai
client = genai.Client()
env = client.environments.get(id="YOUR_ENVIRONMENT_ID")
print(f"Environment ID: {env.id}, Status: {env.status}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const env = await client.environments.get("YOUR_ENVIRONMENT_ID");
console.log(`Environment ID: ${env.id}, Status: ${env.status}`);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.environments.Environment;
Client client = new Client();
Environment env = client.environments.getEnvironment("YOUR_ENVIRONMENT_ID").environment().get();
System.out.println("Environment ID: " + env.id().orElse("") + ", Status: " + env.status().orElse(null));
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)
}
REST
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/YOUR_ENVIRONMENT_ID" \
-H "x-goog-api-key: $GEMINI_API_KEY"
응답은 다음과 비슷하게 보여요.
{
"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)
작업이나 파이프라인이 끝나면 환경을 명시적으로 종료·삭제해 샌드박스 리소스를 정리해요.
Python
from google import genai
client = genai.Client()
client.environments.delete(id="YOUR_ENVIRONMENT_ID")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
await client.environments.delete("YOUR_ENVIRONMENT_ID");
Java
import com.google.genai.Client;
Client client = new Client();
client.environments.deleteEnvironment("YOUR_ENVIRONMENT_ID");
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)
}
}
REST
curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/environments/YOUR_ENVIRONMENT_ID" \
-H "x-goog-api-key: $GEMINI_API_KEY"
환경에서 파일 관리
에이전트는 실행 중 샌드박스 안에서 파일을 만들고 수정해요. 디렉터리 내용을 탐색하고, 파일 메타데이터를 가져오고, 개별 파일이나 디렉터리 전체를 tar 아카이브로 다운로드하고, 파일을 업로드하거나 아카이브를 환경에 직접 풀 수 있어요. 샌드박스 환경의 저장 공간에는 공정 사용(fair usage) 제한이 적용돼요.
디렉터리의 파일 나열(List files in a directory)
환경에서 디렉터리의 내용을 나열해요. 기본적으로 루트 디렉터리를 나열해요.
쿼리 매개변수
| 매개변수 | 타입 | 설명 |
|---|---|---|
recursive |
boolean | true이면 모든 파일과 디렉터리를 재귀적으로 나열해요. 기본값: false. |
Python
from google import genai
client = genai.Client()
# List root directory
response = client.environments.files.list(
environment="YOUR_ENVIRONMENT_ID",
path="",
)
for file in response.files:
print(f"{file.name} ({file.type}) - {file.path}")
# List a subdirectory recursively
response = client.environments.files.list(
environment="YOUR_ENVIRONMENT_ID",
path="src",
recursive=True,
)
for file in response.files:
print(f"{file.name} ({file.type}) - {file.path}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
// List root directory
const response = await client.environments.files.list({
environment: "YOUR_ENVIRONMENT_ID",
path: "",
});
for (const file of response.files) {
console.log(`${file.name} (${file.type}) - ${file.path}`);
}
// List a subdirectory recursively
const srcResponse = await client.environments.files.list({
environment: "YOUR_ENVIRONMENT_ID",
path: "src",
recursive: true,
});
for (const file of srcResponse.files) {
console.log(`${file.name} (${file.type}) - ${file.path}`);
}
REST
# List root directory
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files" \
-H "x-goog-api-key: $GEMINI_API_KEY"
# List a subdirectory
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src" \
-H "x-goog-api-key: $GEMINI_API_KEY"
# List all files recursively
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files?recursive=true" \
-H "x-goog-api-key: $GEMINI_API_KEY"
응답은 각 항목의 메타데이터를 가진 files 배열을 반환해요.
{
"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"
}
]
}
파일 항목 필드
| 필드 | 타입 | 설명 |
|---|---|---|
name |
string | 파일 또는 디렉터리 이름. |
path |
string | 환경 루트 기준 전체 경로. |
type |
string | FILE 또는 DIRECTORY 중 하나. |
size_bytes |
string | 파일 크기(바이트, 파일만). |
mime_type |
string | MIME 타입(파일만). |
created |
string | ISO 8601 생성 타임스탬프. |
modified |
string | ISO 8601 마지막 수정 타임스탬프. |
파일 메타데이터 가져오기(Get file metadata)
경로로 특정 파일의 메타데이터를 가져와요.
Python
from google import genai
client = genai.Client()
response = client.environments.files.list(
environment="YOUR_ENVIRONMENT_ID",
path="src/main.py",
)
file = response.files[0]
print(f"Name: {file.name}, Size: {file.size_bytes} bytes, Type: {file.mime_type}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const response = await client.environments.files.list({
environment: "YOUR_ENVIRONMENT_ID",
path: "src/main.py",
});
const file = response.files[0];
console.log(`Name: ${file.name}, Size: ${file.size_bytes} bytes, Type: ${file.mime_type}`);
REST
curl -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src/main.py" \
-H "x-goog-api-key: $GEMINI_API_KEY"
응답은 파일 메타데이터를 files 배열로 감싸서 반환해요.
{
"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"
}
]
}
파일이 존재하지 않으면 API는 404 오류를 반환해요.
{
"error": {
"message": "Path 'nonexistent.txt' not found in environment 'ENV_ID'.",
"code": "not_found"
}
}
단일 파일 다운로드(Download a single file)
특정 파일의 내용을 다운로드해요. SDK에서는 download() 메서드를 사용해요. REST 요청에서는 파일 경로에 ?alt=media 쿼리 매개변수를 추가해요. 서버는 200 OK로 응답하고 원시 파일 내용을 스트리밍해요.
Python
from google import genai
client = genai.Client()
content = client.environments.files.download(
environment="YOUR_ENVIRONMENT_ID",
path="src/main.py",
)
with open("main.py", "wb") as f:
f.write(content)
JavaScript
import { GoogleGenAI } from "@google/genai";
import * as fs from "fs";
const client = new GoogleGenAI({});
const bytes = await client.environments.files.download({
environment: "YOUR_ENVIRONMENT_ID",
path: "src/main.py",
});
fs.writeFileSync("main.py", Buffer.from(bytes));
REST
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src/main.py?alt=media" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o main.py
디렉터리를 tar 아카이브로 다운로드
?alt=media와 함께 디렉터리 경로를 요청해 디렉터리 전체를 tar 아카이브로 다운로드해요. POSIX tar 파일(gzip 아님)을 반환해요. 중첩된 하위 디렉터리를 포함하려면 recursive=true를 사용하세요.
Python
import tarfile
from google import genai
client = genai.Client()
# Download a subdirectory archive
archive = client.environments.files.download(
environment="YOUR_ENVIRONMENT_ID",
path="src",
)
with open("src.tar", "wb") as f:
f.write(archive)
with tarfile.open("src.tar") as tar:
tar.extractall(path="./extracted")
JavaScript
import { GoogleGenAI } from "@google/genai";
import { execSync } from "child_process";
import * as fs from "fs";
const client = new GoogleGenAI({});
// Download a subdirectory archive
const bytes = await client.environments.files.download({
environment: "YOUR_ENVIRONMENT_ID",
path: "src",
});
fs.writeFileSync("src.tar", Buffer.from(bytes));
execSync("tar -xf src.tar -C ./extracted");
REST
# Download a subdirectory (top-level files only)
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/src?alt=media" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o src.tar
# Download a subdirectory recursively (includes nested directories)
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files/config?alt=media&recursive=true" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o config.tar
# Download root directory
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/environments/$ENV_ID/files?alt=media" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-o snapshot.tar
# Extract the archive
tar xf snapshot.tar -C ./extracted
동작 매트릭스
다음 동작 매트릭스는 파일·디렉터리 엔드포인트, HTTP 메서드, 쿼리 매개변수에 따른 예상 응답과 아카이브 동작을 정리한 것이에요.
| 요청 | alt |
recursive |
extract |
overwrite |
응답 |
|---|---|---|---|---|---|
GET /files |
(없음) | (없음) | - | - | 루트 디렉터리의 JSON 목록 |
GET /files/{path} (파일) |
(없음) | - | - | - | 파일의 JSON 메타데이터 |
GET /files/{path} (디렉터리) |
(없음) | false |
- | - | 바로 아래 자식의 JSON 목록 |
GET /files/{path} (디렉터리) |
(없음) | true |
- | - | 모든 하위 항목의 JSON 목록 |
GET /files/{path}?alt=media (파일) |
media |
- | - | - | 원시 파일 내용 |
GET /files/{path}?alt=media (디렉터리) |
media |
false |
- | - | 디렉터리에 있는 바로 아래 파일의 tar 아카이브 |
GET /files/{path}?alt=media (디렉터리) |
media |
true |
- | - | 모든 파일을 재귀적으로 포함한 tar 아카이브 |
GET /files?alt=media |
media |
false |
- | - | 루트 레벨 파일만 담은 tar 아카이브 |
PUT /files/{path} (파일) |
- | - | false |
false |
경로에 파일을 작성. 이미 존재하면 409 Conflict 반환 |
PUT /files/{path}?overwrite=true |
- | - | false |
true |
경로에 파일을 작성하거나 덮어씀 |
PUT /files/{path}?extract=true |
- | - | true |
false |
아카이브를 대상 디렉터리에 풀기. 대상 파일이 존재하면 409 Conflict 반환 |
PUT /files/{path}?extract=true&overwrite=true |
- | - | true |
true |
기존 파일을 대체하며 아카이브 풀기 |
환경에 파일 업로드
HTTP PUT을 사용해 개별 파일이나 디렉터리 아카이브를 기존 환경 샌드박스에 직접 업로드해요. 대상 디렉터리가 없으면 자동으로 생성돼요. 환경의 저장 공간에는 공정 사용 제한이 적용돼요.
참고: REST 업로드는 /upload/ 경로 접두사를 사용해요, 예를 들어 https://generativelanguage.googleapis.com/upload/v1beta/environments/{environment_id}/files/{path}와 같아요. 접두사 없이 보낸 PUT은 400 오류를 반환해요. Python과 JavaScript 클라이언트는 접두사를 자동으로 추가해 줘요.
단일 파일 업로드
Python
from google import genai
client = genai.Client()
with open("local_file.txt", "rb") as f:
result = client.environments.files.upload(
environment="YOUR_ENVIRONMENT_ID",
path="workspace/data/file.txt",
file=f,
mime_type="text/plain",
overwrite=True,
)
file = result.files[0]
print(f"Uploaded: {file.name} ({file.size_bytes} bytes)")
JavaScript
import { GoogleGenAI } from "@google/genai";
import * as fs from "fs";
const client = new GoogleGenAI({});
const content = fs.readFileSync("local_file.txt");
const result = await client.environments.files.upload({
environment: "YOUR_ENVIRONMENT_ID",
path: "workspace/data/file.txt",
file: content,
mime_type: "text/plain",
overwrite: true,
});
const file = result.files[0];
console.log(`Uploaded: ${file.name} (${file.size_bytes} bytes)`);
REST
curl -X PUT "https://generativelanguage.googleapis.com/upload/v1beta/environments/$ENV_ID/files/workspace/data/file.txt" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: text/plain" \
--data-binary @local_file.txt
응답은 목록·조회 엔드포인트와 일관되도록 업로드된 파일의 메타데이터를 files 배열로 감싸 반환해요.
{
"files": [
{
"name": "file.txt",
"path": "workspace/data/file.txt",
"type": "FILE",
"size_bytes": "1024",
"mime_type": "text/plain"
}
]
}
디렉터리 아카이브 업로드 및 풀기
전체 코드베이스나 디렉터리 구조를 한 번의 요청으로 시드하려면 extract=true와 함께 .tar 또는 .tar.gz 아카이브를 업로드하세요.
Python
from google import genai
client = genai.Client()
with open("source.tar.gz", "rb") as f:
result = client.environments.files.upload(
environment="YOUR_ENVIRONMENT_ID",
path="workspace/src/",
file=f,
extract=True,
)
for entry in result.files:
print(f"Extracted: {entry.path}")
JavaScript
import { GoogleGenAI } from "@google/genai";
import * as fs from "fs";
const client = new GoogleGenAI({});
const archive = fs.readFileSync("source.tar.gz");
const result = await client.environments.files.upload({
environment: "YOUR_ENVIRONMENT_ID",
path: "workspace/src/",
file: archive,
extract: true,
});
for (const entry of result.files) {
console.log(`Extracted: ${entry.path}`);
}
REST
curl -X PUT "https://generativelanguage.googleapis.com/upload/v1beta/environments/$ENV_ID/files/workspace/src/?extract=true" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/x-tar" \
--data-binary @source.tar.gz
응답은 아카이브가 작성한 모든 파일을 나열해요.
{
"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"
}
]
}
참고: 아카이브 형식은 페이로드 자체에서 감지되므로, 보내는 Content-Type과 무관하게 .tar와 .tar.gz 모두 동작해요.
재개 가능한 세션으로 대용량 파일 업로드
대용량 페이로드나 불안정한 연결을 통한 업로드에는 전체 본문을 한 번에 보내는 대신 재개 가능한(resumable) 세션을 사용하세요. 재개 가능한 업로드는 전송을 개별 재시도 가능한 청크로 나누므로, 중간에 실패해도 처음부터 다시 시작할 필요가 없어요.
uploadType=resumable로 세션을 시작하세요. 빈 본문을 보내고 X-Upload-Content-Type과 X-Upload-Content-Length 헤더로 업로드할 페이로드의 미디어 타입과 총 크기를 선언해요.
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
응답은 Location 헤더에 세션 URL을 담아요. 이 URL에는 이미 upload_id가 포함되어 있어서 API 키를 다시 필요로 하지 않아요.
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
페이로드를 해당 URL에 청크 단위로 업로드해요. 각 청크는 Content-Range 헤더로 바이트 범위와 총 크기를 선언해요.
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>
마지막 청크를 제외한 모든 청크는 308 Resume Incomplete를 반환해요. Range 헤더는 서버가 커밋한 바이트 수를 알려주는데, 청크가 실패하면 여기서부터 재개하면 돼요.
HTTP/1.1 308 Resume Incomplete
Range: bytes=0-10485759
Content-Length: 0
나머지 청크도 같은 방식으로 보내요.
PUT /upload/v1beta/environments/$ENV_ID/files/workspace/data/large_dataset.bin?uploadType=resumable&upload_id=AJjja9bfHjiYlGi60pUazCaTuPY HTTP/1.1
Host: generativelanguage.googleapis.com
Content-Type: application/octet-stream
Content-Range: bytes 10485760-20971519/20971520
Content-Length: 10485760
<remaining 10 MB binary payload>
마지막 청크는 업로드를 완료하고, 단일 요청 업로드와 같은 files 봉투로 파일 메타데이터를 반환해요.
{
"files": [
{
"name": "large_dataset.bin",
"path": "workspace/data/large_dataset.bin",
"type": "FILE",
"size_bytes": "20971520",
"mime_type": "application/octet-stream"
}
]
}
재개 가능한 세션은 extract와 overwrite와도 함께 동작해요. 이러한 쿼리 매개변수는 개별 청크가 아니라 시작 요청에서 설정하세요.
덮어쓰기 보호(Overwrite protection)
기본적으로 overwrite는 false예요. 대상 경로가 이미 존재하면 요청은 409 Conflict 오류를 반환하고 아무것도 작성하지 않아요.
{
"error": {
"message": "Requested entity already exists",
"code": "aborted"
}
}
기존 파일이나 디렉터리를 대체하려면 overwrite=true를 설정하세요(또는 REST에서 ?overwrite=true를 추가). extract=true의 경우 충돌 검사가 아카이브의 모든 파일에 적용되므로, 대상 파일이 하나라도 존재하면 요청은 실패해요.
전체 스냅샷 다운로드(더 이상 사용되지 않음)
주의: 레거시 /files/environment-{id}:download 엔드포인트는 더 이상 사용되지 않아요(deprecated). 디렉터리나 개별 파일을 다운로드할 때는 환경 파일 엔드포인트를 사용하세요.
기존 코드를 환경 파일 API로 마이그레이션하려면:
- Python: 레거시 파일 다운로드 요청을 다음으로 대체하세요.
archive = client.environments.files.download(
environment="YOUR_ENVIRONMENT_ID",
path="workspace",
)
with open("snapshot.tar", "wb") as f:
f.write(archive)
- JavaScript: 레거시 파일 다운로드 요청을 다음으로 대체하세요.
const bytes = await client.environments.files.download({
environment: "YOUR_ENVIRONMENT_ID",
path: "workspace",
});
fs.writeFileSync("snapshot.tar", Buffer.from(bytes));
- REST:
GET /v1beta/files/environment-$ENV_ID:download?alt=media를 다음으로 대체하세요.
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
가격 및 리소스
각 환경은 고정된 리소스 할당으로 실행돼요.
| 리소스 | 값 |
|---|---|
| CPU | 4 코어 |
| 메모리 | 16 GB |
환경 컴퓨팅(CPU, 메모리, 샌드박스 실행)은 미리보기 기간 동안 청구되지 않아요. 에이전트 토큰 비용은 Pricing 문서를 참고하세요.
제한 사항
- 미리보기 상태: Environments와 관리형 에이전트는 미리보기 중이며, 기능과 스키마가 변경될 수 있어요.
- 인라인 소스 크기: 인라인 소스는 파일당 1 MB, 전체 파일 합산 2 MB로 제한돼요.
- 소스 크기: Git 저장소는 500 MB, Cloud Storage 저장소는 2 GB로 제한돼요.
- 환경 시작: 새 환경 프로비저닝에는 최대 ~5초가 걸려요. 큰 소스 저장소는 이 시간을 늘릴 수 있어요.
- 환경 만료: 비활성 오프라인 환경은 자동 TTL 정리로 만료되기 전 7일간 보관돼요. 만료되거나 잘못된 환경 ID를 전달하면
404 Not Found오류를 반환해요. - 파일 지원: 에이전트는 현재 텍스트와 이미지 파일 읽기로 제한돼요. 바이너리 파일 지원은 아직 제공되지 않아요.
- 루트 마운트 불가: 사용자 정의 소스를 추가할 때 루트(
/)를 target으로 설정할 수 없고, 항상 하위 디렉터리를 지정해야 해요.
다음 단계
- Agents 개요: 관리형 에이전트의 핵심 개념을 알아보세요.
- Quickstart: 멀티 턴 대화와 스트리밍으로 빌드를 시작하세요.
- Antigravity Agent: 기본 에이전트의 기능, 도구, 모델 선택, 가격을 살펴보세요.
- Custom 에이전트 구축:
AGENTS.md와SKILL.md를 사용해 자신만의 에이전트를 정의하세요. - Hooks: 샌드박스 안에서 보안 가드레일을 강제하고 부작용 검증을 실행하세요.
더 알아보기 (Learn more)
관리형 에이전트의 환경은 코드 실행과 파일 보관을 위한 격리된 Linux 샌드박스를 제공해요. remote 문자열, 환경 ID, 또는 구성 객체 세 가지 형태로 환경을 지정하고, 소스 마운트·네트워크 규칙·환경 변수·자격 증명을 조합해 세밀하게 제어할 수 있어요. 관련 안내는 Agents 개요, Custom 에이전트 구축, Antigravity Agent 문서를 이어서 살펴보세요.