شروع به کار با پروتکل Agent2Agent (A2A): تعاملات دربان و فروشنده راه دور با Gemini در Cloud Run و Agent Engine

1. مقدمه

b013ad6b246401eb.png

پروتکل Agent2Agent (A2A) برای استانداردسازی ارتباطات بین عوامل هوش مصنوعی، به ویژه برای آنهایی که در سیستم های خارجی مستقر هستند، طراحی شده است. پیش از این، چنین پروتکل هایی برای ابزارهایی به نام پروتکل بافت مدل (MCP) ایجاد شده بود که یک استاندارد نوظهور برای اتصال LLM ها با داده ها و منابع است. A2A سعی می‌کند MCP را تکمیل کند، جایی که A2A روی یک مشکل متفاوت متمرکز است، در حالی که MCP بر کاهش پیچیدگی برای اتصال عوامل با ابزارها و داده‌ها تمرکز می‌کند، A2A بر نحوه فعال کردن عوامل برای همکاری در روش‌های طبیعی خود تمرکز می‌کند. این به عوامل اجازه می دهد تا به عنوان یک عامل (یا به عنوان کاربر) به جای ابزار ارتباط برقرار کنند. به عنوان مثال، هنگامی که می خواهید چیزی را سفارش دهید، ارتباط رفت و برگشت را فعال کنید.

A2A برای تکمیل MCP قرار گرفته است، در اسناد رسمی توصیه می‌شود که برنامه‌ها از MCP برای ابزارها و A2A برای عوامل استفاده کنند - که توسط AgentCard نشان داده می‌شود (در این مورد بعداً بحث خواهیم کرد). سپس فریم‌ورک‌ها می‌توانند از A2A برای برقراری ارتباط با کاربر خود، عوامل راه دور و سایر عوامل استفاده کنند.

83b1a03588b90b68.png

در این نسخه ی نمایشی، ما با پیاده سازی A2A با استفاده از SDK پایتون آن شروع می کنیم. زمانی که یک نگهبان خرید شخصی داشته باشیم، یک مورد استفاده را بررسی می کنیم که می تواند به ما کمک کند تا با نمایندگان فروش همبرگر و پیتزا برای رسیدگی به سفارشمان ارتباط برقرار کنیم.

A2A از اصل سرویس گیرنده-سرور استفاده می کند. در اینجا جریان معمولی A2A است که در این نسخه نمایشی انتظار خواهیم داشت

aa6c8bc5b5df73f1.jpeg

  1. کلاینت A2A ابتدا تمام کارت عامل A2A Server قابل دسترسی را کشف می کند و از اطلاعات آن برای ایجاد یک کلاینت اتصال استفاده می کند.
  2. در صورت نیاز، A2A Client پیامی را به سرور A2A ارسال می کند، سرور این را به عنوان یک کار برای تکمیل ارزیابی می کند. اگر URL گیرنده فشار اعلان روی کلاینت A2A پیکربندی شده باشد و توسط سرور A2A پشتیبانی شود، سرور همچنین می‌تواند وضعیت پیشرفت کار را به نقطه پایانی دریافت‌کننده روی کلاینت منتشر کند.
  3. پس از اتمام کار، سرور A2A آرتیفکت پاسخ را به مشتری A2A ارسال می کند

از طریق کد لبه، شما یک رویکرد گام به گام را به شرح زیر به کار خواهید گرفت:

  1. پروژه Google Cloud خود را آماده کنید و تمام API مورد نیاز را روی آن فعال کنید
  2. فضای کاری را برای محیط کدنویسی خود تنظیم کنید
  3. متغیرهای env را برای خدمات نمایندگی برگر و پیتزا آماده کنید و به صورت محلی امتحان کنید
  4. عامل برگر و پیتزا را در Cloud Run مستقر کنید
  5. جزئیات نحوه ایجاد سرور A2A را بررسی کنید
  6. متغیرهای env را برای خرید دربان آماده کنید و به صورت محلی امتحان کنید
  7. مستقر خرید نگهبان به Agent Engine
  8. از طریق رابط محلی به موتور عامل متصل شوید
  9. جزئیات نحوه ایجاد مشتری A2A و ​​مدل سازی داده های آن را بررسی کنید
  10. بار و تعامل بین کلاینت و سرور A2A را بررسی کنید

