Bắt đầu sử dụng Giao thức đại lý với đại lý (A2A): Tương tác giữa nhân viên hỗ trợ mua hàng và nhân viên bán hàng từ xa với Gemini trên Cloud Run và Agent Engine

1. Giới thiệu

b013ad6b246401eb.png

Giao thức giữa các tác nhân (A2A) được thiết kế để chuẩn hoá hoạt động giao tiếp giữa các tác nhân AI, đặc biệt là những tác nhân được triển khai trong các hệ thống bên ngoài. Trước đây, những giao thức như vậy được thiết lập cho Công cụ có tên là Giao thức ngữ cảnh mô hình (MCP). Đây là một tiêu chuẩn mới nổi để kết nối các LLM với dữ liệu và tài nguyên. A2A cố gắng bổ sung cho MCP, trong đó A2A tập trung vào một vấn đề khác, còn MCP tập trung vào việc giảm độ phức tạp để kết nối các tác nhân với công cụ và dữ liệu, A2A tập trung vào cách cho phép các tác nhân cộng tác theo phương thức tự nhiên của họ. Việc này cho phép các trợ lý giao tiếp với tư cách là trợ lý (hoặc với tư cách là người dùng) thay vì với tư cách là công cụ; ví dụ: cho phép giao tiếp qua lại khi bạn muốn đặt hàng.

A2A được thiết kế để bổ sung cho MCP. Trong tài liệu chính thức, các ứng dụng nên sử dụng MCP cho các công cụ và A2A cho các tác nhân – được biểu thị bằng AgentCard ( Chúng ta sẽ thảo luận về vấn đề này sau). Sau đó, các khung có thể sử dụng A2A để giao tiếp với người dùng, các tác nhân từ xa và các tác nhân khác.

83b1a03588b90b68.png

Trong bản minh hoạ này, chúng ta sẽ bắt đầu bằng việc triển khai A2A bằng SDK Python. Chúng ta sẽ khám phá một trường hợp sử dụng khi có một trợ lý mua hàng cá nhân có thể giúp chúng ta giao tiếp với các đại lý bán bánh mì kẹp thịt và pizza để xử lý đơn đặt hàng.

A2A sử dụng nguyên tắc máy chủ-máy khách. Sau đây là quy trình A2A điển hình mà chúng ta sẽ thấy trong bản minh hoạ này

aa6c8bc5b5df73f1.jpeg

  1. Trước tiên, A2A Client sẽ khám phá tất cả thẻ tác nhân A2A Server có thể truy cập và sử dụng thông tin của thẻ đó để tạo một ứng dụng kết nối
  2. Khi cần, A2A Client sẽ gửi một thông báo đến A2A Server. Máy chủ sẽ đánh giá thông báo này là một Việc cần làm. Nếu URL của trình nhận thông báo đẩy được định cấu hình trên ứng dụng A2A và được Máy chủ A2A hỗ trợ, thì máy chủ cũng có thể xuất bản trạng thái tiến trình của tác vụ đến điểm cuối nhận trên ứng dụng
  3. Sau khi hoàn tất tác vụ, máy chủ A2A sẽ gửi phản hồi đến A2A Client

Trong lớp học lập trình này, bạn sẽ sử dụng phương pháp từng bước như sau:

  1. Chuẩn bị dự án Google Cloud và Bật tất cả API bắt buộc trên dự án đó
  2. Thiết lập không gian làm việc cho môi trường lập trình
  3. Chuẩn bị các biến môi trường cho các dịch vụ tác nhân bánh mì kẹp thịt và bánh pizza, đồng thời thử cục bộ
  4. Triển khai tác nhân bánh mì kẹp thịt và pizza lên Cloud Run
  5. Kiểm tra thông tin chi tiết về cách thiết lập máy chủ A2A
  6. Chuẩn bị các biến môi trường cho trợ lý mua hàng và thử cục bộ
  7. Triển khai trợ lý mua hàng cho Agent Engine
  8. Kết nối với công cụ tác nhân thông qua giao diện cục bộ
  9. Kiểm tra thông tin chi tiết về cách thiết lập ứng dụng A2A và mô hình hoá dữ liệu
  10. Kiểm tra tải trọng và hoạt động tương tác giữa máy khách và máy chủ A2A

Tổng quan về cấu trúc

Chúng tôi sẽ triển khai cấu trúc dịch vụ sau

9cfc4582f2d8b6f3.jpeg

Chúng ta sẽ triển khai 2 dịch vụ đóng vai trò là máy chủ A2A, tác nhân Burger ( được hỗ trợ bởi khung tác nhân CrewAI) và tác nhân Pizza ( được hỗ trợ bởi khung tác nhân Langgraph). Người dùng sẽ chỉ tương tác trực tiếp với nhân viên hỗ trợ mua hàng được chạy bằng khung Agent Development Kit (ADK) và đóng vai trò là ứng dụng A2A.

Mỗi tác nhân này sẽ có môi trường và hoạt động triển khai riêng.

