Хуки позволяют запускать пользовательские скрипты или внешние 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);
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(""));
ОТДЫХ
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) блокируется прокси-сервером; всегда используйте в качестве целевых внешних конечных точек указанные в списке разрешенные адреса. - Token transformation: You do not need to store API keys or secret bearer tokens inside
.agents/hooks.jsonor mount them into the container. Instead, configure token transformation rules in your network configuration (network.allowlist.transform). The egress proxy automatically intercepts outgoing HTTP hook traffic and injects your real authentication headers on the wire before leaving the sandbox.
Как среда выполнения обрабатывает решения и ошибки
- Синхронное ожидание: агент делает паузу и ждет завершения обработки ваших запросов, прежде чем продолжить.
- Блокировка выполнения инструмента: если ваш пре-инструмент возвращает
{"decision": "deny", "reason": "<your reason>"}, среда выполнения немедленно отменяет вызов инструмента. Модель видит причину вашего отказа в истории диалога и адаптируется, выбирая безопасную альтернативу или объясняя блокировку пользователю. - Handling script crashes, HTTP errors, and timeouts: If a command script crashes (non-zero exit status), an HTTP hook returns a non-2xx status code (such as a 4xx or 5xx server error), or an operation times out or returns unrecognized JSON, the runtime treats it as an approval (
allow). Tool execution continues normally so a broken script or unreachable telemetry server never deadlocks your application.
Типичные сценарии использования
Многоэтапное восстановление данных для обеспечения конфиденциальности и соответствия нормативным требованиям.
Когда обработчик блокирует доступ к ограниченным ресурсам, таким как каталоги, содержащие персональные данные или конфиденциальную финансовую информацию, вы можете передать 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(""));
ОТДЫХ
# 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);
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(""));
ОТДЫХ
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) блокируются прокси-сервером. - Автоматическое подтверждение ошибок: если скрипт-перехватчик завершается с ошибкой (ненулевой код завершения), истекает время ожидания или происходит сбой, среда выполнения регистрирует ошибку и позволяет продолжить вызов инструмента. Это гарантирует, что неисправные скрипты линтера или зависшие процессы никогда не приведут к взаимоблокировке ваших приложений.
- Sandbox configuration protection: Because hooks execute inside the container sandbox, agents with filesystem write tools or shell code execution permissions can modify local
.agents/hooks.jsonor scripts within writable workspaces. Use container hooks as automated policy guidance and operational guardrails; if strict tamper resistance is required against untrusted model executions, mount configuration sources from read-only repositories.
Что дальше?
- Узнайте, как настроить постоянные удаленные песочницы и среды .
- Изучите возможности и встроенные инструменты агента «Антигравитация» .
- Ознакомьтесь с обзором API взаимодействий для многоходовых сессий и потоковой передачи данных.