Fiksueset

"Kapëset" të lejojnë të ekzekutosh skripte të personalizuara ose kërkesa të jashtme HTTP pikërisht para ose pas ekzekutimit të kodit nga agjenti ose modifikimit të skedarëve brenda zonës së tij të sigurt në distancë. Përdor kapëset për të zgjeruar ciklin e agjentit me mbrojtje të automatizuara dhe flukse pune në sfond, si p.sh.:

  • Zbatimi i mbrojtjeve të sigurisë dhe qasjes para se të ekzekutohen komandat e guaskës me rrezik të lartë ose leximet e skedarëve të kufizuar.
  • Automatizimi i transformimeve të linjës së të dhënave menjëherë pasi një agjent krijon ose modifikon skedarët.
  • Transmetimi i telemetrisë së auditimit të ndërmarrjes në sistemet e monitorimit të jashtëm pas ekzekutimit të veglës.

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-09-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-09-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.CodeExecution;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;

Client client = new Client();

String hooksConfig = """
{
  "security-gate": {
    "pre_tool_execution": [
      {
        "matcher": "code_execution",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /.agents/hooks-scripts/gate.py",
            "timeout": 10
          }
        ]
      }
    ]
  }
}
""";

String gateScript = "#!/usr/bin/env python3\n"
    + "import sys, json\n"
    + "data = json.load(sys.stdin)\n"
    + "cmd = str(data.get(\"tool_call\", {}).get(\"args\", {}))\n"
    + "if \"rm -rf\" in cmd:\n"
    + "    print(json.dumps({\"decision\": \"deny\", \"reason\": \"Destructive command blocked by security gate.\"}))\n"
    + "else:\n"
    + "    print(json.dumps({\"decision\": \"allow\"}))\n";

Environment env = Environment.builder()
    .sources(List.of(
        Source.builder()
            .type(SourceType.INLINE)
            .target(".agents/hooks.json")
            .content(hooksConfig)
            .build(),
        Source.builder()
            .type(SourceType.INLINE)
            .target(".agents/hooks-scripts/gate.py")
            .content(gateScript)
            .build()
    ))
    .build();

CreateAgentInteraction params = CreateAgentInteraction.builder()
    .agent(AgentOption.of("antigravity-preview-09-2026"))
    .input(InteractionsInput.of("Run `rm -rf /tmp/forbidden` using code_execution."))
    .tools(List.of(CodeExecution.builder().build()))
    .environment(CreateAgentInteractionEnvironment.of(env))
    .build();

Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));

Go

package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
    "google.golang.org/genai/interactions/models/interactions"
    "google.golang.org/genai/interactions/models/operations"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    hooksConfig := `{
  "security-gate": {
    "pre_tool_execution": [
      {
        "matcher": "code_execution",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /.agents/hooks-scripts/gate.py",
            "timeout": 10
          }
        ]
      }
    ]
  }
}`

    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"}))
