Hooks

Gli hook ti consentono di eseguire script personalizzati o richieste HTTP esterne subito prima o dopo che l'agente esegue il codice o modifica i file all'interno della sua sandbox remota. Utilizza gli hook per estendere il ciclo dell'agente con guardrail automatizzati e flussi di lavoro in background, ad esempio:

  • Applicazione di guardrail di sicurezza e accesso prima dell'esecuzione di comandi shell ad alto rischio o letture di file con limitazioni.
  • Automatizzazione delle trasformazioni della pipeline di dati subito dopo che un agente crea o modifica i file.
  • Streaming della telemetria di controllo aziendale ai sistemi di monitoraggio esterni dopo l'esecuzione dello strumento.

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);

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"
              }
          ]
      }
  }'

Eventi del ciclo di vita supportati

Gli hook supportano 2 eventi all'interno della sandbox:

Evento Quando viene attivato Descrizione
pre_tool_execution Subito prima dell'esecuzione di uno strumento Può approvare (allow) o bloccare (deny) lo strumento prima dell'esecuzione. Quando viene bloccato, il modello vede il motivo del rifiuto e si adatta.
post_tool_execution Subito dopo il completamento di uno strumento Esegue attività di follow-up come la formattazione del codice, l'esecuzione di unit test o la registrazione della telemetria. Non è possibile bloccare o annullare le azioni completate.

pre_tool_execution

Viene attivato subito prima dell'esecuzione di uno strumento. Lo script legge i dettagli della chiamata allo strumento da stdin e restituisce il JSON della decisione (allow o deny) a stdout.

Payload di input (stdin):

{
  "tool_call": {
    "name": "code_execution",
    "args": {
      "code": "rm -rf /tmp/forbidden",
      "language": "bash"
    }
  },
  "environment_id": "env_xyz789"
}

Risposta di output (stdout):

Per approvare la chiamata allo strumento:

{
  "decision": "allow"
}

Per bloccare la chiamata allo strumento e restituire feedback al modello:

{
  "decision": "deny",
  "reason": "Destructive command blocked by security gate."
}

Quando un hook nega un comando, la chiamata allo strumento viene ignorata immediatamente. L'agente vede un risultato di errore contenente il motivo del rifiuto direttamente nel turno corrente. Il modello può quindi correggersi scegliendo un comando alternativo o spiegando il blocco all'utente.

Se lo script restituisce JSON non riconosciuto, testo normale o qualsiasi altro elemento diverso da {"decision": "deny"}, il runtime considera la risposta come un'approvazione (allow).

post_tool_execution

Viene attivato subito dopo il completamento di uno strumento. Lo script legge i dettagli dell'esecuzione e lo stato di eventuali errori da stdin.

Payload di input (stdin):

{
  "tool_call": {
    "name": "code_execution",
    "args": {
      "code": "python3 /workspace/app.py",
      "language": "bash"
    }
  },
  "environment_id": "env_xyz789"
}

Se un comando shell stampa errori sull'errore standard (stderr) o un'operazione del file system non riesce, nel payload viene incluso un campo "error" contenente il testo dell'errore. Quando il comando viene eseguito correttamente senza errori, il "error" campo viene omesso completamente.

Risposta di output (stdout):

{}

Poiché gli hook post-strumento vengono eseguiti rigorosamente per attività in background come la formattazione del codice o la registrazione, il runtime ignora tutti i valori di decisione restituiti su stdout.

Rilevamento della configurazione

Il runtime rileva automaticamente le definizioni degli hook da .agents/hooks.json o /.agents/hooks.json all'interno dell'ambiente sandbox. Puoi fornire hooks.json insieme agli script personalizzati utilizzando qualsiasi origine dell'ambiente supportata:

  • Montaggio del repository: un repository Git contenente .agents/hooks.json insieme a AGENTS.md.
  • Cloud Storage (gcs): un bucket GCS contenente hooks.json copiato nell'ambiente.
  • Origini in linea: stringa JSON non elaborata e contenuti dello script passati in environment.sources quando si chiama client.interactions.create.

Schema hooks.json

