Mit Hooks können Sie benutzerdefinierte Skripts oder externe HTTP-Anfragen ausführen, kurz bevor oder nachdem der Agent Code ausführt oder Dateien in seiner Remote-Sandbox ändert. Verwenden Sie Hooks, um die Agentenschleife mit automatisierten Schutzmaßnahmen und Hintergrund-Workflows zu erweitern, z. B.:
- Sicherheits- und Zugriffsschutzmaßnahmen erzwingen , bevor Shell-Befehle mit hohem Risiko oder eingeschränkte Dateilesevorgänge ausgeführt werden.
- Datentransformationen in der Datenpipeline automatisieren , direkt nachdem ein Agent Dateien erstellt oder geändert hat.
Streaming von Audit-Telemetriedaten für Unternehmen an externe Monitoring-Systeme nach der Ausführung des Tools.
Python
import json
from google import genai
client = genai.Client()
hooks_config = {
"security-gate": {
"pre_tool_execution": [
{
"matcher": "code_execution",
"hooks": [
{
"type": "command",
"command": "python3 /.agents/hooks-scripts/gate.py",
"timeout": 10,
}
],
}
]
}
}
gate_script = """#!/usr/bin/env python3
import sys, json
data = json.load(sys.stdin)
cmd = str(data.get("tool_call", {}).get("args", {}))
if "rm -rf" in cmd:
print(json.dumps({"decision": "deny", "reason": "Destructive command blocked by security gate."}))
else:
print(json.dumps({"decision": "allow"}))
"""
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Run `rm -rf /tmp/forbidden` using code_execution.",
tools=[{"type": "code_execution"}],
environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/hooks.json",
"content": json.dumps(hooks_config, indent=2),
},
{
"type": "inline",
"target": ".agents/hooks-scripts/gate.py",
"content": gate_script,
},
],
},
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const hooksConfig = {
"security-gate": {
pre_tool_execution: [
{
matcher: "code_execution",
hooks: [
{
type: "command",
command: "python3 /.agents/hooks-scripts/gate.py",
timeout: 10,
},
],
},
],
},
};
const gateScript = `#!/usr/bin/env python3
import sys, json
data = json.load(sys.stdin)
cmd = str(data.get("tool_call", {}).get("args", {}))
if "rm -rf" in cmd:
print(json.dumps({"decision": "deny", "reason": "Destructive command blocked by security gate."}))
else:
print(json.dumps({"decision": "allow"}))
`;
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Run `rm -rf /tmp/forbidden` using code_execution.",
tools: [{ type: "code_execution" }],
environment: {
type: "remote",
sources: [
{
type: "inline",
target: ".agents/hooks.json",
content: JSON.stringify(hooksConfig, null, 2),
},
{
type: "inline",
target: ".agents/hooks-scripts/gate.py",
content: gateScript,
},
],
},
});
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.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
CreateAgentInteraction params =
CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Build a simple REST API server in Node.js."))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": [{"type": "text", "text": "Run `rm -rf /tmp/forbidden` using code_execution."}],
"tools": [{"type": "code_execution"}],
"environment": {
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/hooks.json",
"content": "{\"security-gate\": {\"pre_tool_execution\": [{\"matcher\": \"code_execution\", \"hooks\": [{\"type\": \"command\", \"command\": \"python3 /.agents/hooks-scripts/gate.py\", \"timeout\": 10}]}]}}"
},
{
"type": "inline",
"target": ".agents/hooks-scripts/gate.py",
"content": "#!/usr/bin/env python3\nimport sys, json\ndata = json.load(sys.stdin)\ncmd = str(data.get(\"tool_call\", {}).get(\"args\", {}))\nif \"rm -rf\" in cmd:\n print(json.dumps({\"decision\": \"deny\", \"reason\": \"Destructive command blocked by security gate.\"}))\nelse:\n print(json.dumps({\"decision\": \"allow\"}))\n"
}
]
}
}'
Unterstützte Lifecycle-Events
Hooks unterstützen zwei Ereignisse in der Sandbox:
| Ereignis | Wann es ausgelöst wird | Funktion |
|---|---|---|
pre_tool_execution |
Kurz bevor ein Tool ausgeführt wird | Kann das Tool genehmigen (allow) oder blockieren (deny), bevor es ausgeführt wird. Wenn es blockiert wird, sieht das Modell den Grund für die Ablehnung und passt sich an. |
post_tool_execution |
Direkt nach Abschluss eines Tools | Führt Folgeaufgaben aus, z. B. Code formatieren, Unit-Tests ausführen oder Telemetriedaten protokollieren. Abgeschlossene Aktionen können nicht blockiert oder rückgängig gemacht werden. |
pre_tool_execution
Wird ausgelöst, kurz bevor ein Tool ausgeführt wird. Ihr Skript liest die Details des Toolaufrufs aus stdin und gibt die JSON-Entscheidung (allow oder deny) an stdout aus.
Eingabe-Payload (stdin):
{
"tool_call": {
"name": "code_execution",
"args": {
"code": "rm -rf /tmp/forbidden",
"language": "bash"
}
},
"environment_id": "env_xyz789"
}
Ausgabeantwort (stdout):
So genehmigen Sie den Toolaufruf:
{
"decision": "allow"
}
So blockieren Sie den Toolaufruf und geben Feedback an das Modell zurück:
{
"decision": "deny",
"reason": "Destructive command blocked by security gate."
}
Wenn ein Hook einen Befehl ablehnt, wird der Toolaufruf sofort übersprungen. Der Agent sieht direkt in seiner aktuellen Runde ein Fehlerergebnis mit dem Grund für die Ablehnung. Das Modell kann sich dann selbst korrigieren, indem es einen alternativen Befehl auswählt oder dem Nutzer die Blockierung erklärt.
Wenn Ihr Skript nicht erkannte JSON, Nur-Text oder etwas anderes als {"decision": "deny"} ausgibt, behandelt die Laufzeit die Antwort als Genehmigung (allow).
post_tool_execution
Wird ausgelöst, direkt nachdem ein Tool abgeschlossen wurde. Ihr Skript liest die Ausführungsdetails und alle Fehlerstatus aus stdin.
Eingabe-Payload (stdin):
{
"tool_call": {
"name": "code_execution",
"args": {
"code": "python3 /workspace/app.py",
"language": "bash"
}
},
"environment_id": "env_xyz789"
}
Wenn ein Shell-Befehl Fehler an die Standardfehlerausgabe (stderr) ausgibt oder ein Dateisystemvorgang fehlschlägt, wird ein Feld "error" mit dem Fehlertext in die Payload aufgenommen. Wenn der Befehl ohne Fehler ausgeführt wird, wird das "error" Feld vollständig weggelassen.
Ausgabeantwort (stdout):
{}
Da Post-Tool-Hooks ausschließlich für Hintergrundaufgaben wie die Codeformatierung oder das Logging ausgeführt werden, ignoriert die Laufzeit alle Entscheidungswerte, die an stdout zurückgegeben werden.
Konfigurationserkennung
Die Laufzeit erkennt Hook-Definitionen automatisch aus .agents/hooks.json oder /.agents/hooks.json in der Sandbox-Umgebung. Sie können hooks.json zusammen mit Ihren benutzerdefinierten Skripts über eine beliebige unterstützte Umgebungsquelle bereitstellen:
- Repository-Mount: Ein Git-Repository mit
.agents/hooks.jsonnebenAGENTS.md. - Cloud Storage (
gcs): Ein GCS-Bucket mithooks.json, das in die Umgebung kopiert wurde. - Inline-Quellen: JSON-Rohstring und Skriptinhalte, die beim Aufrufen von
client.interactions.createinenvironment.sourcesübergeben werden.
hooks.json-Schema
In einer hooks.json-Datei werden Ereignisdefinitionen (pre_tool_execution oder post_tool_execution) unter benutzerdefinierten Namen gruppiert. Sie können jede Gruppe unabhängig aktivieren oder deaktivieren:
{
"security-gate": {
"enabled": true,
"pre_tool_execution": [
{
"matcher": "code_execution",
"hooks": [
{
"type": "command",
"command": "python3 /.agents/hooks-scripts/gate.py",
"timeout": 10
}
]
}
]
},
"auto-format": {
"post_tool_execution": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "python3 /.agents/hooks-scripts/auto_lint.py",
"timeout": 15
}
]
}
]
}
}
Matcher-Syntax und -Regeln
Jede Regelgruppe in hooks.json definiert mit den Eigenschaften matcher und hooks, wann und wie Handler ausgelöst werden:
| Feld | Typ | Beschreibung |
|---|---|---|
enabled |
boolean |
Optional. Legen Sie false fest, um die Gruppe zu deaktivieren (true ist die Standardeinstellung). |
matcher |
string |
Regulärer Ausdruck, der mit den Namen der Zieltools im Container übereinstimmt. |
hooks |
array |
Geordnete Liste von Handler-Definitionen (command oder http). Handler werden sequenziell in der Reihenfolge der Deklaration ausgeführt. |
Funktionsweise der regulären Ausdrucksauswertung
Wenn der Agent ein Tool in der Sandbox aufruft, wertet die Laufzeit den Containernamen des Tools anhand Ihres matcher-Musters mit regulären Standardausdrücken von RE2 aus. Wenn der reguläre Ausdruck mit dem Toolnamen übereinstimmt, werden alle Handler im hooks-Array in der Reihenfolge ausgeführt. Wenn mehrere Regelgruppen mit demselben Tool übereinstimmen, werden alle entsprechenden Handler-Arrays ausgeführt.
Sie können jeden integrierten Containertoolnamen verwenden: Codeausführung (code_execution) oder Dateisystemvorgänge (read_file, write_file, list_files und delete_file).
Häufig verwendete Matcher-Ausdrücke
"code_execution": Exakte Stringübereinstimmung für Shell-Befehle und Skriptausführungen."write_file": Exakte Übereinstimmung für die Erstellung von Dateisystemdateien und Festplattenschreibvorgänge."read_file|write_file": Die Trennung durch einen senkrechten Strich ermöglicht die Übereinstimmung mit mehreren bestimmten Toolnamen in einer einzigen Regel.".*_file": Regulärer Ausdruck mit Platzhalter, der mit jedem Tool übereinstimmt, das mit_fileendet (z. B.read_file,write_fileoderdelete_file). Für reguläre Standardausdrücke von RE2 ist.*erforderlich. Einfache Shell-Globs wie*_filesind keine gültige Syntax für reguläre Ausdrücke und führen zu keiner Übereinstimmung.".*"oder"*"oder"": Catch-all-Muster, das jeden Toolaufruf im Container abfängt.
Handler-Typen
Befehls-Hooks
Befehls-Hooks führen einen Shell-Befehl oder ein Skript in der Sandbox aus. Das Skript empfängt das Ereignis-JSON über stdin und gibt die JSON-Entscheidung über stdout aus.
| Feld | Typ | Beschreibung |
|---|---|---|
type |
string |
Muss "command" sein. |
command |
string |
Befehlszeile, die in der Sandbox ausgeführt werden soll (z. B. python3 /.agents/hooks-scripts/gate.py). |
timeout |
integer |
Zeitlimit in Sekunden. Standard: 30. |
HTTP-Hooks
HTTP-Hooks senden das Ereignis-JSON als POST-Anfrage direkt aus dem Sandbox-Netzwerk an eine externe HTTPS-URL. Der Zielserver gibt seine Entscheidung im HTTP-Antworttext im genau gleichen JSON-Format zurück ({"decision": "allow"} oder {"decision": "deny", "reason": "..."}).
| Feld | Typ | Beschreibung |
|---|---|---|
type |
string |
Muss "http" sein. |
url |
string |
Externer HTTPS-Endpunkt, an den die Ereignis-Payload gesendet werden soll. |
headers |
object |
Optionale Schlüssel/Wert-Paare für nicht vertrauliche benutzerdefinierte Header (z. B. {"X-Event-Source": "agent-sandbox"}). Verwenden Sie stattdessen den Netzwerkproxy für Authentifizierungsdaten. |
timeout |
integer |
Zeitlimit in Sekunden. Standard: 30. |
Egress-Proxy und Token-Transformation
Da HTTP-Hooks direkt aus dem Netzwerk-Namespace der Sandbox ausgeführt werden, werden ausgehende Anfragen über den transparenten Egress-Proxy geleitet. Diese Architektur bietet zwei entscheidende Sicherheitsvorteile:
- Netzwerk-Allowlisting: Zielendpunkte müssen in der
network.allowlistIhrer Umgebung explizit zugelassen werden. Loopback-Traffic (127.0.0.1oderlocalhost) wird vom Proxy blockiert. Verwenden Sie immer zugelassene externe Endpunkte. - Token-Transformation: Sie müssen keine API-Schlüssel oder geheimen Bearertokens in
.agents/hooks.jsonspeichern oder in den Container einbinden. Konfigurieren Sie stattdessen Regeln für die Token-Transformation in Ihrer Netzwerkkonfiguration (network.allowlist.transform). Der Egress-Proxy fängt ausgehenden HTTP-Hook-Traffic automatisch ab und fügt Ihre echten Authentifizierungsheader ein, bevor er die Sandbox verlässt.
Umgang der Laufzeit mit Entscheidungen und Fehlern
- Synchrone Wartezeit: Der Agent pausiert und wartet, bis Ihre Hooks abgeschlossen sind, bevor er fortfährt.
- Blockieren der Toolausführung: Wenn Ihr Pre-Tool-Hook
{"decision": "deny", "reason": "<your reason>"}zurückgibt, bricht die Laufzeit den Toolaufruf sofort ab. Der Grund für die Ablehnung wird im Unterhaltungsverlauf des Modells angezeigt. Das Modell passt sich an, indem es eine sichere Alternative auswählt oder dem Nutzer die Blockierung erklärt. - Umgang mit Skriptabstürzen, HTTP-Fehlern und Zeitüberschreitungen: Wenn ein Befehlsskript abstürzt (Exit-Status ungleich null), ein HTTP-Hook einen Statuscode ungleich 2xx zurückgibt (z. B. einen 4xx- oder 5xx-Serverfehler) oder ein Vorgang eine Zeitüberschreitung verursacht oder nicht erkannte JSON zurückgibt, behandelt die Laufzeit dies als Genehmigung (
allow). Die Toolausführung wird normal fortgesetzt, sodass ein fehlerhaftes Skript oder ein nicht erreichbarer Telemetrieserver Ihre Anwendung niemals blockieren kann.
Gängige Anwendungsfälle
Wiederherstellung in mehreren Runden für Datenschutz und Compliance
Wenn ein Hook den Zugriff auf eingeschränkte Ressourcen blockiert, z. B. auf Verzeichnisse mit personenbezogenen Daten oder vertraulichen Finanzdaten, können Sie previous_interaction_id im nächsten Aufruf übergeben, um die Runde in derselben Umgebung fortzusetzen. Der Agent liest die Erklärung für die Ablehnung und stellt automatisch eine Verbindung wieder her, indem er stattdessen genehmigte öffentliche Tabellen abfragt.
Python
import json
from google import genai
client = genai.Client()
hooks_config = {
"privacy-gate": {
"pre_tool_execution": [
{
"matcher": "read_file",
"hooks": [
{
"type": "command",
"command": "python3 /.agents/hooks-scripts/check_privacy.py",
"timeout": 5,
}
],
}
]
}
}
check_privacy_script = """#!/usr/bin/env python3
import sys, json
data = json.load(sys.stdin)
path = str(data.get("tool_call", {}).get("args", {}).get("path", ""))
if "/private/" in path:
resp = {
"decision": "deny",
"reason": "Access to confidential `/private/` records is blocked by PII compliance policy. Query approved `/public/` summary tables instead."
}
else:
resp = {"decision": "allow"}
print(json.dumps(resp))
"""
# Step 1: Agent attempts to read confidential PII records and is intercepted
int_1 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Use your filesystem tool to read `/workspace/private/employees.json` and summarize the employee details.",
environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/hooks.json",
"content": json.dumps(hooks_config, indent=2),
},
{
"type": "inline",
"target": ".agents/hooks-scripts/check_privacy.py",
"content": check_privacy_script,
},
{
"type": "inline",
"target": "workspace/private/employees.json",
"content": '{"employees": [{"id": 1, "salary": 150000, "ssn": "000-00-0000"}]}',
},
{
"type": "inline",
"target": "workspace/public/summary.json",
"content": '{"department": "Engineering", "team_size": 42, "status": "active"}',
},
],
},
)
print(int_1.output_text)
# Step 2: Continue in the same environment using previous_interaction_id; agent recovers with public tables
int_2 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Understood. Please read the approved `/workspace/public/summary.json` file instead and provide the summary.",
environment=int_1.environment_id,
previous_interaction_id=int_1.id,
)
print(int_2.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const hooksConfig = {
"privacy-gate": {
pre_tool_execution: [
{
matcher: "read_file",
hooks: [
{
type: "command",
command: "python3 /.agents/hooks-scripts/check_privacy.py",
timeout: 5,
},
],
},
],
},
};
const checkPrivacyScript = `#!/usr/bin/env python3
import sys, json
data = json.load(sys.stdin)
path = str(data.get("tool_call", {}).get("args", {}).get("path", ""))
if "/private/" in path:
resp = {
"decision": "deny",
"reason": "Access to confidential \`/private/\` records is blocked by PII compliance policy. Query approved \`/public/\` summary tables instead."
}
else:
resp = {"decision": "allow"}
print(json.dumps(resp))
`;
const int1 = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Use your filesystem tool to read `/workspace/private/employees.json` and summarize the employee details.",
environment: {
type: "remote",
sources: [
{
type: "inline",
"target": ".agents/hooks.json",
content: JSON.stringify(hooksConfig, null, 2),
},
{
type: "inline",
"target": ".agents/hooks-scripts/check_privacy.py",
content: checkPrivacyScript,
},
{
type: "inline",
"target": "workspace/private/employees.json",
content: '{"employees": [{"id": 1, "salary": 150000, "ssn": "000-00-0000"}]}',
},
{
type: "inline",
"target": "workspace/public/summary.json",
content: '{"department": "Engineering", "team_size": 42, "status": "active"}',
},
],
},
});
console.log(int1.output_text);
const int2 = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Understood. Please read the approved `/workspace/public/summary.json` file instead and provide the summary.",
environment: int1.environment_id,
previous_interaction_id: int1.id,
});
console.log(int2.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.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
CreateAgentInteraction params =
CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Build a simple REST API server in Node.js."))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
# Step 1: Attempt to access restricted PII directory (blocked by hook)
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": [{"type": "text", "text": "Use your filesystem tool to read /workspace/private/employees.json and summarize the employee details."}],
"environment": {
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/hooks.json",
"content": "{\"privacy-gate\": {\"pre_tool_execution\": [{\"matcher\": \"read_file\", \"hooks\": [{\"type\": \"command\", \"command\": \"python3 /.agents/hooks-scripts/check_privacy.py\", \"timeout\": 5}]}]}}"
},
{
"type": "inline",
"target": ".agents/hooks-scripts/check_privacy.py",
"content": "#!/usr/bin/env python3\nimport sys, json\ndata = json.load(sys.stdin)\npath = str(data.get(\"tool_call\", {}).get(\"args\", {}).get(\"path\", \"\"))\nif \"/private/\" in path:\n resp = {\"decision\": \"deny\", \"reason\": \"Access to confidential `/private/` records is blocked by PII compliance policy. Query approved `/public/` summary tables instead.\"}\nelse:\n resp = {\"decision\": \"allow\"}\nprint(json.dumps(resp))\n"
},
{
"type": "inline",
"target": "workspace/private/employees.json",
"content": "{\"employees\": [{\"id\": 1, \"salary\": 150000, \"ssn\": \"000-00-0000\"}]}"
},
{
"type": "inline",
"target": "workspace/public/summary.json",
"content": "{\"department\": \"Engineering\", \"team_size\": 42, \"status\": \"active\"}"
}
]
}
}'
# Step 2: Continue in the same environment using $ENV_ID and $INTERACTION_ID from the previous response
# curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
# -H "Content-Type: application/json" \
# -H "x-goog-api-key: $GEMINI_API_KEY" \
# -d '{
# "agent": "antigravity-preview-05-2026",
# "input": [{"type": "text", "text": "Understood. Please read the approved /workspace/public/summary.json file instead and provide the summary."}],
# "environment": "'"$ENV_ID"'",
# "previous_interaction_id": "'"$INTERACTION_ID"'"
# }'
Externes Audit-Logging und Telemetrie
Senden Sie in Echtzeit Auditereignisse aus der Sandbox an einen externen Überwachungsserver, wenn Dateien gelesen oder geändert werden.
- Mehrere Tools abgleichen: Da Matcher reguläre Standardausdrücke verwenden, können Sie mehrere Tools in einer einzigen Regel kombinieren, indem Sie senkrechte Striche (
read_file|write_file) oder Platzhalter (.*_file) verwenden. Geheimnisse aus der Konfiguration entfernen: Definieren Sie Authentifizierungstokens in der Netzwerkkonfiguration Ihrer Umgebung (
network.allowlist.transform). Der Egress-Proxy fügt ausgehenden Anfragen automatisch Ihre echten Bearertokens hinzu.
Python
import json
from google import genai
client = genai.Client()
# Define hook without secrets; the egress proxy injects headers dynamically
hooks_config = {
"audit-logging": {
"post_tool_execution": [
{
"matcher": "read_file|write_file",
"hooks": [
{
"type": "http",
"url": "https://telemetry.example.com/api/v1/agent-events",
"timeout": 10,
}
],
}
]
}
}
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Use your filesystem tool to create `/workspace/audit.log` containing 'event 1', then immediately read it back using your filesystem read tool.",
environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/hooks.json",
"content": json.dumps(hooks_config, indent=2),
}
],
"network": {
"allowlist": [
{
"domain": "telemetry.example.com",
"transform": {
"Authorization": "Bearer telemetry_secret_token_123",
},
},
{"domain": "*"},
]
},
},
)
print(interaction.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
// Define hook without secrets; the egress proxy injects headers dynamically
const hooksConfig = {
"audit-logging": {
post_tool_execution: [
{
matcher: "read_file|write_file",
hooks: [
{
type: "http",
url: "https://telemetry.example.com/api/v1/agent-events",
timeout: 10,
},
],
},
],
},
};
const interaction = await client.interactions.create({
agent: "antigravity-preview-05-2026",
input: "Use your filesystem tool to create `/workspace/audit.log` containing 'event 1', then immediately read it back using your filesystem read tool.",
environment: {
type: "remote",
sources: [
{
type: "inline",
target: ".agents/hooks.json",
content: JSON.stringify(hooksConfig, null, 2),
},
],
network: {
allowlist: [
{
domain: "telemetry.example.com",
transform: {
Authorization: "Bearer telemetry_secret_token_123",
},
},
{ 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.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
CreateAgentInteraction params =
CreateAgentInteraction.builder()
.agent(AgentOption.of("antigravity-preview-05-2026"))
.input(InteractionsInput.of("Build a simple REST API server in Node.js."))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": [{"type": "text", "text": "Use your filesystem tool to create /workspace/audit.log containing event 1, then immediately read it back using your filesystem read tool."}],
"environment": {
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/hooks.json",
"content": "{\"audit-logging\": {\"post_tool_execution\": [{\"matcher\": \"read_file|write_file\", \"hooks\": [{\"type\": \"http\", \"url\": \"https://telemetry.example.com/api/v1/agent-events\", \"timeout\": 10}]}]}}"
}
],
"network": {
"allowlist": [
{
"domain": "telemetry.example.com",
"transform": {
"Authorization": "Bearer telemetry_secret_token_123"
}
},
{"domain": "*"}
]
}
}
}'
Beschränkungen
- Sandbox-Toolbereich: Hooks fangen integrierte Tools in der Sandbox ab: Code-Ausführung (
code_execution) und Dateisystemvorgänge (read_file,write_file,list_filesunddelete_file). Sie werden nicht für benutzerdefinierte Funktionsaufrufe (function) oder externe Model Context Protocol-Tools (mcp_server) ausgelöst, die außerhalb des Containers verarbeitet werden. - Netzwerk-Allowlists: HTTP-Hooks werden im Containernetzwerk ausgeführt. Sie müssen Ziel-URLs in der
network.allowlistIhrer Umgebung explizit zulassen. Loopback-Adressen (localhost,127.0.0.1) werden vom Proxy blockiert. - Automatische Genehmigung bei Fehlern: Wenn ein Hook-Skript abstürzt (Exit-Status ungleich null), eine Zeitüberschreitung verursacht oder fehlschlägt, protokolliert die Laufzeit den Fehler und lässt den Toolaufruf fortfahren. So wird verhindert, dass fehlerhafte Linter-Skripts oder hängende Prozesse Ihre Anwendungen blockieren.
- Schutz der Sandbox-Konfiguration: Da Hooks in der Container-Sandbox ausgeführt werden, können Agents mit Dateisystem-Schreibtools oder Berechtigungen zur Ausführung von Shell-Code die lokale Datei
.agents/hooks.jsonoder Skripts in beschreibbaren Arbeitsbereichen ändern. Verwenden Sie Container-Hooks als automatisierte Richtlinien und operative Schutzmaßnahmen. Wenn ein strenger Manipulationsschutz gegen nicht vertrauenswürdige Modellausführungen erforderlich ist, binden Sie Konfigurationsquellen aus schreibgeschützten Repositories ein.
Nächste Schritte
- Informationen zum Konfigurieren von persistenten Remote-Sandboxes und -Umgebungen.
- Funktionen und integrierte Tools des Antigravity-Agents.
- Überblick zur Interactions API für Mehrfachdialog-Sitzungen und Streaming.