Điều kiện tiên quyết

  • Thoải mái làm việc với Python
  • Hiểu biết về cấu trúc cơ bản của ngăn xếp đầy đủ bằng cách sử dụng dịch vụ HTTP

Kiến thức bạn sẽ học được

  • Cấu trúc cốt lõi của Máy chủ A2A
  • Cấu trúc cốt lõi của Ứng dụng A2A
  • Triển khai dịch vụ tác nhân lên Cloud Run
  • Triển khai dịch vụ tác nhân cho Agent Engine
  • Cách A2A Client kết nối với A2A Server
  • Cấu trúc yêu cầu và phản hồi trên kết nối không phát trực tuyến

Bạn cần có

  • Trình duyệt web Chrome
  • Tài khoản Gmail
  • Một Dự án trên đám mây đã bật tính năng thanh toán

Lớp học lập trình này được thiết kế cho nhà phát triển ở mọi cấp độ (kể cả người mới bắt đầu), sử dụng Python trong ứng dụng mẫu. Tuy nhiên, bạn không cần có kiến thức về Python để hiểu các khái niệm được trình bày.

2. Trước khi bắt đầu

Chọn dự án đang hoạt động trong Cloud Console

Lớp học lập trình này giả định rằng bạn đã có một dự án trên Google Cloud đã bật tính năng thanh toán. Nếu chưa có, bạn có thể làm theo hướng dẫn bên dưới để bắt đầu.

  1. Trong Google Cloud Console, trên trang chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud.
  2. Đảm bảo bạn đã bật tính năng thanh toán cho dự án trên Cloud. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trên một dự án hay không.

bc8d176ea42fbb7.png

Thiết lập dự án trên Cloud trong thiết bị đầu cuối Cloud Shell

  1. Bạn sẽ sử dụng Cloud Shell, một môi trường dòng lệnh chạy trong Google Cloud và được tải sẵn bằng bq. Nhấp vào biểu tượng Kích hoạt Cloud Shell ở đầu bảng điều khiển Google Cloud. Nếu hệ thống nhắc bạn uỷ quyền, hãy nhấp vào Uỷ quyền

1829c3759227c19b.png

  1. Sau khi kết nối với Cloud Shell, bạn có thể kiểm tra để đảm bảo rằng bạn đã được xác thực và dự án được đặt thành mã dự án của bạn bằng lệnh sau:
gcloud auth list
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn.
gcloud config list project
  1. Nếu bạn chưa đặt dự án, hãy dùng lệnh sau để đặt dự án:
gcloud config set project <YOUR_PROJECT_ID>

Ngoài ra, bạn cũng có thể xem mã PROJECT_ID trong bảng điều khiển

4032c45803813f30.jpeg

Nhấp vào đó, bạn sẽ thấy tất cả dự án và mã dự án ở bên phải

8dc17eb4271de6b5.jpeg

  1. Bật các API bắt buộc thông qua lệnh bên dưới. Quá trình này có thể mất vài phút, vì vậy, vui lòng kiên nhẫn chờ đợi.
gcloud services enable aiplatform.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       cloudresourcemanager.googleapis.com

Khi thực thi lệnh thành công, bạn sẽ thấy một thông báo tương tự như thông báo dưới đây:

Operation "operations/..." finished successfully.

Bạn có thể thay thế lệnh gcloud bằng cách tìm kiếm từng sản phẩm trên bảng điều khiển hoặc sử dụng đường liên kết này.

Nếu bỏ lỡ API nào, bạn luôn có thể bật API đó trong quá trình triển khai.

Tham khảo tài liệu để biết các lệnh và cách sử dụng gcloud.

Chuyển đến Cloud Shell Editor và thiết lập thư mục làm việc của ứng dụng

Bây giờ, chúng ta có thể thiết lập trình chỉnh sửa mã để thực hiện một số việc liên quan đến mã hoá. Chúng ta sẽ sử dụng Trình chỉnh sửa Cloud Shell cho việc này

  1. Nhấp vào nút Open Editor (Mở trình chỉnh sửa). Thao tác này sẽ mở Cloud Shell Editor. Chúng ta có thể viết mã tại đây b16d56e4979ec951.png
  2. Đảm bảo dự án Cloud Code được đặt ở góc dưới bên trái (thanh trạng thái) của trình chỉnh sửa Cloud Shell, như được đánh dấu trong hình bên dưới và được đặt thành dự án Google Cloud đang hoạt động mà bạn đã bật tính năng thanh toán. Uỷ quyền nếu được nhắc. Nếu bạn đã làm theo lệnh trước đó, nút này cũng có thể trỏ trực tiếp đến dự án đã kích hoạt của bạn thay vì nút đăng nhập

f5003b9c38b43262.png

  1. Tiếp theo, hãy sao chép thư mục làm việc của mẫu cho lớp học lập trình này từ GitHub bằng cách chạy lệnh sau. Thao tác này sẽ tạo thư mục đang hoạt động trong thư mục purchasing-concierge-a2a
