हुक की मदद से, कस्टम स्क्रिप्ट या बाहरी एचटीटीपी अनुरोधों को एजेंट के कोड चलाने या अपने रिमोट सैंडबॉक्स में मौजूद फ़ाइलों में बदलाव करने से ठीक पहले या बाद में चलाया जा सकता है. ऑटोमेटेड गार्डरेल और बैकग्राउंड वर्कफ़्लो के साथ एजेंट लूप को बढ़ाने के लिए, हुक का इस्तेमाल करें. जैसे:
- ज़्यादा जोखिम वाले शेल कमांड या पाबंदी वाली फ़ाइलें पढ़ने से पहले, सुरक्षा और ऐक्सेस गार्डरेल लागू करना.
- एजेंट के फ़ाइलें बनाने या उनमें बदलाव करने के तुरंत बाद, डेटा पाइपलाइन के बदलावों को ऑटोमेट करना.
टूल के चलने के बाद, एंटरप्राइज़ ऑडिट टेलीमेट्री को बाहरी मॉनिटरिंग सिस्टम पर स्ट्रीम करना.
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"
}
]
}
}'
काम करने वाले लाइफ़साइकल इवेंट
हुक, सैंडबॉक्स में दो इवेंट के साथ काम करते हैं:
| इवेंट | यह कब ट्रिगर होता है | यह क्या करता है |
|---|---|---|
pre_tool_execution |
किसी टूल के चलने से ठीक पहले | टूल के चलने से पहले, उसे अनुमति (allow) दी जा सकती है या ब्लॉक (deny) किया जा सकता है. ब्लॉक करने पर, मॉडल को अस्वीकार करने की वजह दिखती है और वह उसके हिसाब से काम करता है. |
post_tool_execution |
किसी टूल के खत्म होने के तुरंत बाद | फ़ॉलो-अप टास्क चलाता है. जैसे, कोड को फ़ॉर्मैट करना, यूनिट टेस्ट चलाना या टेलीमेट्री लॉग करना. पूरे हो चुके ऐक्शन को ब्लॉक या अनडू नहीं किया जा सकता. |
pre_tool_execution
यह किसी टूल के चलने से ठीक पहले ट्रिगर होता है. आपकी स्क्रिप्ट, stdin से टूल कॉल की जानकारी पढ़ती है और stdout पर अपना फ़ैसला JSON (allow या deny) के तौर पर दिखाती है.
इनपुट पेलोड (stdin):
{
"tool_call": {
"name": "code_execution",
"args": {
"code": "rm -rf /tmp/forbidden",
"language": "bash"
}
},
"environment_id": "env_xyz789"
}
आउटपुट रिस्पॉन्स (stdout):
टूल कॉल को अनुमति देने के लिए:
{
"decision": "allow"
}
टूल कॉल को ब्लॉक करने और मॉडल को सुझाव देने के लिए:
{
"decision": "deny",
"reason": "Destructive command blocked by security gate."
}
जब कोई हुक किसी कमांड को अस्वीकार करता है, तो टूल कॉल को तुरंत छोड़ दिया जाता है. एजेंट को, मौजूदा टर्न में ही गड़बड़ी का नतीजा दिखता है. इसमें, अस्वीकार करने की वजह शामिल होती है. इसके बाद, मॉडल कोई दूसरा कमांड चुनकर या उपयोगकर्ता को ब्लॉक करने की वजह बताकर, खुद को ठीक कर सकता है.
अगर आपकी स्क्रिप्ट, पहचाना नहीं गया JSON, सामान्य टेक्स्ट या {"decision": "deny"} के अलावा कोई और वैल्यू दिखाती है, तो रनटाइम, रिस्पॉन्स को अनुमति (allow) के तौर पर लेता है.
post_tool_execution
यह किसी टूल के खत्म होने के तुरंत बाद ट्रिगर होता है. आपकी स्क्रिप्ट, stdin से चलने की जानकारी और गड़बड़ी का स्टेटस पढ़ती है.
इनपुट पेलोड (stdin):
{
"tool_call": {
"name": "code_execution",
"args": {
"code": "python3 /workspace/app.py",
"language": "bash"
}
},
"environment_id": "env_xyz789"
}
अगर कोई शेल कमांड, स्टैंडर्ड एरर (stderr) पर गड़बड़ियां दिखाता है या फ़ाइल सिस्टम का कोई ऑपरेशन पूरा नहीं होता है, तो पेलोड में "error" फ़ील्ड शामिल किया जाता है. इसमें, गड़बड़ी का टेक्स्ट शामिल होता है. जब कमांड बिना किसी गड़बड़ी के पूरा होता है, तो "error" फ़ील्ड पूरी तरह से हटा दिया जाता है.
आउटपुट रिस्पॉन्स (stdout):
{}
पोस्ट-टूल हुक, सिर्फ़ बैकग्राउंड टास्क के लिए चलते हैं. जैसे, कोड को फ़ॉर्मैट करना या लॉग करना. इसलिए, रनटाइम, stdout पर दिखाई गई किसी भी फ़ैसले की वैल्यू को अनदेखा करता है.
कॉन्फ़िगरेशन की खोज
रनटाइम, सैंडबॉक्स एनवायरमेंट में मौजूद .agents/hooks.json या /.agents/hooks.json से हुक की परिभाषाओं का पता अपने-आप लगाता है. किसी भी काम करने वाले एनवायरमेंट सोर्स का इस्तेमाल करके, अपनी कस्टम स्क्रिप्ट के साथ hooks.json दिया जा सकता है:
- डेटा स्टोर करने की जगह को माउंट करना: इसमें, Git डेटा स्टोर करने की जगह शामिल है. इसमें
.agents/hooks.jsonके साथAGENTS.mdमौजूद है. - Cloud Storage (
gcs): इसमें, GCS बकेट शामिल है. इसमें, एनवायरमेंट में कॉपी किया गयाhooks.jsonमौजूद है. - इनलाइन सोर्स: इसमें, रॉ JSON स्ट्रिंग और स्क्रिप्ट का कॉन्टेंट शामिल है. इसे
environment.sourcesको कॉल करते समय,client.interactions.createमें पास किया जाता है.
hooks.json स्कीमा
hooks.json फ़ाइल, कस्टम नामों के तहत इवेंट की परिभाषाओं (pre_tool_execution या post_tool_execution) को ग्रुप करती है. हर ग्रुप को अलग-अलग चालू या बंद किया जा सकता है:
{
"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
}
]
}
]
}
}
मैचर सिंटैक्स और नियम
hooks.json में मौजूद हर नियम ग्रुप, matcher और hooks प्रॉपर्टी का इस्तेमाल करके यह तय करता है कि हैंडलर कब और कैसे ट्रिगर होते हैं:
| फ़ील्ड | टाइप | ब्यौरा |
|---|---|---|
enabled |
boolean |
ज़रूरी नहीं. ग्रुप को बंद करने के लिए, false पर सेट करें. यह डिफ़ॉल्ट रूप से true पर सेट होता है. |
matcher |
string |
कंटेनर में टारगेट टूल के नामों से मेल खाने वाला रेगुलर एक्सप्रेशन पैटर्न. |
hooks |
array |
हैंडलर की परिभाषाओं (command या http) की क्रम से लगाई गई सूची. हैंडलर, एलान के क्रम में चलते हैं. |
रेगुलर एक्सप्रेशन के आकलन का तरीका
जब एजेंट, सैंडबॉक्स में किसी टूल को शुरू करता है, तो रनटाइम, स्टैंडर्ड RE2 रेगुलर एक्सप्रेशन का इस्तेमाल करके, आपके matcher पैटर्न के हिसाब से टूल के कंटेनर के नाम का आकलन करता है. अगर रेगुलर एक्सप्रेशन, टूल के नाम से मेल खाता है, तो hooks कलेक्शन में मौजूद सभी हैंडलर क्रम से चलते हैं. अगर एक से ज़्यादा नियम ग्रुप, एक ही टूल से मेल खाते हैं, तो उनसे जुड़े सभी हैंडलर कलेक्शन चलते हैं.
किसी भी बिल्ट-इन कंटेनर टूल के नाम को टारगेट किया जा सकता है: कोड एक्ज़ीक्यूशन (code_execution) या फ़ाइल सिस्टम के ऑपरेशन (read_file, write_file, list_files, और delete_file).
मैचर के सामान्य एक्सप्रेशन
"code_execution": शेल कमांड और स्क्रिप्ट के एक्ज़ीक्यूशन के लिए, स्ट्रिंग का सटीक मिलान."write_file": फ़ाइल सिस्टम में फ़ाइल बनाने और डिस्क पर लिखने के लिए, सटीक मिलान."read_file|write_file": पाइप से अलग करने पर, एक ही नियम में कई खास टूल के नाम मैच होते हैं.".*_file": रेगुलर एक्सप्रेशन वाइल्डकार्ड,_fileपर खत्म होने वाले किसी भी टूल से मैच होता है. जैसे,read_file,write_fileयाdelete_file. स्टैंडर्ड RE2 रेगुलर एक्सप्रेशन के लिए.*की ज़रूरत होती है. वहीं,*_fileजैसे सामान्य शेल ग्लोब, रेगुलर एक्सप्रेशन के मान्य सिंटैक्स नहीं हैं. इसलिए, ये मैच नहीं हो पाएंगे.".*"या"*"या"": यह ऐसा पैटर्न है जो कंटेनर में मौजूद हर टूल कॉल को इंटरसेप्ट करता है.
हैंडलर के टाइप
कमांड हुक
कमांड हुक, सैंडबॉक्स में शेल कमांड या स्क्रिप्ट चलाते हैं. स्क्रिप्ट को stdin पर इवेंट JSON मिलता है और वह stdout पर अपना फ़ैसला JSON के तौर पर दिखाती है.
| फ़ील्ड | टाइप | ब्यौरा |
|---|---|---|
type |
string |
यह "command" होना चाहिए. |
command |
string |
सैंडबॉक्स में चलाने के लिए कमांड लाइन. उदाहरण के लिए, python3 /.agents/hooks-scripts/gate.py. |
timeout |
integer |
सेकंड में टाइम आउट. डिफ़ॉल्ट: 30. |
एचटीटीपी हुक
एचटीटीपी हुक, इवेंट JSON को सैंडबॉक्स नेटवर्क में सीधे बाहरी एचटीटीपीएस यूआरएल पर POST अनुरोध के तौर पर भेजते हैं. टारगेट सर्वर, एचटीटीपी रिस्पॉन्स बॉडी में अपना फ़ैसला, JSON के ठीक उसी फ़ॉर्मैट ({"decision": "allow"} या {"decision": "deny", "reason": "..."}) में दिखाता है.
| फ़ील्ड | टाइप | ब्यौरा |
|---|---|---|
type |
string |
यह "http" होना चाहिए. |
url |
string |
इवेंट पेलोड को पोस्ट करने के लिए, बाहरी एचटीटीपीएस एंडपॉइंट. |
headers |
object |
संवेदनशील नहीं होने वाले कस्टम हेडर के लिए, ज़रूरी नहीं है कि इसमें कुंजी-वैल्यू पेयर शामिल हों. जैसे, {"X-Event-Source": "agent-sandbox"}. पुष्टि करने के क्रेडेंशियल के लिए, नेटवर्क प्रॉक्सी का इस्तेमाल करें. |
timeout |
integer |
सेकंड में टाइम आउट. डिफ़ॉल्ट: 30. |
ईग्रेस प्रॉक्सी और टोकन ट्रांसफ़ॉर्मेशन
एचटीटीपी हुक, सैंडबॉक्स नेटवर्क नेमस्पेस में सीधे चलते हैं. इसलिए, आउटगोइंग अनुरोध, ट्रांसपैरंट ईग्रेस प्रॉक्सी से होकर गुज़रते हैं. इस आर्किटेक्चर से, आपको सुरक्षा से जुड़े दो अहम फ़ायदे मिलते हैं:
- नेटवर्क की अनुमति वाली सूची: टारगेट एंडपॉइंट को आपके एनवायरमेंट के
network.allowlistमें साफ़ तौर पर अनुमति देनी होगी. लूपबैक ट्रैफ़िक (127.0.0.1याlocalhost) को प्रॉक्सी ब्लॉक कर देती है. इसलिए, हमेशा अनुमति वाली सूची में शामिल बाहरी एंडपॉइंट को टारगेट करें. - टोकन ट्रांसफ़ॉर्मेशन: आपको
.agents/hooks.jsonमें एपीआई कुंजियां या सीक्रेट बियरर टोकन सेव करने या उन्हें कंटेनर में माउंट करने की ज़रूरत नहीं है. इसके बजाय, अपने नेटवर्क कॉन्फ़िगरेशन (network.allowlist.transform) में टोकन ट्रांसफ़ॉर्मेशन के नियम कॉन्फ़िगर करें. ईग्रेस प्रॉक्सी, आउटगोइंग एचटीटीपी हुक ट्रैफ़िक को अपने-आप इंटरसेप्ट करती है और सैंडबॉक्स से बाहर निकलने से पहले, वायर पर आपके असली पुष्टि करने वाले हेडर को इंजेक्ट करती है.
रनटाइम, फ़ैसलों और गड़बड़ियों को कैसे हैंडल करता है
- सिंक्रोनस इंतज़ार: एजेंट, आपके हुक के खत्म होने तक रुकता है और उसके बाद ही आगे बढ़ता है.
- टूल के एक्ज़ीक्यूशन को ब्लॉक करना: अगर आपका प्री-टूल हुक,
{"decision": "deny", "reason": "<your reason>"}दिखाता है, तो रनटाइम, टूल कॉल को तुरंत रद्द कर देता है. मॉडल को, बातचीत के इतिहास में अस्वीकार करने की वजह दिखती है. इसके बाद, वह सुरक्षित विकल्प चुनकर या उपयोगकर्ता को ब्लॉक करने की वजह बताकर, उसके हिसाब से काम करता है. - स्क्रिप्ट क्रैश होने, एचटीटीपी गड़बड़ियों, और टाइम आउट को हैंडल करना: अगर कोई कमांड स्क्रिप्ट क्रैश होती है (नॉन-ज़ीरो एक्ज़िट स्टेटस), कोई एचटीटीपी हुक, नॉन-2xx स्टेटस कोड (जैसे, 4xx या 5xx सर्वर की गड़बड़ी) दिखाता है या कोई ऑपरेशन टाइम आउट हो जाता है या पहचाना नहीं गया JSON दिखाता है, तो रनटाइम इसे अनुमति (
allow) के तौर पर लेता है. टूल का एक्ज़ीक्यूशन सामान्य तरीके से जारी रहता है. इसलिए, खराब स्क्रिप्ट या पहुंच से बाहर टेलीमेट्री सर्वर की वजह से, आपका ऐप्लिकेशन कभी भी डेडलॉक नहीं होता.
इस्तेमाल के सामान्य उदाहरण
डेटा की निजता और अनुपालन के लिए, मल्टी-टर्न रिकवरी
जब कोई हुक, पाबंदी वाले संसाधनों के ऐक्सेस को ब्लॉक करता है, तो उसी एनवायरमेंट में टर्न जारी रखने के लिए, अगले कॉल पर previous_interaction_id पास किया जा सकता है. जैसे, व्यक्तिगत पहचान से जुड़ी जानकारी (पीआईआई) या गोपनीय वित्तीय रिकॉर्ड वाले डायरेक्ट्री. एजेंट, अस्वीकार करने की वजह पढ़ता है और अनुमति वाली सार्वजनिक टेबल के लिए क्वेरी करके, अपने-आप रिकवर हो जाता है.
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"'"
# }'
बाहरी ऑडिट लॉगिंग और टेलीमेट्री
जब भी फ़ाइलें पढ़ी या उनमें बदलाव किया जाता है, तब सैंडबॉक्स से रीयल-टाइम ऑडिट इवेंट को बाहरी मॉनिटरिंग सर्वर पर भेजें.
- एक से ज़्यादा टूल मैच करना: मैचर, स्टैंडर्ड रेगुलर एक्सप्रेशन का इस्तेमाल करते हैं. इसलिए, पाइप (
read_file|write_file) या वाइल्डकार्ड (.*_file) का इस्तेमाल करके, एक ही नियम में एक से ज़्यादा टूल को जोड़ा जा सकता है. अपने कॉन्फ़िगरेशन में सीक्रेट न रखें: अपने एनवायरमेंट के नेटवर्क कॉन्फ़िगरेशन (
network.allowlist.transform) में पुष्टि करने वाले टोकन तय करें. ईग्रेस प्रॉक्सी, आउटगोइंग अनुरोधों पर आपके असली बियरर टोकन को अपने-आप इंजेक्ट करती है.
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": "*"}
]
}
}
}'
सीमाएं
- सैंडबॉक्स टूल का दायरा: हुक, सैंडबॉक्स में मौजूद बिल्ट-इन टूल को इंटरसेप्ट करते हैं: कोड एक्ज़ीक्यूशन (
code_execution) और फ़ाइल सिस्टम के ऑपरेशन (read_file,write_file,list_files, औरdelete_file). ये कस्टम फ़ंक्शन कॉल (function) या बाहरी मॉडल कॉन्टेक्स्ट प्रोटोकॉल (mcp_server) टूल के लिए ट्रिगर नहीं होते. इन्हें कंटेनर के बाहर हैंडल किया जाता है. - नेटवर्क की अनुमति वाली सूची: एचटीटीपी हुक, कंटेनर नेटवर्क में चलते हैं. आपको अपने एनवायरमेंट के
network.allowlistमें टारगेट यूआरएल को साफ़ तौर पर अनुमति देनी होगी. लूपबैक पतों (localhost,127.0.0.1) को प्रॉक्सी ब्लॉक कर देती है. - गड़बड़ियों पर अपने-आप अनुमति: अगर कोई हुक स्क्रिप्ट क्रैश होती है (नॉन-ज़ीरो एक्ज़िट स्टेटस), टाइम आउट हो जाती है या काम नहीं करती है, तो रनटाइम, गड़बड़ी को लॉग करता है और टूल कॉल को जारी रखने की अनुमति देता है. इससे यह पक्का होता है कि खराब लिंटर स्क्रिप्ट या हैंग होने वाली प्रोसेस की वजह से, आपके ऐप्लिकेशन कभी भी डेडलॉक नहीं होते.
- सैंडबॉक्स कॉन्फ़िगरेशन की सुरक्षा: हुक, कंटेनर सैंडबॉक्स में चलते हैं. इसलिए, फ़ाइल सिस्टम में लिखने वाले टूल या शेल कोड एक्ज़ीक्यूशन की अनुमतियों वाले एजेंट, स्थानीय
.agents/hooks.jsonया लिखने की अनुमति वाले वर्कस्पेस में मौजूद स्क्रिप्ट में बदलाव कर सकते हैं. कंटेनर हुक का इस्तेमाल, ऑटोमेटेड नीति के दिशा-निर्देश और ऑपरेशनल गार्डरेल के तौर पर करें. अगर भरोसेमंद नहीं माने जाने वाले मॉडल के एक्ज़ीक्यूशन के ख़िलाफ़, छेड़छाड़ से बचाने के लिए सख्त सुरक्षा की ज़रूरत है, तो सिर्फ़ पढ़ने की अनुमति वाली डेटा स्टोर करने की जगहों से कॉन्फ़िगरेशन सोर्स माउंट करें.
आगे क्या करना है
- परसिस्टेंट रिमोट सैंडबॉक्स और एनवायरमेंट को कॉन्फ़िगर करने का तरीका जानें.
- Antigravity एजेंट की क्षमताओं और बिल्ट-इन टूल के बारे में जानें.
- सिलसिलेवार बातचीत वाले सेशन और स्ट्रीमिंग के लिए, Interactions API की खास जानकारी देखें.