১. ভূমিকা

"গোল্ডফিশ" সমস্যা
ধরুন, টোকিওতে আপনার স্বপ্নের ছুটি কাটানোর প্ল্যান করার জন্য আপনি একজন ট্রাভেল এজেন্টকে ভাড়া করেছেন। "গোল্ডফিশ সমস্যা" অ্যাকশনে দেখতে সেশন এজেন্ট ব্যবহার করুন।
আপনি তাদের অফিসে গিয়ে বলেন:
"হ্যালো! আমি টোকিওতে ২ দিনের ট্রিপ প্ল্যান করতে চাই। আমি ঐতিহাসিক স্থান ও সুশি সম্পর্কে জানতে আগ্রহী।"
এজেন্ট উৎসাহের সাথে উত্তর দেয়:
"দারুণ! আমি ইম্পেরিয়াল প্যালেস ঘুরে দেখার এবং সুকিয়াবাসি জিরোতে সুশি ডিনারের প্ল্যান করেছি।"
আপনি হেসে বলেন:
"দারুণ! তুমি কি আমাকে ভ্রমণসূচী পাঠাতে পারবে?"
এজেন্ট আপনার দিকে শূন্য দৃষ্টিতে তাকিয়ে জিজ্ঞাসা করে:
"হ্যালো! আজকে ট্রিপ প্ল্যান করার ব্যাপারে আমি আপনাকে কীভাবে সাহায্য করতে পারি?"
এটি হল "গোল্ডফিশ সমস্যা।" মেমরি ছাড়া, প্রতিটি ইন্টার্যাকশন একটি ফাঁকা স্লেটের মতো। ইন্টেলিজেন্স আছে—এজেন্ট জানে কীভাবে ট্রিপ প্ল্যান করতে হয়—কিন্তু ধারাবাহিকতা নেই। AI এজেন্টকে সত্যিই উপযোগী করে তুলতে, এটিকে মনে রাখতে হবে।
আজকের মিশন
এই ওয়ার্কশপে, আপনি এমন একটি ট্রাভেল এজেন্ট তৈরি করে গোল্ডফিশ সমস্যার সমাধান করবেন যা মনে রাখে, শেখে এবং মানিয়ে নেয়। আপনি এজেন্ট মেমরির ৬টি লেভেল-এর মাধ্যমে এগিয়ে যাবেন, এমন একটি সিস্টেম তৈরি করবেন যা চ্যাটবটের মতো কম এবং একজন ডেডিকেটেড ব্যক্তিগত সহকারীর মতো বেশি আচরণ করে।
লেভেল | ধারণা | "সুপারপাওয়ার" |
লেভেল ১ | সেশন ও স্টেট | ভুলে না গিয়ে কথোপকথন চালিয়ে যাওয়া |
লেভেল ২ | মাল্টি-এজেন্ট স্টেট | টিম মেম্বারদের মধ্যে নোট শেয়ার করা |
লেভেল ৩ | অধ্যবসায় | সিস্টেম রিবুট করার পরেও আপনাকে মনে রাখা |
লেভেল ৪ | কলব্যাক | সম্পূর্ণ স্বয়ংক্রিয়ভাবে মেমরি আপডেট করা হচ্ছে |
লেভেল ৫ | কাস্টম টুল | ব্যবহারকারীর স্ট্রাকচার্ড প্রোফাইল পড়া ও লেখা |
লেভেল ৬ | মাল্টিমোডাল মেমরি | ফটো ও ভিডিও "দেখা" ও মনে রাখা |
ADK মেমরি স্ট্যাক
কোড লেখার আগে, আমরা যে টুল ব্যবহার করছি তা বুঝে নেওয়া যাক। Google Agent Development Kit (ADK) মেমরি ম্যানেজ করার জন্য একটি স্ট্রাকচার্ড উপায় প্রদান করে:
- সেশন: কথোপকথনের কন্টেনার। এটি যা বলা হয়েছে তার ইতিহাস ধরে রাখে।
- স্টেট: সেশনের সাথে অ্যাটাচ করা একটি কী-ভ্যালু "স্ক্র্যাচপ্যাড"। এজেন্টরা নির্দিষ্ট তথ্য (যেমন,
destination="Tokyo") স্টোর করতে এটি ব্যবহার করে। - MemoryService: দীর্ঘমেয়াদী স্টোরেজ। এখানে আমরা ব্যবহারকারীর পছন্দ বা বিশ্লেষণ করা ডকুমেন্টের মতো জিনিস চিরকালের জন্য রাখি।
২. সেট-আপ
আমাদের AI এজেন্টকে শক্তিশালী করতে, আমাদের দুটি জিনিস প্রয়োজন: ভিত্তি প্রদান করার জন্য একটি Google Cloud প্রোজেক্ট।
প্রথম ভাগ: বিলিং অ্যাকাউন্ট চালু করা
এই কোডল্যাব রান করতে, আপনার একটি বিলিং অ্যাকাউন্ট প্রয়োজন যাতে কিছু ক্রেডিট আছে। শুরু করতে এই কোডল্যাবের উপরে ব্যানারে দেখানো ক্রেডিট ব্যবহার করুন। আপনি আগে থেকেই কোনও বিলিং অ্যাকাউন্টের সাথে কানেক্ট করে থাকলে, এই ধাপটি এড়িয়ে যেতে পারেন।
পার্ট টু: ওপেন এনভায়রনমেন্ট
- 👉 সরাসরি Cloud Shell Editor-এ নেভিগেট করতে এই লিঙ্কে ক্লিক করুন
- 👉 আজ যেকোনও সময় অনুমোদন করার জন্য প্রম্পট করা হলে, চালিয়ে যেতে অনুমোদন করুন বিকল্পে ক্লিক করুন।

