Tạo và triển khai các tác nhân ADK (Agent Deployment Kit) có mã nguồn thấp bằng ADK Visual Builder

1. Mục tiêu của tính năng này trong Labs

Trong lớp học thực hành này, bạn sẽ tìm hiểu cách tạo các tác nhân bằng Trình tạo trực quan ADK (Bộ công cụ phát triển tác nhân). ADK (Agent Development Kit) Visual Builder cung cấp một cách thức ít mã để tạo các tác nhân ADK (Agent Development Kit). Bạn sẽ tìm hiểu cách kiểm thử ứng dụng cục bộ và triển khai trong Cloud Run.

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

a7c151e463f26e19.jpeg

Hình 1: Với ADK Visual Builder, bạn có thể tạo các tác nhân bằng GUI với ít mã

2. Thiết lập dự án

  • Nếu chưa có dự án nào có thể sử dụng, bạn sẽ cần tạo một dự án mới trong Bảng điều khiển GCP. Chọn dự án tại bộ chọn dự án (phía trên cùng bên trái của Google Cloud Console) 6fce70b12b5fc94.png

Hình 2: Khi nhấp vào hộp ngay bên cạnh biểu trưng Google Cloud, bạn có thể chọn dự án của mình. Đảm bảo bạn đã chọn dự án của mình.

  • Trong phòng thí nghiệm này, chúng ta sẽ sử dụng Cloud Shell Editor để thực hiện các nhiệm vụ. Mở Cloud Shell và thiết lập dự án bằng Cloud Shell.
  • Nhấp vào đường liên kết này để chuyển trực tiếp đến Cloud Shell Editor
  • Mở cửa sổ Terminal (Thiết bị đầu cuối) nếu cửa sổ này chưa mở bằng cách nhấp vào Terminal>New Terminal (Thiết bị đầu cuối> Mới) trong trình đơn. Bạn có thể chạy tất cả các lệnh trong hướng dẫn này trên thiết bị đầu cuối này.
  • Bạn có thể kiểm tra xem dự án đã được xác thực hay chưa bằng lệnh sau trong thiết bị đầu cuối Cloud Shell.
gcloud auth list
  • Chạy lệnh sau trong Cloud Shell để xác nhận dự án của bạn
gcloud config list project
  • Sao chép mã dự án rồi dùng lệnh sau để đặt mã dự án
gcloud config set project <YOUR_PROJECT_ID>
  • Nếu không nhớ mã dự án, bạn có thể liệt kê tất cả mã dự án bằng cách sử dụng
gcloud projects list

3. Bật API

Chúng ta cần bật một số dịch vụ API để chạy lớp học này. Chạy lệnh sau trong Cloud Shell.

gcloud services enable aiplatform.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com

Giới thiệu về các API

  • API Vertex AI (aiplatform.googleapis.com) cho phép truy cập vào nền tảng Vertex AI , cho phép ứng dụng của bạn tương tác với các mô hình Gemini để tạo văn bản, phiên trò chuyện và gọi hàm.
  • Cloud Resource Manager API (cloudresourcemanager.googleapis.com) cho phép bạn quản lý siêu dữ liệu theo phương thức lập trình cho các dự án trên Google Cloud, chẳng hạn như mã nhận dạng và tên dự án. Đây là thông tin thường được các công cụ và SDK khác yêu cầu để xác minh danh tính và quyền của dự án.

4. Xác nhận xem bạn đã sử dụng các khoản tín dụng hay chưa

Trong giai đoạn Thiết lập dự án, bạn đã đăng ký nhận khoản tín dụng miễn phí để có thể sử dụng các dịch vụ trong Google Cloud. Khi bạn áp dụng khoản tín dụng, một tài khoản thanh toán miễn phí mới có tên là "Tài khoản thanh toán dùng thử Google Cloud Platform" sẽ được tạo. Để đảm bảo các khoản tín dụng đã được áp dụng, hãy làm theo các bước sau trong Cloud Shell Editor

curl -s https://raw.githubusercontent.com/haren-bh/gcpbillingactivate/main/activate.py | python3

Nếu thành công, bạn sẽ thấy kết quả như bên dưới: Nếu thấy "Successfully linked project" (Đã liên kết dự án thành công), tức là tài khoản thanh toán của bạn đã được thiết lập đúng cách. Bằng cách thực hiện bước trên, bạn có thể kiểm tra xem tài khoản của mình đã được liên kết hay chưa. Nếu chưa, hệ thống sẽ liên kết tài khoản cho bạn. Nếu chưa chọn dự án, hệ thống sẽ nhắc bạn chọn một dự án hoặc bạn có thể chọn trước bằng cách làm theo các bước trong phần thiết lập dự án. e0268411fd0691a2.png

Hình 3: Xác nhận tài khoản thanh toán được liên kết

5. Giới thiệu về Agent Development Kit

Agent Development Kit (Bộ công cụ phát triển tác nhân) mang lại một số lợi thế chính cho nhà phát triển khi xây dựng các ứng dụng dựa trên tác nhân:

  1. Hệ thống nhiều tác nhân: Xây dựng các ứng dụng có thể mở rộng và theo mô-đun bằng cách kết hợp nhiều tác nhân chuyên biệt trong một hệ thống phân cấp. Cho phép phối hợp và uỷ quyền phức tạp.
  2. Hệ sinh thái công cụ đa dạng: Trang bị cho các đặc vụ nhiều chức năng: sử dụng các công cụ được tạo sẵn (Tìm kiếm, Thực thi mã, v.v.), tạo các hàm tuỳ chỉnh, tích hợp các công cụ từ khung đặc vụ của bên thứ ba (LangChain, CrewAI) hoặc thậm chí sử dụng các đặc vụ khác làm công cụ.
  3. Điều phối linh hoạt: Xác định quy trình công việc bằng cách sử dụng các tác nhân quy trình công việc (SequentialAgent, ParallelAgentLoopAgent) cho các quy trình có thể dự đoán hoặc tận dụng tính năng định tuyến linh hoạt dựa trên LLM (LlmAgent chuyển) cho hành vi thích ứng.
  4. Trải nghiệm tích hợp cho nhà phát triển: Phát triển, kiểm thử và gỡ lỗi cục bộ bằng một CLI mạnh mẽ và giao diện người dùng tương tác dành cho nhà phát triển. Kiểm tra các sự kiện, trạng thái và bước thực thi của tác nhân từng bước.
  5. Đánh giá tích hợp: Đánh giá hiệu suất của tác nhân một cách có hệ thống bằng cách đánh giá cả chất lượng của câu trả lời cuối cùng và quỹ đạo thực thi từng bước dựa trên các trường hợp kiểm thử được xác định trước.
  6. Sẵn sàng triển khai: Đóng gói và triển khai các tác nhân của bạn ở bất cứ đâu – chạy cục bộ, mở rộng quy mô bằng Vertex AI Agent Engine hoặc tích hợp vào cơ sở hạ tầng tuỳ chỉnh bằng Cloud Run hoặc Docker.

Mặc dù các SDK hoặc khung tác nhân AI tạo sinh khác cũng cho phép bạn truy vấn các mô hình và thậm chí trang bị cho chúng các công cụ, nhưng việc phối hợp linh hoạt giữa nhiều mô hình đòi hỏi bạn phải nỗ lực đáng kể.

Agent Development Kit cung cấp một khung cấp cao hơn so với những công cụ này, giúp bạn dễ dàng kết nối nhiều tác nhân với nhau để tạo ra các quy trình làm việc phức tạp nhưng dễ duy trì.

e97ad3e26ceb7a2f.png

Hình 4: Vị trí của ADK (Agent Development Kit)

Trong các phiên bản gần đây, một công cụ ADK Visual Builder đã được thêm vào ADK (Agent Development Kit). Công cụ này cho phép bạn tạo các tác nhân ADK (Agent Development Kit) bằng mã nguồn tối thiểu. Trong lớp học lập trình này, chúng ta sẽ khám phá chi tiết Công cụ ADK Visual Builder.

