হুক

এজেন্ট তার রিমোট স্যান্ডবক্সের মধ্যে কোড এক্সিকিউট বা ফাইল পরিবর্তন করার ঠিক আগে বা পরে হুক আপনাকে কাস্টম স্ক্রিপ্ট বা এক্সটার্নাল 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-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)

জাভাস্ক্রিপ্ট

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

খুলুন

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

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

কাজ করে এমন লাইফসাইকেল ইভেন্ট

হুক স্যান্ডবক্সের মধ্যে ২টি ইভেন্ট কাজ করে:

ইভেন্ট এটি কখন ফায়ার করে এর কাজ কী
pre_tool_execution টুল রান করার ঠিক আগে টুলটি এক্সিকিউট করার আগে সেটি অনুমোদন (allow) বা ব্লক (deny) করতে পারবেন। ব্লক করা হলে, মডেলটি আপনার বাতিল করার কারণ দেখতে পায় এবং সেই অনুযায়ী নিজেকে মানিয়ে নেয়।
post_tool_execution টুল শেষ হওয়ার সাথে সাথেই কোড ফর্ম্যাট করা, ইউনিট টেস্ট চালানো বা টেলিমেট্রি লগ করার মতো ফলো-আপ টাস্ক রান করে। সম্পূর্ণ হয়ে যাওয়া অ্যাকশন ব্লক বা আগের অবস্থায় ফেরানো যায় না।

pre_tool_execution

কোনও টুল এক্সিকিউট করার ঠিক আগে ফায়ার করে। আপনার স্ক্রিপ্ট stdin থেকে টুল কলের বিবরণ পড়ে এবং stdout-এ এর সিদ্ধান্ত JSON (allow বা deny) আউটপুট করে।

ইনপুট পেলোড (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):

{}

কারণ, টুল-পরবর্তী হুক শুধুমাত্র কোড ফর্ম্যাটিং বা লগিংয়ের মতো ব্যাকগ্রাউন্ড টাস্কের জন্য চলে, তাই রানটাইম stdout-এ রিটার্ন করা যেকোনও সিদ্ধান্তমূলক ভ্যালুকে উপেক্ষা করে।

কনফিগারেশন ডিসকভারি

রানটাইম স্যান্ডবক্স এনভায়রনমেন্টের মধ্যে .agents/hooks.json বা /.agents/hooks.json থেকে হুক ডেফিনিশন অটোমেটিক খুঁজে নেয়। আপনি যেকোনও কাজ করে এমন এনভায়রনমেন্ট সোর্স ব্যবহার করে আপনার কাস্টম স্ক্রিপ্টের সাথে hooks.json প্রদান করতে পারবেন:

  • রিপোজিটরি মাউন্ট করা: AGENTS.md-এর সাথে .agents/hooks.json থাকা একটি Git রিপোজিটরি।
  • ক্লাউড স্টোরেজ (gcs): এনভায়রনমেন্টে কপি করা hooks.json সহ একটি GCS বাকেট।
  • ইনলাইন সোর্স: environment.sources-এ পাস করা কাঁচা JSON স্ট্রিং ও স্ক্রিপ্টের কন্টেন্ট 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)। হ্যান্ডলারগুলি ঘোষণা করার ক্রম অনুযায়ী পরপর রান করে।

রেগুলার এক্সপ্রেশন মূল্যায়ন কীভাবে কাজ করে

স্যান্ডবক্সের মধ্যে এজেন্ট কোনও টুল ইনভোক করলে, রানটাইম স্ট্যান্ডার্ড RE2 রেগুলার এক্সপ্রেশন ব্যবহার করে আপনার matcher প্যাটার্নের সাথে টুলের কন্টেনার নামের মূল্যায়ন করে। টুলের নামের সাথে regex মিলে গেলে, hooks অ্যারের মধ্যে থাকা সবকটি হ্যান্ডলার পর পর এক্সিকিউট হয়। একাধিক নিয়ম গ্রুপ একই টুলের সাথে ম্যাচ করলে, সংশ্লিষ্ট সবকটি হ্যান্ডলার অ্যারে রান করে।

আপনি যেকোনও বিল্ট-ইন কন্টেনার টুলের নাম টার্গেট করতে পারেন: কোড এক্সিকিউশন (code_execution) বা ফাইলসিস্টেম অপারেশন (view_file, write_to_file, replace_file_content, list_dir এবং delete_file)।