نمای کلی معماری

ما معماری سرویس زیر را مستقر خواهیم کرد

9cfc4582f2d8b6f3.jpeg

ما 2 سرویس را مستقر خواهیم کرد که به عنوان سرور A2A عمل می کنند، عامل Burger (با پشتیبانی چارچوب عامل CrewAI) و عامل Pizza (با پشتیبانی چارچوب عامل Langgraph). کاربر فقط مستقیماً با دربان خرید که با استفاده از چارچوب کیت توسعه عامل (ADK) اجرا می شود که به عنوان مشتری A2A عمل می کند، تعامل خواهد داشت.

هر یک از این عوامل محیط و استقرار خود را به تنهایی خواهند داشت.

پیش نیازها

  • کار راحت با پایتون
  • درک معماری پایه تمام پشته با استفاده از سرویس HTTP

چیزی که یاد خواهید گرفت

  • ساختار اصلی سرور A2A
  • ساختار اصلی مشتری A2A
  • استقرار سرویس عامل در Cloud Run
  • استقرار سرویس عامل به Agent Engine
  • نحوه اتصال کلاینت A2A به سرور A2A
  • ساختار درخواست و پاسخ در اتصال غیر جریانی

آنچه شما نیاز دارید

  • مرورگر وب کروم
  • یک اکانت جیمیل
  • یک پروژه Cloud با فعال کردن صورت‌حساب

این کد لبه که برای توسعه دهندگان همه سطوح (از جمله مبتدیان) طراحی شده است، از پایتون در برنامه نمونه خود استفاده می کند. با این حال، دانش پایتون برای درک مفاهیم ارائه شده مورد نیاز نیست.

2. قبل از شروع

Active Project را در Cloud Console انتخاب کنید

این کد لبه فرض می کند که شما قبلاً یک پروژه Google Cloud با فعال بودن صورتحساب دارید. اگر هنوز آن را ندارید، می توانید دستورالعمل های زیر را برای شروع دنبال کنید.

  1. در Google Cloud Console ، در صفحه انتخاب پروژه، یک پروژه Google Cloud را انتخاب یا ایجاد کنید.
  2. مطمئن شوید که صورتحساب برای پروژه Cloud شما فعال است. با نحوه بررسی فعال بودن صورت‌حساب در پروژه آشنا شوید.

bc8d176ea42fbb7.png

راه اندازی پروژه Cloud در ترمینال Cloud Shell

  1. شما از Cloud Shell استفاده خواهید کرد، یک محیط خط فرمان در حال اجرا در Google Cloud که با bq از قبل بارگذاری شده است. روی Activate Cloud Shell در بالای کنسول Google Cloud کلیک کنید. اگر از شما خواست که مجوز دهید، روی Authorize کلیک کنید

1829c3759227c19b.png

  1. پس از اتصال به Cloud Shell، با استفاده از دستور زیر بررسی می‌کنید که قبلاً احراز هویت شده‌اید و پروژه به ID پروژه شما تنظیم شده است:
gcloud auth list
  1. دستور زیر را در Cloud Shell اجرا کنید تا تأیید کنید که دستور 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 از دست رفته است، همیشه می توانید آن را در طول پیاده سازی فعال کنید.

برای دستورات و استفاده از gcloud به اسناد مراجعه کنید.

به Cloud Shell Editor and Setup Application Working Directory بروید

اکنون، می‌توانیم ویرایشگر کد خود را برای انجام برخی موارد کدنویسی تنظیم کنیم. برای این کار از Cloud Shell Editor استفاده خواهیم کرد

  1. روی دکمه Open Editor کلیک کنید، با این کار یک Cloud Shell Editor باز می شود، ما می توانیم کد خود را اینجا بنویسیم b16d56e4979ec951.png
  2. مطمئن شوید که پروژه Cloud Code در گوشه سمت چپ پایین (نوار وضعیت) ویرایشگر Cloud Shell تنظیم شده است، همانطور که در تصویر زیر مشخص شده است و روی پروژه فعال Google Cloud که در آن صورت‌حساب را فعال کرده‌اید، تنظیم شده است. در صورت درخواست مجوز دهید . اگر از قبل دستور قبلی را دنبال کرده اید، دکمه ممکن است به جای دکمه ورود مستقیماً به پروژه فعال شده شما اشاره کند

