১. সংক্ষিপ্ত বিবরণ
কৃত্রিম বুদ্ধিমত্তা (AI) এবং প্রযুক্তির জগৎ এতটাই দ্রুত পরিবর্তিত হচ্ছে যে এর গতি কেউ ধরতে পারে না। প্রতিদিন নতুন নতুন মডেল, গবেষণাপত্র এবং পণ্য আসছে। এমন একটি ডাইজেস্ট এজেন্ট, যা আজকের প্রধান খবরগুলো সংগ্রহ করে, সংক্ষিপ্ত সারসংক্ষেপ লেখে এবং প্রতিদিন সকালে একটি পিডিএফ তৈরি করে দেয়, তা এই সমস্যার সমাধান করতে পারত। কিন্তু আগে এমন একটি এজেন্ট তৈরি করতে হলে একটি ফ্রেমওয়ার্ক বেছে নিতে হতো, পাইথনে টুলস সংজ্ঞায়িত করতে হতো, একটি অর্কেস্ট্রেশন লুপ লিখতে হতো, একটি কন্টেইনার প্যাকেজ করতে হতো এবং ক্লাউড রানে ডেপ্লয় করতে হতো। আর এই সবকিছুই করতে হতো এজেন্টটি একটিও ওয়েব রিকোয়েস্ট পাঠানোর আগেই।
জেমিনি এপিআই-এর ম্যানেজড এজেন্ট পুরো পরিস্থিতিটাই পাল্টে দেয়। আপনি দুটি মার্কডাউন কনফিগারেশন ফাইল এবং একটি প্রি-বিল্ট রেন্ডারার স্ক্রিপ্ট লেখেন, একটি মাত্র এপিআই কল করেন, আর একটি আসল উবুন্টু স্যান্ডবক্স বুট হয়, ওয়েব ব্রাউজ করে, আপনার সামারিগুলো লেখে এবং একটি পিডিএফ তৈরি করে। কোনো কন্টেইনার নেই। কোনো ডেপ্লয়মেন্ট নেই। কোনো অর্কেস্ট্রেশন কোড নেই।
এই কোডল্যাবে আপনি ঠিক সেই এজেন্টটিই তৈরি করবেন: একটি খালি ফাংশন থেকে শুরু করে, ধাপে ধাপে একটি কার্যকর দৈনিক সারসংক্ষেপ পর্যন্ত।
আপনি যা তৈরি করবেন
- একটি বাস্তব লিনাক্স স্যান্ডবক্সে আপনার প্রথম পরিচালিত এজেন্ট তৈরি করুন এবং চালান।
- সম্পাদকীয় বাচনভঙ্গি, ওয়েব উৎস এবং পিডিএফ দক্ষতা দিয়ে এজেন্টটিকে কাস্টমাইজ করুন।
- ক্ষতিকর কমান্ডগুলো চলার আগেই ব্লক করতে একটি সেফটি হুক যোগ করুন।
- এজেন্ট কর্তৃক তৈরি করা পিডিএফটি ডাউনলোড করুন।
- ওয়েব থেকে পুনরায় তথ্য না এনেই একাধিক পালাবিশিষ্ট কথোপকথনের সারসংক্ষেপ পরিমার্জন করুন।
- এজেন্ট কনফিগারেশনটি সংরক্ষণ করুন এবং পরবর্তী রানগুলিতে আইডি দ্বারা এটিকে চালু করুন।
- জিমেইল এপিআই (Gmail API) ব্যবহার করে সারসংক্ষেপটি আপনার ইনবক্সে পাঠান।
- এজেন্টটিকে প্রতিদিন স্বয়ংক্রিয়ভাবে চালানো এবং পাঠানোর জন্য সময়সূচী নির্ধারণ করুন।
আপনার যা যা লাগবে
- পাইথন ৩.১০+
- একটি জেমিনি এপিআই কী: aistudio.google.com/api-keys (ফ্রি টিয়ার অন্তর্ভুক্ত; নিরবচ্ছিন্নভাবে চালানোর জন্য বিলিং সুপারিশ করা হয়)
২. জেমিনি এপিআই-তে ম্যানেজড এজেন্ট বলতে কী বোঝায়?
এআই সিস্টেমের তিনটি স্তর
কোডে প্রবেশ করার আগে, দুটি বিকল্পের তুলনায় ম্যানেজড এজেন্ট কোথায় অবস্থান করে তা এখানে তুলে ধরা হলো:
স্তর | এটা কি | অবকাঠামো কে পরিচালনা করে? |
স্ট্যান্ডার্ড এলএলএম | আপনি নির্দেশ দেন, এটি টেক্সটের মাধ্যমে উত্তর দেয়। হাত নেই, মেমরি নেই, ইন্টারনেটও নেই। | প্রযোজ্য নয়: এটি নিজে থেকে কিছুই করতে পারে না। |
সেলফ-হোস্টেড এজেন্ট | আপনি ADK/LangChain/AutoGen + Docker + টুলস + মেমরি সংযুক্ত করেন। | আপনি: এই সব (অথবা এজেন্ট ইঞ্জিনের মতো একটি পরিচালিত প্ল্যাটফর্ম) |
পরিচালিত এজেন্ট | আপনি একে একটি লক্ষ্য দেন। গুগল একটি সুরক্ষিত স্যান্ডবক্স প্রস্তুত করে। এজেন্টটি স্বয়ংক্রিয়ভাবে কোড লেখে, তা চালায়, ত্রুটি পড়ে, ওয়েবে অনুসন্ধান করে এবং বাগ সংশোধন করে। | গুগল: এর সবকিছু |
এই কোডল্যাবটি তৃতীয় সারি সম্পর্কিত। আপনাকে একটি টাস্ক এবং কনফিগারেশন ফাইল সরবরাহ করতে হবে। বাকি সবকিছু গুগল সামলে নেবে।
ADK + ক্লাউড রান দিয়ে আপনি যা তৈরি করবেন
এমন একটি নিউজ ডাইজেস্ট এজেন্ট তৈরি করতে, যা ওয়েব ব্রাউজ করে, পাইথন চালায় এবং একটি পিডিএফ তৈরি করে, আপনার ADK + Cloud Run-এর সাথে এই সবকিছুর প্রয়োজন হবে:
# agent.py: define tools and wire up the agent
from google.adk.agents import LlmAgent
from google.adk.tools import google_search, built_in_code_execution
agent = LlmAgent(
name="digest-agent",
model=MODEL,
instruction=AGENTS_MD, # your editorial voice and rules
tools=[google_search, built_in_code_execution],
)
# app.py: serve the agent over HTTP
from google.adk.runners import FastApiRunner
runner = FastApiRunner(agent=agent)
app = runner.app
# pdf_tool.py: custom tool, install reportlab, render PDF
# scraper.py: custom tool, fetch each news source
# streaming.py: wire agent events to your SSE endpoint
# Dockerfile: package everything
FROM python:3.12
COPY . /app
RUN pip install google-adk reportlab requests
CMD ["uvicorn", "app:app", "--host", "0.0.0.0"]
# Deploy to Cloud Run
gcloud run deploy digest-agent \
--image gcr.io/your-project/digest-agent \
--set-secrets GEMINI_API_KEY=gemini-key:latest \
--memory 2Gi
এটি এজেন্ট একবারও চলার আগের কথা। স্যান্ডবক্স আইসোলেশন (যাতে এজেন্ট আপনার সার্ভারের ক্ষতি করতে না পারে), প্যাকেজ ইনস্টলেশন, টুল কলগুলোর মধ্যে স্টেট ম্যানেজমেন্ট এবং ক্লায়েন্টের কাছে ইভেন্ট পাঠানোর জন্য স্ট্রিমিং পরিকাঠামোর দায়িত্ব তখনও আপনারই থাকে।
ম্যানেজড এজেন্টরা এটিকে যা দিয়ে প্রতিস্থাপন করে
from google import genai
client = genai.Client()
stream = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Generate the digest.",
stream=True,
environment={
"type": "remote",
"sources": [ # your config files, mounted at startup
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": AGENTS_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/SKILL.md",
"content": SKILL_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
"content": GENERATE_PDF_PY,
},
],
},
)
ADK + ক্লাউড রানের যা প্রয়োজন | ম্যানেজড এজেন্টরা আপনার জন্য যা পরিচালনা করে |
কন্টেইনার ইমেজ + ডকারফাইল + সিআই/সিডি | সম্পূর্ণরূপে পরিচালিত উবুন্টু স্যান্ডবক্স (পাইথন ৩.১২, নোড ২২, ৪ সিপিইউ / ১৬ জিবি র্যাম) |
ক্লাউড রান ডেপ্লয়মেন্ট + স্কেলিং | প্রতিটি ব্যবহারের জন্য বরাদ্দকৃত, ৭ দিন নিষ্ক্রিয় থাকলে স্বয়ংক্রিয়ভাবে মেয়াদ শেষ হয়ে যায়। |
স্যান্ডবক্স বিচ্ছিন্নতা | মিথস্ক্রিয়া অনুসারে বিচ্ছিন্ন |
কাস্টম পিডিএফ টুল + | এজেন্ট স্যান্ডবক্সের ভিতরে প্যাকেজ ইনস্টল করে। |
এসএসই স্ট্রিমিং পরিকাঠামো | |
পাইথনে টুলের সংজ্ঞা | অন্তর্নির্মিত সরঞ্জাম: ওয়েব ব্রাউজ, কোড এক্সিকিউশন, ফাইল সিস্টেম |
টুল কলের মধ্যে অবস্থা ব্যবস্থাপনা | এজেন্ট রিজনিং লুপের মধ্যে নির্মিত |
আপনি কনফিগারেশন ফাইলগুলো ( AGENTS.md , SKILL.md , একটি প্রি-বিল্ট স্ক্রিপ্ট) লেখেন এবং একটি এপিআই কল করেন। বাকি সবকিছু গুগল সামলে নেয়।
স্যান্ডবক্স কীভাবে কাজ করে
interactions.create() call
│
▼
Google provisions Ubuntu sandbox (Python 3.12, Node 22, 4 CPU / 16 GB RAM)
│
▼
Agent reasoning loop:
plan → fetch URLs → run Python → write files → reason → repeat
│
▼
Events stream back in real time: tool calls, text chunks, completion
│
▼
interaction.completed → environment_id + interaction_id
স্যান্ডবক্সটি ৭ দিন নিষ্ক্রিয় থাকার পরেও টিকে থাকে। আপনি আউটপুট পরিমার্জন করতে, পরবর্তী কাজগুলো চালাতে, অথবা এটিকে একটি সংরক্ষিত নামযুক্ত এজেন্টে ফোর্ক করতে environment_id ব্যবহার করে এটিকে পুনরায় চালু করতে পারেন।
৩. সেট আপ করুন
বিকল্প A: ক্লাউড শেল (প্রস্তাবিত)
গুগল ক্লাউড শেলে এই কোডল্যাবটি খুলতে নিচের বোতামটি ক্লিক করুন। সমস্ত নির্ভরতা আগে থেকেই ইনস্টল করা আছে।
বিকল্প বি: স্থানীয় সেটআপ
git clone https://github.com/Saoussen-CH/tech-digest-managed-agent.git
cd tech-digest-managed-agent
প্রয়োজনে uv ইনস্টল করুন:
curl -LsSf https://astral.sh/uv/install.sh | sh
আপনার এপিআই কী কনফিগার করুন
cp .env.example .env
cloudshell edit .env
আপনার চাবি সেট করুন:
GEMINI_API_KEY=your-key-here
নির্ভরতা ইনস্টল করুন
uv sync
৪. এজেন্টের সাথে প্রথমবার যোগাযোগ করুন
স্টার্টার ফাইলটি খুলুন
cloudshell edit run_digest.py
run_digest() এখন পূরণ করার জন্য একটি TODO এবং পরবর্তী ধাপের জন্য আরও তিনটি রয়েছে। এর উপরে দুটি হেল্পার ইতিমধ্যেই পূরণ করা আছে:
-
load_source(path): স্ক্রিপ্টের সাপেক্ষে.agents/থেকে একটি ফাইল পড়ে। পরবর্তী অনুশীলনীতে স্যান্ডবক্সে এডিটোরিয়াল ভয়েস, পিডিএফ প্লেবুক এবং রেন্ডারার মাউন্ট করার জন্য আপনি এটি ব্যবহার করবেন। -
run_stream(stream): ইভেন্ট স্ট্রিমটি প্রসেস করে এবং(environment_id, interaction_id)রিটার্ন করে। আপনাকে নিজে থেকে ইভেন্ট লুপ লিখতে হবে না।
কী যোগ করতে হবে
করণীয় ১: pass এর পরিবর্তে ব্যবহার করুন (আপাতত করণীয় ৩ ও ৪ উপেক্ষা করুন; ওগুলো পরবর্তী ধাপের জন্য):
from google import genai
client = genai.Client()
stream = client.interactions.create(
agent=BASE_AGENT,
agent_config={"type": "antigravity", "model": "gemini-3.7-flash"},
input="Fetch the Hacker News front page and list the top 5 stories.",
stream=True,
environment="remote",
)
environment_id, interaction_id = run_stream(stream)
print(f"\nDone. environment_id={environment_id}")
প্রতিটি অংশ কী করে
genai.Client() এনভায়রনমেন্ট থেকে GEMINI_API_KEY পড়ে নেয়। বাকি সবকিছু এই ক্লায়েন্টের মাধ্যমেই সম্পন্ন হয়।
interactions.create() হলো মূল কল। চারটি প্যারামিটার এটিকে কার্যকর করে তোলে:
-
agent=BASE_AGENT: এটি অ্যান্টিগ্র্যাভিটি এজেন্ট (antigravity-preview-05-2026) নির্বাচন করে, যা ডিফল্টরূপে জেমিনি ৩.৭ ফ্ল্যাশ দ্বারা চালিত একটি সাধারণ-উদ্দেশ্যমূলক পরিচালিত এজেন্ট। আপনিagent_configব্যবহার করে অন্তর্নিহিত মডেলটি কনফিগার করতে পারেন (বিকল্পসমূহ:gemini-3.7-flash,gemini-3.6-flash,gemini-3.5-flash,gemini-3.5-flash-lite)। এটিতে ডিফল্টরূপে তিনটি বিল্ট-ইন টুল সক্রিয় থাকে:code_execution(Bash, Python, Node.js চালানোর জন্য),google_search, এবংurl_context(ওয়েব পেজ আনা ও পড়ার জন্য)। আপনি যখনenvironmentপ্যারামিটারটি পাস করেন, তখন ফাইলসিস্টেম টুলগুলো (read_file,write_file,list_files) স্বয়ংক্রিয়ভাবে সক্রিয় হয়ে যায়। একবার কল করলেই Python 3.12, Node.js 22, git, pip, এবং curl আগে থেকে ইনস্টল করা একটি সম্পূর্ণ পরিচালিত উবুন্টু পরিবেশ প্রস্তুত হয়ে যায়। কোনো কন্টেইনার তৈরি করার বা কোনো ডেপ্লয়মেন্ট চালানোর প্রয়োজন নেই। -
input: এই রানের জন্য নির্ধারিত কাজ। এজেন্টটি হ্যাকার নিউজ ব্রাউজ করে এবং প্রাপ্ত ফলাফলগুলো নিয়ে যুক্তি-তর্ক করে। -
environment="remote": এই ইন্টারঅ্যাকশনের জন্য একটি নতুন ক্লাউড স্যান্ডবক্স প্রস্তুত করা হবে। -
stream=True: ব্লক করার পরিবর্তে ইভেন্টগুলোর একটি ইটারেবল রিটার্ন করে। এটি ছাড়া, কলটি ৩০-৯০ সেকেন্ড অপেক্ষা করে এবংinteraction.output_textহিসেবে সমস্ত আউটপুট একবারে রিটার্ন করে। স্ট্রিমিং চালু থাকলে, এজেন্ট যখন যা করে, আপনি তখনই তা দেখতে পান। এখানে স্ট্রিমিং কোনো অ্যাডভান্সড ফিচার নয়: এটিই সঠিক ডিফল্ট, কারণ ৯০-সেকেন্ডের একটি ব্ল্যাক বক্স আপনাকে কোনো সংকেত দেয় না যে এজেন্ট কাজ করছে নাকি আটকে আছে।
environment_id হলো এইমাত্র চালানো স্যান্ডবক্সটির একটি হ্যান্ডেল। interaction.completed পরে, স্যান্ডবক্সটি বন্ধ হয় না: এটি ৭ দিন পর্যন্ত সচল থাকে। environment_id এর মাধ্যমেই আপনি এতে ফিরে যেতে পারবেন। দ্বিতীয় একটি interactions.create() কলে এটি পাস করলে এজেন্টটি একই ফাইলসিস্টেমে, একই ফাইল এবং ইনস্টল করা প্যাকেজসহ পুনরায় চালু হয়, যেন এটি কখনও বন্ধই হয়নি। পরবর্তী ধাপে এজেন্টকে পুনরায় না চালিয়েই পিডিএফ ডাউনলোড করার জন্য এটি ব্যবহৃত হয়, এবং তার পরের ধাপে কথোপকথন চালিয়ে যাওয়ার জন্য এটি ব্যবহার করা হয়।
interaction_id হলো এইমাত্র শেষ হওয়া কথোপকথনের পালাটির একটি হ্যান্ডেল। পরবর্তী কলে এটিকে previous_interaction_id হিসেবে পাস করুন, তাহলে এই পালায় এজেন্ট কী বলেছে এবং কী করেছে তার সম্পূর্ণ স্মৃতি তার মনে থাকবে।
যাচাই করুন
uv run python run_digest.py
এজেন্ট কাজ করার সময় আপনি সরাসরি আউটপুট দেখতে পাবেন:
[agent started]
[tool] run_code
Here are the top 5 stories currently on the Hacker News front page, retrieved via the official Hacker News API:
1. **Qwen 3.6 27B is the sweet spot for local development** (471 points)
2. **.self: A new top-level domain designed to support self-hosting** (116 points)
...
Done. environment_id=e3de58774073f75a6ef42924c6ce2e88
environment="remote" করা থাকলেও API-টি একটি আসল environment_id রিটার্ন করে। স্যান্ডবক্সটি চলেছে। যা নেই তা হলো কনফিগারেশন: কোনো ভয়েস, স্কিল বা পিডিএফ জেনারেটর নেই। এজেন্টটি শুধু স্টোরিগুলো টেক্সট হিসেবে প্রিন্ট করে থেমে গেছে। পরবর্তী ধাপে এগুলো যোগ করা হবে।
আউটপুটের প্রতিটি লাইন run_stream() থেকে আসা একটি ইভেন্টের সাথে সম্পর্কিত:
| এটা কি | |
| এজেন্ট একটি URL আনছে | |
| এজেন্ট স্যান্ডবক্সে কোড চালাচ্ছে | |
| এজেন্ট ওয়েব অনুসন্ধান করছে | |
| ফাইল টুল এবং অন্যান্য | |
| এজেন্ট টেক্সট লিখছে | সরাসরি stdout-এ স্ট্রিম করা হয়েছে |
৫. এজেন্টকে কাস্টমাইজ করুন
এজেন্টের কোনো নির্দেশনা ছিল না: কোনো ভয়েস, কোনো স্কিল, কোনো পিডিএফ জেনারেটর ছিল না। এই ধাপে আপনি .agents/ থেকে কনফিগারেশন ফাইলগুলো লোড করে স্যান্ডবক্সে মাউন্ট করবেন।
কী পরিবর্তন করতে হবে
run_digest.py ফাইলে চারটি পরিবর্তন করুন:
করণীয় ২: load_source() এর নিচে, তিনটি মডিউল-স্তরের কনস্ট্যান্ট যোগ করুন (এগুলো run_digest() এর বাইরে, ফাইলের শীর্ষে থাকবে):
AGENTS_MD = load_source(".agents/AGENTS.md")
SKILL_MD = load_source(".agents/skills/digest-pdf/SKILL.md")
GENERATE_PDF_PY = load_source(".agents/skills/digest-pdf/scripts/generate_pdf.py")
আপনি কী লোড করছেন তা দেখতে প্রতিটি ফাইল খুলুন: AGENTS.md ফাইলটি সম্পাদকীয় ভাষা এবং কর্মপ্রবাহের নিয়মাবলী নির্ধারণ করে; SKILL.md হলো ধাপে ধাপে নির্দেশিকা সম্বলিত পিডিএফ প্লেবুক; generate_pdf.py হলো আগে থেকে তৈরি করা রেন্ডারার যা এজেন্টটি চালাবে।
এখন run_digest() এর ভিতরে আরও দুটি পরিবর্তন করুন:
করণীয় ৩: environment "remote" থেকে sources dict-এ পরিবর্তন করুন, এবং input "Generate the digest."
environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": AGENTS_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/SKILL.md",
"content": SKILL_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
"content": GENERATE_PDF_PY,
},
],
},
করণীয় ৪: print(f"\nDone. environment_id={environment_id}") এর ঠিক পরেই এই লাইনটি যোগ করুন:
save_env(ENVIRONMENT_ID=environment_id, INTERACTION_ID=interaction_id)
run_digest.py ফাইলে save_env আগে থেকেই সংজ্ঞায়িত করা আছে। এটি উভয় আইডি .env ফাইলে লিখে রাখে, ফলে পরবর্তী ধাপে এজেন্টকে পুনরায় না চালিয়েই পিডিএফ ডাউনলোড করা যায়।
প্রতিটি উৎস যা করে
প্রতিটি সোর্স হলো একটি ফাইল যা এজেন্ট চালু হওয়ার আগে স্টার্টআপের সময় স্যান্ডবক্স ফাইলসিস্টেমে মাউন্ট করা হয়। target পাথগুলো সেই জায়গার সাথে মিলে যায় যেখানে অ্যান্টিগ্র্যাভিটি হারনেস সেগুলোকে খুঁজে পাওয়ার আশা করে:
.agents/
├── AGENTS.md ← auto-loaded as global instructions
└── skills/
└── digest-pdf/
├── SKILL.md ← auto-discovered and registered as a skill
└── scripts/
└── generate_pdf.py ← pre-built renderer the agent can run
| পরিবর্তনশীল | হারনেসটি এটি দিয়ে যা করে |
| | স্থায়ী নির্দেশাবলী হিসেবে স্বয়ংক্রিয়ভাবে লোড হয়: সম্পাদকীয় ভাষা, কর্মপ্রবাহ, কার্যনির্বাহের নিয়মাবলী |
| | স্বয়ংক্রিয়ভাবে আবিষ্কৃত এবং একটি নামযুক্ত দক্ষতা হিসাবে নিবন্ধিত; এজেন্ট এটিকে নাম ধরে আহ্বান করে। |
| | পূর্ব-নির্মিত পিডিএফ রেন্ডারার; এজেন্টটি |
যাচাই করুন
uv run python run_digest.py
এই প্রক্রিয়াটি সম্পন্ন হতে এখন ১-৩ মিনিট সময় লাগে। আপনি দেখবেন এজেন্টটি কনফিগারেশন ফাইলগুলো পড়ছে, সারাংশ লিখছে এবং পিডিএফটি সংরক্ষণ করছে।
[agent started]
[tool] read_file (/.agents/skills/digest-pdf/SKILL.md)
[tool] list_files (/.agents/skills/digest-pdf/scripts)
[tool] read_file (/.agents/skills/digest-pdf/scripts/generate_pdf.py)
[tool] run_code
[tool] write_file (/workspace/summaries.json)
[tool] run_code
[tool] delete_file (/tmp/test_scrape.py)
I have successfully generated today's tech news digest and saved the formatted document to /workspace/digest.pdf.
Done. environment_id=4129ffd75574e308748e9425d7ec828f
environment_id এখন একটি বাস্তব মান: স্যান্ডবক্সটি আপনার কনফিগারেশন ফাইলগুলো দিয়ে চলেছে এবং এজেন্টটি digest.pdf তৈরি করেছে। পরবর্তী ধাপে ডাউনলোডের আগে একটি সেফটি হুক যোগ করা হয়।
৬. একটি নিরাপত্তা হুক যোগ করুন।
হুক আপনাকে প্রতিটি টুল কলের আগে বা পরে স্যান্ডবক্সের ভিতরে একটি স্ক্রিপ্ট চালানোর সুযোগ দেয়। ডাইজেস্ট এজেন্ট পাইথন স্ক্রিপ্ট চালানোর জন্য code_execution ব্যবহার করে, তাই একটি pre_tool_execution হুক সেই কলগুলোকে ইন্টারসেপ্ট করতে পারে এবং ক্ষতিকর শেল কমান্ডগুলো কার্যকর হওয়ার আগেই ব্লক করতে পারে।
রানটাইম স্যান্ডবক্স থেকে .agents/hooks.json ফাইলটি পড়ে। প্রতিটি ম্যাচিং টুল কল করার আগে, এটি কলের বিবরণ stdin এ আপনার গেট স্ক্রিপ্টে পাইপ করে। স্ক্রিপ্টটি stdout এ {"decision": "allow"} অথবা {"decision": "deny", "reason": "..."} প্রিন্ট করে। একটি 'deny' টুল কলটি বাতিল করে দেয় এবং এজেন্ট আপনার কারণটি দেখে নিজেকে সংশোধন করে নেয়।
কী যোগ করতে হবে
করণীয় ৫: run_digest.py ফাইলে, বিদ্যমান load_source কলগুলোর পরে, উপরের দিকে এই দুটি কনস্ট্যান্ট যোগ করুন:
import json
HOOKS_JSON = json.dumps({
"safety-gate": {
"pre_tool_execution": [
{
"matcher": "code_execution",
"hooks": [
{
"type": "command",
"command": "python3 /.agents/hooks-scripts/gate.py",
"timeout": 10,
}
],
}
]
}
}, indent=2)
GATE_PY = """\
#!/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 safety gate."}))
else:
print(json.dumps({"decision": "allow"}))
"""
করণীয় ৬: interactions.create() এর ভিতরে sources তালিকায় আরও দুটি এন্ট্রি যোগ করুন:
{"type": "inline", "target": ".agents/hooks.json", "content": HOOKS_JSON},
{"type": "inline", "target": ".agents/hooks-scripts/gate.py", "content": GATE_PY},
ডাইজেস্ট রানে হুকগুলো কীভাবে সক্রিয় হয়
প্রতিবার যখন এজেন্ট কোনো পাইথন স্ক্রিপ্ট বা শেল কমান্ড চালানোর জন্য code_execution কল করে, তখন রানটাইম প্রথমে কলের বিবরণ gate.py তে পাইপ করে। যদি কমান্ডে rm -rf থাকে, তাহলে হুকটি deny রিটার্ন করে এবং এজেন্ট প্রত্যাখ্যানের কারণ পেয়ে একটি নিরাপদ বিকল্প দিয়ে পুনরায় চেষ্টা করে। অন্য সব কোড এক্সিকিউশন কল অপরিবর্তিতভাবে চলে যায়।
যাচাই করুন
uv run python run_digest.py
আউটপুটটি আগের মতোই: সেফটি গেটটি পিডিএফ তৈরির সমস্ত সাধারণ কমান্ডকে অনুমতি দেয়। হুকটি কার্যকর হচ্ছে কিনা তা নিশ্চিত করতে, এজেন্টের ইনপুটটি সাময়িকভাবে পরিবর্তন করে তাকে rm -rf /tmp/test চালাতে বলুন — আপনি দেখবেন এজেন্টটি জানাবে যে কমান্ডটি ব্লক করা হয়েছে এবং একটি বিকল্প বেছে নেবে।
৭. পিডিএফটি ডাউনলোড করুন।
এজেন্ট স্যান্ডবক্সের ভিতরে /workspace/digest.pdf এ digest.pdf লিখেছে। পরিবেশের স্ন্যাপশটটি জেমিনি ফাইলস এপিআই (Gemini Files API)-এর মাধ্যমে একটি ট্যার (tar) আর্কাইভ হিসেবে পাওয়া যাচ্ছে।
প্রয়োজনে requests ইনস্টল করুন:
uv pip install requests
কী পূরণ করতে হবে
download_pdf.py খুলুন। এতে দুটি TODO আছে।
করণীয় ১: requests.get() কলটি পূরণ করুন:
r = requests.get(
f"https://generativelanguage.googleapis.com/v1beta/files/environment-{environment_id}:download",
params={"alt": "media"},
headers={"x-goog-api-key": api_key},
allow_redirects=True,
)
r.raise_for_status()
URL-টি স্যান্ডবক্স স্ন্যাপশটকে নির্দেশ করে। params={"alt": "media"} মেটাডেটার পরিবর্তে সরাসরি বাইট ফেরত দেয়। আপনার বিদ্যমান GEMINI_API_KEY ফাইলস এপিআই-কেও প্রমাণীকরণ করে।
করণীয় ২: tar আর্কাইভ থেকে PDF ফাইলটি খুঁজুন এবং এক্সট্র্যাক্ট করুন:
member = next(m for m in tar.getmembers() if m.name.endswith("workspace/digest.pdf"))
tar.extract(member, path=tmp, filter="data")
টার পাথের প্রিফিক্স একেকবার একেক রকম হয়, তাই সঠিক পাথটি হার্ডকোড করার পরিবর্তে সাফিক্স দিয়ে সার্চ করুন। filter="data" অনিরাপদ টার এক্সট্র্যাকশন সংক্রান্ত পাইথন ৩.১৩-এর ডেপ্রিকেশন ওয়ার্নিংটি দমন করে।
যাচাই করুন
uv run python download_pdf.py
Saved digest.pdf (48,231 bytes)
একই ডিরেক্টরিতে থাকা digest.pdf খুলুন। এতে এজেন্টের তৈরি করা লাইভ ওয়েব পেজগুলোর ফরম্যাট করা সারসংক্ষেপটি রয়েছে।
৮. কথোপকথন চালিয়ে যান
আপনার কাছে ইতিমধ্যে digest.pdf আছে। আপনি যদি শুধু ফাইলটিই চেয়ে থাকেন, তাহলে আপনার কাজ শেষ। এই ধাপটি ভিন্ন একটি বিষয় নিয়ে: ওয়েব পুনরায় ফেচ না করেই এজেন্টকে ডাইজেস্ট পরিবর্তন করতে বলা।
স্যান্ডবক্সটি এখনও সচল আছে। এজেন্টের কাছে এখনও /workspace/digest.pdf আছে এবং এটি তার সারসংক্ষেপ করা প্রতিটি স্টোরি মনে রেখেছে। দ্বিতীয়বার interactions.create() কল করলে সেই একই স্যান্ডবক্সে একটি ফলো-আপ মেসেজ পাঠানো হয়। এখানে আপনি প্রতিটি স্টোরির নিচে একটি "Why it matters" নোট যোগ করতে বলেন, এবং এটি কোনো রকম রি-ফেচিং বা রি-সামারাইজিং ছাড়াই পিডিএফটি সরাসরি আপডেট করে দেয়।
কী পূরণ করতে হবে
refine_digest.py খুলুন। এতে তিনটি করণীয় কাজ (TODO) রয়েছে।
করণীয় ১ ও ২: interactions.create() এর ভিতরে দুটি মাল্টি-টার্ন প্যারামিটার পূরণ করুন:
environment=environment_id,
previous_interaction_id=interaction_id,
environment=environment_id একই স্যান্ডবক্সকে তার ফাইল ও প্যাকেজসহ পুনরায় চালু করে। previous_interaction_id=interaction_id এজেন্টকে তার কথোপকথনের ইতিহাস প্রদান করে। প্রথম কল থেকে আর কিছুই পরিবর্তন হয় না।
করণীয় ৩: ইভেন্ট লুপের পরে নতুন interaction_id .env ফাইলে সংরক্ষণ করুন:
save_env(INTERACTION_ID=interaction_id)
প্রতিটি interactions.create() কল একটি নতুন interaction_id তৈরি করে। এটিকে আবার লিখে রাখলে পরবর্তী রান এই পরিমার্জনটিকে previous_interaction_id হিসেবে পাস করে, ফলে টার্নগুলো সঠিকভাবে চেইন হয়। স্যান্ডবক্স আইডি কখনও পরিবর্তন হয় না, তাই ENVIRONMENT_ID আপডেট করার প্রয়োজন হয় না।
যে দুটি প্যারামিটার মাল্টি-টার্নকে কার্যকর করে তোলে
আইডি | এটি যা সংরক্ষণ করে | সাদৃশ্য |
| ফাইল, ইনস্টল করা প্যাকেজ, সিস্টেমের অবস্থা: লিনাক্স ফাইলসিস্টেমের সবকিছু। | মিটিংয়ের মাঝে একই অফিসের ডেস্ক রাখা |
| কথোপকথনের ইতিহাস: পূর্ববর্তী পালাগুলোতে এজেন্ট যা বলেছিল এবং করেছিল | গত বৈঠকে যা আলোচনা হয়েছিল তা স্মরণ করে |
আপনি যেকোনো একটি আইডি আলাদাভাবে পাস করতে পারেন:
- শুধু
environment_id: ফাইল ও প্যাকেজ পুনরায় ব্যবহার করুন, কিন্তু একটি নতুন আলোচনা শুরু করুন। একই ওয়ার্কস্পেসে নতুন কোনো কাজের জন্য এটি উপযোগী। - শুধুমাত্র
previous_interaction_idক্ষেত্রে: কথোপকথনের প্রেক্ষাপট চালিয়ে যান, কিন্তু একটি নতুন স্যান্ডবক্সে (ফাইলগুলো মুছে ফেলা হবে)। - উভয় ক্ষেত্রেই: পূর্ণ ধারাবাহিকতা, যা এই ধাপে ব্যবহৃত হয়।
environment_id ছাড়া: ফাঁকা স্যান্ডবক্স, কোনো পিডিএফ নেই। previous_interaction_id ছাড়া: কোনো কনটেক্সট নেই, এজেন্ট কোনো নির্দিষ্ট সেকশন পরিমার্জন করতে পারে না।
যাচাই করুন
uv run python refine_digest.py
স্ট্রিমটি দ্রুত হওয়া উচিত; এজেন্ট কোনো কিছু পুনরায় ফেচ করছে না। এটি শেষ হওয়ার পর:
Refinement done.
Saved digest_v2.pdf (52,418 bytes)
digest_v2.pdf খুলুন এবং digest.pdf এর সাথে তুলনা করুন। এখন প্রতিটি গল্পের সাথে 'কেন এটি গুরুত্বপূর্ণ' এই লাইনটি যুক্ত থাকা উচিত।
৯. একটি পরিচালিত এজেন্ট কনফিগারেশন স্থায়ী করুন
এখন পর্যন্ত প্রতিটি কলে AGENTS.md , SKILL.md এবং generate_pdf.py ফাইলগুলো ইনলাইনভাবে পাস করা হয়েছে। এটা কাজ করে, কিন্তু আপনার কলিং কোড প্রতিটি রানে ফাইলের সম্পূর্ণ বিষয়বস্তু বহন করে। agents.create() ফাংশনটি গুগলের দিকে একটি সংরক্ষিত নামযুক্ত এজেন্টের মধ্যে কনফিগারেশনটি স্থায়ীভাবে যুক্ত করে দেয়। পরবর্তী আহ্বানে শুধু এজেন্ট আইডিটি পাস করা হয়:
Inline calls: send sources on every call
Named agent: bake once → invoke by ID, no sources
কী পূরণ করতে হবে
save_agent.py খুলুন। এটির একটি TODO (TODO 1) রয়েছে।
লক্ষ্য করুন যে ধ্রুবকগুলি সরাসরি run_digest.py থেকে আমদানি করা হয়েছে (কোন পুনরাবৃত্তি নেই):
from run_digest import BASE_AGENT, AGENTS_MD, SKILL_MD, GENERATE_PDF_PY
করণীয় ১: agents.create() কলটি পূরণ করুন:
agent = client.agents.create(
id="my-digest",
base_agent=BASE_AGENT,
agent_config={
"type": "antigravity",
"model": "gemini-3.7-flash",
},
description="Daily tech digest with editorial voice and PDF generation.",
base_environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": AGENTS_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/SKILL.md",
"content": SKILL_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
"content": GENERATE_PDF_PY,
},
],
},
)
agent_config অন্তর্নিহিত মডেল নির্ধারণ করে। gemini-3.7-flash হলো ডিফল্ট এবং এই ওয়ার্কফ্লোর জন্য সেরা পছন্দ; যদি আপনি আরও হালকা বা কম খরচে চালাতে চান, তাহলে gemini-3.6-flash , gemini-3.5-flash , এবং gemini-3.5-flash-lite উপলব্ধ আছে।
আগের ধাপের ইনলাইন কলের সাথে মূল পার্থক্যটি হলো base_environment ( environment নয়): সোর্সগুলো গুগলের দিকে সংরক্ষিত থাকে এবং পরবর্তী প্রতিটি আহ্বানে স্বয়ংক্রিয়ভাবে মাউন্ট হয়। এটি একবার চালান, প্রতিটি ডাইজেস্ট রানের সময় নয়।
যাচাই করুন: এজেন্টটি সংরক্ষণ করুন
uv run python save_agent.py
Saved: my-digest
my-digest: Daily tech digest with editorial voice and PDF generation.
সংরক্ষিত এজেন্টকে আহ্বান করুন
invoke_agent.py খুলুন। এটি কোনো সোর্স ছাড়াই আইডি দ্বারা সেভ করা এজেন্টকে কল করে:
stream = client.interactions.create(
agent="my-digest",
input="Generate the digest.",
stream=True,
environment="remote",
)
ইনলাইন কলের সাথে এটি তুলনা করুন: agent=BASE_AGENT এর পরিবর্তে "my-digest" ব্যবহৃত হয়েছে, এবং তিনটি ইনলাইন সোর্স সহ সম্পূর্ণ environment ব্লকটির পরিবর্তে environment="remote" ব্যবহৃত হয়েছে। কনফিগারেশনটি গুগলের পক্ষ থেকে আগে থেকেই অন্তর্ভুক্ত করা আছে।
যাচাই করুন: সংরক্ষিত এজেন্টটি চালু করুন
uv run python invoke_agent.py
আপনি ইনলাইন রানের মতোই একই লাইভ স্ট্রিম দেখতে পাবেন, কিন্তু এই কলে কোনো সোর্স ফাইল থাকে না। রান শেষ হওয়ার পর, .env ফাইলের ENVIRONMENT_ID এবং INTERACTION_ID আপডেট হয়ে যায়, ফলে আপনি আগের মতোই refine_digest.py নিয়ে কাজ চালিয়ে যেতে পারেন।
[agent started]
[tool] read_file
[tool] write_file
[tool] run_code
I have successfully created today's tech news digest.
Done. environment_id=9a1c3e02-...
১০. জিমেইলের মাধ্যমে পাঠান
এজেন্ট ডাইজেস্টটি তৈরি করে /workspace/digest.pdf এ সংরক্ষণ করেছে। এখন পর্যন্ত আপনি এটি স্থানীয়ভাবে ডাউনলোড করেছেন। এই ধাপে, এজেন্ট স্যান্ডবক্সের ভেতর থেকে জিমেইল REST API কল করার মাধ্যমে এটি সরাসরি আপনার ইনবক্সে পৌঁছে দেবে।
পদ্ধতিটি হলো: আপনি স্থানীয়ভাবে একটি OAuth 2.0 অ্যাক্সেস টোকেন সংগ্রহ করে input প্রম্পটে এজেন্টের কাছে পাঠান। এজেন্ট code_execution ব্যবহার করে সংযুক্ত পিডিএফ সহ একটি MIME ইমেল তৈরি করে এবং সেটি Gmail API-তে POST করে। কোনো কাস্টম টুল বা MCP সার্ভার রেজিস্ট্রেশনের প্রয়োজন নেই।
পূর্বশর্ত
আপনার GCP প্রজেক্টে Gmail API সক্রিয় করুন এবং একটি OAuth 2.0 ক্লায়েন্ট আইডি তৈরি করুন:
- console.cloud.google.com/apis/library/gmail.googleapis.com- এ যান এবং Gmail API সক্রিয় করুন।
- API ও পরিষেবা > ক্রেডেনশিয়াল > ক্রেডেনশিয়াল তৈরি করুন > OAuth 2.0 ক্লায়েন্ট আইডি- তে যান।
- অ্যাপ্লিকেশনের ধরণ: ডেস্কটপ অ্যাপ । JSON ফাইলটি ডাউনলোড করে প্রজেক্ট রুটে
credentials.jsonনামে সেভ করুন।
আপনার প্রাপকের ইমেল .env ফাইলে যোগ করুন:
RECIPIENT_EMAIL=you@gmail.com
প্রয়োজন হলে অথোরাইজেশন লাইব্রেরিগুলো ইনস্টল করুন:
uv sync
কী পূরণ করতে হবে
send_digest.py খুলুন। এতে দুটি TODO আছে।
করণীয় ১: একটি OAuth 2.0 অ্যাক্সেস টোকেন লোড বা রিফ্রেশ করুন:
creds = None
if TOKEN_FILE.exists():
creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
TOKEN_FILE.write_text(creds.to_json())
else:
flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES)
creds = flow.run_local_server(port=8080, open_browser=False)
TOKEN_FILE.write_text(creds.to_json())
raise NotImplementedError লাইনটি যোগ করার পর মুছে ফেলুন। প্রথমবার চালানোর সময় এটি OAuth সম্মতি স্ক্রিনের জন্য একটি ব্রাউজার খোলে। পরবর্তী রানগুলোর জন্য টোকেনটি .gmail_token.json ফাইলে ক্যাশ করা থাকে।
করণীয় ২: input="" এর পরিবর্তে ইমেইলের নির্দেশাবলী দিন। টোকেনটি creds.token হিসেবে ইতোমধ্যেই স্কোপের মধ্যে আছে।
input=(
"Use the Gmail REST API to send an email:\n"
f" To: {recipient}\n"
" Subject: Tech Digest - <today's date in YYYY-MM-DD format>\n"
" Attachment: /workspace/digest.pdf attached as digest.pdf\n\n"
"For the body, read /workspace/summaries.json and format it as a "
"human-readable newsletter, NOT raw JSON. Use this structure:\n"
" Tech Digest - <date>\n\n"
" === <source name> ===\n"
" 1. <title>\n"
" <summary>\n\n"
"Steps:\n"
"1. Parse /workspace/summaries.json and build the formatted body text above.\n"
"2. Read /workspace/digest.pdf as bytes.\n"
"3. Build a MIME multipart message using Python's email library.\n"
"4. Base64url-encode the raw message.\n"
"5. POST to https://gmail.googleapis.com/gmail/v1/users/me/messages/send "
"with Authorization header using this token: "
f"{creds.token}"
),
প্রতিটি অংশ কী করে
ইন্টারঅ্যাকশনটি সেই একই স্যান্ডবক্সে পুনরায় শুরু হয় যেখানে এজেন্ট ইতিমধ্যে digest.pdf এবং summaries.json তৈরি করেছে। previous_interaction_id এজেন্টকে তার কথোপকথনের ইতিহাস প্রদান করে।
অ্যাক্সেস টোকেনটি input স্ট্রিং-এর মাধ্যমে পাঠানো হয়। এজেন্ট প্রম্পট থেকে এটি পড়ে নেয় এবং Gmail API কল করার সময় Authorization: Bearer হেডারে ব্যবহার করে। এটি আপনার লোকাল মেশিন বা ফাইলসিস্টেমকে কখনও স্পর্শ করে না।
এজেন্টটি স্যান্ডবক্সের ভিতরে একটি পাইথন স্ক্রিপ্ট লিখতে ও চালাতে code_execution ব্যবহার করে: এটি summaries.json ফাইলটি পড়ে, সেটিকে একটি নিউজলেটার হিসেবে ফরম্যাট করে, digest.pdf ফাইলটি পড়ে, একটি MIME মাল্টিপার্ট মেসেজ তৈরি করে, সেটিকে base64url-এনকোড করে এবং https://gmail.googleapis.com/gmail/v1/users/me/messages/send gmail/v1/users/me/messages/send` ঠিকানায় POST করে।
যাচাই করুন
uv run python send_digest.py
Sending digest...
[agent started]
[tool] read_file (/workspace/summaries.json)
[tool] run_code
[tool] run_code
Email sent successfully.
Email sent. Check your inbox.
আপনার ইনবক্স দেখুন। ইমেলটি নিউজলেটারের ফরম্যাটে মূল অংশ এবং digest.pdf সংযুক্ত অবস্থায় আসবে।
১১. দৈনিক দৌড়ের সময়সূচী নির্ধারণ করুন
এখন পর্যন্ত প্রতিটি ধাপ ম্যানুয়ালি চালু করা হয়েছে। ট্রিগার আপনাকে একটি ক্রন এক্সপ্রেশনের মাধ্যমে নির্দিষ্ট এজেন্টকে স্বয়ংক্রিয়ভাবে চালানোর জন্য সময়সূচী নির্ধারণ করতে দেয়। এজেন্টটি নির্ধারিত সময়ে চালু হয়, সম্পূর্ণ ডাইজেস্ট ওয়ার্কফ্লোটি চালায় এবং পরিবেশটি প্রতিটি এক্সিকিউশনের মাঝেও বজায় থাকে, ফলে প্রথমবার চালানোর সময় ইনস্টল করা প্যাকেজগুলো পরবর্তী প্রতিটি রানেও উপলব্ধ থাকে।
Manual: python run_digest.py → runs once, now
Trigger: client.triggers.create() → runs every morning, automatically
কী পূরণ করতে হবে
create_trigger.py খুলুন। এতে একটি TODO আছে।
করণীয় ১: triggers.create() কলটি পূরণ করুন। ট্রিগারটি প্রতিদিন সম্পূর্ণ ওয়ার্কফ্লোটি চালায়: ডাইজেস্ট তৈরি করে এবং সেটি আপনার ইনবক্সে পাঠায়। যেহেতু অ্যাক্সেস টোকেন এক ঘণ্টায় মেয়াদোত্তীর্ণ হয়ে যায়, তাই এটি .gmail_token.json থেকে রিফ্রেশ টোকেনটিকে একটি ইনলাইন সোর্স হিসেবে যুক্ত করে, যাতে এজেন্ট প্রতিটি রানে এটিকে একটি নতুন টোকেনের সাথে বিনিময় করতে পারে।
trigger = client.triggers.create(
schedule="0 9 * * *",
time_zone="UTC",
display_name="daily-tech-digest",
max_consecutive_failures=3,
execution_timeout_seconds=600,
interaction={
"agent": "my-digest",
"input": (
f"Generate the daily tech digest following AGENTS.md instructions. "
f"Then send an email to {recipient}:\n"
"- Subject: Tech Digest - <today's date in YYYY-MM-DD format>\n"
"- Body: the content of /workspace/summaries.json formatted as a readable "
"newsletter (NOT raw JSON).\n"
"- Attachment: /workspace/digest.pdf\n\n"
"For Gmail auth: read /workspace/.gmail_creds.json, POST to "
"https://oauth2.googleapis.com/token with grant_type=refresh_token "
"and the client_id, client_secret, refresh_token from the file to get an "
"access_token. Then POST to "
"https://gmail.googleapis.com/gmail/v1/users/me/messages/send "
"with Authorization: Bearer <access_token>."
),
"environment": {
"type": "remote",
"sources": [
{
"type": "inline",
"target": "/workspace/.gmail_creds.json",
"content": gmail_creds,
}
],
},
},
)
execution_timeout_seconds=600 হলো ডিফল্ট টাইমআউট। max_consecutive_failures=3 পরপর ৩টি ব্যর্থ রানের পর ট্রিগারটিকে স্বয়ংক্রিয়ভাবে থামিয়ে দেয় (API-এর ডিফল্ট হলো ৫; একটি ওয়ার্কশপের জন্য ৩ সংখ্যাটি অধিক সতর্কতামূলক)।
sources লিস্টটি /workspace/.gmail_creds.json এ থাকা স্যান্ডবক্সে .gmail_creds.json ফাইলটি ইনজেক্ট করে। এজেন্ট এটি পড়ে, রিফ্রেশ টোকেনটির পরিবর্তে একটি নতুন অ্যাক্সেস টোকেন নেয় এবং জিমেইল এপিআই (Gmail API) কল করে। রিফ্রেশ টোকেনের কোনো মেয়াদ শেষ হয় না, তাই কোনো ম্যানুয়াল টোকেন রিফ্রেশ ছাড়াই এটি প্রতিটি নির্ধারিত রানে কাজ করে।
কলটি যোগ করার পর raise NotImplementedError লাইনটি মুছে ফেলুন।
যাচাই করুন
uv run python create_trigger.py
Trigger created: trig_abc123
Next run: 2026-07-23T09:00:00Z
create_trigger.py স্বয়ংক্রিয়ভাবে ট্রিগার আইডিটি .env ফাইলে সংরক্ষণ করে।
রান শেষ হওয়ার পর এক্সিকিউশন হিস্ট্রি চেক করতে:
uv run python check_trigger.py
পরবর্তী নির্ধারিত সময়ের জন্য অপেক্ষা না করে অবিলম্বে ট্রিগারটি সক্রিয় করতে:
uv run python fire_trigger.py
ট্রিগারটি থামাতে বা মুছে ফেলতে:
uv run python pause_trigger.py
১২. পরিষ্কার করা
৭ দিন নিষ্ক্রিয় থাকার পর স্যান্ডবক্সটি স্বয়ংক্রিয়ভাবে মেয়াদোত্তীর্ণ হয়ে যায়। কোনো সার্ভার বন্ধ করার প্রয়োজন নেই। কোনো কন্টেইনার মুছে ফেলার প্রয়োজন নেই।
আপনি যদি কোনো এজেন্ট কনফিগ সংরক্ষণ করে থাকেন, তাহলে সেটি মুছে ফেলুন:
uv run python delete_agent.py
১৩. সারসংক্ষেপ
আপনি একেবারে শূন্য থেকে, একটি একটি করে ধারণা তৈরি করে একটি ম্যানেজড এজেন্ট গড়ে তুলেছেন। প্রতিটি অনুশীলন থেকে যা শিখেছেন তা নিচে দেওয়া হলো:
ব্যায়াম | ধারণা | মূল এপিআই |
আপনার প্রথম কলটি করুন | একটি বাস্তব লিনাক্স স্যান্ডবক্স প্রস্তুত করুন এবং এর ইভেন্টগুলো সরাসরি স্ট্রিম করুন। | |
এজেন্টকে কাস্টমাইজ করুন | একই রানে কনফিগারেশন ফাইল মাউন্ট করুন; | |
একটি নিরাপত্তা হুক যোগ করুন | টুল কলগুলো কার্যকর হওয়ার আগেই আটকান; ক্ষতিকর কমান্ড প্রত্যাখ্যান করুন। | |
পিডিএফ ডাউনলোড করুন | এজেন্টটি পুনরায় না চালিয়ে পিডিএফটি ডাউনলোড করুন। | জেমিনি ফাইলস এপিআই |
কথোপকথন চালিয়ে যান | ওয়েব পুনরায় না খুলেই কথোপকথন চালিয়ে যান। | |
এজেন্ট কনফিগারেশন স্থায়ী করুন | এজেন্ট কনফিগারেশন সংরক্ষণ করুন; আইডি দ্বারা আহ্বান করুন, কোনো উৎসের প্রয়োজন নেই। | |
জিমেইলের মাধ্যমে পাঠান | স্থানীয়ভাবে একটি OAuth টোকেন সংগ্রহ করুন; সেটি এজেন্টের কাছে পাঠান, যা | OAuth 2.0, |
দৈনিক দৌড়ের সময়সূচী | ক্রন শিডিউল অনুযায়ী এজেন্টটিকে স্বয়ংক্রিয়ভাবে চালান। | |
মূল নিদর্শনগুলি
- একটি কল, একটি স্যান্ডবক্স :
interactions.create()সমস্ত পরিকাঠামো পরিচালনা করে (কোনো কন্টেইনার স্থাপন করার প্রয়োজন নেই, স্থানীয়ভাবে কোনো প্যাকেজ ইনস্টল করার দরকার নেই)। - প্রগতিশীল স্ট্রিমিং :
stream=Trueএকটি ৯০-সেকেন্ডের ব্ল্যাক বক্সকে টুল কল এবং টেক্সট খণ্ডের একটি লাইভ ফিডে পরিণত করে। - ইনলাইন সোর্স : কোনো আপলোড বা ডেপ্লয়মেন্ট ধাপ ছাড়াই
AGENTS.md,SKILL.mdএবং প্রি-বিল্ট স্ক্রিপ্টগুলোকে স্যান্ডবক্সে মাউন্ট করুন। - স্বয়ংক্রিয় আবিষ্কারের সুবিধা নিন :
.agents/ফোল্ডারে রাখা ফাইলগুলো স্বয়ংক্রিয়ভাবে খুঁজে নেওয়া হয় (কোনো SDK কনফিগারেশনের প্রয়োজন নেই)। - দ্বি-মাত্রিক অবস্থা :
environment_idফাইল এবং প্যাকেজ ট্র্যাক করে;previous_interaction_idকথোপকথনের প্রেক্ষাপট ট্র্যাক করে; যেকোনো একটি স্বাধীনভাবে পাস করা যেতে পারে। - স্ন্যাপশট ডাউনলোড : পরিবেশটি একটি সম্পূর্ণ ফাইলসিস্টেম tar, যা Gemini Files API-এর মাধ্যমে অ্যাক্সেসযোগ্য।
- নামযুক্ত এজেন্ট :
agents.create()কনফিগারেশন স্থায়ীভাবে তৈরি করে; পরবর্তী কলগুলিতে শুধুমাত্র এজেন্ট আইডি এবংenvironment="remote"পাঠানো হয়, কোনো সোর্স ছাড়া। - হুকস :
hooks.json+ একটি গেট স্ক্রিপ্ট টুল কলগুলো কার্যকর হওয়ার আগেই সেগুলোকে বাধা দেয়; একটিdenyরেসপন্স কলটি বাতিল করে দেয় এবং এজেন্ট নিজে থেকেই তা সংশোধন করে নেয়। - এক্সটার্নাল এপিআই কল :
inputপ্রম্পটে একটি ক্রেডেনশিয়াল প্রদান করুন; এজেন্টcode_executionএর মাধ্যমে স্যান্ডবক্সের ভিতরে ইন্টিগ্রেশন কোডটি লেখে এবং চালায়। - ট্রিগার :
client.triggers.create()ব্যবহার করে একটি ক্রন এক্সপ্রেশনের মাধ্যমে এজেন্টকে শিডিউল করুন; এই এনভায়রনমেন্টটি একাধিক এক্সিকিউশন জুড়ে অপরিবর্তিত থাকে।
ADK + ক্লাউড রান বনাম ম্যানেজড এজেন্ট: এক নজরে পার্থক্য
সক্ষমতা | ADK + ক্লাউড রান | জেমিনি এপিআই-তে পরিচালিত এজেন্ট |
একটি স্যান্ডবক্স সরবরাহ করুন | | |
সরঞ্জাম সংজ্ঞায়িত করুন | এজেন্টের সাথে নিবন্ধিত পাইথন ফাংশন | অন্তর্নির্মিত: ওয়েব ব্রাউজ, কোড এক্সিকিউশন, ফাইল সিস্টেম |
প্যাকেজ ইনস্টল করুন | ডকারফাইলে | এজেন্ট স্যান্ডবক্সের ভিতরে |
স্ট্রিম ইভেন্ট | কাস্টম এসএসই পরিকাঠামো | |
একটি সেশন চালিয়ে যান | সেশন ডাটাবেস + কনটেক্সট ইনজেকশন | |
কনফিগারেশন ফাইল | এজেন্টে হার্ড-কোড করা অথবা স্টার্টআপের সময় ইনজেক্ট করা | |
ব্যবস্থাপনার জন্য অবকাঠামো | কন্টেইনার, ক্লাউড রান, আইএএম, সিক্রেটস | কোনোটিই না |