ম্যাচার এক্সপ্রেশন

  • "code_execution": শেল কমান্ড ও স্ক্রিপ্ট এক্সিকিউশনের জন্য হুবহু স্ট্রিং ম্যাচ।
  • "write_to_file": ফাইলসিস্টেম ফাইল তৈরি ও ডিস্কে লেখার ক্ষেত্রে হুবহু মিল।
  • "view_file|write_to_file": পাইপ সেপারেশন একটি নিয়মের মধ্যে একাধিক নির্দিষ্ট টুলের নামের সাথে ম্যাচ করছে।
  • ".*_file": _file দিয়ে শেষ হওয়া যেকোনও টুলের সাথে ম্যাচ করা রেগুলার এক্সপ্রেশন ওয়াইল্ডকার্ড (যেমন, view_file, write_to_file বা delete_file)। এটি ফাইলসিস্টেম টুলসেটের শুধুমাত্র একটি অংশ কভার করে, replace_file_content এবং list_dir _file দিয়ে শেষ হয় না, তাই আপনার যখন প্রয়োজন হবে তখন স্পষ্টভাবে তাদের নাম উল্লেখ করুন। স্ট্যান্ডার্ড RE2 রেগুলার এক্সপ্রেশনে .* প্রয়োজন; *_file-এর মতো সাধারণ শেল গ্লোব ভুল রেজেক্স সিনট্যাক্স এবং ম্যাচ করতে পারবে না।
  • ".*" বা "*" বা "": কন্টেনারের মধ্যে থাকা প্রতিটি টুল কল ইন্টারসেপ্ট করে এমন ক্যাচ-অল প্যাটার্ন।

হ্যান্ডলারের ধরন

কমান্ড হুক

কমান্ড হুক স্যান্ডবক্সের মধ্যে একটি শেল কমান্ড বা স্ক্রিপ্ট এক্সিকিউট করে। স্ক্রিপ্টটি stdin-এ ইভেন্ট JSON পায় এবং stdout-এ তার সিদ্ধান্ত JSON আউটপুট করে।

ফিল্ড ধরন বিবরণ
type string "command" হতে হবে।
command string স্যান্ডবক্সের মধ্যে রান করার জন্য কমান্ড লাইন (যেমন, python3 /.agents/hooks-scripts/gate.py)।
timeout integer টাইম-আউট সেকেন্ডে। ডিফল্ট: 30.

HTTP হুক

HTTP হুক, স্যান্ডবক্স নেটওয়ার্কের মধ্যে থেকে সরাসরি কোনও এক্সটার্নাল HTTPS URL-এ ইভেন্ট JSON-কে POST অনুরোধ হিসেবে পাঠায়। টার্গেট সার্ভার ঠিক একই JSON ফর্ম্যাট ({"decision": "allow"} বা {"decision": "deny", "reason": "..."}) ব্যবহার করে HTTP রেসপন্স বডিতে তার সিদ্ধান্ত রিটার্ন করে।

ফিল্ড ধরন বিবরণ
type string "http" হতে হবে।
url string ইভেন্ট পেলোড পোস্ট করার জন্য এক্সটার্নাল HTTPS এন্ডপয়েন্ট।
headers object সংবেদনশীল নয় এমন কাস্টম হেডারের জন্য ঐচ্ছিক কী-ভ্যালু পেয়ার (যেমন {"X-Event-Source": "agent-sandbox"})। যাচাইকরণের জন্য, নেটওয়ার্কের অনুমোদিত তালিকায় ক্রেডেনশিয়াল ব্যবহার করুন।
timeout integer টাইম-আউট সেকেন্ডে। ডিফল্ট: 30.

এগ্রেস প্রক্সি ও টোকেন ট্রান্সফর্মেশন