6. Cài đặt ADK và thiết lập môi trường

Trước hết, chúng ta cần thiết lập môi trường để có thể chạy ADK (Bộ công cụ phát triển tác nhân). Trong phòng thí nghiệm này, chúng ta sẽ chạy ADK (Bộ công cụ phát triển tác nhân) và thực hiện tất cả các tác vụ trong Google Cloud trong Cloud Shell Editor .

Chuẩn bị Cloud Shell Editor

  1. Nhấp vào đường liên kết này để chuyển trực tiếp đến Cloud Shell Editor
  2. Nhấp vào Tiếp tục.
  3. Khi được nhắc cho phép Cloud Shell, hãy nhấp vào Cho phép.
  4. Trong phần còn lại của bài tập này, bạn có thể làm việc trong cửa sổ này với tư cách là IDE bằng Cloud Shell Editor và Cloud Shell Terminal.
  5. Mở một cửa sổ dòng lệnh mới bằng cách chọn Terminal>New Terminal (Cửa sổ dòng lệnh>Cửa sổ dòng lệnh mới) trong Trình chỉnh sửa Cloud Shell. Tất cả các lệnh dưới đây sẽ được chạy trên thiết bị đầu cuối này.

Khởi động Trình chỉnh sửa trực quan ADK

  1. Thực thi các lệnh sau để sao chép nguồn cần thiết từ github và cài đặt các thư viện cần thiết. Chạy các lệnh trong cửa sổ dòng lệnh được mở trong Trình chỉnh sửa Cloud Shell.
#create the project directory
mkdir ~/adkui
cd ~/adkui
  1. Chúng ta sẽ dùng uv để tạo môi trường Python (Chạy trong Cloud Shell Editor Terminal):
#Install uv if you do not have installed yet
pip install uv

#go to the project directory
cd ~/adkui

#Create the virtual environment
uv venv


#use the newly created environment
source .venv/bin/activate

#install libraries
uv pip install google-adk==1.22.1
uv pip install python-dotenv

Lưu ý: Nếu bạn cần khởi động lại cửa sổ dòng lệnh, hãy nhớ thiết lập môi trường python bằng cách thực thi "source .venv/bin/activate"

  1. Trong trình chỉnh sửa, hãy chuyển đến View->Toggle hidden files (Xem > Chuyển đổi tệp ẩn). Trong thư mục adkui, hãy tạo một tệp .env có nội dung sau.
#go to adkui folder
cd ~/adkui
cat <<EOF>> .env
GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
GOOGLE_CLOUD_LOCATION=us-central1
IMAGEN_MODEL="imagen-3.0-generate-002"
GENAI_MODEL="gemini-2.5-flash"
EOF

7. Tạo một Agent đơn giản bằng ADK Visual Builder

Trong phần này, chúng ta sẽ tạo một tác nhân đơn giản bằng ADK Visual Builder.ADK Visual Builder là một công cụ dựa trên web, cung cấp môi trường thiết kế quy trình làm việc trực quan để tạo và quản lý các tác nhân ADK (Bộ công cụ phát triển tác nhân). Công cụ này cho phép bạn thiết kế, tạo và kiểm thử các tác nhân trong một giao diện đồ hoạ thân thiện với người mới bắt đầu, đồng thời có một trợ lý dựa trên AI để giúp bạn tạo các tác nhân.

a62f805e02759763.jpeg

Hình 5: Công cụ tạo trực quan ADK

  1. Quay lại thư mục trên cùng adkui trong cửa sổ dòng lệnh và thực thi lệnh sau để chạy tác nhân cục bộ (Chạy trong cửa sổ dòng lệnh Cloud Shell Editor). Bạn sẽ có thể khởi động máy chủ ADK và thấy kết quả tương tự như Hình 6 trong thiết bị đầu cuối.
#go to the directory adkui
cd ~/adkui
# Run the following command to run ADK locally
adk web

dfda0b40b44e9230.png

Hình 6: Khởi động ứng dụng ADK

  1. Ctrl+Click (CMD+Click đối với MacOS) trên URL http:// xuất hiện trên thiết bị đầu cuối để mở công cụ GUI dựa trên trình duyệt ADK (Agent Development Kit).

8b5b97c99563987e.png

Hình 7: Giao diện người dùng web ADK, ADK có các thành phần sau: 1: Bật/tắt chế độ sáng và tối 2: Thu gọn bảng điều khiển 3: Tạo tác nhân 4: Chỉnh sửa và tác nhân

  1. Để tạo một Agent mới, hãy nhấn vào nút "+".

8be783739a4fa361.png

Hình 8: Hộp thoại tạo ứng dụng mới

  1. Đặt tên là "Agent1" rồi nhấp vào Tạo.

75b41854cf000b5a.png

Hình 9: Giao diện người dùng cho trình tạo trợ lý ảo

  1. Bảng điều khiển được chia thành 3 phần chính: bên trái là phần Controls (Các chế độ kiểm soát) để tạo tác nhân dựa trên GUI, phần giữa cung cấp hình ảnh trực quan về tiến trình của bạn và phần bên phải chứa Assistant (Trợ lý) để tạo tác nhân bằng ngôn ngữ tự nhiên.
  2. Đã tạo thành công Nhân viên hỗ trợ của bạn. Nhấp vào nút Lưu để tiếp tục. (Lưu ý: Để tránh mất nội dung thay đổi, bạn phải nhấn vào Lưu.)
  3. Giờ đây, nhân viên hỗ trợ đã sẵn sàng để kiểm thử. Để bắt đầu, hãy nhập một câu lệnh vào hộp Chat, chẳng hạn như:
Hi, what can you do?

3fbcbca52ec22bb5.png

Hình 10: Kiểm thử tác nhân.

7.Quay lại trình chỉnh sửa, hãy xem xét các tệp mới được tạo. Bạn sẽ thấy trình khám phá ở bên trái. Chuyển đến thư mục adkgui rồi mở rộng thư mục này để hiển thị thư mục Agent 1. Trong thư mục này, bạn có thể kiểm tra tệp YAML xác định tác nhân, như minh hoạ trong hình bên dưới.

3af1515bad1387a4.png

Hình 11: Định nghĩa tác nhân bằng tệp YAML

  1. Bây giờ, hãy quay lại trình chỉnh sửa GUI và thêm một số tính năng cho tác nhân. Để thực hiện việc này, hãy nhấn vào nút chỉnh sửa (xem Hình 7, thành phần số 4, biểu tượng bút).
  2. Chúng tôi sẽ thêm tính năng Google Tìm kiếm vào tác nhân. Để làm như vậy, chúng tôi cần thêm Google Tìm kiếm làm một công cụ mà tác nhân có thể sử dụng. Để làm như vậy, hãy nhấp vào dấu "+" bên cạnh phần Công cụ ở dưới cùng bên trái màn hình, rồi nhấp vào Công cụ tích hợp trong trình đơn (Xem Hình 12). 1c021cb0c9a2432a.png

Hình 12: Thêm một công cụ mới vào một tác nhân

  1. Trong danh sách Công cụ tích hợp, hãy chọn google_search rồi nhấp vào Tạo (Xem Hình 12). Thao tác này sẽ thêm Google Tìm kiếm làm một công cụ trong tác nhân của bạn.
  2. Nhấn vào nút Lưu để lưu các thay đổi.

43e4f68dbb048347.png

Hình 13: Danh sách các công cụ có trong giao diện người dùng ADK Visual Builder

  1. Giờ đây, bạn đã sẵn sàng kiểm thử Agent. Trước tiên, hãy khởi động lại Máy chủ ADK. Chuyển đến thiết bị đầu cuối nơi bạn đã khởi động máy chủ ADK (Agent Development Kit) rồi nhấn tổ hợp phím CTRL+C để tắt máy chủ nếu máy chủ vẫn đang chạy. Thực hiện lệnh sau để khởi động lại máy chủ.
#make sure you are in the right folder.
cd ~/adkui