git clone https://github.com/alphinside/purchasing-concierge-intro-a2a-codelab-starter.git purchasing-concierge-a2a
  1. Sau đó, hãy chuyển đến phần trên cùng của Cloud Shell Editor rồi nhấp vào File->Open Folder (Tệp->Mở thư mục), tìm thư mục username (tên người dùng) của bạn, tìm thư mục purchasing-concierge-a2a (trợ lý mua hàng a2a) rồi nhấp vào nút OK. Thao tác này sẽ đặt thư mục đã chọn làm thư mục làm việc chính. Trong ví dụ này, tên người dùng là alvinprayuda, do đó, đường dẫn thư mục được hiển thị bên dưới

2c53696f81d805cc.png

253b472fa1bd752e.png

Giờ đây, Cloud Shell Editor sẽ có dạng như sau

aedd0725db87717e.png

Thiết lập môi trường

Bước tiếp theo là chuẩn bị môi trường phát triển. Thiết bị đầu cuối đang hoạt động hiện tại của bạn phải nằm trong thư mục làm việc purchasing-concierge-a2a. Chúng ta sẽ sử dụng Python 3.12 trong lớp học lập trình này và sử dụng trình quản lý dự án uv python để đơn giản hoá nhu cầu tạo và quản lý phiên bản python cũng như môi trường ảo

  1. Nếu bạn chưa mở cửa sổ dòng lệnh, hãy mở bằng cách nhấp vào Terminal (Cửa sổ dòng lệnh) -> New Terminal (Cửa sổ dòng lệnh mới) hoặc sử dụng tổ hợp phím Ctrl + Shift + C. Thao tác này sẽ mở một cửa sổ dòng lệnh ở phần dưới cùng của trình duyệt

f8457daf0bed059e.jpeg

  1. Bây giờ, hãy khởi tạo môi trường ảo của nhân viên hỗ trợ mua hàng bằng cách sử dụng uv (đã được cài đặt sẵn trên thiết bị đầu cuối đám mây). Chạy lệnh này
uv sync --frozen

Thao tác này sẽ tạo thư mục .venv và cài đặt các phần phụ thuộc. Xem nhanh pyproject.toml sẽ cung cấp cho bạn thông tin về các phần phụ thuộc xuất hiện như sau

dependencies = [
    "a2a-sdk>=0.2.16",
    "google-adk>=1.8.0",
    "gradio>=5.38.2",
]
  1. Để kiểm thử môi trường ảo, hãy tạo tệp mới main.py rồi sao chép mã sau
def main():
   print("Hello from purchasing-concierge-a2a!")

if __name__ == "__main__":
   main()
  1. Sau đó, hãy chạy lệnh sau
uv run main.py

Bạn sẽ nhận được kết quả đầu ra như minh hoạ bên dưới

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

Điều này cho thấy dự án Python đang được thiết lập đúng cách.

Bây giờ, chúng ta có thể chuyển sang bước tiếp theo, định cấu hình và triển khai tác nhân bán hàng từ xa

3. Triển khai Agent của người bán từ xa – Máy chủ A2A đến Cloud Run

Trong bước này, chúng ta sẽ triển khai 2 tác nhân bán hàng từ xa này, được đánh dấu bằng hộp màu đỏ. Trợ lý bánh mì kẹp thịt sẽ được trang bị khung trợ lý CrewAI và trợ lý bánh pizza sẽ được trang bị trợ lý Langgraph, cả hai đều được trang bị mô hình Gemini Flash 2.0

e91777eecfbae4f7.png

Triển khai Remote Burger Agent

Mã nguồn của tác nhân burger nằm trong thư mục remote_seller_agents/burger_agent. Bạn có thể kiểm tra quá trình khởi chạy nhân viên hỗ trợ trên tập lệnh agent.py. Sau đây là đoạn mã của tác nhân đã khởi chạy

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

...

Tất cả các tệp có trong thư mục remote_seller_agents/burger_agent đều đã đủ để triển khai tác nhân của chúng ta vào Cloud Run để có thể truy cập dưới dạng một dịch vụ. Chúng ta sẽ thảo luận về vấn đề này sau. Chạy lệnh sau để triển khai

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}

Nếu bạn nhận được lời nhắc rằng một kho lưu trữ vùng chứa sẽ được tạo để triển khai từ nguồn, hãy trả lời Y. Điều này chỉ xảy ra nếu trước đây bạn chưa từng triển khai từ nguồn đến Cloud Run. Sau khi triển khai thành công, nhật ký sẽ có dạng như sau.

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

Phần xxxx ở đây sẽ là một giá trị nhận dạng duy nhất khi chúng tôi triển khai dịch vụ này. Bây giờ, hãy thử truy cập vào https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json các dịch vụ tác nhân bánh mì kẹp thịt đã triển khai đó thông qua trình duyệt. Đây là URL để truy cập vào thẻ tác nhân máy chủ A2A đã triển khai.

Nếu triển khai thành công, bạn sẽ thấy phản hồi như hình bên dưới trong trình duyệt khi truy cập vào https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json :