f5003b9c38b43262.png

  1. سپس، بیایید دایرکتوری کار قالب را برای این کد لبه از Github کلون کنیم، دستور زیر را اجرا کنیم. دایرکتوری کاری را در دایرکتوری purchasing-concierge-a2a ایجاد می کند
git clone https://github.com/alphinside/purchasing-concierge-intro-a2a-codelab-starter.git purchasing-concierge-a2a
  1. پس از آن، به بخش بالای Cloud Shell Editor بروید و روی File->Open Folder کلیک کنید، فهرست نام کاربری خود را پیدا کنید و دایرکتوری purchasing-concierge-a2a را پیدا کنید و سپس روی دکمه OK کلیک کنید. این دایرکتوری انتخاب شده را به عنوان دایرکتوری اصلی تبدیل می کند. در این مثال، نام کاربری alvinprayuda است، از این رو مسیر دایرکتوری در زیر نشان داده شده است

2c53696f81d805cc.png

253b472fa1bd752e.png

حال، ویرایشگر پوسته ابری شما باید به این شکل باشد

aedd0725db87717e.png

راه اندازی محیط

مرحله بعدی آماده سازی محیط توسعه است. ترمینال فعال فعلی شما باید در دایرکتوری کاری purchasing-concierge-a2a باشد. ما از Python 3.12 در این کد لبه استفاده خواهیم کرد و از مدیر پروژه uv python برای ساده سازی نیاز به ایجاد و مدیریت نسخه پایتون و محیط مجازی استفاده خواهیم کرد.

  1. اگر هنوز ترمینال را باز نکرده اید، آن را با کلیک بر روی Terminal -> New Terminal باز کنید یا از 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. استقرار Remote Seller Agent - A2A Server در Cloud Run

در این مرحله، این دو عامل فروشنده از راه دور که با کادر قرمز مشخص شده اند را مستقر می کنیم. عامل برگر توسط فریم ورک عامل CrewAI و عامل پیتزا توسط عامل Langgraph، هر دوی آنها توسط Gemini Flash 2.0 مدل طراحی شده اند.

e91777eecfbae4f7.png

استقرار Remote Burger Agent

کد منبع عامل برگر در دایرکتوری 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 وجود دارند، از قبل برای استقرار عامل ما در Cloud Run کافی هستند تا به عنوان یک سرویس قابل دسترسی باشد. بعداً در این مورد بحث خواهیم کرد. دستور زیر را برای استقرار آن اجرا کنید

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 است.

در صورت استقرار موفقیت آمیز، هنگام دسترسی به https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json ، پاسخی مانند شکل زیر را در مرورگر خود مشاهده خواهید کرد:

72fdf3f52b5e8313.png

این اطلاعات کارت عامل همبرگر است که باید برای اهداف کشف در دسترس باشد. بعداً در این مورد بحث خواهیم کرد. توجه داشته باشید که مقدار url همچنان در http://0.0.0.0:8080/ در اینجا تنظیم شده است. این مقدار url باید اطلاعات اصلی A2A Client برای ارسال پیام از دنیای خارج باشد و به درستی پیکربندی نشده است. برای این نسخه نمایشی، باید با افزودن یک متغیر محیطی اضافی HOST_OVERRIDE ، این مقدار را به URL سرویس عامل همبرگر خود به‌روزرسانی کنیم.

به روز رسانی ارزش URL عامل Burger در کارت نماینده از طریق متغیر Environment

برای افزودن HOST_OVERRIDE به سرویس نمایندگی همبرگر، مراحل زیر را انجام دهید

  1. Search Cloud در نوار جستجو در بالای کنسول ابری خود اجرا کنید

1adde569bb345b48.png

  1. روی سرویس اجرای ابری عامل همبرگر که قبلاً مستقر شده بود کلیک کنید

9091c12526fb7f41.png

  1. URL سرویس همبرگر را کپی کنید، سپس روی Edit کلیک کنید و نسخه جدید را اجرا کنید

2701da8b124793b9.png

  1. سپس بر روی قسمت Variable & Secrets کلیک کنید