- 👉 স্ক্রিনের নিচে টার্মিনাল দেখা না গেলে, এটি খুলুন:
- দেখুন বিকল্পে ক্লিক করুন
- টার্মিনাল
বিকল্পে ক্লিক করুন
- 👉💻 টার্মিনালে, আপনি আগে থেকেই যাচাইকৃত কিনা এবং নিম্নলিখিত কমান্ড ব্যবহার করে প্রোজেক্টটি আপনার প্রোজেক্ট আইডিতে সেট করা আছে কিনা তা যাচাই করুন:
gcloud auth list - 👉💻 GitHub থেকে বুটস্ট্র্যাপ প্রোজেক্ট ক্লোন করুন:
git clone https://github.com/cuppibla/memory_agent_starter - 👉💻 প্রোজেক্ট ডিরেক্টরি থেকে সেটআপ স্ক্রিপ্ট রান করুন।
স্ক্রিপ্টটি সেট-আপ প্রক্রিয়ার বাকি অংশ অটোমেটিক ম্যানেজ করবে।cd ~/memory_agent_starter ./init.sh - 👉💻 প্রয়োজনীয় প্রোজেক্ট আইডি সেট করুন:
gcloud config set project $(cat ~/project_id.txt) --quiet
পার্ট তিন: অনুমতি সেট-আপ করা
- 👉💻 নিম্নলিখিত কমান্ড ব্যবহার করে প্রয়োজনীয় API চালু করুন। এর জন্য কয়েক মিনিট সময় লাগতে পারে।
gcloud services enable \ cloudresourcemanager.googleapis.com \ servicenetworking.googleapis.com \ run.googleapis.com \ aiplatform.googleapis.com \ compute.googleapis.com - 👉💻 টার্মিনালে নিম্নলিখিত কমান্ড রান করে প্রয়োজনীয় অনুমতি দিন:
. ~/memory_agent_starter/set_env.sh
লক্ষ্য করো যে তোমার জন্য একটি .env ফাইল তৈরি করা হয়েছে। যা আপনার প্রোজেক্টের তথ্য দেখায়।
৩. The Foundation - সেশন ও স্টেট

