Agent2Agent (A2A) প্রোটোকল দিয়ে শুরু করা: ক্লাউড রান এবং এজেন্ট ইঞ্জিনে জেমিনীর সাথে একটি ক্রয়কারী কনসিয়ার এবং দূরবর্তী বিক্রেতা এজেন্ট ইন্টারঅ্যাকশন

1. ভূমিকা

b013ad6b246401eb.png

Agent2Agent (A2A) প্রোটোকল AI এজেন্টদের মধ্যে যোগাযোগের মানসম্মত করার জন্য ডিজাইন করা হয়েছে, বিশেষ করে যারা বহিরাগত সিস্টেমে মোতায়েন করা হয় তাদের জন্য। পূর্বে, মডেল কনটেক্সট প্রোটোকল (MCP) নামক সরঞ্জামগুলির জন্য এই ধরনের প্রোটোকল প্রতিষ্ঠিত হয়েছিল যা ডেটা এবং সংস্থানগুলির সাথে এলএলএমগুলিকে সংযুক্ত করার জন্য একটি উদীয়মান মান। A2A MCP-কে পরিপূরক করার চেষ্টা করে যেখানে A2A একটি ভিন্ন সমস্যার উপর দৃষ্টি নিবদ্ধ করে, যখন MCP এজেন্টদেরকে টুলস এবং ডেটার সাথে সংযুক্ত করার জটিলতা কমানোর উপর ফোকাস করে, A2A কিভাবে এজেন্টদের তাদের প্রাকৃতিক পদ্ধতিতে সহযোগিতা করতে সক্ষম করা যায় তার উপর ফোকাস করে। এটি এজেন্টদেরকে এজেন্ট হিসেবে (বা ব্যবহারকারী হিসেবে) যোগাযোগ করার সুযোগ দেয় টুল হিসেবে না করে; উদাহরণস্বরূপ, আপনি যখন কিছু অর্ডার করতে চান তখন সামনে এবং পিছনে যোগাযোগ সক্ষম করুন।

A2A এমসিপির পরিপূরক করার জন্য অবস্থান করা হয়েছে, অফিসিয়াল ডকুমেন্টেশনে এটি সুপারিশ করা হয়েছে যে অ্যাপ্লিকেশনগুলি টুলগুলির জন্য MCP এবং এজেন্টদের জন্য A2A ব্যবহার করবে - এজেন্টকার্ড দ্বারা প্রতিনিধিত্ব করা হয় (আমরা এটি পরে আলোচনা করব)। ফ্রেমওয়ার্কগুলি তখন তাদের ব্যবহারকারী, দূরবর্তী এজেন্ট এবং অন্যান্য এজেন্টদের সাথে যোগাযোগ করতে A2A ব্যবহার করতে পারে।

83b1a03588b90b68.png

এই ডেমোতে, আমরা এর পাইথন SDK ব্যবহার করে A2A বাস্তবায়ন শুরু করব। যখন আমাদের কাছে একটি ব্যক্তিগত ক্রয়কারী কনসিয়ার থাকবে তখন আমরা একটি ব্যবহারের ক্ষেত্রে অন্বেষণ করব যা আমাদের অর্ডার পরিচালনা করার জন্য বার্গার এবং পিৎজা বিক্রেতা এজেন্টদের সাথে যোগাযোগ করতে সাহায্য করতে পারে।

A2A ক্লায়েন্ট-সার্ভার নীতি ব্যবহার করে। এখানে সাধারণ A2A প্রবাহ যা আমরা এই ডেমোতে আশা করব

aa6c8bc5b5df73f1.jpeg

  1. A2A ক্লায়েন্ট প্রথমে সমস্ত অ্যাক্সেসযোগ্য A2A সার্ভার এজেন্ট কার্ড আবিষ্কার করবে এবং একটি সংযোগ ক্লায়েন্ট তৈরি করতে এর তথ্য ব্যবহার করবে
  2. যখন প্রয়োজন হয়, A2A ক্লায়েন্ট A2A সার্ভারে একটি বার্তা পাঠাবে, সার্ভার এটিকে একটি টাস্ক হিসেবে মূল্যায়ন করবে। যদি পুশ নোটিফিকেশন রিসিভার URL A2A ক্লায়েন্টে কনফিগার করা থাকে এবং A2A সার্ভার দ্বারা সমর্থিত হয়, তাহলে সার্ভারটি ক্লায়েন্টের প্রাপ্তির শেষ পয়েন্টে টাস্ক অগ্রগতির অবস্থা প্রকাশ করতেও সক্ষম হবে
  3. কাজ শেষ হওয়ার পরে, A2A সার্ভার A2A ক্লায়েন্টের কাছে প্রতিক্রিয়া আর্টিফ্যাক্ট পাঠাবে

কোডল্যাবের মাধ্যমে, আপনি নিম্নলিখিত হিসাবে একটি ধাপে ধাপে পদ্ধতি ব্যবহার করবেন:

  1. আপনার Google ক্লাউড প্রকল্প প্রস্তুত করুন এবং এতে প্রয়োজনীয় সমস্ত API সক্ষম করুন৷
  2. আপনার কোডিং পরিবেশের জন্য ওয়ার্কস্পেস সেটআপ করুন
  3. বার্গার এবং পিৎজা এজেন্ট পরিষেবার জন্য env ভেরিয়েবল প্রস্তুত করুন এবং স্থানীয়ভাবে চেষ্টা করুন
  4. ক্লাউড রানে বার্গার এবং পিজা এজেন্ট স্থাপন করুন
  5. কিভাবে A2A সার্ভার প্রতিষ্ঠিত হয়েছে তার বিশদ পরিদর্শন করুন
  6. কনসিয়ারেজ কেনার জন্য env ভেরিয়েবল প্রস্তুত করুন এবং স্থানীয়ভাবে চেষ্টা করুন
  7. এজেন্ট ইঞ্জিনে ক্রয় দ্বারস্থ করুন
  8. স্থানীয় ইন্টারফেসের মাধ্যমে এজেন্ট ইঞ্জিনের সাথে সংযোগ করুন
  9. কিভাবে A2A ক্লায়েন্ট প্রতিষ্ঠিত হয়েছে এবং এর ডেটা মডেলিং তার বিস্তারিত পরিদর্শন করুন
  10. A2A ক্লায়েন্ট এবং সার্ভারের মধ্যে পেলোড এবং মিথস্ক্রিয়া পরিদর্শন করুন

আর্কিটেকচার ওভারভিউ

আমরা নিম্নলিখিত পরিষেবা আর্কিটেকচার স্থাপন করব

9cfc4582f2d8b6f3.jpeg

আমরা 2টি পরিষেবা স্থাপন করব যা A2A সার্ভার হিসাবে কাজ করবে, বার্গার এজেন্ট (CrewAI এজেন্ট ফ্রেমওয়ার্ক দ্বারা সমর্থিত) এবং পিজা এজেন্ট (Langgraph এজেন্ট ফ্রেমওয়ার্ক দ্বারা সমর্থিত)। ব্যবহারকারী শুধুমাত্র ক্রয়কারীর সাথে সরাসরি যোগাযোগ করবে যা এজেন্ট ডেভেলপমেন্ট কিট (ADK) ফ্রেমওয়ার্ক ব্যবহার করে চালানো হবে যা A2A ক্লায়েন্ট হিসাবে কাজ করবে।

এই এজেন্টদের প্রত্যেকের নিজস্ব পরিবেশ এবং তাদের নিজস্ব স্থাপনা থাকবে।

পূর্বশর্ত

  • পাইথনের সাথে কাজ করা আরামদায়ক
  • HTTP পরিষেবা ব্যবহার করে মৌলিক ফুল-স্ট্যাক আর্কিটেকচারের একটি বোঝাপড়া

আপনি কি শিখবেন

  • A2A সার্ভারের মূল কাঠামো
  • A2A ক্লায়েন্টের মূল কাঠামো
  • ক্লাউড রানে এজেন্ট পরিষেবা স্থাপন করা হচ্ছে
  • এজেন্ট ইঞ্জিনে এজেন্ট পরিষেবা স্থাপন করা হচ্ছে
  • কিভাবে A2A ক্লায়েন্ট A2A সার্ভারের সাথে সংযোগ করে
  • নন-স্ট্রিমিং সংযোগে অনুরোধ এবং প্রতিক্রিয়া কাঠামো

আপনি কি প্রয়োজন হবে

  • ক্রোম ওয়েব ব্রাউজার
  • একটি জিমেইল অ্যাকাউন্ট
  • বিলিং সক্ষম সহ একটি ক্লাউড প্রকল্প৷