`

    env := interactions.Environment{
        Sources: []interactions.Source{
            {
                Type:    interactions.SourceTypeInline.ToPointer(),
                Target:  genai.Ptr(".agents/hooks.json"),
                Content: genai.Ptr(hooksConfig),
            },
            {
                Type:    interactions.SourceTypeInline.ToPointer(),
                Target:  genai.Ptr(".agents/hooks-scripts/gate.py"),
                Content: genai.Ptr(gateScript),
            },
        },
    }

    res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
        Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{
            Agent:       interactions.AgentOption("antigravity-preview-09-2026"),
            Input:       interactions.NewInteractionsInput("Run `rm -rf /tmp/forbidden` using code_execution."),
            Tools:       []interactions.Tool{interactions.NewTool(interactions.CodeExecution{})},
            Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)),
        }),
    })
    if err != nil {
        log.Fatal(err)
    }
    if res.Interaction.OutputText != nil {
        fmt.Println(*res.Interaction.OutputText)
    }
}

QETËSI

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

Ngjarjet e mbështetura të ciklit të jetës

"Kapëset" mbështesin 2 ngjarje brenda mjedisit të provës:

Ngjarje Kur aktivizohet Çfarë bën
pre_tool_execution Pak para se të ekzekutohet një vegël Mund ta miratojë (allow) ose ta bllokojë (deny) veglën para se ajo të ekzekutohet. Kur bllokohet, modeli sheh arsyen tënde të refuzimit dhe përshtatet.
post_tool_execution Menjëherë pasi të përfundojë një vegël Ekzekuton detyrat vijuese si formatimi i kodit, ekzekutimi i testeve të njësisë ose regjistrimi i telemetrisë. Veprimet e përfunduara nuk mund të bllokohen ose të zhbëhen.

pre_tool_execution

Aktivizohet pikërisht para se të ekzekutohet një vegël. Skripti yt lexon detajet e thirrjes së veglës nga stdin dhe nxjerr vendimin e tij në formatin JSON (allow ose deny) te stdout.

Ngarkesa e hyrjes (stdin):

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

Përgjigjja e daljes (stdout):

Për të miratuar thirrjen e veglës:

{
  "decision": "allow"
}

Për të bllokuar thirrjen e veglës dhe për t'i kthyer komentet te modeli:

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

Kur një kapëse mohon një komandë, thirrja e veglës kapërcehet menjëherë. Agjenti sheh një rezultat gabimi që përmban arsyen e refuzimit tënd pikërisht brenda radhës së tij aktuale. Modeli mund të korrigjohet më pas vetë duke zgjedhur një komandë alternative ose duke i shpjeguar bllokimin përdoruesit.

Nëse skripti yt nxjerr JSON të panjohur, tekst të thjeshtë ose çfarëdo tjetër përveç {"decision": "deny"}, mjedisi ekzekutues e trajton përgjigjen si miratim (allow).

post_tool_execution

Aktivizohet menjëherë pasi një vegël përfundon. Skripti yt lexon detajet e ekzekutimit dhe çdo status gabimi nga stdin.

Ngarkesa e hyrjes (stdin):

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

Nëse një komandë e shell-it printon gabime në gabimin standard (stderr) ose një operacion i sistemit të skedarëve dështon, një fushë "error" që përmban tekstin e gabimit përfshihet në ngarkesë. Kur komanda kryhet me sukses pa gabime, fusha "error" hiqet plotësisht.

Përgjigjja e daljes (stdout):

{}

Duke qenë se aktivizuesit e veglave pas ekzekutimit funksionojnë vetëm për detyrat në sfond si formatimi i kodit ose regjistrimi, koha e ekzekutimit shpërfill çdo vlerë vendimi të kthyer në stdout.

Zbulimi i konfigurimit

Koha e ekzekutimit zbulon automatikisht përkufizimet e lidhjeve nga .agents/hooks.json ose /.agents/hooks.json brenda mjedisit të sandbox-it. Mund të japësh hooks.json së bashku me skriptet e tua të personalizuara duke përdorur çdo burim të mbështetur të mjedisit:

  • Montimi i depove: Një depo Git që përmban .agents/hooks.json bashkë me AGENTS.md.
  • Hapësira ruajtëse në renë kompjuterike (gcs): Një grup GCS që përmban hooks.json të kopjuar në mjedis.
  • Burimet e integruara: Vargu i papërpunuar JSON dhe përmbajtjet e skriptit të kaluara në environment.sources kur thërritet client.interactions.create.

Skema hooks.json

Një skedar hooks.json grupon përkufizimet e ngjarjeve (pre_tool_execution ose post_tool_execution) nën emra të personalizuar. Mund të aktivizosh ose çaktivizosh çdo grup në mënyrë të pavarur:

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

Sintaksa dhe rregullat e përputhësit

Çdo grup rregullash në hooks.json përcakton se kur dhe si aktivizohen trajtimet duke përdorur vetitë matcher dhe hooks:

Fusha Lloji Përshkrimi
enabled boolean Opsionale. Cakto në false për të çaktivizuar grupin (true si parazgjedhje).
matcher string Motivi i shprehjes së rregullt që përputhet me emrat e veglave të synuara brenda kontejnerit.
hooks array Lista e renditur e përkufizimeve të trajtimit (command ose http). Trajtuesit ekzekutohen në mënyrë sekuenciale në rendin e deklarimit.

Si funksionon vlerësimi i shprehjeve të rregullta

Kur agjenti thërret një vegël brenda mjedisit të provës, mjedisi i ekzekutimit vlerëson emrin e kontejnerit të veglës në lidhje me modelin tënd matcher duke përdorur shprehjet e zakonshme standarde RE2. Nëse shprehja e zakonshme përputhet me emrin e veglës, të gjithë trajtuarët në vargun hooks ekzekutohen në rend. Nëse disa grupe rregullash përputhen me të njëjtën vegël, ekzekutohen të gjitha vargjet përkatëse të trajtimit.

Mund të synosh çdo emër të veglës së integruar të kontejnerit: ekzekutimi i kodit (code_execution) ose operacionet e sistemit të skedarëve (view_file, write_to_file, replace_file_content, list_dir dhe delete_file).

Shprehjet e zakonshme të përputhjes

  • "code_execution": Përputhje e saktë e vargut për komandat e shell-it dhe ekzekutimet e skriptit.
  • "write_to_file": Përputhje e saktë për krijimin e skedarëve të sistemit të skedarëve dhe shkrimet në disk.
  • "view_file|write_to_file": Ndarja me tub përputhet me disa emra specifikë të veglave në një rregull të vetëm.
  • ".*_file": Karakteri i përgjithshëm i shprehjes së rregullt që përputhet me çdo vegël që përfundon me _file (si p.sh. view_file, write_to_file ose delete_file). Kjo mbulon vetëm një pjesë të paketës së veglave të sistemit të skedarëve. replace_file_content dhe list_dir nuk përfundojnë me _file, prandaj emërtoji ato në mënyrë të qartë kur të të duhen. Shprehjet e rregullta standarde RE2 kërkojnë .*; globs të thjeshta të shell-it si *_file janë sintaksë e pavlefshme e shprehjeve të rregullta dhe nuk do të përputhen.
  • ".*" ose "*" ose "": Model i përgjithshëm që ndërpret çdo thirrje të veçantë të veglës brenda kontejnerit.

Llojet e trajtimit

Elementet fiksuese të komandave

Kthesat e komandave ekzekutojnë një komandë ose skript të terminalit brenda kufizuesit. Skripti merr JSON-in e ngjarjes në stdin dhe nxjerr JSON-in e vendimit në stdout.

Fusha Lloji Përshkrimi
type string Duhet të jetë "command".
command string Rreshti i komandës për t'u ekzekutuar brenda kufizuesit (për shembull, python3 /.agents/hooks-scripts/gate.py).
timeout integer Koha e pritjes në sekonda. Parazgjedhja: 30.

Grepa të HTTP-së

Grepat HTTP dërgojnë JSON-in e ngjarjes si një kërkesë POST në një URL të jashtme HTTPS drejtpërdrejt nga brenda rrjetit të sandbox-it. Serveri i synuar e kthen vendimin e tij në trupin e përgjigjes HTTP duke përdorur të njëjtin format JSON ({"decision": "allow"} ose {"decision": "deny", "reason": "..."}).

Fusha Lloji Përshkrimi
type string Duhet të jetë "http".
url string Pika përfundimtare e jashtme HTTPS për të POST-uar ngarkesën e ngjarjes.
headers object Çifte opsionale çelës-vlerë për tituj të personalizuar jo të ndjeshëm (si p.sh. {"X-Event-Source": "agent-sandbox"}). Për vërtetimin, përdor një kredencial në listën e lejimeve të rrjetit.
timeout integer Koha e pritjes në sekonda. Parazgjedhja: 30.

Transformimi i proxy-t dhe kodit të daljes

Për shkak se kapëset HTTP ekzekutohen drejtpërdrejt nga brenda hapësirës së emrit të rrjetit të sandbox-it, kërkesat dalëse kalojnë nëpërmjet ndërmjetësuesit transparent të daljes. Kjo arkitekturë të jep 2 avantazhe kritike sigurie:

  • Lista e lejimeve të rrjetit: Pikat fundore të synuara duhet të lejohen në mënyrë të qartë në network.allowlist të mjedisit tënd. Trafiku i kthimit (127.0.0.1 ose localhost) bllokohet nga proksi; syno gjithmonë pikat përfundimtare të jashtme të listës së lejimeve.
  • Injektimi i kredencialeve: Nuk ke nevojë të ruash çelësat e API-së ose tokenat sekretë të mbajtësit brenda .agents/hooks.json ose t'i montosh ato në kontejner. Ruaje sekretin një herë si një kredencial dhe referoju atij me ID nga network.allowlist i mjedisit tënd. Serveri proxy i daljes ndërpret automatikisht trafikun dalës të lidhjes HTTP dhe injekton titullin e vërtetë të vërtetimit në linjë para se të largohet nga zona e provave. Titujt e grupit të rregullave të integruara të transform i vendosin në të njëjtën mënyrë në tel, një kredencial është ai që duhet të përdorësh kur dëshiron të ripërdorësh sekretin nëpër projekt dhe ta rotullosh atë në një vend të vetëm. Shiko konfigurimin e rrjetit.

Si i menaxhon mjedisi ekzekutues vendimet dhe dështimet

  • Pritja sinkrone: Agjenti ndalon dhe pret që të përfundojnë pyetjet e tua para se të vazhdojë.
  • Bllokimi i ekzekutimit të veglës: Nëse kthehet {"decision": "deny", "reason": "<your reason>"} nga kodi i paraveglës, mjedisi i ekzekutimit anulon menjëherë thirrjen e veglës. Modeli e sheh arsyen e refuzimit në historikun e bisedave dhe përshtatet duke zgjedhur një alternativë të sigurt ose duke ia shpjeguar bllokimin përdoruesit.
  • Trajtimi i bllokimeve të skriptit, gabimeve HTTP dhe tejkalimeve të kohës: Nëse një skript komandash bllokohet (status daljeje jo zero), një kapëse HTTP kthen një kod statusi jo 2xx (si p.sh. një gabim serveri 4xx ose 5xx) ose një operacion tejkalon kohën ose kthen JSON të panjohur, mjedisi ekzekutues e trajton atë si miratim (allow). Ekzekutimi i veglës vazhdon normalisht, kështu që një skript i prishur ose një server i paarritshëm i telemetrisë nuk e bllokon kurrë aplikacionin tënd.

Rastet e zakonshme të përdorimit

Rikthimi me shumë hapa për privatësinë e të dhënave dhe përputhshmërinë

Kur një kapëse bllokon qasjen në burime të kufizuara, si p.sh. direktoritë që përmbajnë informacione personalisht të identifikueshme (PII) ose regjistrime financiare konfidenciale, mund të kalosh previous_interaction_id në telefonatën tjetër për të vazhduar radhën në të njëjtin mjedis. Agjenti lexon shpjegimin e refuzimit dhe rikuperohet automatikisht duke kërkuar në tabelat publike të miratuara në vend të tyre.

Python

import json
from google import genai

client = genai.Client()

hooks_config = {
    "privacy-gate": {
        "pre_tool_execution": [
            {
                "matcher": "view_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-09-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-09-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: "view_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-09-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-09-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.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;

Client client = new Client();

String hooksConfig = """
{
  "privacy-gate": {
    "pre_tool_execution": [
      {
        "matcher": "read_file",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /.agents/hooks-scripts/check_privacy.py",
            "timeout": 5
          }
        ]
      }
    ]
  }
}
""";

String checkPrivacyScript = "#!/usr/bin/env python3\n"
    + "import sys, json\n"
    + "data = json.load(sys.stdin)\n"
    + "path = str(data.get(\"tool_call\", {}).get(\"args\", {}).get(\"path\", \"\"))\n"
    + "if \"/private/\" in path:\n"
    + "    resp = {\n"
    + "        \"decision\": \"deny\",\n"
    + "        \"reason\": \"Access to confidential `/private/` records is blocked by PII compliance policy. Query approved `/public/` summary tables instead.\"\n"
    + "    }\n"
    + "else:\n"
    + "    resp = {\"decision\": \"allow\"}\n"
    + "print(json.dumps(resp))\n";

Environment env = Environment.builder()
    .sources(List.of(
        Source.builder()
            .type(SourceType.INLINE)
            .target(".agents/hooks.json")
            .content(hooksConfig)
            .build(),
        Source.builder()
            .type(SourceType.INLINE)
            .target(".agents/hooks-scripts/check_privacy.py")
            .content(checkPrivacyScript)
            .build(),
        Source.builder()
            .type(SourceType.INLINE)
            .target("workspace/private/employees.json")
            .content("{\"employees\": [{\"id\": 1, \"salary\": 150000, \"ssn\": \"000-00-0000\"}]}")
            .build(),
        Source.builder()
            .type(SourceType.INLINE)
            .target("workspace/public/summary.json")
            .content("{\"department\": \"Engineering\", \"team_size\": 42, \"status\": \"active\"}")
            .build()
    ))
    .build();

// Step 1: Agent attempts to read confidential PII records and is intercepted
CreateAgentInteraction params1 = CreateAgentInteraction.builder()
    .agent(AgentOption.of("antigravity-preview-09-2026"))
    .input(InteractionsInput.of("Use your filesystem tool to read `/workspace/private/employees.json` and summarize the employee details."))
    .environment(CreateAgentInteractionEnvironment.of(env))
    .build();

Interaction int1 = client.interactions.create(CreateInteractionRequestBody.of(params1)).interaction().get();
System.out.println(int1.outputText().orElse(""));

// Step 2: Continue in the same environment using previous_interaction_id; agent recovers with public tables
CreateAgentInteraction params2 = CreateAgentInteraction.builder()
    .agent(AgentOption.of("antigravity-preview-09-2026"))
    .input(InteractionsInput.of("Understood. Please read the approved `/workspace/public/summary.json` file instead and provide the summary."))
    .environment(CreateAgentInteractionEnvironment.of(int1.environmentId().orElse("")))
    .previousInteractionId(int1.id().orElse(""))
    .build();

Interaction int2 = client.interactions.create(CreateInteractionRequestBody.of(params2)).interaction().get();
System.out.println(int2.outputText().orElse(""));

Go

package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
    "google.golang.org/genai/interactions/models/interactions"
    "google.golang.org/genai/interactions/models/operations"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    hooksConfig := `{
  "privacy-gate": {
    "pre_tool_execution": [
      {
        "matcher": "read_file",
        "hooks": [
          {
            "type": "command",
            "command": "python3 /.agents/hooks-scripts/check_privacy.py",
            "timeout": 5
          }
        ]
      }
    ]
  }
}`

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

    env := interactions.Environment{
        Sources: []interactions.Source{
            {
                Type:    interactions.SourceTypeInline.ToPointer(),
                Target:  genai.Ptr(".agents/hooks.json"),
                Content: genai.Ptr(hooksConfig),
            },
            {
                Type:    interactions.SourceTypeInline.ToPointer(),
                Target:  genai.Ptr(".agents/hooks-scripts/check_privacy.py"),
                Content: genai.Ptr(checkPrivacyScript),
            },
            {
                Type:    interactions.SourceTypeInline.ToPointer(),
                Target:  genai.Ptr("workspace/private/employees.json"),
                Content: genai.Ptr(`{"employees": [{"id": 1, "salary": 150000, "ssn": "000-00-0000"}]}`),
            },
            {
                Type:    interactions.SourceTypeInline.ToPointer(),
                Target:  genai.Ptr("workspace/public/summary.json"),
                Content: genai.Ptr(`{"department": "Engineering", "team_size": 42, "status": "active"}`),
            },
        },
    }

    // Step 1: Agent attempts to read confidential PII records and is intercepted
    res1, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
        Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{
            Agent:       interactions.AgentOption("antigravity-preview-09-2026"),
            Input:       interactions.NewInteractionsInput("Use your filesystem tool to read `/workspace/private/employees.json` and summarize the employee details."),
            Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)),
        }),
    })
    if err != nil {
        log.Fatal(err)
    }
    int1 := res1.Interaction
    if int1.OutputText != nil {
        fmt.Println(*int1.OutputText)
    }

    // Step 2: Continue in the same environment using previous_interaction_id; agent recovers with public tables
    res2, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
        Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{
            Agent:                 interactions.AgentOption("antigravity-preview-09-2026"),
            Input:                 interactions.NewInteractionsInput("Understood. Please read the approved `/workspace/public/summary.json` file instead and provide the summary."),
            Environment:           genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(*int1.EnvironmentID)),
            PreviousInteractionID: int1.ID,
        }),
    })
    if err != nil {
        log.Fatal(err)
    }
    if res2.Interaction.OutputText != nil {
        fmt.Println(*res2.Interaction.OutputText)
    }
}

QETËSI

# 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-09-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\": \"view_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-09-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"'"
#   }'

Evidentimi i auditit të jashtëm dhe telemetria

Dërgo ngjarjet e auditimit në kohë reale nga brenda zonës së provave në një server monitorimi të jashtëm sa herë që skedarët lexohen ose modifikohen.

  • Përputh disa vegla: Për shkak se përputhësit përdorin shprehje të zakonshme standarde, mund të kombinosh disa vegla në një rregull të vetëm duke përdorur tubacione (view_file|write_to_file|replace_file_content) ose karaktere të pakujdesshme (.*_file).
  • Mbaji sekretet jashtë konfigurimit tënd: Ruaje kodin e vërtetimit si një kredencial dhe referoju atij me ID nga konfigurimi i rrjetit i mjedisit tënd (network.allowlist.credential). Ndërmjetësi i daljes injekton kodin e vërtetë të autorizimit në kërkesat dalëse. Ky shembull e vendos titullin në linjë me transform në vend të kësaj, i cili mbrohet nga i njëjti proxy dhe përshtatet kur kodi i qasjes i përket këtij konfigurimi.

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": "view_file|write_to_file|replace_file_content",
                "hooks": [
                    {
                        "type": "http",
                        "url": "https://telemetry.example.com/api/v1/agent-events",
                        "timeout": 10,
                    }
                ],
            }
        ]
    }
}

interaction = client.interactions.create(
    agent="antigravity-preview-09-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: "view_file|write_to_file|replace_file_content",
                hooks: [
                    {
                        type: "http",
                        url: "https://telemetry.example.com/api/v1/agent-events",
                        timeout: 10,
                    },
                ],
            },
        ],
    },
};

const interaction = await client.interactions.create({
    agent: "antigravity-preview-09-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.Allowlist;
import com.google.genai.gaos.models.interactions.AllowlistEntry;
import com.google.genai.gaos.models.interactions.CreateAgentInteraction;
import com.google.genai.gaos.models.interactions.CreateAgentInteractionEnvironment;
import com.google.genai.gaos.models.interactions.Environment;
import com.google.genai.gaos.models.interactions.EnvironmentNetworkEgressAllowlist;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Network;
import com.google.genai.gaos.models.interactions.Source;
import com.google.genai.gaos.models.interactions.SourceType;
import com.google.genai.gaos.models.interactions.Transform;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.List;
import java.util.Map;

Client client = new Client();

// Define hook without secrets; the egress proxy injects headers dynamically
String 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
          }
        ]
      }
    ]
  }
}
""";

Environment env = Environment.builder()
    .sources(List.of(
        Source.builder()
            .type(SourceType.INLINE)
            .target(".agents/hooks.json")
            .content(hooksConfig)
            .build()
    ))
    .network(Network.of(
        EnvironmentNetworkEgressAllowlist.builder()
            .allowlist(Allowlist.of(List.of(
                AllowlistEntry.builder()
                    .domain("telemetry.example.com")
                    .transform(Transform.of(Map.of(
                        "Authorization", "Bearer telemetry_secret_token_123"
                    )))
                    .build(),
                AllowlistEntry.builder().domain("*").build()
            )))
            .build()
    ))
    .build();

CreateAgentInteraction params = CreateAgentInteraction.builder()
    .agent(AgentOption.of("antigravity-preview-09-2026"))
    .input(InteractionsInput.of("Use your filesystem tool to create `/workspace/audit.log` containing 'event 1', then immediately read it back using your filesystem read tool."))
    .environment(CreateAgentInteractionEnvironment.of(env))
    .build();

Interaction interaction = client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));

Go

package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
    "google.golang.org/genai/interactions/models/interactions"
    "google.golang.org/genai/interactions/models/operations"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    // Define hook without secrets; the egress proxy injects headers dynamically
    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
          }
        ]
      }
    ]
  }
}`

    env := interactions.Environment{
        Sources: []interactions.Source{
            {
                Type:    interactions.SourceTypeInline.ToPointer(),
                Target:  genai.Ptr(".agents/hooks.json"),
                Content: genai.Ptr(hooksConfig),
            },
        },
        Network: genai.Ptr(interactions.NewNetwork(interactions.EnvironmentNetworkEgressAllowlist{
            Allowlist: genai.Ptr(interactions.NewAllowlist([]interactions.AllowlistEntry{
                {
                    Domain: "telemetry.example.com",
                    Transform: genai.Ptr(interactions.NewTransform(map[string]string{
                        "Authorization": "Bearer telemetry_secret_token_123",
                    })),
                },
                {
                    Domain: "*",
                },
            })),
        })),
    }

    res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
        Body: operations.NewCreateInteractionRequestBody(interactions.CreateAgentInteraction{
            Agent:       interactions.AgentOption("antigravity-preview-09-2026"),
            Input:       interactions.NewInteractionsInput("Use your filesystem tool to create `/workspace/audit.log` containing 'event 1', then immediately read it back using your filesystem read tool."),
            Environment: genai.Ptr(interactions.NewCreateAgentInteractionEnvironment(env)),
        }),
    })
    if err != nil {
        log.Fatal(err)
    }
    if res.Interaction.OutputText != nil {
        fmt.Println(*res.Interaction.OutputText)
    }
}