#start the server
adk web
  1. Nhấn Ctrl+Nhấp vào URL (ví dụ: http://localhost:8000) xuất hiện trên màn hình. Giao diện người dùng ADK (Agent Development Kit) sẽ xuất hiện trên thẻ trình duyệt.
  2. Chọn Agent1 trong danh sách nhân viên hỗ trợ. Giờ đây, tác nhân của bạn có thể tìm kiếm trên Google. Trong hộp trò chuyện, hãy kiểm thử bằng câu lệnh sau.
What is the weather today in Yokohama?

Bạn sẽ thấy câu trả lời từ Google Tìm kiếm như bên dưới. 71d9377da4a0bd0c.png

Hình 14: Google Tìm kiếm có đại lý

  1. Bây giờ, hãy quay lại trình chỉnh sửa và kiểm tra mã đã được tạo ở bước này. Trong bảng điều khiển bên Trình khám phá của Trình chỉnh sửa, hãy nhấp vào root_agent.yaml để mở. Xác nhận rằng google_search đã được thêm làm công cụ (Hình 15).

2ac95d98921ec54d.png

Hình 15: Xác nhận rằng google_search đã được thêm làm công cụ trong Agent1

8. Triển khai Agent lên Cloud Run

Bây giờ, hãy triển khai tác nhân đã tạo lên Cloud Run! Với Cloud Run, bạn có thể nhanh chóng tạo ứng dụng hoặc trang web trên một nền tảng được quản lý hoàn toàn.

Bạn có thể chạy các dịch vụ phụ trợ và giao diện người dùng, các công việc hàng loạt, lưu trữ LLM và xử lý các khối lượng công việc theo hàng đợi mà không cần quản lý cơ sở hạ tầng.

Trong Cloud Shell Editor Terminal, nếu bạn vẫn đang chạy máy chủ ADK (Agent Development Kit), hãy nhấn Ctrl+C để dừng máy chủ này.

  1. Chuyển đến thư mục gốc của dự án.
cd ~/adkui
  1. Lấy mã triển khai. Sau khi chạy lệnh, bạn sẽ thấy tệp deploycloudrun.py trong ngăn Trình khám phá của Trình chỉnh sửa Cloud Shell
curl -LO https://raw.githubusercontent.com/haren-bh/codelabs/main/adk_visual_builder/deploycloudrun.py
  1. Kiểm tra các lựa chọn triển khai trong deploycloudrun.py. Chúng ta sẽ dùng lệnh adk deploy để triển khai tác nhân của mình đến Cloud Run. ADK (Bộ phát triển tác nhân) có lựa chọn tích hợp để triển khai tác nhân cho Cloud Run. Chúng ta cần chỉ định các tham số như mã dự án trên Google Cloud, Khu vực, v.v. Đối với đường dẫn ứng dụng, tập lệnh này giả định rằng agent_path=./Agent1. Chúng ta cũng sẽ tạo một tài khoản dịch vụ mới có các quyền cần thiết và đính kèm tài khoản đó vào Cloud Run. Cloud Run cần có quyền truy cập vào các dịch vụ như Vertex AI, Cloud Storage để chạy Tác nhân.
   command = [
        "adk", "deploy", "cloud_run",
        f"--project={project_id}",
        f"--region={location}",
        f"--service_name={service_name}",
        f"--app_name={app_name}",
        f"--artifact_service_uri=memory://",
        f"--with_ui",
        agent_path,
        f"--",
        f"--service-account={sa_email}",
    ]
  1. Chạy tập lệnh deploycloudrun.py**. Quá trình triển khai sẽ bắt đầu như minh hoạ trong hình bên dưới.**
python3 deploycloudrun.py

Nếu bạn nhận được thông báo xác nhận như bên dưới, hãy nhấn Y rồi nhấn Enter cho tất cả thông báo. depoycloudrun.py giả định rằng nhân viên hỗ trợ của bạn nằm trong thư mục Agent1 như đã tạo ở trên.

a62b6b35bc5992db.png

Hình 16: Triển khai tác nhân vào Cloud Run, nhấn Y cho mọi thông báo xác nhận.

  1. Sau khi triển khai xong, bạn sẽ thấy URL dịch vụ như https://agent1service-78833623456.us-central1.run.app
  2. Truy cập vào URL trong trình duyệt web để chạy ứng dụng.

baaf3bcb8117883.png

        Figure 17: Agent running in Cloud Run

9. Tạo một tác nhân có tác nhân phụ và công cụ tuỳ chỉnh

Trong phần trước, bạn đã tạo một tác nhân duy nhất bằng Công cụ tìm kiếm của Google tích hợp. Trong phần này, bạn sẽ tạo một hệ thống nhiều tác nhân, trong đó chúng ta cho phép các tác nhân sử dụng các công cụ tuỳ chỉnh.

  1. Trước tiên, hãy khởi động lại Máy chủ ADK (Agent Development Kit). Chuyển đến thiết bị đầu cuối nơi bạn đã khởi động máy chủ ADK (Bộ công cụ phát triển tác nhân)nhấn CTRL+C để tắt máy chủ nếu máy chủ vẫn đang chạy. Thực hiện lệnh sau để khởi động lại máy chủ.
#make sure you are in the right folder.
cd ~/adkui

#start the server
adk web
  1. Nhấn Ctrl+Nhấp vào URL (ví dụ: http://localhost:8000) xuất hiện trên màn hình. Giao diện người dùng ADK (Agent Development Kit) sẽ xuất hiện trên thẻ trình duyệt.
  2. Nhấp vào nút "+" để tạo một Nhân viên mới. Trên hộp thoại tác nhân, hãy nhập "Agent2" (Hình 18) rồi nhấp vào "Tạo".

c657dfeb5185a42c.png

Hình 18: Tạo một ứng dụng Agent mới.

  1. Trong phần hướng dẫn của Agent2, hãy nhập nội dung sau.
You are an agent that takes image creation instruction from the user and passes it to your sub agent
  1. Bây giờ, chúng ta sẽ thêm một tác nhân phụ vào tác nhân gốc. Để làm như vậy, hãy nhấp vào nút "+" ở bên trái của trình đơn Sub Agent (Tác nhân phụ) ở cuối ngăn bên trái (Hình 19) rồi nhấp vào "LLM Agent" (Tác nhân LLM). Thao tác này sẽ tạo một Đặc vụ mới dưới dạng đặc vụ phụ mới của đặc vụ gốc.

c7e13dca96faa084.png

Hình 19: Thêm một Nhân viên phụ mới.

  1. Trong phần Hướng dẫn cho sub_agent_1, hãy nhập văn bản sau.
You are an Agent that can take instructions about an image and create an image using the create_image tool.
  1. Bây giờ, hãy thêm một công cụ tuỳ chỉnh vào tác nhân phụ này. Công cụ này sẽ gọi mô hình Imagen để tạo hình ảnh theo chỉ dẫn của người dùng. Để thực hiện việc này, trước tiên, hãy nhấp vào Nhân viên phụ được tạo ở bước trước rồi nhấp vào nút "+" bên cạnh trình đơn Công cụ. Trong danh sách các lựa chọn về công cụ, hãy nhấp vào "Công cụ hàm". Công cụ này sẽ cho phép chúng ta thêm mã tuỳ chỉnh của riêng mình vào công cụ.

dd4ed4726300a1b1.png

Hình 20: Nhấp vào công cụ Hàm để tạo một công cụ mới. 8. Đặt tên cho công cụ Agent2.image_creation_tool.create_image trong hộp thoại. feb5c69a876e8dda.png

Hình 21: Thêm tên công cụ

  1. Nhấp vào nút Lưu để lưu nội dung thay đổi.
  2. Trong Terminal của Cloud Shell Editor, hãy nhấn tổ hợp phím Ctrl+S để tắt máy chủ adk.
  3. Trong Terminal, hãy nhập lệnh sau để tạo tệp image_creation_tool.py.
touch ~/adkui/Agent2/image_creation_tool.py
  1. Mở tệp image_creation_tool.py vừa tạo bằng cách nhấp vào tệp đó trong ngăn Explorer của Cloud Shell Editor. Sau đó, thay thế nội dung của image_creation_tool.py bằng nội dung sau rồi Lưu nội dung đó (Ctrl+S).
import os
import io
import vertexai
from vertexai.preview.vision_models import ImageGenerationModel
from dotenv import load_dotenv
import uuid
from typing import Union
from datetime import datetime
from google import genai
from google.genai import types
from google.adk.tools import ToolContext
import logging

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

async def create_image(prompt: str,tool_context: ToolContext) -> Union[bytes, str]:
  """
  Generates an image based on a text prompt using a Vertex AI Imagen model.
  Args:
      prompt: The text prompt to generate the image from.

  Returns:
      The binary image data (PNG format) on success, or an error message string on failure.
  """
  print(f"Attempting to generate image for prompt: '{prompt}'")

  try:
      # Load environment variables from .env file two levels up
      dotenv_path = os.path.join(os.path.dirname(__file__), '..', '..', '.env')
      load_dotenv(dotenv_path=dotenv_path)
      project_id = os.getenv("GOOGLE_CLOUD_PROJECT")
      location = os.getenv("GOOGLE_CLOUD_LOCATION")
      model_name = os.getenv("IMAGEN_MODEL")
      client = genai.Client(
          vertexai=True,
          project=project_id,
          location=location,
      )
      response = client.models.generate_images(
          model="imagen-3.0-generate-002",
          prompt=prompt,
          config=types.GenerateImagesConfig(
              number_of_images=1,
              aspect_ratio="9:16",
              safety_filter_level="block_low_and_above",
              person_generation="allow_adult",
          ),
      )
      if not all([project_id, location, model_name]):
          return "Error: Missing GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION, or IMAGEN_MODEL in .env file."
      vertexai.init(project=project_id, location=location)
      model = ImageGenerationModel.from_pretrained(model_name)
      images = model.generate_images(
          prompt=prompt,
          number_of_images=1
      )
      if response.generated_images is  None:
          return "Error: No image was generated."
      for generated_image in response.generated_images:
          # Get the image bytes
          image_bytes = generated_image.image.image_bytes
          counter = str(tool_context.state.get("loop_iteration", 0))
          artifact_name = f"generated_image_" + counter + ".png"
          # Save as ADK artifact (optional, if still needed by other ADK components)
          report_artifact = types.Part.from_bytes(
              data=image_bytes, mime_type="image/png"
          )
          await tool_context.save_artifact(artifact_name, report_artifact)
          logger.info(f"Image also saved as ADK artifact: {artifact_name}")
          return {
              "status": "success",
              "message": f"Image generated .  ADK artifact: {artifact_name}.",
              "artifact_name": artifact_name,
          }
  except Exception as e:
      error_message = f"An error occurred during image generation: {e}"
      print(error_message)
      return error_message
  1. Trước tiên, hãy khởi động lại Máy chủ ADK (Agent Development Kit). Chuyển đến thiết bị đầu cuối nơi bạn đã khởi động máy chủ ADK (Bộ công cụ phát triển tác nhân)nhấn CTRL+C để tắt máy chủ nếu máy chủ vẫn đang chạy. Thực hiện lệnh sau để khởi động lại máy chủ.
#make sure you are in the right folder.
cd ~/adkui

#start the server
adk web
  1. Nhấn Ctrl+Nhấp vào URL (ví dụ: http://localhost:8000) xuất hiện trên màn hình. Giao diện người dùng ADK (Agent Development Kit) sẽ xuất hiện trên thẻ trình duyệt.
  1. Trong thẻ giao diện người dùng ADK (Bộ công cụ phát triển tác nhân), hãy chọn Agent2 trong danh sách Agent rồi nhấn nút chỉnh sửa (biểu tượng Bút). Trong Trình chỉnh sửa trực quan ADK (Bộ công cụ phát triển tác nhân), hãy nhấp vào nút Lưu để lưu các thay đổi.
  2. Bây giờ, chúng ta có thể kiểm thử Agent mới.
  3. Trong giao diện trò chuyện trên giao diện người dùng ADK (Agent Development Kit), hãy nhập câu lệnh sau. Bạn cũng có thể thử các câu lệnh khác. Bạn sẽ thấy kết quả như trong Hình 22)
Create an image of a cat

5ef38727b5af2c88.png

Hình 22: Giao diện trò chuyện trên giao diện người dùng ADK

10. Tạo một tác nhân quy trình công việc

Trong khi bước trước đó liên quan đến việc xây dựng một tác nhân bằng một tác nhân phụ và các công cụ tạo hình ảnh chuyên biệt, thì giai đoạn này tập trung vào việc tinh chỉnh các chức năng của tác nhân. Chúng tôi sẽ cải thiện quy trình này bằng cách đảm bảo câu lệnh ban đầu của người dùng được tối ưu hoá trước khi quá trình tạo hình ảnh diễn ra. Để đạt được điều này, một tác nhân Tuần tự sẽ được tích hợp vào Tác nhân gốc để xử lý quy trình gồm 2 bước sau:

  1. Nhận câu lệnh từ Root Agent và thực hiện việc cải thiện câu lệnh.
  2. Chuyển câu lệnh đã tinh chỉnh cho Agent tạo hình ảnh để tạo ra hình ảnh cuối cùng bằng IMAGEN.
  3. Trước tiên, hãy khởi động lại Máy chủ ADK (Agent Development Kit). Chuyển đến thiết bị đầu cuối nơi bạn đã khởi động máy chủ ADK (Bộ công cụ phát triển tác nhân)nhấn CTRL+C để tắt máy chủ nếu máy chủ vẫn đang chạy. Thực hiện lệnh sau để khởi động lại máy chủ.
#make sure you are in the right folder.
cd ~/adkui

#start the server
adk web
  1. Nhấn Ctrl+Nhấp vào URL (ví dụ: http://localhost:8000) xuất hiện trên màn hình. Giao diện người dùng ADK (Agent Development Kit) sẽ xuất hiện trên thẻ trình duyệt.
  2. Chọn Agent2 trong bộ chọn tác nhân rồi nhấp vào nút Chỉnh sửa (biểu tượng Bút).
  3. Nhấp vào Agent2 (Root Agent) rồi nhấp vào nút "+" bên cạnh trình đơn Sub Agents (Đại lý phụ). Trong danh sách các lựa chọn, hãy nhấp vào Sequential Agent (Tác nhân tuần tự)
  4. Bạn sẽ thấy Cấu trúc tác nhân giống như cấu trúc trong Hình 2368ad7cee0619895f.png

Hình 23: Cấu trúc tác nhân tuần tự

  1. Bây giờ, chúng ta sẽ thêm tác nhân đầu tiên vào Sequential Agent (Tác nhân tuần tự) để đóng vai trò là một tác nhân nâng cao câu lệnh. Để thực hiện việc này, hãy Nhấp vào Nút Thêm tác nhân phụ bên trong hộp SequentialAgent rồi nhấp vào LLM Agent
  2. Chúng ta cần thêm một Agent khác vào chuỗi, vì vậy hãy lặp lại Bước 6 để thêm một LLM Agent khác (Nhấn nút + rồi chọn LLMAgent).
  3. Nhấp vào sub_agent_4 rồi thêm một Công cụ mới bằng cách nhấp vào biểu tượng"+" bên cạnh Công cụ trên ngăn bên trái. Nhấp vào "Công cụ hàm" trong các lựa chọn. Trên DialogBox, hãy đặt tên cho công cụ này là Agent2.image_creation_tool.create_image rồi nhấn vào "Create" (Tạo).
  4. Bây giờ, chúng ta có thể xoá sub_agent_1 vì nó đã được thay thế bằng sub_agent_2 nâng cao hơn. Để làm như vậy, hãy nhấp vào nút Xoá ở bên phải sub_agent_1 trong sơ đồ.

d859376fd77299a.png

Hình 24: Xoá sub_agent_1 10. Cấu trúc của tác nhân có dạng như trong Hình 25.

f2f9dae3183d2b6.png

Hình 25: Cấu trúc cuối cùng của Enhanced Agent

  1. Nhấp vào sub_agent_3 rồi nhập nội dung sau vào phần hướng dẫn.
     Act as a professional AI Image Prompt Engineer. I will provide you 
    with a basic idea for an image. Your job is to expand my idea into 
    a detailed, high-quality prompt for models like Imagen. 
    
    For every input, output the following structure:
    1. **Optimized Prompt**: A vivid, descriptive paragraph including 
    subject, background, lighting, and textures.
    2. **Style & Medium**: Specify if it is photorealistic, digital art, 
    oil painting, etc.
    3. **Camera & Lighting**: Define the lens (e.g., 85mm), angle, 
    and light quality (e.g., volumetric, golden hour).
    
    Guidelines: Use sensory language, avoid buzzwords like 'photorealistic' 
    unless necessary, and focus on specific artistic descriptors.
    Once the prompt is created send the prompt to the 
  1. Nhấp vào sub_agent_4. Thay đổi hướng dẫn thành nội dung sau.
You are an agent that takes instructions about an image and can generate the image using the create_image tool.
  1. Nhấp vào nút Lưu
  2. Chuyển đến ngăn Trình khám phá của Trình chỉnh sửa Cloud Shell rồi mở các tệp yaml của tác nhân. Các tệp tác nhân sẽ có dạng như dưới đây
root_agent.yaml

name: Agent2
model: gemini-2.5-flash
agent_class: LlmAgent
instruction: You are an agent that takes image creation instruction from the
  user and passes it to your sub agent
sub_agents:
  - config_path: ./sub_agent_2.yaml
tools: []
sub_agent_2.yaml

name: sub_agent_2
agent_class: SequentialAgent
sub_agents:
  - config_path: ./sub_agent_3.yaml
  - config_path: ./sub_agent_4.yaml
sub_agent_3.yaml

name: sub_agent_3
model: gemini-2.5-flash
agent_class: LlmAgent
instruction: |
  Act as a professional AI Image Prompt Engineer. I will provide you  with a
  basic idea for an image. Your job is to expand my idea into  a detailed,
  high-quality prompt for models like Imagen. 

  For every input, output the following structure: 1. **Optimized Prompt**: A
  vivid, descriptive paragraph including  subject, background, lighting, and
  textures. 2. **Style & Medium**: Specify if it is photorealistic, digital
  art,  oil painting, etc. 3. **Camera & Lighting**: Define the lens (e.g.,
  85mm), angle,  and light quality (e.g., volumetric, golden hour).

  Guidelines: Use sensory language, avoid buzzwords like
  'photorealistic'  unless necessary, and focus on specific artistic
  descriptors. Once the prompt is created send the prompt to the 
sub_agents: []
tools: []
sub_agent_4.yaml

name: sub_agent_4
model: gemini-2.5-flash
agent_class: LlmAgent
instruction: You are an agent that takes instructions about an image and
  generate the image using the create_image tool.
sub_agents: []
tools:
  - name: Agent2.image_creation_tool.create_image
  1. Bây giờ, hãy kiểm thử.
  2. Trước tiên, hãy khởi động lại Máy chủ ADK (Agent Development Kit). Chuyển đến thiết bị đầu cuối nơi bạn đã khởi động máy chủ ADK (Bộ công cụ phát triển tác nhân)nhấn CTRL+C để tắt máy chủ nếu máy chủ vẫn đang chạy. Thực hiện lệnh sau để khởi động lại máy chủ.
#make sure you are in the right folder.
cd ~/adkui

#start the server
adk web
  1. Nhấn Ctrl+Nhấp vào URL (ví dụ: http://localhost:8000) xuất hiện trên màn hình. Giao diện người dùng ADK (Agent Development Kit) sẽ xuất hiện trên thẻ trình duyệt.
  2. Chọn Agent2 trong danh sách nhân viên hỗ trợ. Sau đó, hãy nhập câu lệnh sau.
Create an image of a Cat
  1. Trong khi Agent đang hoạt động, bạn có thể xem Terminal trong Cloud Shell Editor để biết những gì đang diễn ra ở chế độ nền. Kết quả cuối cùng sẽ có dạng như Hình 26.

dfbd8a88cf7f86a.png

Hình 26: Thử nghiệm Agent

11. Tạo một tác nhân bằng Trợ lý tạo tác nhân

Trợ lý Agent Builder là một phần của ADK Visual Builder (Trình tạo trực quan ADK). Trợ lý này cho phép tạo tác nhân tương tác thông qua các câu lệnh trong một giao diện trò chuyện đơn giản, cho phép các mức độ phức tạp khác nhau. Bằng cách sử dụng Công cụ tạo trực quan ADK, bạn có thể nhận được phản hồi trực quan ngay lập tức về các tác nhân mà bạn phát triển. Trong phòng thí nghiệm này, chúng ta sẽ xây dựng một tác nhân có khả năng tạo truyện tranh HTML theo yêu cầu của người dùng. Người dùng có thể đưa ra một câu lệnh đơn giản như "Tạo một truyện tranh về Hansel và Gretel" hoặc nhập toàn bộ câu chuyện. Sau đó, tác nhân sẽ phân tích nội dung, chia thành nhiều khung và sử dụng Nanobanana để tạo hình ảnh truyện tranh, cuối cùng đóng gói kết quả ở định dạng HTML.

d02de8d649d7c8aa.png

Hình 27: Giao diện người dùng của Trợ lý Agent Builder

Hãy bắt đầu!

  1. Trước tiên, hãy khởi động lại Máy chủ ADK (Agent Development Kit). Chuyển đến thiết bị đầu cuối nơi bạn đã khởi động máy chủ ADK (Bộ công cụ phát triển tác nhân)nhấn CTRL+C để tắt máy chủ nếu máy chủ vẫn đang chạy. Thực hiện lệnh sau để khởi động lại máy chủ.
#make sure you are in the right folder.
cd ~/adkui

#start the server
adk web
  1. Nhấn Ctrl+Nhấp vào URL (ví dụ: http://localhost:8000) xuất hiện trên màn hình. Giao diện người dùng ADK (Agent Development Kit) sẽ xuất hiện trên thẻ trình duyệt.
  2. Trong giao diện người dùng ADK (Agent Development Kit), hãy nhấp vào nút "+" để tạo một Agent mới.
  3. Trong hộp thoại, hãy nhập "Agent3" rồi nhấp vào nút "Tạo". 7300603c2dbfcbbd.png

Hình 28: Tạo Nhân viên hỗ trợ mới Agent3

  1. Trên ngăn Trợ lý ở bên phải, hãy nhập câu lệnh sau. Câu lệnh bên dưới có tất cả hướng dẫn cần thiết để tạo một hệ thống gồm các tác nhân nhằm tạo một tác nhân dựa trên HTML.
System Goal: You are the Studio Director (Root Agent). Your objective is to manage a linear pipeline of four ADK Sequential Agents to transform a user's seed idea into a fully rendered, responsive HTML5 comic book. 

0. Root Agent: The Studio Director
Role: Orchestrator and State Manager.

Logic: Receives the user's initial request. It initializes the workflow and ensures the output of each Sub-Agent is passed as the context for the next. It monitors the sequence to ensure no steps are skipped. Make sure the query explicitly mentions "Create me a comic of ..." if it's just a general question or prompt just answer the question.

1. Sub-Agent: The Scripting Agent (Sequential Step 1)
Role: Narrative & Character Architect.

Input: Seed idea from Root Agent.

Logic: 1. Create a Character Manifest: Define 3 specific, unchangeable visual identifiers 
          for every character (e.g., "Gretel: Blue neon hair ribbons, silver apron, 
          glowing boots"). 
       2. Expand the seed idea into a coherent narrative arc.

Output: A narrative script and a mandatory character visual guide.

2. Sub-Agent: The Panelization Agent (Sequential Step 2)
Role: Cinematographer & Storyboarder.

Input: Script and Character Manifest from Step 1.

Logic: 
     1. Divide the script into exactly X panels (User-defined or default to 8). 
     2. For each panel, define a specific composition (e.g., "Panel 1: 
        Wide shot of the gingerbread house").


Output: A structured list of exactly X panel descriptions.

3. Sub-Agent: The Image Synthesis Agent (Sequential Step 3)
Role: Technical Artist & Asset Generator.

Input: The structured list of panel descriptions from Step 2.

Logic: 
     1. Iterative Generation: You must execute the "generate_image" tool in 
     "image_generation.py" file 
     (Nano Banana) individually for each panel defined in Step 2. 
     2. Prompt Engineering: For every panel, translate the description into a 
     Nano Banana prompt, strictly enforcing the character identifiers 
     (e.g., the "blue neon ribbons") and the global style: "vibrant comic book style, 
     heavy ink lines, cel-shaded, 4k." . Make sure that the necessary speech bubbles
     are present in the image representing the dialogue.
     3. Mapping: Associate each generated image URL with its corresponding panel 
     number and dialogue.

Output: A complete gallery of X images mapped to their respective panel data.

4. Sub-Agent: The Assembly Agent (Sequential Step 4)
Role: Frontend Developer.

Input: The mapped images and panel text from Step 3.

Logic: 
     1. Write a clean, responsive HTML5/CSS3 file that shows the comic. The comic should be
        Scrollable with image on the top and the description below the image.   
     2. Use "write_comic_html" tool in file_writer.py to write the created html file in 
        the "output" folder.      
     4. In the "write_comic_html" tool add logic to copy the images folder to the 
        output folder so that the images in the html file are actually visible when 
        the user opens the html file.

Output: A final, production-ready HTML code block.
  1. Có thể bạn sẽ được yêu cầu nhập mô hình để sử dụng. Trong trường hợp đó, hãy nhập gemini-2.5-pro trong số các lựa chọn được cung cấp.

f2773d0bf9a861e1.png Hình 29: Nhập gemini-2.5-pro nếu bạn nhận được lời nhắc nhập mô hình sẽ được sử dụng

  1. Trợ lý có thể đưa ra kế hoạch và yêu cầu bạn xác nhận xem bạn có muốn tiếp tục hay không. Kiểm tra kế hoạch rồi nhập "OK" và nhấn "Enter".

7bc52b1e4ec468a4.png Hình 30: Nhập OK nếu kế hoạch có vẻ ổn 8. Sau khi Trợ lý hoàn tất quá trình xử lý, bạn sẽ thấy Cấu trúc tác nhân như minh hoạ trong Hình 31.

7f6ed3d590253cf2.png Hình 31: Nhân viên hỗ trợ do Trợ lý tạo nhân viên hỗ trợ tạo ra 9. Trong image_synthesis_agent (tên của bạn có thể khác), hãy nhấp vào công cụ "Agent3.tools.image_generation.gene...". Nếu phần cuối cùng của tên công cụ không phải là image_generation.generate_image change, hãy thay đổi thành image_generation.generate_image. Nếu tên đã được đặt thì bạn không cần thay đổi tên. Nhấn vào nút "Lưu" để lưu.

e48d3e712ba79a57.png Hình 32: Thay đổi tên công cụ thành image_generation.generate_image rồi nhấn vào Lưu.

  1. Trong assembly_agent (Tên tác nhân của bạn có thể khác), hãy nhấp vào công cụ **Agent3.tools.file_writer.write_comic_...**. Nếu phần cuối cùng của tên công cụ không phải là **file_writer.write_comic_html**, hãy thay đổi thành **file_writer.write_comic_html**.

cfff7ecb78a95246.png Hình 33: Thay đổi tên công cụ thành file_writer.write_comic_html 11. Nhấn nút Lưu ở dưới cùng bên trái của bảng điều khiển bên trái để lưu Agent mới tạo. 12. Trong ngăn Trình khám phá của Cloud Shell Editor, hãy mở rộng thư mục Agent3. Bên trong thư mục Agent3/ sẽ có thư mục tools. Nhấp vào Agent3/tools/file_writer.py để mở tệp này rồi thay thế nội dung của Agent3/tools/file_writer.py bằng đoạn mã sau. Nhấn tổ hợp phím Ctrl+S để lưu. Lưu ý: Mặc dù Trợ lý AI có thể đã tạo mã chính xác, nhưng trong lớp học này, chúng ta sẽ sử dụng mã đã được kiểm thử.

import os
import shutil

def write_comic_html(html_content: str, image_directory: str = "images") -> str:
   """
   Writes the final HTML content to a file and copies the image assets.

   Args:
       html_content: A string containing the full HTML of the comic.
       image_directory: The source directory where generated images are stored.

   Returns:
       A confirmation message indicating success or failure.
   """
   output_dir = "output"
   images_output_dir = os.path.join(output_dir, image_directory)

   try:
       # Create the main output directory
       if not os.path.exists(output_dir):
           os.makedirs(output_dir)

       # Copy the entire image directory to the output folder
       if os.path.exists(image_directory):
           if os.path.exists(images_output_dir):
               shutil.rmtree(images_output_dir)  # Remove old images
           shutil.copytree(image_directory, images_output_dir)
       else:
           return f"Error: Image directory '{image_directory}' not found."

       # Write the HTML file
       html_file_path = os.path.join(output_dir, "comic.html")
       with open(html_file_path, "w") as f:
           f.write(html_content)

       return f"Successfully created comic at '{html_file_path}'"

   except Exception as e:
       return f"An error occurred: {e}"
  1. Trong ngăn Trình khám phá của Cloud Shell Editor, hãy mở rộng thư mục Agent3 và bên trong thư mục **Agent3/**phải có thư mục tools. Nhấp vào Agent3/tools/image_generation.py để mở tệp này rồi thay thế nội dung của Agent3/tools/image_generation.py bằng đoạn mã sau. Nhấn Ctrl+S để lưu. Lưu ý: Mặc dù Trợ lý AI có thể đã tạo mã chính xác, nhưng trong lớp học này, chúng ta sẽ sử dụng mã đã được kiểm thử.
import time
import os
import io
import vertexai
from vertexai.preview.vision_models import ImageGenerationModel
from dotenv import load_dotenv
import uuid
from typing import Union
from datetime import datetime
from google import genai
from google.genai import types
from google.adk.tools import ToolContext

import logging
import asyncio

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# It's better to initialize the client once and reuse it.
# IMPORTANT: Your Google Cloud Project ID must be set as an environment variable
# for the client to authenticate correctly.


def edit_image(client, prompt: str, previous_image: str, model_id: str) -> Union[bytes, None]:
   """
   Calls the model to edit an image based on a prompt.

   Args:
       prompt: The text prompt for image editing.
       previous_image: The path to the image to be edited.
       model_id: The model to use for the edit.

   Returns:
       The raw image data as bytes, or None if an error occurred.
   """

   try:
       with open(previous_image, "rb") as f:
           image_bytes = f.read()

       response = client.models.generate_content(
           model=model_id,
           contents=[
               types.Part.from_bytes(
                   data=image_bytes,
                   mime_type="image/png",  # Assuming PNG, adjust if necessary
               ),
               prompt,
           ],
           config=types.GenerateContentConfig(
               response_modalities=['IMAGE'],
           )
       )

       # Extract image data
       for part in response.candidates[0].content.parts:
           if part.inline_data:
               return part.inline_data.data

       logger.warning("Warning: No image data was generated for the edit.")
       return None

   except FileNotFoundError:
       logger.error(f"Error: The file {previous_image} was not found.")
       return None
   except Exception as e:
       logger.error(f"An error occurred during image editing: {e}")
       return None

async def generate_image(tool_context: ToolContext, prompt: str, image_name: str, previous_image: str = None) -> dict:
   """
   Generates or edits an image and saves it to the 'images/' directory.

   If 'previous_image' is provided, it edits that image. Otherwise, it generates a new one.

   Args:
       prompt: The text prompt for the operation.
       image_name: The desired name for the output image file (without extension).
       previous_image: Optional path to an image to be edited.

   Returns:
       A confirmation message with the path to the saved image or an error message.
   """
   load_dotenv()
   project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
   if not project_id:
       return "Error: GOOGLE_CLOUD_PROJECT environment variable is not set."
  
   try:
       client = genai.Client(vertexai=True, project=project_id, location="global")
   except Exception as e:
       return f"Error: Failed to initialize genai.Client: {e}"

   image_data = None
   model_id = "gemini-3-pro-image-preview"

   try:
       if previous_image:
           logger.info(f"Editing image: {previous_image}")
           image_data = edit_image(
               client=client,
               prompt=prompt,
               previous_image=previous_image,
               model_id=model_id
           )
       else:
           logger.info("Generating new image")
           # Generate the image
           response = client.models.generate_content(
               model=model_id,
               contents=prompt,
               config=types.GenerateContentConfig(
                   response_modalities=['IMAGE'],
                   image_config=types.ImageConfig(aspect_ratio="16:9"),
               ),
           )

           # Check for errors
           if response.candidates[0].finish_reason != types.FinishReason.STOP:
               return f"Error: Image generation failed. Reason: {response.candidates[0].finish_reason}"

           # Extract image data
           for part in response.candidates[0].content.parts:
               if part.inline_data:
                   image_data = part.inline_data.data
                   break

       if not image_data:
           return {"status": "error", "message": "No image data was generated.", "artifact_name": None}

       # Create the images directory if it doesn't exist
       output_dir = "images"
       os.makedirs(output_dir, exist_ok=True)

       # Save the image to file system
       file_path = os.path.join(output_dir, f"{image_name}.png")
       with open(file_path, "wb") as f:
           f.write(image_data)

       # Save as ADK artifact
       counter = str(tool_context.state.get("loop_iteration", 0))
       artifact_name = f"{image_name}_" + counter + ".png"
       report_artifact = types.Part.from_bytes(data=image_data, mime_type="image/png")
       await tool_context.save_artifact(artifact_name, report_artifact)
       logger.info(f"Image also saved as ADK artifact: {artifact_name}")

       return {
           "status": "success",
           "message": f"Image generated and saved to {file_path}. ADK artifact: {artifact_name}.",
           "artifact_name": artifact_name,
       }

   except Exception as e:
       return f"An error occurred: {e}"
  1. Các tệp YAML cuối cùng được tạo trong môi trường của tác giả được cung cấp bên dưới để bạn tham khảo (Xin lưu ý rằng các tệp trong môi trường của bạn có thể hơi khác). Vui lòng đảm bảo rằng cấu trúc YAML của tác nhân tương ứng với bố cục xuất hiện trong ADK Visual Builder.
root_agent.yamlname: studio_director
model: gemini-2.5-pro
agent_class: LlmAgent
description: The Studio Director who manages the comic creation pipeline.
instruction: >
 You are the Studio Director. Your objective is to manage a linear pipeline of
 four sequential agents to transform a user's seed idea into a fully rendered,
 responsive HTML5 comic book.


 Your role is to be the primary orchestrator and state manager. You will
 receive the user's initial request.


 **Workflow:**

 1.  If the user's prompt starts with "Create me a comic of ...", you must
 delegate the task to your sub-agent to begin the comic creation pipeline.

 2.  If the user asks a general question or provides a prompt that does not
 explicitly ask to create a comic, you must answer the question directly
 without triggering the comic creation pipeline.

 3.  Monitor the sequence to ensure no steps are skipped. Ensure the output of
 each Sub-Agent is passed as the context for the next.
sub_agents:
 - config_path: ./comic_pipeline.yaml
tools: []
comic_pipline.yaml
name: comic_pipeline
agent_class: SequentialAgent
description: A sequential pipeline of agents to create a comic book.
sub_agents:
 - config_path: ./scripting_agent.yaml
 - config_path: ./panelization_agent.yaml
 - config_path: ./image_synthesis_agent.yaml
 - config_path: ./assembly_agent.yaml
scripting_agent.yamlname: scripting_agent
model: gemini-2.5-pro
agent_class: LlmAgent
description: Narrative & Character Architect.
instruction: >
 You are the Scripting Agent, a Narrative & Character Architect.

 Your input is a seed idea for a comic.


 **Your Logic:**

 1.  **Create a Character Manifest:** You must define exactly 3 specific,
 unchangeable visual identifiers for every character. For example: "Gretel:
 Blue neon hair ribbons, silver apron, glowing boots". This is mandatory.

 2.  **Expand the Narrative:** Expand the seed idea into a coherent narrative
 arc with dialogue.


 **Output:**

 You must output a JSON object containing:

 - "narrative_script": A detailed script with scenes and dialogue.

 - "character_manifest": The mandatory character visual guide.
sub_agents: []
tools: []
panelization_agent.yamlname: panelization_agent
model: gemini-2.5-pro
agent_class: LlmAgent
description: Cinematographer & Storyboarder.
instruction: >
 You are the Panelization Agent, a Cinematographer & Storyboarder.

 Your input is a narrative script and a character manifest.


 **Your Logic:**

 1.  **Divide the Script:** Divide the script into a specific number of panels.
 The user may define this number, or you should default to 8 panels.

 2.  **Define Composition:** For each panel, you must define a specific
 composition, camera shot (e.g., "Wide shot", "Close-up"), and the dialogue for
 that panel.


 **Output:**

 You must output a JSON object containing a structured list of exactly X panel
 descriptions, where X is the number of panels. Each item in the list should
 have "panel_number", "composition_description", and "dialogue".
sub_agents: []
tools: []
image_synthesis_agent.yaml
name: image_synthesis_agent
model: gemini-2.5-pro
agent_class: LlmAgent
description: Technical Artist & Asset Generator.
instruction: >
 You are the Image Synthesis Agent, a Technical Artist & Asset Generator.

 Your input is a structured list of panel descriptions.


 **Your Logic:**

 1.  **Iterate and Generate:** You must iterate through each panel description
 provided in the input. For each panel, you will execute the `generate_image`
 tool.

 2.  **Construct Prompts:** For each panel, you will construct a detailed
 prompt for the image generation tool. This prompt must strictly enforce the
 character visual identifiers from the manifest and include the global style:
 "vibrant comic book style, heavy ink lines, cel-shaded, 4k". The prompt must
 also describe the composition and include a request for speech bubbles to
 contain the dialogue.

 3.  **Map Output:** You must associate each generated image URL with its
 corresponding panel number and dialogue.


 **Output:**

 You must output a JSON object containing a complete gallery of all generated
 images, mapped to their respective panel data (panel_number, dialogue,
 image_url).
sub_agents: []
tools:
 - name: Agent3.tools.image_generation.generate_image
assembly_agent.yamlname: assembly_agent
model: gemini-2.5-pro
agent_class: LlmAgent
description: Frontend Developer for comic book assembly.
instruction: >
 You are the Assembly Agent, a Frontend Developer.

 Your input is the mapped gallery of images and panel data.


 **Your Logic:**

 1.  **Generate HTML:** You will write a clean, responsive HTML5/CSS3 file to
 display the comic. The comic must be vertically scrollable, with each panel
 displaying its image on top and the corresponding dialogue or description
 below it.

 2.  **Write File:** You must use the `write_comic_html` tool to save the
 generated HTML to a file named `comic.html` in the `output/` folder.

 3.  Pass the list of image URLs to the tool so it can handle the image assets
 correctly.


 **Output:**

 You will output a confirmation message indicating the path to the final HTML
 file.
sub_agents: []
tools:
 - name: Agent3.tools.file_writer.write_comic_html
  1. Chuyển đến thẻ giao diện người dùng ADK (Bộ công cụ phát triển tác nhân) , chọn "Agent3" rồi nhấp vào nút chỉnh sửa ("Biểu tượng bút").
  2. Nhấp vào nút Lưu ở dưới cùng bên trái màn hình. Thao tác này sẽ duy trì tất cả các thay đổi về mã mà bạn đã thực hiện đối với tác nhân chính.
  3. Bây giờ, chúng ta có thể bắt đầu kiểm thử tác nhân!
  4. Đóng thẻ giao diện người dùng ADK (Bộ công cụ phát triển tác nhân) hiện tại rồi quay lại thẻ Cloud Shell Editor.
  5. Trong cửa sổ dòng lệnh bên trong thẻ Cloud Shell Editor, trước tiên, hãy khởi động lại Máy chủ ADK (Bộ công cụ phát triển tác nhân). Chuyển đến thiết bị đầu cuối nơi bạn đã khởi động máy chủ ADK (Bộ công cụ phát triển tác nhân)nhấn CTRL+C để tắt máy chủ nếu máy chủ vẫn đang chạy. Thực hiện lệnh sau để khởi động lại máy chủ.
#make sure you are in the right folder.
cd ~/adkui

#start the server
adk web
  1. Nhấn Ctrl+Nhấp vào URL (ví dụ: http://localhost:8000) xuất hiện trên màn hình. Giao diện người dùng ADK (Agent Development Kit) sẽ xuất hiện trên thẻ trình duyệt.
  2. Chọn Agent3 trong danh sách Nhân viên hỗ trợ.
  3. Nhập câu lệnh sau
Create a Comic Book based on the following story,

Title: The Story of Momotaro

The story of Momotaro (Peach Boy) is one of Japan's most famous and beloved folktales. It is a classic "hero's journey" that emphasizes the virtues of courage, filial piety, and teamwork.

The Miraculous Birth
Long, long ago, in a small village in rural Japan, lived an elderly couple. They were hardworking and kind, but they were sad because they had never been blessed with children.

One morning, while the old woman was washing clothes by the river, she saw a magnificent, giant peach floating downstream. It was larger than any peach she had ever seen. With great effort, she pulled it from the water and brought it home to her husband for their dinner.

As they prepared to cut the fruit open, the peach suddenly split in half on its own. To their astonishment, a healthy, beautiful baby boy stepped out from the pit.

"Don't be afraid," the child said. "The Heavens have sent me to be your son."

Overjoyed, the couple named him Momotaro (Momo meaning peach, and Taro being a common name for an eldest son).

The Call to Adventure
Momotaro grew up to be stronger and kinder than any other boy in the village. During this time, the village lived in fear of the Oniogres and demons who lived on a distant island called Onigashima. These Oni would often raid the mainland, stealing treasures and kidnapping villagers.

When Momotaro reached young adulthood, he approached his parents with a request. "I must go to Onigashima," he declared. "I will defeat the Oni and bring back the stolen treasures to help our people."

Though they were worried, his parents were proud. As a parting gift, the old woman prepared Kibi-dango (special millet dumplings), which were said to provide the strength of a hundred men.

Gathering Allies
Momotaro set off on his journey toward the sea. Along the way, he met three distinct animals:

The Spotted Dog: The dog growled at first, but Momotaro offered him one of his Kibi-dango. The dog, tasting the magical dumpling, immediately swore his loyalty.

The Monkey: Further down the road, a monkey joined the group in exchange for a dumpling, though he and the dog bickered constantly.

The Pheasant: Finally, a pheasant flew down from the sky. After receiving a piece of the Kibi-dango, the bird joined the team as their aerial scout.

Momotaro used his leadership to ensure the three animals worked together despite their differences, teaching them that unity was their greatest strength.

The Battle of Onigashima
The group reached the coast, built a boat, and sailed to the dark, craggy shores of Onigashima. The island was guarded by a massive iron gate.

The Pheasant flew over the walls to distract the Oni and peck at their eyes.

The Monkey climbed the walls and unbolted the Great Gate from the inside.

The Dog and Momotaro charged in, using their immense strength to overpower the demons.

The Oni were caught off guard by the coordinated attack. After a fierce battle, the King of the Oni fell to his knees before Momotaro, begging for mercy. He promised to never trouble the villagers again and surrendered all the stolen gold, jewels, and precious silks.

The Triumphant Return
Momotaro and his three companions loaded the treasure onto their boat and returned to the village. The entire town celebrated their homecoming.

Momotaro used the wealth to ensure his elderly parents lived the rest of their lives in comfort and peace. He remained in the village as a legendary protector, and his story was passed down for generations as a reminder that bravery and cooperation can overcome even the greatest evils.
  1. Trong khi Agent đang hoạt động, bạn có thể xem các sự kiện trong cửa sổ dòng lệnh của Cloud Shell Editor.
  2. Có thể mất một lúc để tạo tất cả hình ảnh, vì vậy, vui lòng kiên nhẫn hoặc tranh thủ uống một tách cà phê! Khi quá trình tạo hình ảnh bắt đầu, bạn sẽ thấy những hình ảnh liên quan đến câu chuyện như bên dưới.

2dbdfb6916b75ef0.jpeg

Hình 34: Câu chuyện về Momotaro dưới dạng truyện tranh liên hoàn 25. Nếu mọi thứ diễn ra suôn sẻ, tệp html được tạo sẽ được lưu trong thư mục html. Nếu muốn cải thiện Trợ lý ảo, bạn có thể quay lại Trợ lý ảo và yêu cầu Trợ lý ảo thực hiện thêm các thay đổi!

a4840cb8a82ec55.jpeg

Hình 35: Nội dung của thư mục đầu ra

  1. Nếu bước 25 chạy đúng cách và bạn nhận được comic.html trong thư mục output. Bạn có thể chạy các bước sau để kiểm thử. Trước hết, hãy mở một cửa sổ dòng lệnh mới bằng cách nhấp vào Terminal>New Terminal (Cửa sổ dòng lệnh > Cửa sổ dòng lệnh mới) trên trình đơn chính của Cloud Shell Editor (Trình chỉnh sửa Cloud Shell). Thao tác này sẽ mở một cửa sổ Terminal mới.
#go to the project folder
cd ~/adkui

#activate python virtual environment
source .venv/bin/activate

#Go to the output folder
cd ~/adkui/output

#start local web server
python -m http.server 8080
  1. Nhấp vào http://0.0.0.0:8080 bằng tổ hợp phím Ctrl

16e0108a9f27e44e.png

Hình 36: Chạy máy chủ web cục bộ

  1. Nội dung của thư mục sẽ xuất hiện trong thẻ trình duyệt. Nhấp vào tệp html (ví dụ: comic.html). Truyện tranh sẽ hiển thị như bên dưới (Kết quả đầu ra của bạn có thể hơi khác). 4fb869f885cb938b.jpeg

Hình 37: Chạy trên máy chủ cục bộ

12. Dọn dẹp

Bây giờ, hãy dọn dẹp những gì chúng ta vừa tạo.

  1. Xoá ứng dụng Cloud Run mà chúng ta vừa tạo. Chuyển đến Cloud Run bằng cách truy cập vào Cloud Run . Bạn sẽ thấy ứng dụng mà mình đã tạo ở bước trước. Đánh dấu vào hộp bên cạnh ứng dụng rồi nhấp vào nút Xoá.

db630152398108cb.png Hình 38: Xoá ứng dụng Cloud Run 2. Xoá các tệp trong Cloud Shell

#Execute the following to delete the files
cd ~
rm -R ~/adkui

13. Kết luận

Xin chúc mừng! Bạn đã tạo thành công các tác nhân ADK (Bộ công cụ phát triển tác nhân) bằng Trình tạo trực quan ADK tích hợp. Bạn cũng đã tìm hiểu cách triển khai ứng dụng này trên Cloud Run. Đây là một thành tựu đáng kể bao gồm vòng đời cốt lõi của một ứng dụng hiện đại dựa trên đám mây, mang đến cho bạn nền tảng vững chắc để triển khai các hệ thống đại lý phức tạp của riêng mình.

Tóm tắt

Trong phòng thực hành này, bạn đã học được cách:

Tài nguyên hữu ích