تسمح لك الخطّافات بتشغيل نصوص برمجية مخصّصة أو طلبات HTTP خارجية قبل أن ينفّذ الوكيل الرمز أو يعدّل الملفات داخل وضع الحماية عن بُعد أو بعد ذلك مباشرةً. يمكنك استخدام الخطّافات لتوسيع حلقة الوكيل باستخدام إجراءات وقائية آلية وسير عمل في الخلفية، مثل:
- فرض إجراءات وقائية للأمان والوصول قبل تنفيذ أوامر shell عالية المخاطر أو عمليات قراءة الملفات المحظورة
- أتمتة عمليات تحويل مسار البيانات بعد أن ينشئ الوكيل الملفات أو يعدّلها مباشرةً
بثّ بيانات قياس عن بُعد لعمليات التدقيق في المؤسسة إلى أنظمة المراقبة الخارجية بعد تنفيذ الأداة
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);
جافا
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 ويعرض قرارها بتنسيق JSON (allow أو deny) على stdout.
حمولة الإدخال (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"
}
إذا كان أمر shell يعرض أخطاء في الخطأ العادي (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). يتم تشغيل المعالِجات بالتسلسل حسب ترتيب الإعلان. |
آلية عمل تقييم التعبير العادي
عندما يستدعي الوكيل أداة داخل وضع الحماية، يقيّم وقت التشغيل اسم حاوية الأداة مقابل نمط matcher باستخدام تعابير RE2 العادية. إذا كان التعبير العادي يطابق اسم الأداة، يتم تنفيذ جميع المعالِجات في مصفوفة hooks بالترتيب. إذا كانت مجموعات قواعد متعدّدة تطابق الأداة نفسها، يتم تشغيل جميع مصفوفات المعالِجات المقابلة.
يمكنك استهداف أي اسم أداة حاوية مضمّنة: تطبيق الرموز البرمجية (code_execution) أو عمليات نظام الملفات (read_file وwrite_file وlist_files وdelete_file).
تعبيرات المطابقة الشائعة
"code_execution": مطابقة السلسلة النصية الدقيقة لأوامر shell وعمليات تنفيذ النصوص البرمجية"write_file": مطابقة دقيقة لعمليات إنشاء الملفات على نظام الملفات وعمليات الكتابة على القرص"read_file|write_file": تطابق الفواصل المتصلة أسماء أدوات محدّدة متعدّدة في قاعدة واحدة".*_file": حرف بدل للتعبير العادي يطابق أي أداة تنتهي بـ_file(مثلread_fileأوwrite_fileأوdelete_file). تتطلّب التعابير العادية القياسية RE2 استخدام.*، بينما لا تعتبر تعابير shell البسيطة، مثل*_file، بنية تعبير عادي صالحة ولن تتم مطابقتها.".*"أو"*"أو"": نمط شامل يعترض كل استدعاء أداة داخل الحاوية
أنواع المعالِجات
خطّافات الأوامر
تنفّذ خطّافات الأوامر أمر shell أو نصًا برمجيًا داخل وضع الحماية. يتلقّى النص البرمجي JSON الحدث على stdin ويعرض JSON القرار على stdout.
| الحقل | النوع | الوصف |
|---|---|---|
type |
string |
يجب أن تكون القيمة "command". |
command |
string |
سطر الأوامر لتشغيله داخل وضع الحماية (على سبيل المثال، python3 /.agents/hooks-scripts/gate.py) |
timeout |
integer |
المهلة بالثواني القيمة التلقائية: 30 |
خطّافات HTTP
ترسل خطّافات HTTP JSON الحدث كطلب POST إلى عنوان URL خارجي لبروتوكول HTTPS مباشرةً من داخل شبكة وضع الحماية. يعرض الخادم المستهدَف قراره في نص استجابة HTTP باستخدام تنسيق JSON نفسه تمامًا ({"decision": "allow"} أو {"decision": "deny", "reason": "..."}).
| الحقل | النوع | الوصف |
|---|---|---|
type |
string |
يجب أن تكون القيمة "http". |
url |
string |
نقطة نهاية خارجية لبروتوكول HTTPS يتم إرسال حمولة الحدث إليها باستخدام طريقة POST |
headers |
object |
أزواج اختيارية من المفاتيح والقيم للعناوين المخصّصة غير الحسّاسة (مثل {"X-Event-Source": "agent-sandbox"}). لاستخدام بيانات اعتماد المصادقة، استخدِم الخادم الوكيل للشبكة بدلاً من ذلك. |
timeout |
integer |
المهلة بالثواني القيمة التلقائية: 30 |
الخادم الوكيل للوصول إلى الإنترنت وتحويل الرمز المميّز
بما أنّ خطّافات HTTP يتم تنفيذها مباشرةً من داخل مساحة اسم شبكة وضع الحماية، تمر الطلبات الصادرة عبر الخادم الوكيل الشفاف للوصول إلى الإنترنت. تمنحك هذه البنية ميزتَين أمنيتَين مهمتَين:
- قائمة عناوين الشبكة المسموح بها: يجب السماح بشكلٍ صريح بنقاط النهاية المستهدَفة في
network.allowlistفي بيئتك. يحظر الخادم الوكيل زيارات عنوان الاسترجاع (127.0.0.1أوlocalhost)، لذا استهدِف دائمًا نقاط النهاية الخارجية المسموح بها. - تحويل الرمز المميّز: لست بحاجة إلى تخزين مفاتيح واجهة برمجة التطبيقات أو الرموز المميّزة لحامل سرّي داخل
.agents/hooks.jsonأو تثبيتها في الحاوية. بدلاً من ذلك، اضبط قواعد تحويل الرموز المميّزة في إعدادات الشبكة (network.allowlist.transform). يعترض الخادم الوكيل للوصول إلى الإنترنت تلقائيًا زيارات خطّاف HTTP الصادرة ويُدرِج عناوين المصادقة الحقيقية على الشبكة قبل مغادرة وضع الحماية.
آلية تعامل وقت التشغيل مع القرارات والإخفاقات
- الانتظار المتزامن: يتوقف الوكيل وينتظر انتهاء الخطّافات قبل المتابعة.
- حظر تنفيذ الأداة: إذا كان خطّاف ما قبل الأداة يعرض
{"decision": "deny", "reason": "<your reason>"}، يلغي وقت التشغيل استدعاء الأداة على الفور. يرى النموذج سبب الرفض في سجلّ المحادثات ويتكيّف معه من خلال اختيار بديل آمن أو شرح سبب الحظر للمستخدم. - التعامل مع أعطال النصوص البرمجية وأخطاء HTTP والمهلات: إذا تعرّض نص برمجي للأوامر لعطل (حالة الخروج غير صفرية) أو عرض خطّاف HTTP رمز حالة غير 2xx (مثل خطأ في الخادم 4xx أو 5xx) أو انتهت مهلة عملية أو عرضت JSON غير معروف، سيتعامل وقت التشغيل معها على أنّها موافقة (
allow). يستمر تنفيذ الأداة بشكلٍ طبيعي، لذا لا يمكن أن يؤدي نص برمجي معطّل أو خادم بيانات قياس عن بُعد غير متاح إلى توقف تطبيقك.
حالات الاستخدام الشائعة
الاسترداد المتعدّد الأدوار لخصوصية البيانات والامتثال
عندما يحظر الخطّاف الوصول إلى الموارد المحظورة، مثل الأدلة التي تحتوي على معلومات تكشف الهوية الشخصية (PII) أو السجلات المالية السرية، يمكنك تمرير 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);
جافا
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);
جافا
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) التي تتم معالجتها خارج الحاوية. - قوائم عناوين الشبكة المسموح بها: يتم تشغيل خطّافات HTTP داخل شبكة الحاوية. يجب السماح بشكلٍ صريح بعناوين URL المستهدَفة في
network.allowlistفي بيئتك. يحظر الخادم الوكيل عناوين الاسترجاع (localhostو127.0.0.1). - الموافقة التلقائية على الأخطاء: إذا تعرّض نص برمجي للخطّاف لعطل (حالة الخروج غير صفرية) أو انتهت مهلته أو تعذّر تنفيذه، يسجِّل وقت التشغيل الإخفاق ويسمح بمتابعة استدعاء الأداة. يضمن ذلك ألا تؤدي النصوص البرمجية المعطّلة أو العمليات المعلقة إلى توقف تطبيقاتك.
- حماية إعدادات وضع الحماية: بما أنّ الخطّافات يتم تنفيذها داخل وضع حماية الحاوية، يمكن للوكلاء الذين لديهم أدوات كتابة على نظام الملفات أو أذونات تطبيق الرموز البرمجية لـ shell تعديل
.agents/hooks.jsonأو النصوص البرمجية المحلية داخل مساحات العمل القابلة للكتابة. استخدِم خطّافات الحاوية كإرشادات آلية للسياسات وإجراءات وقائية تشغيلية. إذا كانت هناك حاجة إلى مقاومة صارمة للتلاعب ضد عمليات تنفيذ النموذج غير الموثوق بها، ثبِّت مصادر الإعدادات من المستودعات للقراءة فقط.
الخطوات التالية
- كيفية ضبط بيئات وضع الحماية عن بُعد المستمرة .
- استكشاف إمكانات وأدوات الوكيل Antigravity المضمّنة
- مراجعة نظرة عامة على واجهة برمجة التطبيقات Interactions للجلسات المتعدّدة الأدوار والبث