31ea00e12134d74d.png

  1. پس از آن، روی افزودن متغیر کلیک کنید و مقدار HOST_OVERRIDE را روی URL سرویس تنظیم کنید (الگوی https://burger-agent-xxxxxxxxx.us-central1.run.app )

52b382da7cf33cd5.png

  1. در نهایت، روی دکمه deploy کلیک کنید تا سرویس شما مجدداً راه اندازی شود

11464f4a51ffe54.png

اکنون، وقتی دوباره به کارت عامل همبرگر در مرورگر https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json دسترسی پیدا می کنید، مقدار url قبلاً به درستی پیکربندی می شود.

2ed7ebcb530f070a.png

استقرار Remote Pizza Agent

به طور مشابه، کد منبع عامل پیتزا در دایرکتوری 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 وجود دارند، از قبل برای استقرار عامل ما در Cloud Run کافی هستند تا به عنوان یک سرویس قابل دسترسی باشد. دستور زیر را برای استقرار آن اجرا کنید

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 در اینجا یک شناسه منحصر به فرد زمانی که سرویس را اجرا می کنیم خواهد بود. در مورد عامل همبرگر هم همینطور است، وقتی می‌خواهید به مسیر https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json از طریق مرورگر بروید تا به کارت عامل سرور A2A دسترسی پیدا کنید، نشانی url نماینده پیتزا هنوز بر روی کارت نماینده آن مطابقت ندارد. همچنین باید HOST_OVERRIDE به متغیر محیطی آن اضافه کنیم

به روز رسانی مقدار URL نماینده پیتزا در کارت نماینده از طریق متغیر محیطی

برای افزودن HOST_OVERRIDE به سرویس نمایندگی پیتزا، مراحل زیر را انجام دهید

  1. Search Cloud در نوار جستجو در بالای کنسول ابری خود اجرا کنید

1adde569bb345b48.png

  1. روی سرویس اجرای ابری پیتزا-عامل قبلاً مستقر شده کلیک کنید

5743b0aa0555741f.png

  1. روی Edit کلیک کنید و نسخه جدید را گسترش دهید

d60ba267410183be.png

  1. URL سرویس پیتزا را کپی کنید، سپس بر روی قسمت Variable & Secrets کلیک کنید

618e9da2f94ed415.png

  1. پس از آن، روی Add متغیر کلیک کنید و مقدار HOST_OVERRIDE را روی URL سرویس تنظیم کنید (یکی با الگوی https://pizza-agent-xxxxxxxxx.us-central1.run.app )

214a6eb98f877e65.png

  1. در نهایت، روی دکمه deploy کلیک کنید تا سرویس شما مجدداً راه اندازی شود

11464f4a51ffe54.png

اکنون، وقتی دوباره به کارت نماینده پیتزا در مرورگر https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json دسترسی پیدا می کنید، مقدار url قبلاً به درستی پیکربندی شده است.

c37b26ec80c821b6.png

در این مرحله، ما هم‌اکنون خدمات همبرگر و پیتزا را با موفقیت در Cloud Run پیاده‌سازی کرده‌ایم. حالا بیایید اجزای اصلی سرور A2A را مورد بحث قرار دهیم

4. اجزای اصلی سرور A2A

حالا بیایید در مورد مفهوم اصلی و اجزای سرور A2A بحث کنیم

کارت نماینده

هر یک از سرورهای A2A باید یک کارت عامل داشته باشد که در منبع /.well-known/agent.json قابل دسترسی باشد. این برای پشتیبانی از مرحله کشف در مشتری A2A است، که باید اطلاعات و زمینه های کاملی در مورد نحوه دسترسی به عامل و دانستن همه قابلیت های آن ارائه دهد. این به نوعی مشابه با اسناد API مستند شده با استفاده از Swagger یا Postman است.

این محتوای کارت نماینده همبرگر مستقر ما است

{
  "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 python 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 را در مرحله قبل اضافه کنیم.

Task Queue و Agent Execuor

سرور A2A ممکن است درخواست های نمایندگان یا کاربران مختلف را مدیریت کند و بتواند هر کار را کاملاً ایزوله کند. برای تجسم بهتر زمینه های اینها، می توانید تصویر زیر را بررسی کنید

b9eb6b4025db4642.jpeg

بنابراین، هر سرور A2A باید بتواند وظایف ورودی را ردیابی کرده و اطلاعات مناسب در مورد آن را ذخیره کند. A2A SDK ماژول هایی برای رفع این چالش در سرور A2A فراهم می کند. ابتدا، می‌توانیم منطق را در مورد نحوه رسیدگی به درخواست دریافتی مثال بزنیم. با به ارث بردن از کلاس انتزاعی 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())

...

در کد بالا، ما یک طرح پردازش اولیه را پیاده‌سازی می‌کنیم که در آن عامل به‌طور مستقیم هنگام درخواست دریافتی فراخوانی می‌شود و رویدادهای وظیفه تکمیل‌شده را پس از پایان فراخوانی ارسال می‌کند. با این حال، ما روش لغو را در اینجا اجرا نکردیم زیرا به عنوان یک عملیات در حال اجرا کوتاه در نظر گرفته شد.

پس از ساختن اجراکننده، می‌توانیم مستقیماً از DefaultRequestHandler داخلی، InMemoryTaskStore و A2AStarletteApplication برای چرخش سرور HTTP استفاده کنیم. این پیاده سازی را می توان در 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 را برای دسترسی به کارت عامل و همچنین نقطه پایانی POST برای پشتیبانی از پروتکل A2A در اختیار شما قرار می دهد.

خلاصه

به طور خلاصه، تا کنون سرور A2A ما با استفاده از Python SDK مستقر شده است که می تواند از 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 Agent Engine مجموعه‌ای از خدمات است که توسعه‌دهندگان را قادر می‌سازد تا عوامل هوش مصنوعی را در تولید مستقر کنند، مدیریت کنند و مقیاس دهند. این زیرساخت را برای مقیاس بندی عوامل در تولید مدیریت می کند تا بتوانیم روی ایجاد برنامه ها تمرکز کنیم. در این سند می توانید اطلاعات بیشتری در این مورد بخوانید. اگر قبلاً نیاز به تهیه فایل‌های مورد نیاز برای استقرار سرویس عامل خود داشته باشیم (مانند اسکریپت سرور اصلی و Dockerfile)، در این صورت می‌توانیم عامل خود را مستقیماً از اسکریپت پایتون بدون نیاز به توسعه سرویس پشتیبان خود با استفاده از ترکیبی از ADK و Agent Engine مستقر کنیم. برای استقرار آن این مراحل را دنبال کنید:

  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 اجرای Cloud از مراحل قبلی به‌روزرسانی کنیم.

اگر این موضوع را فراموش کردید، بیایید از کنسول Cloud Run دیدن کنیم. "Cloud Run" را در نوار جستجوی بالای کنسول خود تایپ کنید و روی نماد Cloud Run کلیک راست کنید تا در یک تب جدید باز شود.

1adde569bb345b48.png

شما باید خدمات عامل فروشنده راه دور مستقر قبلی ما را مانند شکل زیر ببینید

179e55cc095723a8.png

اکنون برای مشاهده 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 ما در موتور عامل لازم است. ابتدا باید یک شی AdkApp از ADK root_agent خود ایجاد کنیم. سپس می‌توانیم متد agent_engines.create را با ارائه شی adk_app ، مشخص کردن الزامات در قسمت requirements ، مشخص کردن مسیر دایرکتوری agent در 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

تست Deployed Agent در Agent Engine

تعامل با موتور عامل می تواند از طریق دستور 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. مشتری سعی می کند هر کارت عامل منتشر شده را در URL عامل راه دور ارائه شده در مسیر /.well-known/agent.json پیدا کند.
  2. سپس، در صورت لزوم، پیامی با پیام و پارامترهای فراداده لازم (مثلاً شناسه جلسه، زمینه تاریخی و غیره) برای آن عامل ارسال می کند. سرور این پیام را به عنوان یک کار برای تکمیل درک خواهد کرد
  3. سرور A2A درخواست را پردازش می‌کند، اگر سرور از اعلان‌های فشاری پشتیبانی کند، همچنین می‌تواند برخی از اعلان‌ها را در طول پردازش کار منتشر کند (این عملکرد خارج از محدوده این نرم‌افزار است).
  4. پس از اتمام، سرور A2A آرتیفکت پاسخ را برای مشتری ارسال می کند

برخی از اشیاء اصلی برای تعاملات فوق این موارد هستند (جزئیات بیشتر را می توانید در اینجا بخوانید ):

  • پیام: یک چرخش ارتباطی بین یک مشتری و یک عامل راه دور
  • وظیفه : واحد اساسی کار که توسط A2A مدیریت می شود و با یک شناسه منحصر به فرد مشخص می شود
  • مصنوع: خروجی (به عنوان مثال، یک سند، تصویر، داده های ساختاریافته) که توسط عامل در نتیجه یک کار تولید می شود، که از قطعات تشکیل شده است.
  • قسمت: کوچکترین واحد محتوا در یک پیام یا مصنوع. بخش می تواند متن، تصویر، ویدئو، فایل و غیره باشد.

کشف کارت

هنگامی که سرویس A2A Client در حال توسعه است، فرآیند معمولی این است که سعی کنید اطلاعات کارت نماینده را دریافت کنید و آن را ذخیره کنید تا در صورت نیاز به راحتی به آن دسترسی داشته باشید. در این کد لبه، ما آن را در 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 Client A2ACardResolver به تمام کارت‌های عامل موجود دسترسی پیدا کنیم، سپس اتصال مورد نیاز برای ارسال پیام به نماینده را جمع‌آوری می‌کنیم، پس از آن نیز باید تمام عامل موجود و مشخصات آن را در اعلان فهرست کنیم تا نماینده ما آگاه باشد که می‌تواند با این عوامل ارتباط برقرار کند.

اعلان و ارسال Task Tool

این اعلان و ابزاری است که ما در اینجا در اختیار نماینده 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 ارائه می‌کنیم.

پروتکل های ارتباطی

تعریف Task دامنه ای است که متعلق به سرور 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. تست یکپارچه سازی و بازرسی بار

اکنون اجازه دهید دربان خرید خود را با تعامل نماینده راه دور با استفاده از یک رابط کاربری وب بررسی کنیم.

ابتدا، باید 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 در ترمینال کلیک کنید یا روی دکمه پیش نمایش وب کلیک کنید تا رابط کاربری وب باز شود.

b38b428d9e4582bc.png

سعی کنید مکالمه ای مانند این داشته باشید:

  • منوی برگر و پیتزا را به من نشان دهید
  • من می خواهم 1 پیتزا مرغ کباب پز و 1 برگر کاجون تند سفارش بدهم

و مکالمه را تا پایان سفارش ادامه دهید. بررسی کنید که تعامل چگونه پیش می رود و فراخوانی و پاسخ ابزار چیست؟ تصویر زیر نمونه ای از نتیجه تعامل است.

ff5f752965816b2b.png

6f65155c7a289964.png

b390f4b15f1c5a8c.png

ff44c54b50c36e1a.png

می بینیم که برقراری ارتباط با 2 عامل مختلف، 2 رفتار متفاوت را به همراه دارد و A2A می تواند به خوبی از عهده این امر برآید. نماینده فروشنده پیتزا مستقیماً درخواست نماینده خرید ما را می‌پذیرد، در حالی که نماینده همبرگر قبل از ادامه درخواست ما به تأیید ما نیاز دارد و پس از تأیید ما، نماینده می‌تواند تأییدیه را به نمایندگی برگر تکیه کند.

اکنون، مفاهیم اولیه A2A را به پایان رسانده ایم و می بینیم که چگونه به عنوان معماری مشتری و سرور پیاده سازی می شود

8. چالش

حالا، آیا می‌توانید فایل لازم را آماده کنید و اپلیکیشن Gradio را در فضای ابری که توسط خودتان اجرا می‌شود، مستقر کنید؟ وقت آن است که چالش را انجام دهید!

9. پاکسازی کنید

برای جلوگیری از تحمیل هزینه به حساب Google Cloud خود برای منابع مورد استفاده در این Codelab، این مراحل را دنبال کنید:

  1. در کنسول Google Cloud، به صفحه مدیریت منابع بروید.
  2. در لیست پروژه، پروژه ای را که می خواهید حذف کنید انتخاب کنید و سپس روی Delete کلیک کنید.
  3. در محاوره، شناسه پروژه را تایپ کنید و سپس روی Shut down کلیک کنید تا پروژه حذف شود.
  4. یا می‌توانید به Cloud Run در کنسول بروید، سرویسی را که به تازگی مستقر کرده‌اید انتخاب کرده و حذف کنید.