HTTP হুক স্যান্ডবক্স নেটওয়ার্ক নেমস্পেসের মধ্যে থেকে সরাসরি এক্সিকিউট হয় বলে, আউটগোয়িং অনুরোধ ট্রান্সপারেন্ট ইগ্রেস প্রক্সির মাধ্যমে পাস হয়। এই আর্কিটেকচার আপনাকে ২টি গুরুত্বপূর্ণ নিরাপত্তা সংক্রান্ত সুবিধা দেয়:

  • নেটওয়ার্ক হোয়াইটলিস্ট করা: আপনার এনভায়রনমেন্টের network.allowlist-এ টার্গেট এন্ডপয়েন্টকে স্পষ্টভাবে অনুমতি দিতে হবে। প্রক্সি লুপব্যাক ট্রাফিক (127.0.0.1 বা localhost) ব্লক করে; সবসময় সাদাতালিকায় থাকা এক্সটার্নাল এন্ডপয়েন্ট টার্গেট করুন।
  • ক্রেডেনশিয়াল ইনজেকশন: আপনাকে .agents/hooks.json-এর মধ্যে API কী বা গোপন বিয়ারার টোকেন স্টোর করতে হবে না অথবা কন্টেনারে মাউন্ট করতে হবে না। ক্রেডেনশিয়াল হিসেবে সিক্রেটটি একবার স্টোর করুন এবং আপনার এনভায়রনমেন্টের network.allowlist থেকে আইডি দিয়ে এটি রেফারেন্স করুন। স্যান্ডবক্স থেকে বেরিয়ে যাওয়ার আগে ইগ্রেস প্রক্সি অটোমেটিক আউটগোয়িং HTTP হুক ট্রাফিক ইন্টারসেপ্ট করে এবং ওয়্যারে আসল যাচাইকরণ হেডার ইনজেক্ট করে। ইনলাইন transform নিয়মগুলি ওয়্যারে একই পদ্ধতিতে হেডার সেট করে, কোনও প্রোজেক্ট জুড়ে সিক্রেট আবার ব্যবহার করতে চাইলে এবং সেটি এক জায়গায় রোটেট করতে চাইলে, একটি ক্রেডেনশিয়াল ব্যবহার করতে হবে। নেটওয়ার্ক কনফিগারেশন দেখুন।

রানটাইম কীভাবে সিদ্ধান্ত ও ব্যর্থতা ম্যানেজ করে

  • সিঙ্ক্রোনাস অপেক্ষা: এজেন্ট পজ করে এবং চালিয়ে যাওয়ার আগে আপনার হুক শেষ হওয়ার জন্য অপেক্ষা করে।
  • ব্লকিং টুল এক্সিকিউশন: আপনার প্রি-টুল হুক {"decision": "deny", "reason": "<your reason>"} রিটার্ন করলে, রানটাইম সাথে সাথেই টুল কল বাতিল করে দেয়। মডেলটি কনভার্সেশন ইতিহাসে আপনার প্রত্যাখ্যানের কারণ দেখে এবং নিরাপদ বিকল্প বেছে নিয়ে বা ব্যবহারকারীকে ব্লক করার কারণ ব্যাখ্যা করে নিজেকে মানিয়ে নেয়।
  • স্ক্রিপ্ট ক্র্যাশ, HTTP সমস্যা ও টাইম-আউট ম্যানেজ করা: কোনও কমান্ড স্ক্রিপ্ট ক্র্যাশ করলে (শূন্য নয় এমন এক্সিট স্ট্যাটাস), কোনও HTTP হুক শূন্য নয় এমন 2xx স্ট্যাটাস কোড (যেমন, 4xx বা 5xx সার্ভার সমস্যা) রিটার্ন করলে অথবা কোনও অপারেশন টাইম-আউট হয়ে গেলে বা শনাক্ত করা যায় না এমন JSON রিটার্ন করলে, রানটাইম এটিকে অনুমোদন (allow) হিসেবে ধরে নেয়। টুল এক্সিকিউশন স্বাভাবিকভাবে চলতে থাকে, তাই কোনও ভাঙা স্ক্রিপ্ট বা নাগালের বাইরে থাকা টেলিমেট্রি সার্ভার আপনার অ্যাপ্লিকেশনকে কখনওই ডেডলক করে না।

সাধারণ ব্যবহারিক প্রয়োগ

ডেটা গোপনীয়তা ও নীতি মেনে চলার জন্য মাল্টি-টার্ন রিকভারি

কোনও হুক যদি বিধিনিষেধযুক্ত রিসোর্সে অ্যাক্সেস ব্লক করে দেয়—যেমন, ব্যক্তিগতভাবে শনাক্তকরণযোগ্য তথ্য (PII) বা গোপন আর্থিক রেকর্ড থাকা ডিরেক্টরি—তাহলে একই এনভায়রনমেন্টে টার্ন চালিয়ে যেতে আপনি পরবর্তী কলে previous_interaction_id পাস করতে পারেন। এজেন্ট প্রত্যাখ্যানের ব্যাখ্যাটি পড়ে এবং পরিবর্তে অনুমোদিত পাবলিক টেবিল কোয়েরি করে অটোমেটিক রিকভার করে।

Python

import json
from google import genai

client = genai.Client()