Un file hooks.json raggruppa le definizioni degli eventi (pre_tool_execution o post_tool_execution) con nomi personalizzati. Puoi attivare o disattivare ogni gruppo in modo indipendente:

{
  "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
          }
        ]
      }
    ]
  }
}

Sintassi e regole del matcher

Ogni gruppo di regole in hooks.json definisce quando e come vengono attivati i gestori utilizzando le proprietà matcher e hooks:

Campo Tipo Descrizione
enabled boolean Facoltativo. Imposta su false per disattivare il gruppo (true per impostazione predefinita).
matcher string Pattern di espressione regolare che corrisponde ai nomi degli strumenti di destinazione all'interno del container.
hooks array Elenco ordinato di definizioni dei gestori (command o http). I gestori vengono eseguiti in sequenza nell'ordine di dichiarazione.

Come funziona la valutazione delle espressioni regolari

Quando l'agente richiama uno strumento all'interno della sandbox, il runtime valuta il nome del container dello strumento rispetto al pattern matcher utilizzando le espressioni regolari RE2 standard. Se l'espressione regolare corrisponde al nome dello strumento, tutti i gestori nell'array hooks vengono eseguiti in ordine. Se più gruppi di regole corrispondono allo stesso strumento, vengono eseguiti tutti gli array di gestori corrispondenti.

Puoi scegliere come target qualsiasi nome di strumento container integrato: esecuzione del codice (code_execution) o operazioni del file system (read_file, write_file, list_files e delete_file).

Espressioni di corrispondenza comuni

  • "code_execution": corrispondenza esatta della stringa per i comandi shell e le esecuzioni di script.
  • "write_file": corrispondenza esatta per la creazione di file del file system e le scritture su disco.
  • "read_file|write_file": la separazione con barra verticale corrisponde a più nomi di strumenti specifici in una singola regola.
  • ".*_file": espressione regolare con carattere jolly che corrisponde a qualsiasi strumento che termina con _file (ad esempio read_file, write_file, o delete_file). Le espressioni regolari RE2 standard richiedono .*; le espressioni shell semplici come *_file non sono sintassi di espressioni regolari valide e non corrisponderanno.
  • ".*" o "*" o "": pattern catch-all che intercetta ogni singola chiamata allo strumento all'interno del container.

Tipi di gestori

Hook di comando

Gli hook di comando eseguono un comando shell o uno script all'interno della sandbox. Lo script riceve il JSON dell'evento su stdin e restituisce il JSON della decisione su stdout.

Campo Tipo Descrizione
type string Deve essere "command".
command string Riga di comando da eseguire all'interno della sandbox (ad esempio, python3 /.agents/hooks-scripts/gate.py).
timeout integer Timeout in secondi. Valore predefinito: 30.

Hook HTTP

Gli hook HTTP inviano il JSON dell'evento come richiesta POST a un URL HTTPS esterno direttamente dall'interno della rete sandbox. Il server di destinazione restituisce la decisione nel corpo della risposta HTTP utilizzando lo stesso formato JSON ({"decision": "allow"} o {"decision": "deny", "reason": "..."}).

Campo Tipo Descrizione
type string Deve essere "http".
url string Endpoint HTTPS esterno a cui inviare il payload dell'evento.
headers object Coppie chiave-valore facoltative per le intestazioni personalizzate non sensibili (ad esempio, {"X-Event-Source": "agent-sandbox"}). Per le credenziali di autenticazione, utilizza invece il proxy di rete.
timeout integer Timeout in secondi. Valore predefinito: 30.

Proxy in uscita e trasformazione dei token

Poiché gli hook HTTP vengono eseguiti direttamente dall'interno dello spazio dei nomi della rete sandbox, le richieste in uscita passano attraverso il proxy in uscita trasparente. Questa architettura offre 2 vantaggi di sicurezza fondamentali:

  • Elenco consentiti di rete: gli endpoint di destinazione devono essere consentiti esplicitamente in network.allowlist dell'ambiente. Il traffico di loopback (127.0.0.1 o localhost) viene bloccato dal proxy; scegli sempre come target gli endpoint esterni inclusi nell'elenco consentiti.
  • Trasformazione dei token: non è necessario archiviare le chiavi API o i token di autenticazione segreti all'interno di .agents/hooks.json o montarli nel container. Configura invece le regole di trasformazione dei token nella configurazione di rete (network.allowlist.transform). Il proxy in uscita intercetta automaticamente il traffico degli hook HTTP in uscita e inserisce le intestazioni di autenticazione reali sulla rete prima di uscire dalla sandbox.