72fdf3f52b5e8313.png

Đây là thông tin thẻ nhân viên hỗ trợ dạng nút hamburger mà người dùng có thể truy cập để khám phá. Chúng ta sẽ thảo luận về vấn đề này sau. Lưu ý rằng giá trị url vẫn được đặt ở http://0.0.0.0:8080/ tại đây. Giá trị url này phải là thông tin chính để A2A Client gửi thông báo từ thế giới bên ngoài và chưa được định cấu hình đúng cách. Đối với bản minh hoạ này, chúng ta cần cập nhật giá trị này thành URL của dịch vụ đại lý burger bằng cách thêm một biến môi trường khác HOST_OVERRIDE.

Cập nhật giá trị URL của Burger Agent trên thẻ Agent thông qua biến môi trường

Để thêm HOST_OVERRIDE vào dịch vụ tác nhân burger, hãy làm theo các bước sau

  1. Tìm Cloud Run trên thanh tìm kiếm ở đầu Cloud Console

1adde569bb345b48.png

  1. Nhấp vào dịch vụ burger-agent Cloud Run đã triển khai trước đó

9091c12526fb7f41.png

  1. Sao chép URL của dịch vụ burger, sau đó nhấp vào Chỉnh sửa và triển khai bản sửa đổi mới

2701da8b124793b9.png

  1. Sau đó, nhấp vào mục Variable & Secrets (Biến và khoá bí mật)

31ea00e12134d74d.png

  1. Sau đó, nhấp vào Thêm biến và đặt HOST_OVERRIDE giá trị thành URL của dịch vụ ( URL có mẫu https://burger-agent-xxxxxxxxx.us-central1.run.app)

52b382da7cf33cd5.png

  1. Cuối cùng, hãy nhấp vào nút deploy (triển khai) để triển khai lại dịch vụ của bạn

11464f4a51ffe54.png

Giờ đây, khi bạn truy cập lại thẻ tác nhân burger-agent trong trình duyệt https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json , giá trị url sẽ được định cấu hình đúng cách

2ed7ebcb530f070a.png

Triển khai Remote Pizza Agent

Tương tự, mã nguồn của tác nhân pizza nằm trong thư mục remote_seller_agents/pizza_agent. Bạn có thể kiểm tra quá trình khởi chạy nhân viên hỗ trợ trên tập lệnh agent.py. Sau đây là đoạn mã của tác nhân đã khởi chạy

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

...

Tương tự như bước triển khai burger-agent trước đó, tất cả các tệp có trong thư mục remote_seller_agents/pizza_agent đều đã đủ để triển khai tác nhân của chúng ta vào Cloud Run để có thể truy cập dưới dạng một dịch vụ. Chạy lệnh sau để triển khai

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}

Sau khi triển khai thành công, nhật ký sẽ có dạng như sau.

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

Phần xxxx ở đây sẽ là một giá trị nhận dạng duy nhất khi chúng tôi triển khai dịch vụ này. Tương tự với tác nhân bánh mì kẹp thịt, khi bạn cố gắng truy cập vào tuyến đường https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json của các dịch vụ tác nhân bánh pizza đã triển khai thông qua trình duyệt để truy cập vào thẻ tác nhân máy chủ A2A, giá trị url của tác nhân bánh pizza trên thẻ tác nhân chưa được định cấu hình đúng cách. Chúng ta cũng cần thêm HOST_OVERRIDE vào biến môi trường của nó

Cập nhật giá trị URL của Pizza Agent trên thẻ Agent thông qua biến môi trường

Để thêm HOST_OVERRIDE vào dịch vụ đại lý bán bánh pizza, hãy làm theo các bước sau

  1. Tìm Cloud Run trên thanh tìm kiếm ở đầu Cloud Console

1adde569bb345b48.png

  1. Nhấp vào dịch vụ pizza-agent Cloud Run đã triển khai trước đó

5743b0aa0555741f.png

  1. Nhấp vào Chỉnh sửa và triển khai bản sửa đổi mới

d60ba267410183be.png

  1. Sao chép URL của dịch vụ pizza, sau đó nhấp vào mục Variable & Secrets (Biến và khoá bí mật)