ধারণা: প্রাসঙ্গিক তথ্যই মূল বিষয়
মেমরির সবচেয়ে প্রাথমিক ফর্ম হল সেশন মেমরি। এর ফলে এজেন্ট বুঝতে পারে যে "আমি এটি কিনতে চাই" বাক্যে "এটি" বলতে আপনি ১০ সেকেন্ড আগে যে জুতোটির কথা বলছিলেন সেটির কথাই বলা হচ্ছে।
ADK-তে, আমরা Session অবজেক্টের মাধ্যমে এটি ম্যানেজ করি।
- স্টেটলেস অ্যাপ্রোচ: প্রতিটি মেসেজের জন্য নতুন সেশন তৈরি করা।
- স্টেটফুল অ্যাপ্রোচ: একটি সেশন তৈরি করা এবং পুরো কথোপকথনের জন্য এটি আবার ব্যবহার করা।
ধাপ ১: এজেন্ট পরীক্ষা করা
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/01_session_agent/agent.py
~/memory_agent_starter/01_session_agent/agent.py খুলুন।
👉 agent.py ফাংশনের মধ্যে # TODO: Create a root agent কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
root_agent = LlmAgent(
name="multi_day_trip_agent",
model="gemini-2.5-flash",
description="Agent that progressively plans a multi-day trip, remembering previous days and adapting to user feedback.",
instruction="""
You are the "Adaptive Trip Planner" 🗺️ - an AI assistant that builds multi-day travel itineraries step-by-step.
Your Defining Feature:
You have short-term memory. You MUST refer back to our conversation to understand the trip's context, what has already been planned, and the user's preferences. If the user asks for a change, you must adapt the plan while keeping the unchanged parts consistent.
Your Mission:
1. **Initiate**: Start by asking for the destination, trip duration, and interests.
2. **Plan Progressively**: Plan ONLY ONE DAY at a time. After presenting a plan, ask for confirmation.
3. **Handle Feedback**: If a user dislikes a suggestion (e.g., "I don't like museums"), acknowledge their feedback, and provide a *new, alternative* suggestion for that time slot that still fits the overall theme.
4. **Maintain Context**: For each new day, ensure the activities are unique and build logically on the previous days. Do not suggest the same things repeatedly.
5. **Final Output**: Return each day's itinerary in MARKDOWN format.
""",
tools=[google_search]
)
নির্দেশটি LLM-কে মনে রাখতে বলে, কিন্তু কোড-কে মনে রাখার ক্ষমতা প্রদান করতে হবে।
ধাপ ২: দুটি পরিস্থিতি
~/memory_agent_starter/01_session_agent/main.py খুলুন।
👉 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/01_session_agent/main.py
~/memory_agent_starter/01_session_agent/main.py খুলুন, main.py ফাংশনের মধ্যে # TODO: Create a runner with in memorysession service কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
runner = Runner(
agent=agent,
session_service=session_service,
app_name=agent.name
)
👉 main.py ফাংশনের মধ্যে # TODO: create a different session to test কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
tokyo_session_2 = await session_service.create_session(
app_name=multi_day_agent.name,
user_id=user_id
)
এটি পরীক্ষা করুন
আমাদের কাছে দুটি ফাংশন আছে যা "গোল্ডফিশ" এবং "হাতি" মেমরির মধ্যে পার্থক্য প্রদর্শন করে।
পরিস্থিতি ১: স্টেটফুল (শেয়ার করা সেশন)
async def run_trip_same_session_scenario(session_service, user_id):
# 1. Create ONE session
trip_session = await session_service.create_session(...)
# 2. Turn 1
await run_agent_query(..., trip_session, ...)
# 3. Turn 2 - REUSING the same session!
# The agent can "see" Turn 1 because it's in the session history.
await run_agent_query(..., trip_session, ...)
পরিস্থিতি ২: স্টেটলেস (প্রতিবার নতুন সেশন)
async def run_trip_different_session_scenario(session_service, user_id):
# Turn 1
tokyo_session = await session_service.create_session(...)
await run_agent_query(..., tokyo_session, ...)
# Turn 2 - Creating a FREASH session
# The agent has NO IDEA what happened in Turn 1.
tokyo_session_2 = await session_service.create_session(...)
await run_agent_query(..., tokyo_session_2, ...)
ধাপ ৩: এজেন্ট রান করান
আসুন, অ্যাকশনে পার্থক্যটি দেখি। স্ক্রিপ্ট চালান:
👉💻 কমান্ড লাইনে, নিচে উল্লেখ করা কমান্ড লাইন রান করুন:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/01_session_agent/main.py
পরিস্থিতি ১ লক্ষ্য করুন: এজেন্ট প্রথম মেসেজ থেকে আপনার পছন্দ মনে রাখে এবং দ্বিতীয় মেসেজে প্ল্যানটি মানিয়ে নেয়।
পরিস্থিতি ২ লক্ষ্য করুন: দ্বিতীয়বার ("খাবারের কোন জিনিসটা আমার ভালো লেগেছিল, তোমার মনে আছে?"), এজেন্ট সম্পূর্ণভাবে ব্যর্থ হয় কারণ এটি একটি নতুন সেশন। এটি কার্যকরভাবে বলে, "আপনি কী বলছেন তা আমি জানি না।"
মূল বিষয়
মেমরির #১ নিয়ম: কথোপকথনের প্রসঙ্গ বজায় রাখতে সবসময় session.id আবার ব্যবহার করুন। Session অবজেক্ট হল আপনার এজেন্টের স্বল্পমেয়াদী মেমরি বাফার।
৪. টিম - মাল্টি-এজেন্ট স্টেট