Come il runtime gestisce le decisioni e gli errori

  • Attesa sincrona: l'agente si mette in pausa e attende il completamento degli hook prima di continuare.
  • Blocco dell'esecuzione dello strumento: se l'hook pre-strumento restituisce {"decision": "deny", "reason": "<your reason>"}, il runtime annulla immediatamente la chiamata allo strumento. Il modello vede il motivo del rifiuto nella cronologia delle conversazioni e si adatta scegliendo un'alternativa sicura o spiegando il blocco all'utente.
  • Gestione di arresti anomali degli script, errori HTTP e timeout: se uno script di comando si arresta in modo anomalo (stato di uscita diverso da zero), un hook HTTP restituisce un codice di stato diverso da 2xx (ad esempio un errore del server 4xx o 5xx) o un'operazione va in timeout o restituisce JSON non riconosciuto, il runtime lo considera come un'approvazione (allow). L'esecuzione dello strumento continua normalmente, quindi uno script danneggiato o un server di telemetria non raggiungibile non blocca mai l'applicazione.

Casi d'uso comuni

Ripristino multi-turno per la privacy e la conformità dei dati

Quando un hook blocca l'accesso a risorse con limitazioni, come directory contenenti informazioni che consentono l'identificazione personale (PII) o registri finanziari riservati, puoi passare previous_interaction_id alla chiamata successiva per continuare il turno nello stesso ambiente. L'agente legge la spiegazione del rifiuto e recupera automaticamente eseguendo una query sulle tabelle pubbliche approvate.

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);

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"'"
#   }'

Telemetria e logging di controllo esterni

Invia eventi di controllo in tempo reale dall'interno della sandbox a un server di monitoraggio esterno ogni volta che i file vengono letti o modificati.

  • Corrispondenza con più strumenti: poiché i matcher utilizzano espressioni regolari standard, puoi combinare più strumenti in una singola regola utilizzando barre verticali (read_file|write_file) o caratteri jolly (.*_file).
  • Mantieni i secret fuori dalla configurazione: definisci i token di autenticazione nella configurazione di rete dell'ambiente (network.allowlist.transform). Il proxy in uscita inserisce automaticamente i token di autenticazione reali nelle richieste in uscita.

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);

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": "*"}
              ]
          }
      }
  }'

Limitazioni

  • Ambito dello strumento sandbox: gli hook intercettano gli strumenti integrati all'interno della sandbox: esecuzione del codice (code_execution) e operazioni del file system (read_file, write_file, list_files e delete_file). Non vengono attivati per le chiamate di funzioni personalizzate (function) o per gli strumenti esterni Model Context Protocol (mcp_server) gestiti al di fuori del container.
  • Elenchi consentiti di rete: gli hook HTTP vengono eseguiti all'interno della rete del container. Devi consentire esplicitamente gli URL di destinazione in network.allowlist dell'ambiente. Gli indirizzi di loopback (localhost, 127.0.0.1) vengono bloccati dal proxy.
  • Approvazione automatica in caso di errori: se uno script di hook si arresta in modo anomalo (stato di uscita diverso da zero), va in timeout o non riesce, il runtime registra l'errore e consente alla chiamata allo strumento di continuare. In questo modo, gli script di linting danneggiati o i processi in sospeso non bloccano mai le applicazioni.
  • Protezione della configurazione sandbox: poiché gli hook vengono eseguiti all'interno della sandbox del container, gli agenti con strumenti di scrittura del file system o autorizzazioni di esecuzione del codice shell possono modificare gli script o .agents/hooks.json locali all'interno degli spazi di lavoro scrivibili. Utilizza gli hook del container come indicazioni sui criteri automatizzati e guardrail operativi; se è richiesta una rigorosa resistenza alle manomissioni rispetto alle esecuzioni di modelli non attendibili, monta le origini di configurazione da repository di sola lettura.

Passaggi successivi