Хуки позволяют запускать пользовательские скрипты или внешние HTTP-запросы непосредственно до или после выполнения агентом кода или изменения файлов в удаленной песочнице. Используйте хуки для расширения цикла работы агента с помощью автоматизированных механизмов защиты и фоновых рабочих процессов, таких как:
- Обеспечение безопасности и контроль доступа перед выполнением команд оболочки, представляющих высокий риск, или операций чтения файлов с ограниченным доступом.
- Автоматизация преобразований в конвейере данных сразу после создания или изменения файлов агентом.
Передача телеметрии корпоративного аудита во внешние системы мониторинга после выполнения инструмента.
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);
ОТДЫХ
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"
}
]
}
}'
Поддерживаемые события жизненного цикла
В песочнице поддерживаются 2 события:
| Событие | Когда он выстрелит | Что это делает |
|---|---|---|
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"
}
Если команда оболочки выводит ошибки в стандартный поток ошибок ( stderr ) или операция с файловой системой завершается с ошибкой, в полезную нагрузку включается поле "error" содержащее текст ошибки. Если команда выполняется успешно без ошибок, поле "error" полностью опускается.
Вывод ответа ( stdout ):
{}
Поскольку обработчики событий post-tool выполняются исключительно для фоновых задач, таких как форматирование кода или логирование, среда выполнения игнорирует любые значения решений, возвращаемые в 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": Точное совпадение строк для команд оболочки и выполнения скриптов. -
"write_file": Точное совпадение для создания файлов в файловой системе и записи на диск. -
"read_file|write_file": Разделение каналов соответствует нескольким конкретным именам инструментов в одном правиле. -
".*_file": Подстановочный знак регулярного выражения, соответствующий любому инструменту, заканчивающемуся на_file(например,read_file,write_fileилиdelete_file). Стандартные регулярные выражения RE2 требуют.*; простые шаблоны оболочки, такие как*_fileявляются недопустимым синтаксисом регулярных выражений и не будут найдены. -
".*"или"*"или"": Обобщенный шаблон, перехватывающий каждый вызов инструмента внутри контейнера.
Типы обработчиков
Перехватчики команд
Перехватчики команд выполняют команду оболочки или скрипт внутри песочницы. Скрипт получает JSON-сообщение о событии через stdin и выводит JSON-сообщение о принятом решении через stdout .
| Поле | Тип | Описание |
|---|---|---|
type | string | Должно быть "command" . |
command | string | Командная строка для запуска внутри песочницы (например, python3 /.agents/hooks-scripts/gate.py ). |
timeout | integer | Время ожидания в секундах. По умолчанию: 30 . |
HTTP-хуки
HTTP-хуки отправляют JSON-событие в виде POST-запроса на внешний 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) блокируется прокси-сервером; всегда используйте в качестве целевых внешних конечных точек указанные в списке разрешенные адреса. - Преобразование токенов: Вам не нужно хранить ключи API или секретные токены bearer в файле
.agents/hooks.jsonили монтировать их в контейнер. Вместо этого настройте правила преобразования токенов в конфигурации вашей сети (network.allowlist.transform). Исходящий прокси автоматически перехватывает исходящий трафик HTTP-хуков и внедряет ваши реальные заголовки аутентификации в сеть перед выходом из песочницы.
Как среда выполнения обрабатывает решения и ошибки
- Синхронное ожидание: агент делает паузу и ждет завершения обработки ваших запросов, прежде чем продолжить.
- Блокировка выполнения инструмента: если ваш пре-инструмент возвращает
{"decision": "deny", "reason": "<your reason>"}, среда выполнения немедленно отменяет вызов инструмента. Модель видит причину вашего отказа в истории диалога и адаптируется, выбирая безопасную альтернативу или объясняя блокировку пользователю. - Обработка сбоев скриптов, HTTP-ошибок и тайм-аутов: если скрипт команды завершается с ошибкой (ненулевой код завершения), HTTP-хук возвращает код состояния, отличный от 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);
ОТДЫХ
# 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). Исходящий прокси автоматически внедряет ваши реальные токены Bearer в исходящие запросы.
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);
ОТДЫХ
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) блокируются прокси-сервером. - Автоматическое подтверждение ошибок: если скрипт-перехватчик завершается с ошибкой (ненулевой код завершения), истекает время ожидания или происходит сбой, среда выполнения регистрирует ошибку и позволяет продолжить вызов инструмента. Это гарантирует, что неисправные скрипты линтера или зависшие процессы никогда не приведут к взаимоблокировке ваших приложений.
- Защита конфигурации в песочнице: поскольку хуки выполняются внутри песочницы контейнера, агенты с правами на запись в файловую систему или выполнение шелл-кода могут изменять локальные файлы
.agents/hooks.jsonили скрипты в рабочих областях с правами на запись. Используйте хуки контейнера в качестве автоматизированных руководств по политикам и оперативных средств защиты; если требуется строгая защита от несанкционированного выполнения моделей, монтируйте источники конфигурации из репозиториев только для чтения.
Что дальше?
- Узнайте, как настроить постоянные удаленные песочницы и среды .
- Изучите возможности и встроенные инструменты агента «Антигравитация» .
- Ознакомьтесь с обзором API взаимодействий для многоходовых сессий и потоковой передачи данных.
Хуки позволяют запускать пользовательские скрипты или внешние HTTP-запросы непосредственно до или после выполнения агентом кода или изменения файлов в удаленной песочнице. Используйте хуки для расширения цикла работы агента с помощью автоматизированных механизмов защиты и фоновых рабочих процессов, таких как:
- Обеспечение безопасности и контроль доступа перед выполнением команд оболочки, представляющих высокий риск, или операций чтения файлов с ограниченным доступом.
- Автоматизация преобразований в конвейере данных сразу после создания или изменения файлов агентом.
Передача телеметрии корпоративного аудита во внешние системы мониторинга после выполнения инструмента.
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);
ОТДЫХ
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"
}
]
}
}'
Поддерживаемые события жизненного цикла
В песочнице поддерживаются 2 события:
| Событие | Когда он выстрелит | Что это делает |
|---|---|---|
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"
}
Если команда оболочки выводит ошибки в стандартный поток ошибок ( stderr ) или операция с файловой системой завершается с ошибкой, в полезную нагрузку включается поле "error" содержащее текст ошибки. Если команда выполняется успешно без ошибок, поле "error" полностью опускается.
Вывод ответа ( stdout ):
{}
Поскольку обработчики событий post-tool выполняются исключительно для фоновых задач, таких как форматирование кода или логирование, среда выполнения игнорирует любые значения решений, возвращаемые в 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": Точное совпадение строк для команд оболочки и выполнения скриптов. -
"write_file": Точное совпадение для создания файлов в файловой системе и записи на диск. -
"read_file|write_file": Разделение каналов соответствует нескольким конкретным именам инструментов в одном правиле. -
".*_file": Подстановочный знак регулярного выражения, соответствующий любому инструменту, заканчивающемуся на_file(например,read_file,write_fileилиdelete_file). Стандартные регулярные выражения RE2 требуют.*; простые шаблоны оболочки, такие как*_fileявляются недопустимым синтаксисом регулярных выражений и не будут найдены. -
".*"или"*"или"": Обобщенный шаблон, перехватывающий каждый вызов инструмента внутри контейнера.
Типы обработчиков
Перехватчики команд
Перехватчики команд выполняют команду оболочки или скрипт внутри песочницы. Скрипт получает JSON-сообщение о событии через stdin и выводит JSON-сообщение о принятом решении через stdout .
| Поле | Тип | Описание |
|---|---|---|
type | string | Должно быть "command" . |
command | string | Командная строка для запуска внутри песочницы (например, python3 /.agents/hooks-scripts/gate.py ). |
timeout | integer | Время ожидания в секундах. По умолчанию: 30 . |
HTTP-хуки
HTTP-хуки отправляют JSON-событие в виде POST-запроса на внешний 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) блокируется прокси-сервером; всегда используйте в качестве целевых внешних конечных точек указанные в списке разрешенные адреса. - Преобразование токенов: Вам не нужно хранить ключи API или секретные токены bearer в файле
.agents/hooks.jsonили монтировать их в контейнер. Вместо этого настройте правила преобразования токенов в конфигурации вашей сети (network.allowlist.transform). Исходящий прокси автоматически перехватывает исходящий трафик HTTP-хуков и внедряет ваши реальные заголовки аутентификации в сеть перед выходом из песочницы.
Как среда выполнения обрабатывает решения и ошибки
- Синхронное ожидание: агент делает паузу и ждет завершения обработки ваших запросов, прежде чем продолжить.
- Блокировка выполнения инструмента: если ваш пре-инструмент возвращает
{"decision": "deny", "reason": "<your reason>"}, среда выполнения немедленно отменяет вызов инструмента. Модель видит причину вашего отказа в истории диалога и адаптируется, выбирая безопасную альтернативу или объясняя блокировку пользователю. - Обработка сбоев скриптов, HTTP-ошибок и тайм-аутов: если скрипт команды завершается с ошибкой (ненулевой код завершения), HTTP-хук возвращает код состояния, отличный от 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);
ОТДЫХ
# 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). Исходящий прокси автоматически внедряет ваши реальные токены Bearer в исходящие запросы.
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);
ОТДЫХ
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) блокируются прокси-сервером. - Автоматическое подтверждение ошибок: если скрипт-перехватчик завершается с ошибкой (ненулевой код завершения), истекает время ожидания или происходит сбой, среда выполнения регистрирует ошибку и позволяет продолжить вызов инструмента. Это гарантирует, что неисправные скрипты линтера или зависшие процессы никогда не приведут к взаимоблокировке ваших приложений.
- Защита конфигурации в песочнице: поскольку хуки выполняются внутри песочницы контейнера, агенты с правами на запись в файловую систему или выполнение шелл-кода могут изменять локальные файлы
.agents/hooks.jsonили скрипты в рабочих областях с правами на запись. Используйте хуки контейнера в качестве автоматизированных руководств по политикам и оперативных средств защиты; если требуется строгая защита от несанкционированного выполнения моделей, монтируйте источники конфигурации из репозиториев только для чтения.
Что дальше?
- Узнайте, как настроить постоянные удаленные песочницы и среды .
- Изучите возможности и встроенные инструменты агента «Антигравитация» .
- Ознакомьтесь с обзором API взаимодействий для многоходовых сессий и потоковой передачи данных.