এই কোডল্যাব, সমস্ত স্তরের বিকাশকারীদের জন্য ডিজাইন করা হয়েছে (শিশুদের সহ), এর নমুনা অ্যাপ্লিকেশনে পাইথন ব্যবহার করে। যাইহোক, উপস্থাপিত ধারণাগুলি বোঝার জন্য পাইথন জ্ঞানের প্রয়োজন নেই।

2. আপনি শুরু করার আগে

ক্লাউড কনসোলে সক্রিয় প্রকল্প নির্বাচন করুন

এই কোডল্যাব ধরে নেয় যে আপনার কাছে ইতিমধ্যেই বিলিং সক্ষম সহ একটি Google ক্লাউড প্রকল্প রয়েছে৷ যদি আপনার কাছে এখনও এটি না থাকে তবে আপনি শুরু করতে নীচের নির্দেশাবলী অনুসরণ করতে পারেন।

  1. Google ক্লাউড কনসোলে , প্রকল্প নির্বাচক পৃষ্ঠায়, একটি Google ক্লাউড প্রকল্প নির্বাচন করুন বা তৈরি করুন।
  2. নিশ্চিত করুন যে আপনার ক্লাউড প্রকল্পের জন্য বিলিং সক্ষম করা আছে৷ একটি প্রকল্পে বিলিং সক্ষম কিনা তা পরীক্ষা করতে শিখুন।

bc8d176ea42fbb7.png

ক্লাউড শেল টার্মিনালে ক্লাউড প্রজেক্ট সেটআপ করুন

  1. আপনি ক্লাউড শেল ব্যবহার করবেন, Google ক্লাউডে চলমান একটি কমান্ড-লাইন পরিবেশ যা bq এর সাথে প্রিলোড করা হয়। গুগল ক্লাউড কনসোলের শীর্ষে সক্রিয় ক্লাউড শেল ক্লিক করুন। যদি এটি আপনাকে অনুমোদনের জন্য অনুরোধ করে, তবে অনুমোদন ক্লিক করুন

1829c3759227c19b.png

  1. একবার ক্লাউড শেলের সাথে সংযুক্ত হয়ে গেলে, আপনি পরীক্ষা করে দেখুন যে আপনি ইতিমধ্যেই প্রমাণীকৃত হয়েছেন এবং নিম্নলিখিত কমান্ডটি ব্যবহার করে প্রকল্পটি আপনার প্রকল্প আইডিতে সেট করা আছে:
gcloud auth list
  1. gcloud কমান্ড আপনার প্রকল্প সম্পর্কে জানে তা নিশ্চিত করতে ক্লাউড শেলে নিম্নলিখিত কমান্ডটি চালান।
gcloud config list project
  1. যদি আপনার প্রজেক্ট সেট করা না থাকে, তাহলে এটি সেট করতে নিম্নলিখিত কমান্ডটি ব্যবহার করুন:
gcloud config set project <YOUR_PROJECT_ID>

বিকল্পভাবে, আপনি কনসোলে PROJECT_ID আইডিও দেখতে পারেন

4032c45803813f30.jpeg

এটিতে ক্লিক করুন এবং আপনি আপনার সমস্ত প্রকল্প এবং প্রকল্প আইডি ডানদিকে পাবেন

8dc17eb4271de6b5.jpeg

  1. নীচে দেখানো কমান্ডের মাধ্যমে প্রয়োজনীয় API গুলি সক্ষম করুন৷ এটি কয়েক মিনিট সময় নিতে পারে, তাই ধৈর্য ধরুন।
gcloud services enable aiplatform.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       cloudresourcemanager.googleapis.com

কমান্ডের সফল সঞ্চালন হলে, আপনি নীচের দেখানো একটি অনুরূপ একটি বার্তা দেখতে হবে:

Operation "operations/..." finished successfully.

gcloud কমান্ডের বিকল্প হল কনসোলের মাধ্যমে প্রতিটি পণ্য অনুসন্ধান করে বা এই লিঙ্কটি ব্যবহার করে।

যদি কোনো API মিস হয়, আপনি সর্বদা বাস্তবায়নের সময় এটি সক্রিয় করতে পারেন।

জিক্লাউড কমান্ড এবং ব্যবহারের জন্য ডকুমেন্টেশন পড়ুন।

ক্লাউড শেল এডিটর এবং সেটআপ অ্যাপ্লিকেশন ওয়ার্কিং ডিরেক্টরিতে যান

এখন, আমরা কিছু কোডিং স্টাফ করতে আমাদের কোড এডিটর সেট আপ করতে পারি। আমরা এর জন্য ক্লাউড শেল এডিটর ব্যবহার করব

  1. Open Editor বাটনে ক্লিক করুন, এটি একটি Cloud Shell Editor খুলবে, আমরা এখানে আমাদের কোড লিখতে পারি b16d56e4979ec951.png
  2. নিশ্চিত করুন যে ক্লাউড কোড প্রকল্পটি ক্লাউড শেল সম্পাদকের নীচের বাম কোণে (স্ট্যাটাস বার) সেট করা আছে, যেমনটি নীচের ছবিতে হাইলাইট করা হয়েছে এবং সক্রিয় Google ক্লাউড প্রকল্পে সেট করা আছে যেখানে আপনি বিলিং সক্ষম করেছেন৷ অনুরোধ করা হলে অনুমোদন করুন । আপনি যদি পূর্ববর্তী কমান্ড অনুসরণ করেন, তাহলে সাইন ইন বোতামের পরিবর্তে বোতামটি সরাসরি আপনার সক্রিয় প্রকল্পের দিকে নির্দেশ করতে পারে

f5003b9c38b43262.png

  1. এর পরে, আসুন Github থেকে এই কোডল্যাবের জন্য টেমপ্লেট ওয়ার্কিং ডিরেক্টরি ক্লোন করি, নিম্নলিখিত কমান্ডটি চালান। এটি purchasing-concierge-a2a ডিরেক্টরিতে কাজের ডিরেক্টরি তৈরি করবে
git clone https://github.com/alphinside/purchasing-concierge-intro-a2a-codelab-starter.git purchasing-concierge-a2a
  1. এর পরে, ক্লাউড শেল এডিটরের উপরের বিভাগে যান এবং ফাইল->ফোল্ডার খুলুন ক্লিক করুন, আপনার ব্যবহারকারীর নাম ডিরেক্টরি খুঁজুন এবং purchasing-concierge-a2a ডিরেক্টরি খুঁজুন তারপর ওকে বোতামে ক্লিক করুন। এটি নির্বাচিত ডিরেক্টরিটিকে প্রধান কার্যকারী ডিরেক্টরি হিসাবে তৈরি করবে। এই উদাহরণে, ব্যবহারকারীর নাম হল alvinprayuda , তাই ডিরেক্টরির পথটি নীচে দেখানো হয়েছে

2c53696f81d805cc.png

253b472fa1bd752e.png

এখন, আপনার ক্লাউড শেল এডিটর দেখতে এইরকম হওয়া উচিত

aedd0725db87717e.png

পরিবেশ সেটআপ

পরবর্তী ধাপ হচ্ছে উন্নয়ন পরিবেশ প্রস্তুত করা। আপনার বর্তমান সক্রিয় টার্মিনালটি purchasing-concierge-a2a ওয়ার্কিং ডিরেক্টরির মধ্যে থাকা উচিত। আমরা এই কোডল্যাবে পাইথন 3.12 ব্যবহার করব এবং পাইথন সংস্করণ এবং ভার্চুয়াল পরিবেশ তৈরি এবং পরিচালনার প্রয়োজনীয়তা সহজ করতে আমরা ইউভি পাইথন প্রকল্প ব্যবস্থাপক ব্যবহার করব

  1. আপনি যদি এখনও টার্মিনাল না খুলে থাকেন, তাহলে টার্মিনাল -> নিউ টার্মিনাল- এ ক্লিক করে এটি খুলুন, অথবা Ctrl + Shift + C ব্যবহার করুন, এটি ব্রাউজারের নীচের অংশে একটি টার্মিনাল উইন্ডো খুলবে।

f8457daf0bed059e.jpeg

  1. এখন uv (ক্লাউড টার্মিনালে আগে থেকেই ইনস্টল করা আছে) ব্যবহার করে ক্রয়কারী দরজার ভার্চুয়াল পরিবেশ শুরু করা যাক। এই কমান্ড চালান
uv sync --frozen