618e9da2f94ed415.png

  1. Sau đó, nhấp vào Thêm biến và đặt HOST_OVERRIDE giá trị thành URL của dịch vụ ( URL có mẫu https://pizza-agent-xxxxxxxxx.us-central1.run.app)

214a6eb98f877e65.png

  1. Cuối cùng, hãy nhấp vào nút deploy (triển khai) để triển khai lại dịch vụ của bạn

11464f4a51ffe54.png

Giờ đây, khi bạn truy cập lại thẻ đại lý pizza-agent trong trình duyệt https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json, giá trị url sẽ được định cấu hình đúng cách

c37b26ec80c821b6.png

Tại thời điểm này, chúng ta đã triển khai thành công cả dịch vụ bánh mì kẹp thịt và bánh pizza lên Cloud Run. Bây giờ, hãy thảo luận về các thành phần cốt lõi của Máy chủ A2A

4. Các thành phần cốt lõi của máy chủ A2A

Bây giờ, hãy thảo luận về khái niệm và các thành phần cốt lõi của máy chủ A2A

Thẻ của nhân viên hỗ trợ

Mỗi A2A Server phải có một thẻ đại lý có thể truy cập trên tài nguyên /.well-known/agent.json. Việc này nhằm hỗ trợ giai đoạn khám phá trên A2A Client, cung cấp thông tin và bối cảnh đầy đủ về cách truy cập vào trợ lý ảo và biết tất cả các chức năng của trợ lý ảo. Điều này tương tự như tài liệu API được ghi lại đầy đủ bằng Swagger hoặc Postman.

Đây là nội dung của thẻ nhân viên hỗ trợ về bánh mì kẹp thịt mà chúng tôi đã triển khai

{
  "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"
}

Những thẻ tác nhân này làm nổi bật nhiều thành phần quan trọng, chẳng hạn như kỹ năng của tác nhân, khả năng truyền phát trực tiếp, các phương thức được hỗ trợ, phiên bản giao thức và những thành phần khác.

Bạn có thể sử dụng tất cả thông tin này để phát triển một cơ chế liên lạc phù hợp để ứng dụng A2A có thể giao tiếp đúng cách. Phương thức và cơ chế xác thực được hỗ trợ đảm bảo có thể thiết lập thông tin liên lạc một cách thích hợp và thông tin skills của nhân viên hỗ trợ có thể được nhúng vào lời nhắc hệ thống của ứng dụng A2A để cung cấp cho nhân viên hỗ trợ của khách hàng bối cảnh về các chức năng và kỹ năng của nhân viên hỗ trợ từ xa sẽ được gọi. Bạn có thể xem các trường chi tiết hơn cho thẻ đại lý này trong tài liệu này.

Trong mã của chúng tôi, việc triển khai thẻ đại lý được thiết lập bằng A2A python sdk, hãy kiểm tra đoạn mã remote_seller_agents/burger_agent/main.py bên dưới để biết cách triển khai

...

        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],
        )

...

Chúng ta có thể thấy một số trường như:

  1. AgentCapabilities : Khai báo các hàm bổ sung không bắt buộc mà dịch vụ tác nhân hỗ trợ,chẳng hạn như khả năng hỗ trợ truyền phát trực tiếp và/hoặc thông báo đẩy
  2. AgentSkill : Công cụ hoặc chức năng mà trợ lý hỗ trợ
  3. Input/OutputModes : Phương thức nhập/xuất được hỗ trợ
  4. Url : Địa chỉ để giao tiếp với tác nhân

Trong cấu hình này, chúng tôi cung cấp một quy trình tạo URL máy chủ lưu trữ tác nhân động để bạn dễ dàng chuyển đổi giữa kiểm thử cục bộ và triển khai trên đám mây. Đó là lý do chúng ta cần thêm biến HOST_OVERRIDE ở bước trước.

Hàng đợi tác vụ và Trình thực thi tác nhân

Máy chủ A2A có thể xử lý các yêu cầu từ nhiều tác nhân hoặc người dùng và có thể tách biệt hoàn toàn từng tác vụ. Để hình dung rõ hơn về bối cảnh của những hình ảnh này, bạn có thể xem xét hình ảnh bên dưới

b9eb6b4025db4642.jpeg

Do đó, mỗi máy chủ A2A phải có khả năng theo dõi các tác vụ đến và lưu trữ thông tin thích hợp về tác vụ đó. SDK A2A cung cấp các mô-đun để giải quyết thách thức này trong máy chủ A2A. Trước tiên, chúng ta có thể tạo thực thể cho logic về cách xử lý yêu cầu đến. Bằng cách kế thừa lớp trừu tượng AgentExecutor, chúng ta có thể kiểm soát cách chúng ta muốn quản lý việc thực thi và huỷ tác vụ. Bạn có thể kiểm tra ví dụ về quy trình triển khai này tại mô-đun remote_seller_agents/burger_agent/agent_executor.py ( đường dẫn tương tự cho trường hợp người bán bánh pizza)

...

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

...

Trong đoạn mã trên, chúng ta triển khai một sơ đồ xử lý cơ bản, trong đó tác nhân sẽ được gọi trực tiếp khi yêu cầu đến và gửi các sự kiện tác vụ đã hoàn tất sau khi hoàn tất lệnh gọi. Tuy nhiên, chúng ta không triển khai phương thức huỷ ở đây vì phương thức này được coi là một thao tác chạy trong thời gian ngắn.

Sau khi tạo trình thực thi, chúng ta có thể trực tiếp sử dụng DefaultRequestHandler, InMemoryTaskStoreA2AStarletteApplication tích hợp sẵn để khởi động Máy chủ HTTP. Bạn có thể kiểm tra quá trình triển khai này trong 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)

...