ধারণা: "টেলিফোন গেম"
একাধিক এজেন্ট একসাথে কাজ করলে, তারা সহকর্মীদের মতো একে অপরের সাথে ফাইল ফোল্ডার আদান-প্রদান করে। একজন এজেন্ট ফোল্ডারে কোনও নোট লিখলে, পরবর্তী এজেন্টকে সেটি পড়তে পারতে হবে।
ADK-তে এই "ফোল্ডার" হল স্টেট।
- State হল একটি ডিকশনারি (
{"key": "value"}) যা সেশনের মধ্যে থাকে। - সেশনের যেকোনও এজেন্ট এটি থেকে পড়তে বা এতে লিখতে পারবেন।
ধাপ ১: ওয়ার্কফ্লো পরীক্ষা করা
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/02_multi_agent/agent.py
👉~/memory_agent_starter/02_multi_agent/agent.py ফাইলে, # TODO: foodie agent কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
foodie_agent = LlmAgent(
name="foodie_agent",
model="gemini-2.5-flash",
tools=[google_search],
instruction="""You are an expert food critic. Your goal is to find the best restaurant based on a user's request.
When you recommend a place, you must output *only* the name of the establishment and nothing else.
For example, if the best sushi is at 'Jin Sho', you should output only: Jin Sho
""",
output_key="destination" # ADK will save the agent's final response to state['destination']
)
👉 agent.py ফাংশনের মধ্যে # TODO: transportation agent কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
transportation_agent = LlmAgent(
name="transportation_agent",
model="gemini-2.5-flash",
tools=[google_search],
instruction="""You are a navigation assistant. Given a destination, provide clear directions.
The user wants to go to: {destination}.
Analyze the user's full original query to find their starting point.
Then, provide clear directions from that starting point to {destination}.
""",
)
👉 agent.py ফাংশনের মধ্যে # TODO: root_agent কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
root_agent = SequentialAgent(
name="find_and_navigate_agent",
sub_agents=[foodie_agent, transportation_agent],
description="A workflow that first finds a location and then provides directions to it."
)
এখন আমাদের কাছে দুটি এজেন্ট আছে যারা একটি ক্রমে কাজ করে:
- ফুডি এজেন্ট: রেস্তোরাঁ খুঁজে দেয়।
- ট্রান্সপোর্টেশন এজেন্ট: সেই রেস্তোরাঁয় যাওয়ার দিকনির্দেশ দেয়।
ম্যাজিক হ্যান্ড-অফ: লক্ষ্য করুন কীভাবে foodie_agent, transportation_agent-কে ব্যাটন পাস করে।
foodie_agent = LlmAgent(
# ...
# CRITICAL: This tells ADK to save the agent's output to state['destination']
output_key="destination"
)
transportation_agent = LlmAgent(
# ...
# CRITICAL: This injects state['destination'] into the prompt
instruction="""
The user wants to go to: {destination}.
Provide clear directions...
""",
)
output_key="destination": Foodie Agent-এর উত্তর দক্ষতার সাথে সেভ করা হয়েছে।{destination}: ট্রান্সপোর্টেশন এজেন্ট অটোমেটিক সেই উত্তর পড়ে।
(কোনও অ্যাকশন নিতে হবে না) ধাপ ২: অর্কেস্ট্রেটর
02_multi_agent/main.py খুলুন।
আমরা একটি SequentialAgent ব্যবহার করি যাতে সেগুলি ক্রমানুসারে চালানো যায়।
# 1. Create a single session for the sequential agent
session = await session_service.create_session(...)
# 2. Run the query
# The SequentialAgent manages the state flow:
# Query -> Foodie -> state['destination'] -> Transportation -> Final Answer
await run_agent_query(root_agent, query, ...)
ব্যবহারকারী একটি প্রম্পট পাঠান:
"Find best sushi in Palo Alto and then tell me how to get there."
এজেন্টরা একসাথে কাজ করে এর উত্তর দেয়।
ধাপ ৩: টিম পরিচালনা করা
👉💻 Cloud Shell Terminal-এ, মাল্টি-এজেন্ট ওয়ার্কফ্লো এক্সিকিউট করুন:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/02_multi_agent/main.py
কী হয়?
- ফুডি এজেন্ট: "জিন শো" (বা একই ধরনের) খুঁজে পায়।
- ADK:
state['destination']-এ "জিন শো" সেভ করে। - পরিবহন এজেন্ট: তার নির্দেশে "জিন শো" গ্রহণ করে।
- ফলাফল: "ক্যালট্রেন স্টেশন থেকে জিন শোতে যেতে, ইউনিভার্সিটি অ্যাভিনিউ ধরে হেঁটে যান..."
মূল বিষয়
মেমরির নিয়ম #২: এজেন্টদের মধ্যে স্ট্রাকচার্ড তথ্য পাস করতে স্টেট ব্যবহার করুন। লিখতে output_key এবং পড়তে {placeholders} ব্যবহার করুন।
৫. The Reboot - Persistence