এটি .venv ডিরেক্টরি তৈরি করবে এবং নির্ভরতাগুলি ইনস্টল করবে। pyproject.toml- এ দ্রুত স্নিক পিক আপনাকে এইভাবে দেখানো নির্ভরতা সম্পর্কে তথ্য দেবে

dependencies = [
    "a2a-sdk>=0.2.16",
    "google-adk>=1.8.0",
    "gradio>=5.38.2",
]
  1. ভার্চুয়াল env পরীক্ষা করতে, নতুন ফাইল main.py তৈরি করুন এবং নিম্নলিখিত কোডটি অনুলিপি করুন
def main():
   print("Hello from purchasing-concierge-a2a!")

if __name__ == "__main__":
   main()
  1. তারপরে, নিম্নলিখিত কমান্ডটি চালান
uv run main.py

আপনি নিচের মত আউটপুট পাবেন

Using CPython 3.12
Creating virtual environment at: .venv
Hello from purchasing-concierge-a2a!

এটি দেখায় যে পাইথন প্রকল্পটি সঠিকভাবে সেট আপ করা হচ্ছে।

এখন আমরা আমাদের দূরবর্তী বিক্রেতা এজেন্ট কনফিগার এবং স্থাপন করে পরবর্তী ধাপে যেতে পারি

3. দূরবর্তী বিক্রেতা এজেন্ট স্থাপন - A2A সার্ভার ক্লাউড রানে

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

e91777eecfbae4f7.png

রিমোট বার্গার এজেন্ট মোতায়েন করা হচ্ছে

বার্গার এজেন্ট সোর্স কোডটি remote_seller_agents/burger_agent ডিরেক্টরির অধীনে রয়েছে। এজেন্ট সূচনা agent.py স্ক্রিপ্টে পরিদর্শন করা যেতে পারে। এখানে শুরু করা এজেন্টের কোড স্নিপেট

from crewai import Agent, Crew, LLM, Task, Process
from crewai.tools import tool

...

       model = LLM(
            model="vertex_ai/gemini-2.5-flash-lite",  # Use base model name without provider prefix
        )
        burger_agent = Agent(
            role="Burger Seller Agent",
            goal=(
                "Help user to understand what is available on burger menu and price also handle order creation."
            ),
            backstory=("You are an expert and helpful burger seller agent."),
            verbose=False,
            allow_delegation=False,
            tools=[create_burger_order],
            llm=model,
        )

        agent_task = Task(
            description=self.TaskInstruction,
            agent=burger_agent,
            expected_output="Response to the user in friendly and helpful manner",
        )

        crew = Crew(
            tasks=[agent_task],
            agents=[burger_agent],
            verbose=False,
            process=Process.sequential,
        )

        inputs = {"user_prompt": query, "session_id": sessionId}
        response = crew.kickoff(inputs)
        return response

...

remote_seller_agents/burger_agent ডিরেক্টরির অধীনে থাকা সমস্ত ফাইল ইতিমধ্যেই আমাদের এজেন্টকে ক্লাউড রানে মোতায়েন করার জন্য যথেষ্ট যাতে এটি একটি পরিষেবা হিসাবে অ্যাক্সেসযোগ্য হতে পারে৷ আমরা এই বিষয়ে পরে আলোচনা করব। এটি স্থাপন করতে নিম্নলিখিত কমান্ডটি চালান

gcloud run deploy burger-agent \
    --source remote_seller_agents/burger_agent \
    --port=8080 \
    --allow-unauthenticated \
    --min 1 \
    --region us-central1 \
    --update-env-vars GOOGLE_CLOUD_LOCATION=us-central1 \
    --update-env-vars GOOGLE_CLOUD_PROJECT={your-project-id}

যদি আপনাকে অনুরোধ করা হয় যে উৎস থেকে স্থাপন করার জন্য একটি ধারক সংগ্রহস্থল তৈরি করা হবে, Y উত্তর দিন। এটি শুধুমাত্র তখনই ঘটে যখন আপনি আগে কখনো উৎস থেকে চালানো কোনো ক্লাউডে স্থাপন করেননি। সফল স্থাপনার পরে এটি এরকম একটি লগ দেখাবে।

Service [burger-agent] revision [burger-agent-xxxxx-xxx] has been deployed and is serving 100 percent of traffic.
Service URL: https://burger-agent-xxxxxxxxx.us-central1.run.app

যখন আমরা পরিষেবাটি স্থাপন করি তখন এখানে xxxx অংশটি একটি অনন্য শনাক্তকারী হবে। এখন, ব্রাউজারের মাধ্যমে সেই বার্গার এজেন্ট পরিষেবাগুলির https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json রুটে যাওয়ার চেষ্টা করা যাক৷ এটি স্থাপন করা A2A সার্ভার এজেন্ট কার্ড অ্যাক্সেস করার URL।

সফলভাবে মোতায়েন করা হলে, https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json অ্যাক্সেস করার সময় আপনি আপনার ব্রাউজারে নীচে দেখানো প্রতিক্রিয়া দেখতে পাবেন :

72fdf3f52b5e8313.png

এটি বার্গার এজেন্ট কার্ডের তথ্য যা আবিষ্কারের উদ্দেশ্যে অ্যাক্সেসযোগ্য হওয়া উচিত। আমরা এই বিষয়ে পরে আলোচনা করব। লক্ষ্য করুন যে url মান এখনও এখানে http://0.0.0.0:8080/ সেট করা আছে। এই url মানটি A2A ক্লায়েন্টের বাইরের বিশ্ব থেকে বার্তা পাঠানোর জন্য প্রধান তথ্য হওয়া উচিত এবং এটি সঠিকভাবে কনফিগার করা নেই। এই ডেমোর জন্য, আমাদের একটি অতিরিক্ত পরিবেশ পরিবর্তনশীল HOST_OVERRIDE যোগ করে আমাদের বার্গার এজেন্ট পরিষেবার URL-এ এই মান আপডেট করতে হবে।

এনভায়রনমেন্ট ভেরিয়েবলের মাধ্যমে এজেন্ট কার্ডে বার্গার এজেন্ট URL মান আপডেট করা হচ্ছে

বার্গার এজেন্ট পরিষেবাতে HOST_OVERRIDE যোগ করতে, নিম্নলিখিত পদক্ষেপগুলি করুন৷

  1. সার্চ ক্লাউড আপনার ক্লাউড কনসোলের উপরে সার্চ বারে চালান

1adde569bb345b48.png

  1. পূর্বে নিয়োজিত বার্গার-এজেন্ট ক্লাউড রান সার্ভিসে ক্লিক করুন

9091c12526fb7f41.png

  1. বার্গার-পরিষেবা URLটি অনুলিপি করুন, তারপর সম্পাদনায় ক্লিক করুন এবং নতুন সংশোধন স্থাপন করুন৷

2701da8b124793b9.png

  1. তারপর, Variable & Secrets বিভাগে ক্লিক করুন