hooks_config = {
    "privacy-gate": {
        "pre_tool_execution": [
            {
                "matcher": "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)

জাভাস্ক্রিপ্ট

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

খুলুন

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

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

এক্সটার্নাল অডিট লগিং ও টেলিমেট্রি

স্যান্ডবক্সের মধ্যে থেকে কোনও ফাইল পড়া বা পরিবর্তন করা হলে, রিয়েল-টাইম অডিট ইভেন্ট এক্সটার্নাল মনিটরিং সার্ভারে পাঠান।

  • একাধিক টুল ম্যাচ করা: ম্যাচ করার টুল স্ট্যান্ডার্ড রেগুলার এক্সপ্রেশন ব্যবহার করে বলে, আপনি পাইপ (view_file|write_to_file|replace_file_content) বা ওয়াইল্ডকার্ড (.*_file) ব্যবহার করে একটি নিয়মের মধ্যে একাধিক টুল একত্রিত করতে পারবেন।
  • কনফিগারেশনে গোপন তথ্য রাখবেন না: ক্রেডেনশিয়াল হিসেবে যাচাইকরণ টোকেন সেভ করুন এবং আপনার এনভায়রনমেন্টের নেটওয়ার্ক কনফিগারেশন (network.allowlist.credential) থেকে আইডি দিয়ে এটি রেফারেন্স করুন। বেরিয়ে যাওয়া অনুরোধে ইগ্রেস প্রক্সি আসল বিয়ারার টোকেন ইনজেক্ট করে। এই উদাহরণে transform-এর সাথে ইনলাইন হেডার সেট করা হয়েছে, যা একই প্রক্সি দ্বারা সুরক্ষিত এবং টোকেনটি এই একটি কনফিগারেশনের হলে ফিট করে।

Python

import json
from google import genai

client = genai.Client()

# Define hook without secrets; the egress proxy injects headers dynamically
hooks_config = {
    "audit-logging": {
        "post_tool_execution": [
            {
                "matcher": "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)

জাভাস্ক্রিপ্ট

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

খুলুন

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

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

সীমাবদ্ধতা

  • স্যান্ডবক্স টুলের স্কোপ: হুক স্যান্ডবক্সের মধ্যে বিল্ট-ইন টুল ইন্টারসেপ্ট করে: কোড এক্সিকিউশন (code_execution) এবং ফাইলসিস্টেম অপারেশন (view_file, write_to_file, replace_file_content, list_dir এবং delete_file)। কন্টেনারের বাইরে ম্যানেজ করা কাস্টম ফাংশন কলিং (function) বা এক্সটার্নাল মডেল কন্টেক্সট প্রোটোকল (mcp_server) টুলের জন্য এগুলি ফায়ার হয় না।
  • নেটওয়ার্ক সাদাতালিকা: HTTP হুক কন্টেনার নেটওয়ার্কের মধ্যে রান করে। আপনার এনভায়রনমেন্টের network.allowlist-এ টার্গেট URL-কে স্পষ্টভাবে অনুমতি দিতে হবে। প্রক্সি লুপব্যাক অ্যাড্রেস (localhost, 127.0.0.1) ব্লক করে দেয়।
  • সমস্যা হলে অটোমেটিক অনুমোদন: কোনও হুক স্ক্রিপ্ট ক্র্যাশ করলে (শূন্য নয় এমন এক্সিট স্ট্যাটাস), টাইম-আউট হয়ে গেলে বা কাজ না করলে, রানটাইম ব্যর্থতা লগ করে এবং টুল কল চালিয়ে যাওয়ার অনুমতি দেয়। এর ফলে, ভাঙা লিন্টার স্ক্রিপ্ট বা ঝুলন্ত প্রসেস আপনার অ্যাপ্লিকেশনকে কখনওই ডেডলক করতে পারে না।
  • স্যান্ডবক্স কনফিগারেশন সুরক্ষা: যেহেতু কন্টেনার স্যান্ডবক্সের মধ্যে হুক এক্সিকিউট হয়, তাই ফাইলসিস্টেম রাইট টুল বা শেল কোড এক্সিকিউশন অনুমতি সহ এজেন্টরা এডিট করা যায় এমন ওয়ার্কস্পেসের মধ্যে লোকাল .agents/hooks.json বা স্ক্রিপ্ট পরিবর্তন করতে পারে। অটোমেটেড নীতি সংক্রান্ত নির্দেশিকা ও অপারেশনাল গার্ডরেল হিসেবে কন্টেনার হুক ব্যবহার করুন; যদি অনির্ভরযোগ্য মডেল এক্সিকিউশনের বিরুদ্ধে কঠোরভাবে টেম্পার প্রতিরোধ করার প্রয়োজন হয়, তাহলে শুধুমাত্র-পঠনযোগ্য রিপোজিটরি থেকে মাউন্ট কনফিগারেশন সোর্স।

এর পরে কী করতে হবে