ধারণা: "রিবুট সংক্রান্ত সমস্যা"
এখনও পর্যন্ত, আমাদের মেমরি InMemory হয়েছে। আপনি স্ক্রিপ্ট বন্ধ করে আবার চালু করলে, এজেন্ট সবকিছু ভুলে যায়। এটি এমন একটি কম্পিউটারের মতো যা আপনি বন্ধ করার সাথে সাথে হার্ড ড্রাইভের সব ডেটা মুছে দেয়।
এটি ঠিক করতে, আমাদের পারসিস্টেন্স প্রয়োজন। আমরা InMemorySessionService-এর পরিবর্তে DatabaseSessionService ব্যবহার করি।
ধাপ ১: ডেটাবেস সুইচ
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/03_persistent_agent/main.py
👉 ~/memory_agent_starter/03_persistent_agent/main.py ফাইলে, # TODO: Configuration for Persistent Sessions কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
SESSIONS_DIR = Path(os.path.expanduser("~")) / ".adk_codelab" / "sessions"
os.makedirs(SESSIONS_DIR, exist_ok=True)
SESSION_DB_FILE = SESSIONS_DIR / "trip_planner.db"
SESSION_URL = f"sqlite:///{SESSION_DB_FILE}"
এখন, প্রতিটি সেশন এবং ইভেন্ট SQLite ফাইলে সেভ করা হয়।
ধাপ ২: ক্রস-সেশন রিট্রিভাল
পারসিস্টেন্স শুধু কথোপকথন আবার শুরু করার অনুমতি দেয় না, বরং পুরনো কথোপকথন থেকে শেখার অনুমতিও দেয়।
একই ফাইলে ~/memory_agent_starter/03_persistent_agent/main.py, টেস্ট কেস ৩: ক্রস-সেশন রিট্রিভাল দেখুন।
👉 কমেন্টটি খুঁজে নিন # TODO: retrieve the previous session manually
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
old_session = await session_service.get_session(
app_name=root_agent.name, user_id="user_01", session_id=session_id
)
👉 main.py ফাংশনের মধ্যে # TODO: Extract content from the OLD session কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
previous_context += f"- {role}: {text}\n"
👉 main.py ফাংশনের মধ্যে # TODO: Manually inject the context to the query কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
query_3 = f"""
{previous_context}
I'm planning a new trip to Osaka this time.
Based on my previous preferences (above), what should I eat?
"""
এটি কয়েক মাস পরে ফিরে আসা ব্যবহারকারীর অ্যাক্টিভিটি সিমুলেট করে। শুধুমাত্র ডেটাবেসের সাহায্যে আপনি সেই পুরনো ইতিহাস ফিরিয়ে আনতে পারবেন।
ধাপ ৩: রিবুট করার পরেও টিকে থাকা
👉💻 টার্মিনালে, স্ক্রিপ্টটি রান করুন:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/03_persistent_agent/main.py
এটি ~/memory_agent_starter/trip_planner.db ফাইল তৈরি করে। এটি করে দেখুন: স্ক্রিপ্টটি দুবার রান করুন।
- দ্বিতীয়বার রান করার সময়, "আগের সেশন আবার শুরু করা হয়েছে" বিকল্পটি খুঁজুন।
- এজেন্ট প্রথমবার রান করার সময় থেকে কন্টেক্সট মনে রাখবে কারণ এটি ডেটাবেস ফাইল থেকে লোড হয়!
মূল বিষয়
মেমরির ৩ নম্বর নিয়ম: প্রোডাকশনের জন্য DatabaseSessionService ব্যবহার করুন। এটি নিশ্চিত করে যে সার্ভার রিস্টার্ট হলেও ব্যবহারকারীর কথোপকথন মুছে যায় না এবং দীর্ঘমেয়াদী ইতিহাস বিশ্লেষণ করার সুবিধা দেয়।
৬. গুপ্তচর - কলব্যাক