Mô-đun này sẽ cung cấp cho bạn phương thức triển khai tuyến /.well-known/agent.json để truy cập vào thẻ đại lý, đồng thời cung cấp điểm cuối POST để hỗ trợ giao thức A2A

Tóm tắt

Tóm lại, cho đến nay, A2A Server mà chúng tôi triển khai bằng Python SDK có thể hỗ trợ 2 chức năng bên dưới:

  1. Xuất bản thẻ nhân viên hỗ trợ trên tuyến đường /.well-known/agent.json
  2. Xử lý yêu cầu JSON-RPC bằng cách xếp hàng tác vụ trong bộ nhớ

Bạn có thể kiểm tra điểm truy cập khi bắt đầu các chức năng này trên tập lệnh __main__.py ( trên remote_seller_agents/burger_agent hoặc remote_seller_agents/pizza_agent) .

5. Triển khai Trợ lý mua hàng – Ứng dụng A2A cho Agent Engine

Trong bước này, chúng ta sẽ triển khai tác nhân hỗ trợ mua hàng. Đây là nhân viên hỗ trợ mà chúng ta sẽ tương tác.

c4a8e7a3d18b1ef.png

Mã nguồn của trợ lý mua hàng nằm trong thư mục purchasing_concierge. Bạn có thể kiểm tra quá trình khởi chạy tác nhân trên tập lệnh purchasing_agent.py. Sau đây là đoạn mã của tác nhân đã khởi tạo.

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,
            ],
        )

...

Chúng tôi sẽ triển khai nhân viên hỗ trợ này cho công cụ nhân viên hỗ trợ. Vertex AI Agent Engine là một bộ dịch vụ cho phép nhà phát triển triển khai, quản lý và mở rộng quy mô các tác nhân AI trong quá trình sản xuất. Nền tảng này xử lý cơ sở hạ tầng để mở rộng quy mô các tác nhân trong quá trình sản xuất, nhờ đó chúng ta có thể tập trung vào việc tạo ứng dụng. Bạn có thể đọc thêm về vấn đề này trong tài liệu này . Nếu trước đây chúng ta cần chuẩn bị các tệp cần thiết để triển khai dịch vụ tác nhân (chẳng hạn như tập lệnh máy chủ chính và Dockerfile), thì trong trường hợp này, chúng ta có thể triển khai tác nhân trực tiếp từ tập lệnh Python mà không cần phát triển dịch vụ phụ trợ của riêng mình bằng cách sử dụng kết hợp ADK và Agent Engine. Hãy làm theo các bước sau để triển khai :

  1. Trước tiên, chúng ta cần tạo bộ nhớ dàn dựng trong Cloud Storage
gcloud storage buckets create gs://purchasing-concierge-{your-project-id} --location=us-central1
  1. Bây giờ, trước tiên chúng ta cần chuẩn bị biến .env, hãy sao chép .env.example vào tệp .env
cp .env.example .env
  1. Bây giờ, hãy mở tệp .env, bạn sẽ thấy nội dung sau
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}

Tác nhân này sẽ giao tiếp với tác nhân bánh mì kẹp thịt và bánh pizza, do đó, chúng ta cần cung cấp thông tin đăng nhập phù hợp cho cả hai. Chúng ta sẽ cần cập nhật PIZZA_SELLER_AGENT_URLBURGER_SELLER_AGENT_URL bằng URL Cloud Run từ các bước trước.

Nếu bạn quên, hãy truy cập vào bảng điều khiển Cloud Run. Nhập "Cloud Run" vào thanh tìm kiếm ở đầu bảng điều khiển, rồi nhấp chuột phải vào biểu tượng Cloud Run để mở trong một thẻ mới

1adde569bb345b48.png

Bạn sẽ thấy các dịch vụ trước đây của chúng tôi về tác nhân bán hàng từ xa được triển khai như minh hoạ bên dưới

179e55cc095723a8.png

Để xem URL công khai của các dịch vụ đó, hãy nhấp vào một trong các dịch vụ và bạn sẽ được chuyển hướng đến trang Chi tiết dịch vụ. Bạn có thể thấy URL ở khu vực trên cùng, ngay bên cạnh thông tin về Khu vực

64c01403a92b1107.png