QETËSI

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-09-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\": \"view_file|write_to_file|replace_file_content\", \"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": "*"}
              ]
          }
      }
  }'

Kufizimet

  • Fushëveprimi i veglës së "Zonës së provave": Hooks ndërpresin veglat e integruara brenda zonës së provave: ekzekutimi i kodit (code_execution) dhe operacionet e sistemit të skedarëve (view_file, write_to_file, replace_file_content, list_dir dhe delete_file). Ato nuk aktivizohen për thirrjen e funksioneve të personalizuara (function) ose veglat e jashtme të Model Context Protocol (mcp_server) që menaxhohen jashtë kontejnerit.
  • Listat e lejimeve të rrjetit: Kapëset HTTP ekzekutohen brenda rrjetit të kontejnerit. Duhet të lejosh në mënyrë të qartë URL-të e synuara në network.allowlist të mjedisit tënd. Adresat e ripërsëritjes (localhost, 127.0.0.1) janë bllokuar nga serveri proxy.
  • Miratimi automatik për gabimet: Nëse një skript i lidhjes së funksioneve ndërpritet (statusi i daljes jo zero), i kalon kufijtë kohorë ose dështon, koha e ekzekutimit regjistron dështimin dhe lejon që thirrja e veglës të vazhdojë. Kjo siguron që skriptet e prishura të analizuesit statik ose proceset e bllokuara të mos i bllokojnë aplikacionet e tua.
  • Mbrojtja e konfigurimit të zonës së provave: Për shkak se kapëset ekzekutohen brenda zonës së provave të kontejnerit, agjentët me veglat e shkrimit të sistemit të skedarëve ose lejet e ekzekutimit të kodit të shell-it mund të modifikojnë .agents/hooks.json lokale ose skriptet brenda hapësirave të punës të shkrueshme. Përdor kapëset e kontejnerëve si udhëzime të automatizuara për politikat dhe mbrojtje operacionale; nëse kërkohet rezistencë e rreptë ndaj ndërhyrjeve për ekzekutimet e modeleve të pabesueshme, monto burimet e konfigurimit nga depot vetëm për lexim.

Çfarë ka më pas