কখনও কখনও, এজেন্ট যা বলে শুধু তার উপর ভিত্তি করে নয়, বরং এজেন্ট যা করে তার উপর ভিত্তি করে আপনাকে অটোমেটিক মেমরি আপডেট করতে হয়। আপনি এমন একজন "গুপ্তচর" চান যে এজেন্টের উপর নজর রাখবে এবং নোট নেবে।
ADK-তে, এই স্পাই হল কলব্যাক। 
after_tool_callback: এজেন্ট কাজ করার সময় প্রতিবার রান করে এমন একটি ফাংশন।ToolContext: সেই ফাংশনের মধ্যে থেকে State-এ লেখার একটি উপায়।
ধাপ ১: লজিক
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/04_stateful_agent/agent.py
👉 ~/memory_agent_starter/04_stateful_agent/agent.py ফাইলে, # TODO: Implement call back logic কমেন্টটি খুঁজুন
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
def save_activity_type_callback(
tool,
args: Dict[str, Any],
tool_context: ToolContext,
tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
"""
Callback to save the TYPE of activity just planned into the session state.
"""
# 1. Get the actual agent name.
if tool.name == "transfer_to_agent":
agent_name = args.get("agent_name")
else:
agent_name = tool.name
activity_type = "unknown"
# 2. Determine the type based on which agent was actually used
if agent_name == "museum_expert":
activity_type = "CULTURAL"
elif agent_name == "restaurant_expert":
activity_type = "FOOD"
elif agent_name == "outdoor_expert":
activity_type = "OUTDOOR"
print(f"\n🔔 [CALLBACK] The planner transferred to '{agent_name}'.")
# 3. Update the state directly
tool_context.state["last_activity_type"] = activity_type
print(f"💾 [STATE UPDATE] 'last_activity_type' is now set to: {activity_type}\n")
return tool_response
👉 একই ফাইলে, 04_stateful_agent/agent.py ফাংশনের মধ্যে # TODO: add callback to root agent কমেন্টটি খুঁজে বের করো।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
after_tool_callback=save_activity_type_callback,
ডায়নামিক নির্দেশাবলী: এজেন্টের নির্দেশাবলী এখন একটি ফাংশন, স্ট্রিং নয়। এটি রাজ্যের উপর ভিত্তি করে পরিবর্তিত হয়!
def get_planner_instruction(context):
last_activity = context.state.get("last_activity_type", "None")
return f"""
The last activity was: {last_activity}
If last_activity is 'CULTURAL' -> `museum_expert` is BANNED.
"""
ধাপ ৩: Spy পরীক্ষা করা
👉💻 টার্মিনালে, নিচের কমান্ড কপি ও পেস্ট করে স্ক্রিপ্ট রান করুন:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/04_stateful_agent/main.py
আপনি এই এজেন্ট রান করালে, একটি লুপ দেখতে পাবেন।
- টার্ন ১: আপনি কোনও মিউজিয়ামের ব্যাপারে জানতে চান। Spy sets
last_activity="CULTURAL". - টার্ন ২: আপনি অন্য মিউজিয়াম সম্পর্কে জানতে চান।
- এজেন্ট নির্দেশাবলী আপডেট: "CULTURAL is BANNED"।
- এজেন্ট বলেছেন: "আমি অন্য কোনও মিউজিয়ামে যেতে পারব না। পার্ক কেমন হবে?"
[CALLBACK] ও [STATE UPDATE]-এর জন্য কনসোল লগ দেখুন। এজেন্ট কাজ করার সাথে সাথে আপনি রিয়েল-টাইমে মেমরি পরিবর্তন হতে দেখতে পারবেন।
মূল বিষয়
মেমরির ৪ নম্বর নিয়ম: স্টেট ম্যানেজমেন্ট অটোমেট করতে কলব্যাক ব্যবহার করুন। আপনার এজেন্ট শুধু নিজের কাজ করার মাধ্যমে নিজস্ব কনটেক্সট তৈরি করে।
৭. ফাইল ক্যাবিনেট - কাস্টম টুল
ধারণা: "স্ট্রাকচার্ড মেমরি"

এখনও পর্যন্ত, "মেমরি" হল একটি চ্যাট লগ বা সাধারণ কী-ভ্যালু পেয়ার। কিন্তু আপনাকে যদি কোনও জটিল ব্যবহারকারীর প্রোফাইল মনে রাখতে হয়? যেমন, diet: vegan, budget: high, pets: [cat, dog]।
এর জন্য, আমরা মেমরিকে একটি টুল হিসেবে বিবেচনা করি। এজেন্ট স্পষ্টভাবে সিদ্ধান্ত নেয় যে কখন ফাইল ক্যাবিনেট খুলতে হবে (পড়তে হবে) এবং কখন রিপোর্ট ফাইল করতে হবে (লিখতে হবে)। 
ধাপ ১: টুল
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/05_profile_agent/tools.py
👉 এই ফাইলে: ~/memory_agent_starter/05_profile_agent/tools.py।
আমাদের এই দুটি নির্দিষ্ট টুল প্রয়োগ করতে হবে:
save_user_preferences: ডেটাবেসে লেখে।recall_user_preferences: ডেটাবেস থেকে পড়ে।
~/memory_agent_starter/05_profile_agent/tools.py ফাংশনের মধ্যে # TODO: implement save_user_preferences tools কমেন্টটি খুঁজে দেখুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
def save_user_preferences(tool_context: ToolContext, new_preferences: Dict[str, Any]) -> str:
user_id = tool_context.session.user_id
with sqlite3.connect(USER_DB_FILE) as conn:
for key, value in new_preferences.items():
conn.execute("INSERT INTO user_preferences (user_id, pref_key, pref_value) VALUES (?, ?, ?) ON CONFLICT(user_id, pref_key) DO UPDATE SET pref_value = excluded.pref_value;",
(user_id, key, json.dumps(value)))
return f"Preferences updated: {list(new_preferences.keys())}"
👉 05/tools.py ফাংশনের মধ্যে # TODO: implement recall_user_preferences tools কমেন্টটি খুঁজুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
def recall_user_preferences(tool_context: ToolContext) -> Dict[str, Any]:
user_id = tool_context.session.user_id
preferences = {}
with sqlite3.connect(USER_DB_FILE) as conn:
rows = conn.execute("SELECT pref_key, pref_value FROM user_preferences WHERE user_id = ?", (user_id,)).fetchall()
if not rows: return {"message": "No preferences found."}
for key, value_str in rows: preferences[key] = json.loads(value_str)
return preferences
নির্দেশটি একটি ওয়ার্কফ্লোকে বাধ্য করে:
instruction="""
1. RECALL FIRST: First action MUST be `recall_user_preferences`.
3. LEARN: If a user states a new preference, use `save_user_preferences`.
"""
ধাপ ২: এক্সিকিউশন
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/05_profile_agent/main.py
~/memory_agent_starter/05_profile_agent/main.py খুলুন।
আগের মডিউলের মতো নয় যেখানে ADK অটোমেটিক স্ট্যাটাস ম্যানেজ করে, এখানে এজেন্ট কন্ট্রোল করে।
- এটি শুরুতে
recall_user_preferences-কে কল করার জন্য বেছে নেয়। - আপনি "আমি ভেগান" বললে, এটি
save_user_preferences-কে কল করার সিদ্ধান্ত নেয়।
ধাপ ৩: প্রোফাইল তৈরি করুন
👉💻 স্ক্রিপ্ট রান করুন:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/05_profile_agent/main.py
এই কথোপকথনের ফ্লো ব্যবহার করে দেখুন:
- "হ্যালো, ডিনারের প্ল্যান করো।" -> এজেন্ট DB চেক করে, কিছুই খুঁজে পায় না। পছন্দ সম্পর্কে জিজ্ঞাসা করে।
- "আমি ভেগান।" -> এজেন্ট DB-তে "ভেগান" সেভ করে।
- স্ক্রিপ্ট রিস্টার্ট করুন।
- "হ্যালো, ডিনারের প্ল্যান করো।" -> এজেন্ট DB চেক করে, "ভেগান" দেখে এবং সাথে সাথে একটি ভেগান রেস্তোরাঁর সাজেশন দেয়।
মূল বিষয়
মেমরির ৫ নম্বর নিয়ম: জটিল, স্ট্রাকচার্ড ডেটার জন্য, আপনার এজেন্টকে পড়া/লেখার টুল দিন। LLM-কে তার নিজস্ব দীর্ঘমেয়াদী স্টোরেজ ম্যানেজ করতে দিন।
৮. The Brain - মাল্টিমোডাল মেমরি

"The Human Experience" কনসেপ্ট
মানুষ টেক্সটের চেয়ে বেশি মনে রাখে। আমরা কোনও ফটোর ভাইব, কোনও ভয়েসের সাউন্ড, কোনও ভিডিওর অনুভূতি মনে রাখি।
Vertex AI Memory Bank আপনার এজেন্টকে মাল্টিমডেল মেমরি ম্যানেজ করার অনুমতি দেয়। এটি ছবি, ভিডিও এবং অডিও ইনজেস্ট করতে, সেগুলি "বুঝতে" এবং পরে সেগুলি ফিরিয়ে আনতে পারে।
ধাপ ১: কনফিগারেশন
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/06_multimodal_agent/main.py
06_multimodal_agent/main.py খুলুন। # TODO: Configure Memory Bank Topic কমেন্টটি খুঁজে দেখুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
travel_topics = [
MemoryTopic(
managed_memory_topic=ManagedMemoryTopic(
managed_topic_enum=ManagedTopicEnum.USER_PREFERENCES
)
),
MemoryTopic(
managed_memory_topic=ManagedMemoryTopic(
managed_topic_enum=ManagedTopicEnum.USER_PERSONAL_INFO
)
),
MemoryTopic(
custom_memory_topic=CustomMemoryTopic(
label="travel_experiences",
description="""Memorable travel experiences including:
- Places visited and impressions
- Favorite restaurants, cafes, and food experiences
- Preferred accommodation types and locations
- Activities enjoyed (museums, hiking, beaches, etc.)
- Travel companions and social preferences
- Photos and videos from trips with location context""",
)
),
MemoryTopic(
custom_memory_topic=CustomMemoryTopic(
label="travel_preferences",
description="""Travel style and preferences:
- Budget preferences (luxury, mid-range, budget)
- Transportation preferences (flying, trains, driving)
- Trip duration preferences
- Season and weather preferences
- Cultural interests and language abilities
- Dietary restrictions and food preferences""",
)
),
MemoryTopic(
custom_memory_topic=CustomMemoryTopic(
label="travel_logistics",
description="""Practical travel information:
- Passport and visa information
- Frequent flyer numbers and hotel loyalty programs
- Emergency contacts
- Medical considerations and insurance
- Packing preferences and essentials
- Time zone preferences and jet lag strategies""",
)
),
]
# TODO: Configure Memory Bank Customization কমেন্টটি খুঁজুন
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
memory_bank_config = {
"customization_configs": [
{
"memory_topics": travel_topics,
}
],
"similarity_search_config": {
"embedding_model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-embedding-001"
},
"generation_config": {
"model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-2.5-flash"
},
}
ধাপ ২: বিশ্বকে ইনজেস্ট করা
test_trip_planner-এ, আমরা এগুলি পাঠাই:
- একটি টেক্সট মেসেজ ("হ্যালো")
- একটি ছবি (ল্যান্ডমার্ক)
- একটি ভিডিও (ভূমধ্যসাগর)
- একটি অডিও ক্লিপ (Gaeta সম্পর্কে ভয়েস নোট)
6_multimodal_agent/main.py ফাংশনের মধ্যে # TODO create session service and memory service কমেন্টটি খুঁজে দেখুন।
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
session_service = VertexAiSessionService(
project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)
memory_service = VertexAiMemoryBankService(
project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)
👉 একই ফাইলে 06_multimodal_agent/main.py, কমেন্টটি খুঁজুন # TODO: create memory from session
এই সম্পূর্ণ লাইনটি নিম্নলিখিত কোড দিয়ে পরিবর্তন করুন:
await memory_service.add_session_to_memory(final_session_state)
এটি হল ম্যাজিক লাইন। এটি Vertex AI-তে সেইসব রিচ মিডিয়া পাঠায়, যা এটি প্রসেস ও ইন্ডেক্স করে।
ধাপ ৩: পুনরুদ্ধার
👉💻 আপনার Cloud Shell টার্মিনালে, এটি রান করে Cloud Shell এডিটরে ফাইলটি খুলুন:
cloudshell edit ~/memory_agent_starter/06_multimodal_agent/agent.py
এজেন্টের কাছে PreloadMemoryTool আছে।
tools=[PreloadMemoryTool(), budget_tool]
নতুন সেশন শুরু হলে, এই টুল অটোমেটিক মেমরি ব্যাঙ্কে প্রাসঙ্গিক অতীতের অভিজ্ঞতা সার্চ করে এবং সেগুলিকে প্রসঙ্গে যোগ করে।
ধাপ ৪: ব্রেন রান করা
👉💻 আপনার Cloud Shell টার্মিনালে, স্ক্রিপ্ট রান করুন (মনে রাখবেন: এর জন্য Vertex AI চালু থাকা Google Cloud প্রোজেক্ট প্রয়োজন):
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/06_multimodal_agent/main.py
যাচাইকরণের শেষ ধাপটি দেখুন:
"আমি আগে আপনার সাথে যে ছবি, ভিডিও এবং অডিও শেয়ার করেছি তার উপর ভিত্তি করে..."
এজেন্ট উত্তর দেবে:
"আপনার গায়েতা ঘুরে আসা উচিত! তুমি আমাকে ভূমধ্যসাগরের একটি ভিডিও এবং একটি অডিও ক্লিপ দেখিয়েছিলে যেখানে তুমি বলেছিলে যে তুমি গায়েতা পছন্দ করো।"
এটি অতীতে বিভিন্ন ধরনের মিডিয়া জুড়ে ডট কানেক্ট করেছে।
মূল বিষয়
মেমরি সংক্রান্ত নিয়ম #৬: মেমরি সংক্রান্ত সেরা অভিজ্ঞতা পেতে Vertex AI মেমরি ব্যাঙ্ক ব্যবহার করুন। এটি টেক্সট, ছবি ও ভিডিওকে একত্রিত করে একটি সার্চযোগ্য ব্রেন তৈরি করে।
৯. উপসংহার
আপনি ভুলো গোল্ডফিশ থেকে মাল্টিমোডাল হাতির মতো স্মৃতিশক্তি অর্জন করেছেন।
আপনি তৈরি করেছেন | ক্ষমতা |
সেশন এজেন্ট | স্বল্পমেয়াদী কনভার্সেশনাল মেমরি |
মাল্টি-এজেন্ট | শেয়ার করা টিম মেমরি |
পারসিস্টেন্ট এজেন্ট | দীর্ঘমেয়াদী ইতিহাস |
স্টেটফুল এজেন্ট | ডায়নামিক, অটোমেটিক আপডেট হওয়া মেমরি |
প্রোফাইল এজেন্ট | স্ট্রাকচার্ড ডেটা মেমরি |
মাল্টিমোডাল এজেন্ট | মানুষের মতো সেন্সরি মেমরি |
মেমরির উপর ভিত্তি করে বিশ্বাস তৈরি হয়। এইসব প্যাটার্ন প্রয়োগ করে, আপনি এমন এজেন্ট তৈরি করেন যা ব্যবহারকারীর সময় ও ইতিহাসকে সম্মান করে, যার ফলে আরও গভীর, আরও কার্যকর ইন্টার্যাকশন হয়।
আজই আপনার পছন্দমতো এজেন্ট তৈরি করা শুরু করুন!