31ea00e12134d74d.png

  1. এর পরে, ভেরিয়েবল যোগ করুন ক্লিক করুন এবং পরিষেবা URL-এ HOST_OVERRIDE মান সেট করুন ( https://burger-agent-xxxxxxxxx.us-central1.run.app প্যাটার্ন সহ )

52b382da7cf33cd5.png

  1. অবশেষে, আপনার পরিষেবা পুনরায় স্থাপন করতে স্থাপনার বোতামে ক্লিক করুন

11464f4a51ffe54.png

এখন, যখন আপনি ব্রাউজার https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json এ আবার বার্গার-এজেন্ট এজেন্ট কার্ড অ্যাক্সেস করবেন, url মান ইতিমধ্যেই সঠিকভাবে কনফিগার করা হবে

2ed7ebcb530f070a.png

রিমোট পিজা এজেন্ট মোতায়েন করা হচ্ছে

একইভাবে, পিৎজা এজেন্ট সোর্স কোডটি remote_seller_agents/pizza_agent ডিরেক্টরির অধীনে রয়েছে। এজেন্ট সূচনা agent.py স্ক্রিপ্টে পরিদর্শন করা যেতে পারে। এখানে শুরু করা এজেন্টের কোড স্নিপেট

from langchain_google_vertexai import ChatVertexAI
from langgraph.prebuilt import create_react_agent

...

self.model = ChatVertexAI(
    model="gemini-2.5-flash-lite",
    location=os.getenv("GOOGLE_CLOUD_LOCATION"),
    project=os.getenv("GOOGLE_CLOUD_PROJECT"),
)
self.tools = [create_pizza_order]
self.graph = create_react_agent(
    self.model,
    tools=self.tools,
    checkpointer=memory,
    prompt=self.SYSTEM_INSTRUCTION,
)

...

পূর্ববর্তী বার্গার-এজেন্ট স্থাপনার পদক্ষেপের মতো, remote_seller_agents/pizza_agent ডিরেক্টরির অধীনে থাকা সমস্ত ফাইল ইতিমধ্যেই আমাদের এজেন্টকে ক্লাউড রানে স্থাপন করার জন্য যথেষ্ট যাতে এটি একটি পরিষেবা হিসাবে অ্যাক্সেসযোগ্য হতে পারে৷ এটি স্থাপন করতে নিম্নলিখিত কমান্ডটি চালান

gcloud run deploy pizza-agent \
    --source remote_seller_agents/pizza_agent \
    --port=8080 \
    --allow-unauthenticated \
    --min 1 \
    --region us-central1 \
    --update-env-vars GOOGLE_CLOUD_LOCATION=us-central1 \
    --update-env-vars GOOGLE_CLOUD_PROJECT={your-project-id}

সফল স্থাপনার পরে এটি এরকম একটি লগ দেখাবে।

Service [pizza-agent] revision [pizza-agent-xxxxx-xxx] has been deployed and is serving 100 percent of traffic.
Service URL: https://pizza-agent-xxxxxxxxx.us-central1.run.app

যখন আমরা পরিষেবাটি স্থাপন করি তখন এখানে xxxx অংশটি একটি অনন্য শনাক্তকারী হবে। বার্গার এজেন্টের ক্ষেত্রেও এটি একই রকম, আপনি যখন A2A সার্ভার এজেন্ট কার্ড অ্যাক্সেস করতে ব্রাউজারের মাধ্যমে নিয়োজিত পিজা এজেন্ট পরিষেবাগুলির https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json রুটে যাওয়ার চেষ্টা করেন, তখন পিৎজা এজেন্টের url মানটি এখনও তার এজেন্ট কার্ডে কনফিগার করা হয়নি। আমাদের HOST_OVERRIDE এর এনভায়রনমেন্ট ভেরিয়েবলে যোগ করতে হবে

এনভায়রনমেন্ট ভেরিয়েবলের মাধ্যমে এজেন্ট কার্ডে পিজা এজেন্ট URL মান আপডেট করা হচ্ছে

পিৎজা এজেন্ট পরিষেবাতে HOST_OVERRIDE যোগ করতে, নিম্নলিখিত পদক্ষেপগুলি করুন৷

  1. সার্চ ক্লাউড আপনার ক্লাউড কনসোলের উপরে সার্চ বারে চালান

1adde569bb345b48.png

  1. পূর্বে নিয়োজিত পিজা-এজেন্ট ক্লাউড রান সার্ভিসে ক্লিক করুন

5743b0aa0555741f.png

  1. এডিট এ ক্লিক করুন এবং নতুন রিভিশন স্থাপন করুন

d60ba267410183be.png

  1. পিজা-পরিষেবা URL অনুলিপি করুন, তারপর পরিবর্তনশীল এবং গোপন বিভাগে ক্লিক করুন

618e9da2f94ed415.png

  1. এর পরে, ভেরিয়েবল যোগ করুন ক্লিক করুন এবং পরিষেবা URL-এ HOST_OVERRIDE মান সেট করুন ( https://pizza-agent-xxxxxxxxx.us-central1.run.app প্যাটার্ন সহ )

214a6eb98f877e65.png

  1. অবশেষে, আপনার পরিষেবা পুনরায় স্থাপন করতে স্থাপনার বোতামে ক্লিক করুন

11464f4a51ffe54.png

এখন, আপনি যখন ব্রাউজার https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json এ পিজা-এজেন্ট এজেন্ট কার্ডটি আবার অ্যাক্সেস করবেন, তখন url মানটি ইতিমধ্যেই সঠিকভাবে কনফিগার করা হবে

c37b26ec80c821b6.png

এই মুহুর্তে, আমরা ইতিমধ্যেই সফলভাবে ক্লাউড রানে বার্গার এবং পিৎজা উভয় পরিষেবাই স্থাপন করেছি। এখন A2A সার্ভারের মূল উপাদান নিয়ে আলোচনা করা যাক

4. A2A সার্ভারের মূল উপাদান

এখন A2A সার্ভারের মূল ধারণা এবং উপাদান নিয়ে আলোচনা করা যাক

এজেন্ট কার্ড

A2A সার্ভারের প্রতিটির একটি এজেন্ট কার্ড থাকতে হবে যা /.well-known/agent.json রিসোর্সে অ্যাক্সেসযোগ্য। এটি A2A ক্লায়েন্টের আবিষ্কারের পর্যায়কে সমর্থন করার জন্য, যাতে এজেন্টকে কীভাবে অ্যাক্সেস করা যায় এবং এর সমস্ত ক্ষমতা জানা যায় সে সম্পর্কে সম্পূর্ণ তথ্য এবং প্রসঙ্গ দেওয়া উচিত। এটি সোয়াগার বা পোস্টম্যান ব্যবহার করে ভাল নথিভুক্ত API ডকুমেন্টেশনের সাথে একরকম।

এটি আমাদের নিয়োজিত বার্গার এজেন্ট এজেন্ট কার্ডের বিষয়বস্তু

{
  "capabilities": {
    "streaming": true
  },
  "defaultInputModes": [
    "text",
    "text/plain"
  ],
  "defaultOutputModes": [
    "text",
    "text/plain"
  ],
  "description": "Helps with creating burger orders",
  "name": "burger_seller_agent",
  "protocolVersion": "0.2.6",
  "skills": [
    {
      "description": "Helps with creating burger orders",
      "examples": [
        "I want to order 2 classic cheeseburgers"
      ],
      "id": "create_burger_order",
      "name": "Burger Order Creation Tool",
      "tags": [
        "burger order creation"
      ]
    }
  ],
  "url": "https://burger-agent-109790610330.us-central1.run.app",
  "version": "1.0.0"
}

এই এজেন্ট কার্ডগুলি অনেক গুরুত্বপূর্ণ উপাদান হাইলাইট করে, যেমন এজেন্ট দক্ষতা, স্ট্রিমিং ক্ষমতা, সমর্থিত পদ্ধতি, প্রোটোকল সংস্করণ এবং অন্যান্য জিনিস।

এই সমস্ত তথ্য একটি সঠিক যোগাযোগ ব্যবস্থা বিকাশের জন্য ব্যবহার করা যেতে পারে যাতে A2A ক্লায়েন্ট সঠিকভাবে যোগাযোগ করতে পারে। সমর্থিত পদ্ধতি এবং প্রমাণীকরণ প্রক্রিয়া নিশ্চিত করে যে যোগাযোগ সঠিকভাবে প্রতিষ্ঠিত হতে পারে এবং এজেন্ট skills তথ্য A2A ক্লায়েন্ট সিস্টেম প্রম্পটে এমবেড করা যেতে পারে যাতে ক্লায়েন্টের এজেন্টকে দূরবর্তী এজেন্টের ক্ষমতা এবং দক্ষতার আহ্বান জানানো হয়। এই এজেন্ট কার্ডের আরও বিস্তারিত ক্ষেত্র এই ডকুমেন্টেশনে পাওয়া যাবে।

আমাদের কোডে, A2A পাইথন sdk ব্যবহার করে এজেন্ট কার্ডের বাস্তবায়ন প্রতিষ্ঠিত হয়েছে, বাস্তবায়নের জন্য নীচে remote_seller_agents/burger_agent/main.py স্নিপেট দেখুন

...

        capabilities = AgentCapabilities(streaming=True)
        skill = AgentSkill(
            id="create_burger_order",
            name="Burger Order Creation Tool",
            description="Helps with creating burger orders",
            tags=["burger order creation"],
            examples=["I want to order 2 classic cheeseburgers"],
        )
        agent_host_url = (
            os.getenv("HOST_OVERRIDE")
            if os.getenv("HOST_OVERRIDE")
            else f"http://{host}:{port}/"
        )
        agent_card = AgentCard(
            name="burger_seller_agent",
            description="Helps with creating burger orders",
            url=agent_host_url,
            version="1.0.0",
            defaultInputModes=BurgerSellerAgent.SUPPORTED_CONTENT_TYPES,
            defaultOutputModes=BurgerSellerAgent.SUPPORTED_CONTENT_TYPES,
            capabilities=capabilities,
            skills=[skill],
        )

...

আমরা সেখানে বেশ কয়েকটি ক্ষেত্র দেখতে পাচ্ছি যেমন:

  1. AgentCapabilities : এজেন্ট পরিষেবা দ্বারা সমর্থিত অতিরিক্ত ঐচ্ছিক ফাংশনগুলির ঘোষণা, যেমন স্ট্রিমিং এবং/অথবা পুশ বিজ্ঞপ্তি সমর্থনের ক্ষমতা
  2. AgentSkill : এজেন্ট দ্বারা সমর্থিত সরঞ্জাম বা ফাংশন
  3. Input/OutputModes : ইনপুট/আউটপুট টাইপ মোড্যালিটি যা সমর্থিত
  4. Url : এজেন্টের সাথে যোগাযোগ করার ঠিকানা

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

টাস্ক কিউ এবং এজেন্ট এক্সিকিউটর

A2A সার্ভার বিভিন্ন এজেন্ট বা ব্যবহারকারীদের কাছ থেকে অনুরোধগুলি পরিচালনা করতে পারে এবং প্রতিটি কাজকে পুরোপুরি আলাদা করতে সক্ষম হতে পারে। এগুলির প্রসঙ্গগুলিকে আরও ভালভাবে কল্পনা করতে, আপনি নীচের চিত্রটি পরিদর্শন করতে পারেন৷

b9eb6b4025db4642.jpeg

সুতরাং, প্রতিটি A2A সার্ভার ইনকামিং কাজগুলি ট্র্যাক করতে এবং এটি সম্পর্কে সঠিক তথ্য সংরক্ষণ করতে সক্ষম হওয়া উচিত। A2A সার্ভারে এই চ্যালেঞ্জ মোকাবেলার জন্য A2A SDK মডিউল প্রদান করে। প্রথমত, আমরা ইনকামিং রিকোয়েস্টকে কীভাবে পরিচালনা করতে চাই তার উপর যুক্তি দেখাতে পারি। AgentExecutor অ্যাবস্ট্রাক্ট ক্লাসের উত্তরাধিকারের মাধ্যমে আমরা কীভাবে টাস্ক এক্সিকিউশন এবং বাতিলকরণ পরিচালনা করতে চাই তা নিয়ন্ত্রণ করতে পারি। এই উদাহরণ বাস্তবায়ন remote_seller_agents/burger_agent/agent_executor.py মডিউলে পরিদর্শন করা যেতে পারে (পিজ্জা বিক্রেতার ক্ষেত্রে অনুরূপ পথ)

...

class BurgerSellerAgentExecutor(AgentExecutor):
    """Burger Seller AgentExecutor."""

    def __init__(self):
        self.agent = BurgerSellerAgent()

    async def execute(
        self,
        context: RequestContext,
        event_queue: EventQueue,
    ) -> None:
        query = context.get_user_input()
        try:
            result = self.agent.invoke(query, context.context_id)
            print(f"Final Result ===> {result}")

            parts = [Part(root=TextPart(text=str(result)))]
            await event_queue.enqueue_event(
                completed_task(
                    context.task_id,
                    context.context_id,
                    [new_artifact(parts, f"burger_{context.task_id}")],
                    [context.message],
                )
            )
        except Exception as e:
            print("Error invoking agent: %s", e)
            raise ServerError(error=ValueError(f"Error invoking agent: {e}")) from e

    async def cancel(
        self, request: RequestContext, event_queue: EventQueue
    ) -> Task | None:
        raise ServerError(error=UnsupportedOperationError())

...

উপরের কোডে, আমরা একটি বেসিক প্রসেসিং স্কিম বাস্তবায়ন করি যেখানে এজেন্টকে সরাসরি আমন্ত্রণ জানানো হবে যখন ইনকামিং অনুরোধ করা হবে এবং আমন্ত্রণ শেষ করার পরে সম্পন্ন করা টাস্ক ইভেন্টগুলি প্রেরণ করা হবে। যাইহোক, আমরা এখানে বাতিলকরণ পদ্ধতি প্রয়োগ করিনি কারণ এটি একটি সংক্ষিপ্ত চলমান অপারেশন হিসাবে বিবেচিত হয়েছিল।

আমরা নির্বাহক তৈরি করার পরে, আমরা সরাসরি HTTP সার্ভার স্পিন আপ করতে বিল্ট-ইন DefaultRequestHandler, InMemoryTaskStore এবং A2AStarletteApplication ব্যবহার করতে পারি। এই বাস্তবায়ন remote_seller_agents/burger_agent/__main__.py এ পরিদর্শন করা যেতে পারে

...

        request_handler = DefaultRequestHandler(
            agent_executor=BurgerSellerAgentExecutor(),
            task_store=InMemoryTaskStore(),
        )
        server = A2AStarletteApplication(
            agent_card=agent_card, http_handler=request_handler
        )

        uvicorn.run(server.build(), host=host, port=port)

...

এই মডিউলটি আপনাকে এজেন্ট কার্ড অ্যাক্সেস করার জন্য /.well-known/agent.json রুটের বাস্তবায়ন এবং A2A প্রোটোকল সমর্থন করার জন্য POST এন্ডপয়েন্ট প্রদান করবে

সারাংশ

সংক্ষেপে, পাইথন SDK ব্যবহার করে আমাদের মোতায়েন করা A2A সার্ভার যা নীচের 2টি কার্যকারিতা সমর্থন করতে পারে:

  1. /.well-known/agent.json রুটে এজেন্ট কার্ড প্রকাশ করা হচ্ছে
  2. মেমরি টাস্ক সারি দিয়ে JSON-RPC অনুরোধ পরিচালনা করুন

এই কার্যকারিতাগুলি শুরু করার এন্ট্রি পয়েন্টটি __main__.py স্ক্রিপ্টে পরিদর্শন করা যেতে পারে ( remote_seller_agents/burger_agent বা remote_seller_agents/pizza_agent এ)।

5. ক্রয় দ্বারস্থ করা - A2A ক্লায়েন্ট থেকে এজেন্ট ইঞ্জিন

এই ধাপে, আমরা ক্রয়কারী কনসিয়ার এজেন্টকে মোতায়েন করব। এই এজেন্ট হল আমরা যার সাথে যোগাযোগ করব।

c4a8e7a3d18b1ef.png

আমাদের ক্রয়কারী কনসিয়েজ এজেন্টের উত্স কোডটি purchasing_concierge ডিরেক্টরির অধীনে রয়েছে। এজেন্ট প্রারম্ভিকতা purchasing_agent.py স্ক্রিপ্টে পরিদর্শন করা যেতে পারে। এখানে শুরু করা এজেন্টের কোড স্নিপেট।

from google.adk import Agent

...

def create_agent(self) -> Agent:
        return Agent(
            model="gemini-2.5-flash-lite",
            name="purchasing_agent",
            instruction=self.root_instruction,
            before_model_callback=self.before_model_callback,
            before_agent_callback=self.before_agent_callback,
            description=(
                "This purchasing agent orchestrates the decomposition of the user purchase request into"
                " tasks that can be performed by the seller agents."
            ),
            tools=[
                self.send_task,
            ],
        )

...

আমরা এই এজেন্টকে এজেন্ট ইঞ্জিনে স্থাপন করব। Vertex AI এজেন্ট ইঞ্জিন হল পরিষেবার একটি সেট যা ডেভেলপারদের উৎপাদনে AI এজেন্ট স্থাপন, পরিচালনা এবং স্কেল করতে সক্ষম করে। এটি উৎপাদনে এজেন্টদের স্কেল করার জন্য অবকাঠামো পরিচালনা করে যাতে আমরা অ্যাপ্লিকেশন তৈরিতে ফোকাস করতে পারি। আপনি এই নথিতে এই সম্পর্কে আরও পড়তে পারেন। পূর্বে যদি আমাদের এজেন্ট পরিষেবা (যেমন প্রধান সার্ভার স্ক্রিপ্ট এবং ডকারফাইল) স্থাপন করার জন্য প্রয়োজনীয় ফাইলগুলি প্রস্তুত করার প্রয়োজন হয়, এই ক্ষেত্রে আমরা ADK এবং এজেন্ট ইঞ্জিনের সংমিশ্রণ ব্যবহার করে আমাদের নিজস্ব ব্যাকএন্ড পরিষেবা বিকাশের প্রয়োজন ছাড়াই পাইথন স্ক্রিপ্ট থেকে সরাসরি আমাদের এজেন্টকে স্থাপন করতে পারি। এটি স্থাপন করতে এই পদক্ষেপগুলি অনুসরণ করুন:

  1. প্রথমত, আমাদের ক্লাউড স্টোরেজে আমাদের স্টেজিং স্টোরেজ তৈরি করতে হবে
gcloud storage buckets create gs://purchasing-concierge-{your-project-id} --location=us-central1
  1. এখন, আমাদের প্রথমে .env ভেরিয়েবল প্রস্তুত করতে হবে, আসুন .env.example কে .env ফাইলে কপি করি।
cp .env.example .env
  1. এখন, .env ফাইলটি খুলুন এবং আপনি নিম্নলিখিত বিষয়বস্তু দেখতে পাবেন
GOOGLE_GENAI_USE_VERTEXAI=TRUE
GOOGLE_CLOUD_PROJECT={your-project-id}
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://purchasing-concierge-{your-project-id}
PIZZA_SELLER_AGENT_URL={your-pizza-agent-url}
BURGER_SELLER_AGENT_URL={your-burger-agent-url}
AGENT_ENGINE_RESOURCE_NAME={your-agent-engine-resource-name}

এই এজেন্ট বার্গার এবং পিৎজা এজেন্টের সাথে যোগাযোগ করবে, এইভাবে আমাদের তাদের উভয়ের জন্য যথাযথ শংসাপত্র সরবরাহ করতে হবে। আমাদের PIZZA_SELLER_AGENT_URL এবং BURGER_SELLER_AGENT_URL পূর্ববর্তী ধাপগুলি থেকে ক্লাউড রান URL এর সাথে আপডেট করতে হবে৷

আপনি যদি এটি ভুলে যান তবে আসুন ক্লাউড রান কনসোলটি দেখুন। আপনার কনসোলের উপরে সার্চ বারে "ক্লাউড রান" টাইপ করুন এবং একটি নতুন ট্যাবে এটি খুলতে ক্লাউড রান আইকনে ডান ক্লিক করুন

1adde569bb345b48.png

আপনি নীচের মত আমাদের পূর্ববর্তী নিয়োজিত দূরবর্তী বিক্রেতা এজেন্ট সেবা দেখতে হবে

179e55cc095723a8.png

এখন সেই পরিষেবাগুলির সর্বজনীন URL দেখতে, পরিষেবাগুলির একটিতে ক্লিক করুন এবং আপনাকে পরিষেবার বিবরণ পৃষ্ঠায় পুনঃনির্দেশিত করা হবে৷ আপনি অঞ্চলের তথ্যের পাশে উপরের অংশে URLটি দেখতে পারেন

64c01403a92b1107.png

চূড়ান্ত পরিবেশ পরিবর্তনশীল এটির অনুরূপ হওয়া উচিত

GOOGLE_GENAI_USE_VERTEXAI=TRUE
GOOGLE_CLOUD_PROJECT={your-project-id}
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://purchasing-concierge-{your-project-id}
PIZZA_SELLER_AGENT_URL=https://pizza-agent-xxxxx.us-central1.run.app
BURGER_SELLER_AGENT_URL=https://burger-agent-xxxxx.us-central1.run.app
AGENT_ENGINE_RESOURCE_NAME={your-agent-engine-resource-name}
  1. এখন, আমরা আমাদের ক্রয়কারী কনসিয়ার এজেন্ট মোতায়েন করতে প্রস্তুত। এই ডেমোতে আমরা স্ক্রিপ্ট deploy_to_agent_engine.py ব্যবহার করে স্থাপন করব যে বিষয়বস্তু নীচে দেখানো হয়েছে
"""
Copyright 2025 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import vertexai
from vertexai.preview import reasoning_engines
from vertexai import agent_engines
from dotenv import load_dotenv
import os
from purchasing_concierge.agent import root_agent

load_dotenv()

PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
LOCATION = os.getenv("GOOGLE_CLOUD_LOCATION")
STAGING_BUCKET = os.getenv("STAGING_BUCKET")

vertexai.init(
    project=PROJECT_ID,
    location=LOCATION,
    staging_bucket=STAGING_BUCKET,
)

adk_app = reasoning_engines.AdkApp(
    agent=root_agent,
)

remote_app = agent_engines.create(
    agent_engine=adk_app,
    display_name="purchasing-concierge",
    requirements=[
        "google-cloud-aiplatform[adk,agent_engines]",
        "a2a-sdk==0.2.16",
    ],
    extra_packages=[
        "./purchasing_concierge",
    ],
    env_vars={
        "GOOGLE_GENAI_USE_VERTEXAI": os.environ["GOOGLE_GENAI_USE_VERTEXAI"],
        "PIZZA_SELLER_AGENT_URL": os.environ["PIZZA_SELLER_AGENT_URL"],
        "BURGER_SELLER_AGENT_URL": os.environ["BURGER_SELLER_AGENT_URL"],
    },
)

print(f"Deployed remote app resource: {remote_app.resource_name}")

আমাদের ADK এজেন্টকে এজেন্ট ইঞ্জিনে মোতায়েন করার জন্য এটি প্রয়োজনীয় পদক্ষেপ। প্রথমে, আমাদের ADK root_agent থেকে একটি AdkApp অবজেক্ট তৈরি করতে হবে। তারপরে আমরা adk_app অবজেক্ট প্রদান করে agent_engines.create পদ্ধতি চালাতে পারি, requirements ক্ষেত্রে প্রয়োজনীয়তা উল্লেখ করে, extra_packages এ এজেন্ট ডিরেক্টরি পাথ উল্লেখ করে এবং প্রয়োজনীয় env ভেরিয়েবল প্রদান করে।

আমরা স্ক্রিপ্ট চালানোর মাধ্যমে এটি স্থাপন করতে পারি:

uv run deploy_to_agent_engine.py

সফল স্থাপনার পরে এটি এরকম একটি লগ দেখাবে। নোট করুন যে xxxx হল আপনার প্রজেক্ট আইডি এবং yyyy হল আপনার এজেন্ট ইঞ্জিন রিসোর্স আইডি

AgentEngine created. Resource name: projects/xxxx/locations/us-central1/reasoningEngines/yyyy
To use this AgentEngine in another session:
agent_engine = vertexai.agent_engines.get('projects/xxxx/locations/us-central1/reasoningEngines/yyyy)
Deployed remote app resource: projects/xxxx/locations/us-central1/reasoningEngines/xxxx

এবং যখন আমরা এজেন্ট ইঞ্জিন ড্যাশবোর্ডে এটি পরিদর্শন করি, (সার্চ বারে "এজেন্ট ইঞ্জিন" অনুসন্ধান করুন) এটি আমাদের পূর্ববর্তী স্থাপনা দেখাবে

29738fbf7e5f5ecc.png

এজেন্ট ইঞ্জিনে নিয়োজিত এজেন্ট পরীক্ষা করা হচ্ছে

এজেন্ট ইঞ্জিনের সাথে মিথস্ক্রিয়া curl কমান্ড এবং SDK এর মাধ্যমে করা যেতে পারে। উদাহরণস্বরূপ, নিয়োজিত এজেন্টের সাথে মিথস্ক্রিয়া করার চেষ্টা করতে নিম্নলিখিত কমান্ডটি চালান।

এজেন্ট সফলভাবে মোতায়েন করা হয়েছে কিনা তা পরীক্ষা করতে আপনি এই ক্যোয়ারী পাঠানোর চেষ্টা করতে পারেন

curl \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://us-central1-aiplatform.googleapis.com/v1/projects/{YOUR_PROJECT_ID}/locations/us-central1/reasoningEngines/{YOUR_AGENT_ENGINE_RESOURCE_ID}:streamQuery?alt=sse -d '{
  "class_method": "stream_query",
  "input": {
    "user_id": "user_123",
    "message": "List available burger menu please",
  }
}'

সফল হলে এটি আপনার কনসোলে এইভাবে স্ট্রিম করা বেশ কয়েকটি প্রতিক্রিয়া ইভেন্ট দেখাবে

{
  "content": {
    "parts": [
      {
        "text": "Here is our burger menu:\n- Classic Cheeseburger: IDR 85K\n- Double Cheeseburger: IDR 110K\n- Spicy Chicken Burger: IDR 80K\n- Spicy Cajun Burger: IDR 85K"
      }
    ],
    "role": "model"
  },
  "usage_metadata": {
    "candidates_token_count": 51,
    "candidates_tokens_details": [
      {
        "modality": "TEXT",
        "token_count": 51
      }
    ],
    "prompt_token_count": 907,
    "prompt_tokens_details": [
      {
        "modality": "TEXT",
        "token_count": 907
      }
    ],
    "total_token_count": 958,
    "traffic_type": "ON_DEMAND"
  },
  "invocation_id": "e-14679918-af68-45f1-b942-cf014368a733",
  "author": "purchasing_agent",
  "actions": {
    "state_delta": {},
    "artifact_delta": {},
    "requested_auth_configs": {}
  },
  "id": "dbe7fc43-b82a-4f3e-82aa-dd97afa8f15b",
  "timestamp": 1754287348.941454
}

আমরা পরবর্তী ধাপে UI ব্যবহার করার চেষ্টা করব, তবে প্রথমে A2A ক্লায়েন্টের মূল উপাদান এবং সাধারণ প্রবাহ কী তা নিয়ে আলোচনা করা যাক।

6. A2A ক্লায়েন্টের মূল উপাদান

aa6c8bc5b5df73f1.jpeg

উপরে দেখানো চিত্রটি A2A মিথস্ক্রিয়াগুলির সাধারণ প্রবাহ:

  1. ক্লায়েন্ট /.well-known/agent.json রুটে প্রদত্ত রিমোট এজেন্ট URL-এ কোনো প্রকাশিত এজেন্ট কার্ড খোঁজার চেষ্টা করবে
  2. তারপর, যখন প্রয়োজন হবে তখন এটি সেই এজেন্টকে বার্তা এবং প্রয়োজনীয় মেটাডেটা প্যারামিটার সহ একটি বার্তা পাঠাবে (যেমন সেশন আইডি, ঐতিহাসিক প্রসঙ্গ, ইত্যাদি)। সার্ভার এই মেসেজটিকে একটি টাস্ক হিসেবে বুঝবে
  3. A2A সার্ভার অনুরোধটি প্রক্রিয়া করে, যদি সার্ভার পুশ বিজ্ঞপ্তি সমর্থন করে, তবে এটি পুরো টাস্ক প্রসেসিং জুড়ে কিছু বিজ্ঞপ্তি প্রকাশ করতে সক্ষম হবে (এই কার্যকারিতা এই কোডল্যাবের সুযোগের বাইরে)
  4. সমাপ্ত হওয়ার পরে, A2A সার্ভার ক্লায়েন্টের কাছে প্রতিক্রিয়া আর্টিফ্যাক্টটি ফেরত পাঠাবে

উপরের মিথস্ক্রিয়াগুলির জন্য কিছু মূল বস্তু হল এই আইটেমগুলি (আরও বিশদ এখানে পড়া যাবে):

  • বার্তা: একটি ক্লায়েন্ট এবং একটি দূরবর্তী এজেন্টের মধ্যে যোগাযোগের মোড়
  • কাজ : A2A দ্বারা পরিচালিত কাজের মৌলিক একক, একটি অনন্য আইডি দ্বারা চিহ্নিত
  • আর্টিফ্যাক্ট: একটি আউটপুট (যেমন, একটি ডকুমেন্ট, ইমেজ, স্ট্রাকচার্ড ডেটা) একটি টাস্কের ফলে এজেন্ট দ্বারা উত্পন্ন, অংশগুলি নিয়ে গঠিত
  • অংশ: একটি বার্তা বা আর্টিফ্যাক্টের মধ্যে সামগ্রীর ক্ষুদ্রতম একক। অংশটি একটি পাঠ্য, চিত্র, ভিডিও, ফাইল ইত্যাদি হতে পারে।

কার্ড আবিষ্কার

যখন A2A ক্লায়েন্ট পরিষেবা চালু করা হচ্ছে, সাধারণ প্রক্রিয়া হল এজেন্ট কার্ডের তথ্য পেতে চেষ্টা করা এবং প্রয়োজনের সময় সহজেই অ্যাক্সেস করার জন্য এটি সংরক্ষণ করা। এই কোডল্যাবে, আমরা before_agent_callback এ এটি বাস্তবায়ন করি, আপনি purchasing_concierge/purchasing_agent.py এ বাস্তবায়ন দেখতে পারেন নীচের কোড স্নিপেটটি দেখুন

...

async def before_agent_callback(self, callback_context: CallbackContext):
        if not self.a2a_client_init_status:
            httpx_client = httpx.AsyncClient(timeout=httpx.Timeout(timeout=30))
            for address in self.remote_agent_addresses:
                card_resolver = A2ACardResolver(
                    base_url=address, httpx_client=httpx_client
                )
                try:
                    card = await card_resolver.get_agent_card()
                    remote_connection = RemoteAgentConnections(
                        agent_card=card, agent_url=card.url
                    )
                    self.remote_agent_connections[card.name] = remote_connection
                    self.cards[card.name] = card
                except httpx.ConnectError:
                    print(f"ERROR: Failed to get agent card from : {address}")
            agent_info = []
            for ra in self.list_remote_agents():
                agent_info.append(json.dumps(ra))
            self.agents = "\n".join(agent_info)

...

এখানে, আমরা বিল্ট-ইন A2A ক্লায়েন্ট A2ACardResolver মডিউল ব্যবহার করে সমস্ত উপলব্ধ এজেন্ট কার্ডগুলি অ্যাক্সেস করার চেষ্টা করি, তারপরে আমরা এজেন্টকে বার্তা পাঠানোর জন্য প্রয়োজনীয় সংযোগ সংগ্রহ করি, তারপরে আমাদের প্রম্পটে সমস্ত উপলব্ধ এজেন্ট এবং এর বৈশিষ্ট্যগুলি তালিকাভুক্ত করতে হবে যাতে আমাদের এজেন্ট সচেতন হয় যে এটি এই এজেন্টদের সাথে যোগাযোগ করতে পারে।

প্রম্পট এবং সেন্ড টাস্ক টুল

এটি হল প্রম্পট এবং টুল যা আমরা এখানে আমাদের ADK এজেন্টকে প্রদান করি

...

def root_instruction(self, context: ReadonlyContext) -> str:
    current_agent = self.check_active_agent(context)
    return f"""You are an expert purchasing delegator that can delegate the user product inquiry and purchase request to the
appropriate seller remote agents.

Execution:
- For actionable tasks, you can use `send_task` to assign tasks to remote agents to perform.
- When the remote agent is repeatedly asking for user confirmation, assume that the remote agent doesn't have access to user's conversation context. 
So improve the task description to include all the necessary information related to that agent
- Never ask user permission when you want to connect with remote agents. If you need to make connection with multiple remote agents, directly
connect with them without asking user permission or asking user preference
- Always show the detailed response information from the seller agent and propagate it properly to the user. 
- If the remote seller is asking for confirmation, rely the confirmation question to the user if the user haven't do so. 
- If the user already confirmed the related order in the past conversation history, you can confirm on behalf of the user
- Do not give irrelevant context to remote seller agent. For example, ordered pizza item is not relevant for the burger seller agent
- Never ask order confirmation to the remote seller agent 

Please rely on tools to address the request, and don't make up the response. If you are not sure, please ask the user for more details.
Focus on the most recent parts of the conversation primarily.

If there is an active agent, send the request to that agent with the update task tool.

Agents:
{self.agents}

Current active seller agent: {current_agent["active_agent"]}
"""

...

async def send_task(self, agent_name: str, task: str, tool_context: ToolContext):
        """Sends a task to remote seller agent

        This will send a message to the remote agent named agent_name.

        Args:
            agent_name: The name of the agent to send the task to.
            task: The comprehensive conversation context summary
                and goal to be achieved regarding user inquiry and purchase request.
            tool_context: The tool context this method runs in.

        Yields:
            A dictionary of JSON data.
        """
        if agent_name not in self.remote_agent_connections:
            raise ValueError(f"Agent {agent_name} not found")
        state = tool_context.state
        state["active_agent"] = agent_name
        client = self.remote_agent_connections[agent_name]
        if not client:
            raise ValueError(f"Client not available for {agent_name}")
        session_id = state["session_id"]
        task: Task
        message_id = ""
        metadata = {}
        if "input_message_metadata" in state:
            metadata.update(**state["input_message_metadata"])
            if "message_id" in state["input_message_metadata"]:
                message_id = state["input_message_metadata"]["message_id"]
        if not message_id:
            message_id = str(uuid.uuid4())

        payload = {
            "message": {
                "role": "user",
                "parts": [
                    {"type": "text", "text": task}
                ],  # Use the 'task' argument here
                "messageId": message_id,
                "contextId": session_id,
            },
        }

        message_request = SendMessageRequest(
            id=message_id, params=MessageSendParams.model_validate(payload)
        )
        send_response: SendMessageResponse = await client.send_message(
            message_request=message_request
        )
        print(
            "send_response",
            send_response.model_dump_json(exclude_none=True, indent=2),
        )

        if not isinstance(send_response.root, SendMessageSuccessResponse):
            print("received non-success response. Aborting get task ")
            return None

        if not isinstance(send_response.root.result, Task):
            print("received non-task response. Aborting get task ")
            return None

        return send_response.root.result

...

প্রম্পটে, আমরা আমাদের ক্রয়কারী দ্বারস্থ এজেন্টকে সমস্ত উপলব্ধ রিমোট এজেন্টের নাম এবং বিবরণ দেই এবং self.send_task টুলে আমরা এজেন্টের সাথে সংযোগ স্থাপনের জন্য উপযুক্ত ক্লায়েন্টকে পুনরুদ্ধার করার জন্য একটি প্রক্রিয়া প্রদান করি এবং SendMessageRequest অবজেক্ট ব্যবহার করে প্রয়োজনীয় মেটাডেটা পাঠাই।

যোগাযোগ প্রোটোকল

টাস্ক সংজ্ঞা হল একটি ডোমেন যা A2A সার্ভারের মালিকানাধীন। যাইহোক, A2A ক্লায়েন্টের দৃষ্টিকোণ থেকে, তারা এটিকে সার্ভারে পাঠানো একটি বার্তা হিসাবে দেখে, এটি সার্ভারের উপর নির্ভর করে কিভাবে ক্লায়েন্ট থেকে আগত বার্তাগুলিকে কোন টাস্ক হিসাবে সংজ্ঞায়িত করা যায় এবং টাস্কটি সম্পূর্ণ করার জন্য ক্লায়েন্টের কাছ থেকে মিথস্ক্রিয়া প্রয়োজন কিনা, আপনি এই ডকুমেন্টেশনে টাস্ক লাইফসাইকেল সম্পর্কে আরও বিশদ পড়তে পারেন। এটির উচ্চ স্তরের ধারণাটি নীচে কল্পনা করা যেতে পারে:

65b8878a4854fd93.jpeg

9ddfae690d40cbbf.jpeg

বার্তার এই আদান-প্রদান -> টাস্কটি JSON-RPC স্ট্যান্ডার্ডের উপরে পেলোড ফর্ম্যাট ব্যবহার করে প্রয়োগ করা হয়েছে যেমনটি message/send প্রোটোকলের নীচের উদাহরণে দেখানো হয়েছে:

{
  # identifier for this request
  "id": "abc123",
  # version of JSON-RPC protocol
  "jsonrpc": "2.0",
  # method name
  "method": "message/send",
  # parameters/arguments of the method
  "params": {
    "message": "hi, what can you help me with?"
  }  
}

বিভিন্ন পদ্ধতি উপলব্ধ রয়েছে, যেমন বিভিন্ন ধরনের যোগাযোগ সমর্থন করার জন্য (যেমন সিঙ্ক, স্ট্রিমিং, অ্যাসিঙ্ক) অথবা টাস্ক স্ট্যাটাসের জন্য বিজ্ঞপ্তি কনফিগার করা। A2A সার্ভার নমনীয়ভাবে এই টাস্ক সংজ্ঞা মানগুলি পরিচালনা করার জন্য কনফিগার করা যেতে পারে। এই পদ্ধতির বিশদ বিবরণ এই নথিতে পড়তে পারেন।

7. ইন্টিগ্রেশন টেস্টিং এবং পেলোড পরিদর্শন

এখন একটি ওয়েব UI ব্যবহার করে দূরবর্তী এজেন্ট মিথস্ক্রিয়া সহ আমাদের ক্রয় দ্বারস্থ পরিদর্শন করা যাক।

প্রথমে, আমাদের AGENT_ENGINE_RESOURCE_NAME এ আপডেট করতে হবে। env ফাইল। নিশ্চিত করুন যে আপনি সঠিক এজেন্ট ইঞ্জিন রিসোর্সের নাম প্রদান করেছেন। আপনার .env ফাইলটি এইরকম হওয়া উচিত:

GOOGLE_GENAI_USE_VERTEXAI=TRUE
GOOGLE_CLOUD_PROJECT={your-project-id}
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://purchasing-concierge-{your-project-id}
PIZZA_SELLER_AGENT_URL=https://pizza-agent-xxxxx.us-central1.run.app
BURGER_SELLER_AGENT_URL=https://burger-agent-xxxxx.us-central1.run.app
AGENT_ENGINE_RESOURCE_NAME=projects/xxxx/locations/us-central1/reasoningEngines/yyyy

এর পরে, একটি Gradio অ্যাপ স্থাপন করতে নিম্নলিখিত কমান্ডটি চালান

uv run purchasing_concierge_ui.py

সফল হলে এটি নিম্নলিখিত আউটপুট দেখাবে

* Running on local URL:  http://0.0.0.0:8080
* To create a public link, set `share=True` in `launch()`.

তারপর, Ctrl + টার্মিনালে http://0.0.0.0:8080 url এ ক্লিক করুন বা ওয়েব UI খুলতে ওয়েব প্রিভিউ বোতামে ক্লিক করুন

b38b428d9e4582bc.png

এই মত একটি কথোপকথন করার চেষ্টা করুন:

  • আমাকে বার্গার এবং পিজ্জা মেনু দেখান
  • আমি 1 bbq ​​চিকেন পিজ্জা এবং 1 মশলাদার কাজুন বার্গার অর্ডার করতে চাই

এবং আপনি অর্ডার শেষ না হওয়া পর্যন্ত কথোপকথন চালিয়ে যান। কিভাবে মিথস্ক্রিয়া চলছে এবং টুল কল এবং প্রতিক্রিয়া কি পরিদর্শন? নিম্নলিখিত চিত্রটি মিথস্ক্রিয়া ফলাফলের একটি উদাহরণ।

ff5f752965816b2b.png

6f65155c7a289964.png

b390f4b15f1c5a8c.png

ff44c54b50c36e1a.png

আমরা দেখতে পাচ্ছি যে 2টি ভিন্ন এজেন্টের সাথে যোগাযোগ করলে 2টি ভিন্ন আচরণ পাওয়া যায় এবং A2A এটিকে ভালোভাবে পরিচালনা করতে পারে। পিৎজা বিক্রেতা এজেন্ট সরাসরি আমাদের ক্রয়কারী এজেন্টের অনুরোধ গ্রহণ করে, যেখানে বার্গার এজেন্টকে আমাদের অনুরোধের সাথে এগিয়ে যাওয়ার আগে আমাদের নিশ্চিতকরণের প্রয়োজন হয় এবং আমরা নিশ্চিত করার পরে এজেন্ট বার্গার এজেন্টের কাছে নিশ্চিতকরণের উপর নির্ভর করতে পারে।

এখন, আমরা A2A এর প্রাথমিক ধারণাগুলি শেষ করেছি এবং এটি ক্লায়েন্ট এবং সার্ভার আর্কিটেকচার হিসাবে কীভাবে প্রয়োগ করা হয়েছে তা দেখুন।

8. চ্যালেঞ্জ

এখন, আপনি কি প্রয়োজনীয় ফাইল প্রস্তুত করতে এবং নিজের দ্বারা চালিত ক্লাউডে গ্র্যাডিও অ্যাপ স্থাপন করতে পারেন? চ্যালেঞ্জ নিতে সময়!

9. পরিষ্কার করুন

এই কোডল্যাবে ব্যবহৃত সংস্থানগুলির জন্য আপনার Google ক্লাউড অ্যাকাউন্টে চার্জ এড়াতে, এই পদক্ষেপগুলি অনুসরণ করুন:

  1. Google ক্লাউড কনসোলে, সম্পদ পরিচালনা পৃষ্ঠাতে যান।
  2. প্রকল্প তালিকায়, আপনি যে প্রকল্পটি মুছতে চান সেটি নির্বাচন করুন এবং তারপরে মুছুন ক্লিক করুন।
  3. ডায়ালগে, প্রজেক্ট আইডি টাইপ করুন এবং তারপরে প্রোজেক্ট মুছে ফেলতে শাট ডাউন ক্লিক করুন।
  4. বিকল্পভাবে আপনি কনসোলে ক্লাউড রানে যেতে পারেন, আপনি যে পরিষেবাটি স্থাপন করেছেন তা নির্বাচন করুন এবং মুছুন।