Biến môi trường cuối cùng sẽ có dạng như sau

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. Giờ đây, chúng ta đã sẵn sàng triển khai trợ lý mua hàng. Trong bản minh hoạ này, chúng ta sẽ triển khai bằng cách sử dụng tập lệnh deploy_to_agent_engine.py. Nội dung của tập lệnh này được trình bày bên dưới
"""
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}")

Đây là các bước cần thiết để triển khai tác nhân ADK của chúng tôi vào công cụ tác nhân. Trước tiên, chúng ta cần tạo một đối tượng AdkApp từ root_agent ADK. Sau đó, chúng ta có thể chạy phương thức agent_engines.create bằng cách cung cấp đối tượng adk_app, chỉ định các yêu cầu trong trường requirements, chỉ định đường dẫn thư mục tác nhân trong extra_packages và cung cấp các biến môi trường cần thiết.

Chúng ta có thể triển khai bằng cách chạy tập lệnh:

uv run deploy_to_agent_engine.py

Sau khi triển khai thành công, nhật ký sẽ có dạng như sau. Lưu ý rằng xxxx là mã dự án của bạn và yyyy là mã tài nguyên công cụ của trợ lý

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

Và khi chúng ta kiểm tra nó trong trang tổng quan về công cụ tác nhân (tìm kiếm "công cụ tác nhân" trên thanh tìm kiếm), nó sẽ cho thấy việc triển khai trước đó của chúng ta

29738fbf7e5f5ecc.png

Kiểm thử Agent đã triển khai trên Agent Engine

Bạn có thể tương tác với công cụ tác nhân thông qua lệnh curl và SDK. Ví dụ: hãy chạy lệnh sau để thử tương tác với tác nhân đã triển khai.

Bạn có thể thử gửi truy vấn này để kiểm tra xem nhân viên hỗ trợ đã được triển khai thành công hay chưa

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

Nếu thành công, bạn sẽ thấy một số sự kiện phản hồi được truyền trực tuyến trên bảng điều khiển của mình như sau

{
  "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
}

Chúng ta sẽ thử sử dụng giao diện người dùng ở bước tiếp theo, tuy nhiên, trước tiên, hãy thảo luận về các thành phần cốt lõi và quy trình điển hình của ứng dụng A2A

6. Các thành phần cốt lõi của ứng dụng A2A

aa6c8bc5b5df73f1.jpeg

Hình ảnh minh hoạ ở trên là quy trình tương tác A2A điển hình:

  1. Ứng dụng sẽ cố gắng tìm mọi thẻ đại lý đã xuất bản trong URL đại lý từ xa được cung cấp trong tuyến đường /.well-known/agent.json
  2. Sau đó, khi cần, nó sẽ gửi một Thông báo đến tác nhân đó kèm theo thông báo và các tham số siêu dữ liệu cần thiết ( ví dụ: mã phiên, bối cảnh trước đây, v.v.). Máy chủ sẽ coi Thông báo này là một Nhiệm vụ cần hoàn thành
  3. Quy trình máy chủ A2A xử lý yêu cầu. Nếu máy chủ hỗ trợ thông báo đẩy, thì máy chủ cũng có thể xuất bản một số thông báo trong quá trình xử lý tác vụ ( Chức năng này nằm ngoài phạm vi của lớp học lập trình này)
  4. Sau khi hoàn tất, máy chủ A2A sẽ gửi lại phản hồi cho ứng dụng

Một số đối tượng cốt lõi cho các hoạt động tương tác nêu trên là những mục này (bạn có thể đọc thêm thông tin chi tiết tại đây) :

  • Tin nhắn: Lượt giao tiếp giữa khách hàng và nhân viên hỗ trợ từ xa
  • Tác vụ: Đơn vị công việc cơ bản do A2A quản lý, được xác định bằng một mã nhận dạng duy nhất
  • Cấu phần phần mềm: Đầu ra (ví dụ: tài liệu, hình ảnh, dữ liệu có cấu trúc) do tác nhân tạo ra trong quá trình thực hiện một tác vụ, bao gồm nhiều Phần
  • Part: Đơn vị nội dung nhỏ nhất trong một Message hoặc Artifact. Phần này có thể là văn bản, hình ảnh, video, tệp, v.v.

Khám phá thẻ

Khi dịch vụ A2A Client đang được khởi động, quy trình thông thường là cố gắng lấy thông tin thẻ đại lý và lưu trữ thông tin đó để dễ dàng truy cập khi cần. Trong lớp học lập trình này, chúng ta sẽ triển khai nó trên before_agent_callback, bạn có thể xem quá trình triển khai trong purchasing_concierge/purchasing_agent.py, hãy xem đoạn mã bên dưới

...

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)

...

Ở đây, chúng ta sẽ cố gắng truy cập vào tất cả các thẻ nhân viên hỗ trợ có sẵn bằng cách sử dụng mô-đun A2ACardResolver của ứng dụng A2A tích hợp sẵn, sau đó thu thập thông tin kết nối cần thiết để gửi tin nhắn cho nhân viên hỗ trợ. Sau đó, chúng ta cũng cần liệt kê tất cả nhân viên hỗ trợ có sẵn và các thông số kỹ thuật của họ vào lời nhắc để nhân viên hỗ trợ của chúng ta biết rằng họ có thể giao tiếp với những nhân viên hỗ trợ này

Công cụ nhắc và gửi việc cần làm

Đây là câu lệnh và công cụ mà chúng tôi cung cấp cho nhân viên hỗ trợ ADK tại đây

...

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

...

Trong lời nhắc, chúng tôi cung cấp cho trợ lý mua hàng tất cả tên và nội dung mô tả của các trợ lý từ xa hiện có. Trong công cụ self.send_task, chúng tôi cung cấp một cơ chế để truy xuất khách hàng phù hợp nhằm kết nối với trợ lý và gửi siêu dữ liệu bắt buộc bằng đối tượng SendMessageRequest.

Giao thức truyền thông

Định nghĩa Task là một miền thuộc quyền sở hữu của máy chủ A2A. Tuy nhiên, theo quan điểm của ứng dụng A2A, ứng dụng này xem đó là một Thông báo được gửi đến máy chủ. Máy chủ sẽ quyết định cách xác định thông báo đến từ ứng dụng là nhiệm vụ nào và liệu việc hoàn thành nhiệm vụ có cần sự tương tác của ứng dụng hay không. Bạn có thể đọc thêm thông tin chi tiết về vòng đời của nhiệm vụ trong tài liệu này. Bạn có thể hình dung khái niệm ở cấp độ cao hơn của việc này như sau:

65b8878a4854fd93.jpeg

9ddfae690d40cbbf.jpeg

Việc trao đổi thông báo -> tác vụ này được triển khai bằng cách sử dụng định dạng tải trọng trên tiêu chuẩn JSON-RPC như minh hoạ trong ví dụ bên dưới về giao thức 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?"
  }  
}

Có nhiều phương thức có sẵn, chẳng hạn như để hỗ trợ nhiều loại hình thức giao tiếp (ví dụ: đồng bộ, phát trực tuyến, không đồng bộ) hoặc để định cấu hình thông báo cho trạng thái của tác vụ. Bạn có thể linh hoạt định cấu hình máy chủ A2A để xử lý các tiêu chuẩn định nghĩa tác vụ này. Bạn có thể đọc thông tin chi tiết về các phương thức này trong tài liệu này.

7. Kiểm thử tích hợp và kiểm tra tải trọng

Bây giờ, hãy kiểm tra trợ lý mua hàng của chúng ta bằng cách tương tác với nhân viên từ xa thông qua giao diện người dùng trên web.

Trước tiên, chúng ta cần cập nhật AGENT_ENGINE_RESOURCE_NAME trong .Tệp env. Đảm bảo rằng bạn cung cấp đúng tên tài nguyên công cụ của tác nhân. Tệp .env của bạn sẽ có dạng như bên dưới:

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

Sau đó, hãy chạy lệnh sau để triển khai một ứng dụng Gradio

uv run purchasing_concierge_ui.py

Nếu thành công, bạn sẽ thấy kết quả sau

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

Sau đó, hãy nhấn Ctrl + nhấp vào URL http://0.0.0.0:8080 trên thiết bị đầu cuối hoặc nhấp vào nút xem trước trên web để mở giao diện người dùng web

b38b428d9e4582bc.png

Hãy thử trò chuyện như sau :

  • Cho tôi xem thực đơn bánh burger và pizza
  • Tôi muốn đặt 1 chiếc bánh pizza gà nướng và 1 chiếc bánh mì kẹp thịt Cajun cay

Sau đó, tiếp tục trò chuyện cho đến khi bạn hoàn tất đơn đặt hàng. Kiểm tra xem hoạt động tương tác diễn ra như thế nào, lệnh gọi và phản hồi của công cụ là gì? Hình ảnh sau đây là một ví dụ về kết quả tương tác.

ff5f752965816b2b.png

6f65155c7a289964.png

b390f4b15f1c5a8c.png

ff44c54b50c36e1a.png

Chúng ta có thể thấy rằng việc giao tiếp với 2 tác nhân khác nhau sẽ mang lại 2 hành vi khác nhau và A2A có thể xử lý tốt việc này. Nhân viên bán bánh pizza chấp nhận trực tiếp yêu cầu của nhân viên mua hàng, trong khi nhân viên bán bánh hamburger cần chúng tôi xác nhận trước khi tiến hành yêu cầu và sau khi chúng tôi xác nhận, nhân viên bán bánh hamburger có thể dựa vào thông tin xác nhận đó.

Giờ đây, chúng ta đã hoàn thành các khái niệm cơ bản về A2A và xem cách khái niệm này được triển khai dưới dạng cấu trúc máy khách và máy chủ

8. Thách thức

Giờ đây, bạn có thể tự chuẩn bị tệp cần thiết và triển khai ứng dụng Gradio vào Cloud Run không? Đã đến lúc tham gia thử thách!

9. Dọn dẹp

Để tránh phát sinh phí cho tài khoản Google Cloud của bạn đối với các tài nguyên được dùng trong lớp học lập trình này, hãy làm theo các bước sau:

  1. Trong Google Cloud Console, hãy chuyển đến trang Quản lý tài nguyên.
  2. Trong danh sách dự án, hãy chọn dự án mà bạn muốn xoá, rồi nhấp vào Xoá.
  3. Trong hộp thoại, hãy nhập mã dự án rồi nhấp vào Tắt để xoá dự án.
  4. Ngoài ra, bạn có thể chuyển đến Cloud Run trên bảng điều khiển, chọn dịch vụ bạn vừa triển khai rồi xoá.