Xây dựng tác nhân AI bằng ADK: Điều phối quy trình công việc của tác nhân

1. Tổng quan

Để đáp ứng một yêu cầu du lịch có nhiều ràng buộc (chẳng hạn như thiết kế một hành trình cả ngày ở Kyoto với ngân sách dưới 100 USD, tập trung vào các ngôi đền lịch sử và ẩm thực địa phương, không có phòng trưng bày nghệ thuật hiện đại), mô hình cần trích xuất các ràng buộc, nghiên cứu các điểm tham quan và địa điểm ăn uống cùng lúc, lập lịch trình chi tiết và kiểm tra kế hoạch cuối cùng. Việc dựa vào một tác nhân nguyên khối duy nhất có nhiều công cụ có thể bỏ qua các bước xác minh hoặc vi phạm các quy tắc loại trừ, vì vậy, quy trình điều phối sẽ điều phối các tác nhân phụ chuyên biệt thông qua bộ điều khiển quy trình làm việc tất định.

Trong phần thứ ba của loạt bài Xây dựng tác nhân AI bằng ADK, bạn sẽ xây dựng một công cụ lập kế hoạch du lịch đa tác nhân độc lập trên Nền tảng tác nhân bằng cách sử dụng bộ điều khiển quy trình công việc (SequentialAgent, ParallelAgent và LoopAgent) của Bộ công cụ phát triển tác nhân (ADK) 2. Qua ba giai đoạn tiến triển (không cần thiết lập không gian làm việc ở Phần 1 hoặc Phần 2), bạn sẽ điều phối sáu tác nhân chuyên biệt dựa trên gemini-3.8-flash với trạng thái phiên dùng chung (output_key), thực thi google_search đồng thời và vòng lặp tinh chỉnh lặp lại giữa người tạo và người kiểm tra.

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

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

  • Cách tạo khung cho một dự án ADK 2 đa tác nhân từ đầu
  • Cách thiết kế một nhóm tác nhân chuyên biệt dùng chung trạng thái phiên bằng output_key
  • Cách sử dụng SequentialAgent để thực thi các tác nhân phụ trong một quy trình từng bước, tất định
  • Cách sử dụng ParallelAgent để chạy đồng thời các tác nhân nghiên cứu độc lập nhằm giảm độ trễ
  • Cách sử dụng tính năng chuyển cấp LoopAgent và ToolContext để triển khai vòng lặp tinh chỉnh lặp lại của người tạo và người kiểm tra
  • Cách kết hợp các mẫu tuần tự, song song và lặp lại thành một quy trình làm việc phân cấp gồm nhiều tác nhân

Bạn cần có

  • Tài khoản Google (sử dụng tài khoản @gmail.com cá nhân nếu bạn muốn nhận tín dụng cho hội thảo)
  • Đường liên kết nhận tín dụng cho hội thảo do người hướng dẫn cung cấp (cùng với camera điện thoại để quét mã QR) hoặc một tài khoản thanh toán trên Cloud đang hoạt động
  • Google Chrome (bạn nên dùng cửa sổ ẩn danh để tránh nhầm lẫn giữa tài khoản cá nhân và tài khoản công việc)

2. Nhận khoản tín dụng Google Cloud (Không bắt buộc)

Nếu bạn đang tham dự một hội thảo có đường liên kết nhận tín dụng cho sự kiện, hãy nhận tín dụng Google Developer Program để cấp tài khoản thanh toán mà không cần thẻ tín dụng.

Nhận khoản tín dụng cho sự kiện

  1. Mở đường liên kết nhận tín dụng hội thảo trong cửa sổ Ẩn danh rồi đăng nhập bằng tài khoản @gmail.com của bạn.
  2. Nhấp vào Nhận tín dụng trên trang Nhận lợi ích:

Thẻ Nhận lợi ích của bạn trên Trung tâm Nhà phát triển của Google, trong đó có nút Nhận tín dụng

  1. Nếu được nhắc tạo hồ sơ Google Developer Program, hãy hoàn tất biểu mẫu.
  2. Khi thông báo Quét để xác minh bạn là người thật xuất hiện, hãy quét mã QR bằng điện thoại và hoàn tất quy trình xác minh (làm mới và nhấp lại vào Nhận tín dụng nếu mã QR không xuất hiện):

Hộp thoại mã QR "Quét để xác minh bạn là người thật" của Google Developer Program

  1. Xác nhận thông báo Đã nhận thành công khoản tín dụng cho sự kiện! xuất hiện, sau đó nhấp vào Mở tài khoản thanh toán:

Trung tâm Nhà phát triển của Google cho thấy thông báo "Đã nhận thành công khoản tín dụng cho sự kiện" và nút "Mở tài khoản thanh toán"

🔍 Kiểm tra bài làm

Quá trình thiết lập tài khoản thanh toán mất tối đa 3 phút:

  1. Mở Google Cloud Billing (hoặc sao chép URL vào cửa sổ ẩn danh) rồi chọn Tài khoản thanh toán của bạn:
https://console.cloud.google.com/billing
  1. Làm mới cho đến khi tài khoản GDP Credit của bạn có trạng thái Đang hoạt động:

Trang quản lý tài khoản thanh toán trên Google Cloud cho thấy một tài khoản thanh toán có khoản tín dụng GDP đang hoạt động

3. Tạo một dự án trên Google Cloud (Không bắt buộc)

Tạo một dự án Google Cloud chuyên biệt để tất cả tài nguyên trong lớp học lập trình này được tách biệt và dễ dọn dẹp.

  1. Mở trang Tạo dự án (hoặc sao chép URL vào cửa sổ ẩn danh):
https://console.cloud.google.com/projectcreate
  1. Nhập thông tin chi tiết về dự án:
    • Tên dự án: Ví dụ: google-cloud-workshop
    • Tài khoản thanh toán (nếu có): Chọn GDP Credit (hoặc tài khoản thanh toán đang hoạt động của bạn)
    • Tài nguyên gốc: Không có tổ chức (hoặc tổ chức của bạn nếu cần)
  2. Ghi lại Mã dự án được tạo bên dưới tên dự án, sau đó nhấp vào Tạo:

Màn hình Tạo dự án trên Google Cloud cho thấy Tên dự án, Mã dự án, Tài nguyên gốc và nút Tạo

🔍 Kiểm tra bài làm

Nhấp vào Notifications (Thông báo) trong thanh công cụ trên cùng bên phải rồi nhấp vào Select Project (Chọn dự án) sau khi tạo xong dự án:

Trình đơn Thông báo trên Google Cloud Console cho thấy đường liên kết Tạo dự án và Chọn dự án

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

Định cấu hình Google Cloud Shell, bật Agent Platform API và tạo một môi trường ảo Python 3.12 tách biệt bằng uv.

Định cấu hình Cloud Shell

  1. Nhấp vào Activate Cloud Shell (Kích hoạt Cloud Shell) (>_) trên thanh công cụ của Google Cloud Console hoặc mở trực tiếp Google Cloud Shell (hoặc sao chép URL vào cửa sổ ẩn danh):
https://shell.cloud.google.com/?show=ide,terminal

Nút Kích hoạt Cloud Shell trên thanh công cụ của Cloud Console

  1. Nhấp vào Authorize (Uỷ quyền) nếu được nhắc:

Hộp thoại uỷ quyền Cloud Shell

  1. Chọn Mã dự án Google Cloud đang hoạt động trong trình đơn được đánh số trong dòng lệnh:
unset CLOUDSDK_CORE_PROJECT
PS3="Select your project (e.g. 1): "
select PROJECT_ID in $(gcloud projects list --format="value(projectId)"); do
  [ -n "$PROJECT_ID" ] && gcloud config set project "$PROJECT_ID" && break
done

Bạn sẽ thấy kết quả tương tự như sau (các dự án chưa được gắn thẻ cũng in một dòng thông tin [environment: untagged]):

1) google-cloud-workshop-4210
2) my-cloud-project-8812
Select your project (e.g. 1): 1
Updated property [core/project].

Xác minh rằng Mã dự án bạn chọn xuất hiện được đánh dấu bằng màu vàng trong lời nhắc của Cloud Shell:

Thiết bị đầu cuối Cloud Shell cho thấy mã dự án đã chọn được đánh dấu bằng màu vàng

Bật các API bắt buộc

Bật Agent Platform API để các tác nhân ADK có thể gọi các mô hình Gemini:

gcloud services enable aiplatform.googleapis.com

Bạn sẽ thấy kết quả tương tự như sau:

Operation "operations/acat.p2-..." finished successfully.

Tạo môi trường ảo Python và cài đặt ADK

Tạo không gian làm việc ~/adk-agents và kích hoạt môi trường ảo Python 3.12:

cd ~
mkdir -p adk-agents && cd ~/adk-agents

which uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"

uv venv .venv --python 3.12
source .venv/bin/activate

Xác nhận tiền tố (.venv) xuất hiện ở đầu lời nhắc của thiết bị đầu cuối:

Cửa sổ dòng lệnh Cloud Shell cho thấy tiền tố .venv trên một môi trường ảo Python đang hoạt động

Cài đặt ADK 2 trong môi trường ảo đang hoạt động:

uv pip install --no-cache "google-adk==2.14.0"

🔍 Kiểm tra bài làm

Xác minh phiên bản adk CLI đã cài đặt:

adk --version

Bạn sẽ thấy kết quả tương tự như sau:

adk, version 2.14.0

5. Tạo khung cho tác nhân lập kế hoạch du lịch

Khi môi trường đã sẵn sàng, hãy sử dụng lệnh adk create tích hợp sẵn của ADK để tạo tệp khởi động cho gói tác nhân travel_planner.

Tạo gói khởi đầu

Chạy adk create từ thư mục ~/adk-agents:

cd ~/adk-agents
adk create travel_planner

Khi được nhắc trong dòng lệnh, hãy chọn các tuỳ chọn cấu hình sau (nếu được nhắc bằng Enable telemetry? [Y/n]: trong lần chạy đầu tiên, hãy nhấn Enter hoặc nhập n rồi nhấn Enter):

  1. Chọn một mô hình cho tác nhân gốc: Nhập 2 để chọn gemini-3.8-flash (lựa chọn 1 chọn gemini-3.5-flash) rồi nhấn phím Enter.
  2. Chọn một phần phụ trợ: Nhập 2 để chọn phần phụ trợ Nền tảng tác nhân của Google Cloud (mục 2 trong trình đơn CLI bên dưới) rồi nhấn phím Enter.
  3. Nhập mã dự án trên Google Cloud: Xác nhận Mã dự án của bạn trong ngoặc bằng cách nhấn phím Enter.
  4. Enter Google Cloud region (Nhập khu vực Google Cloud): Nhập global rồi nhấn Enter.

adk create ghi GOOGLE_GENAI_USE_ENTERPRISE=1, mã dự án và GOOGLE_CLOUD_LOCATION=global vào travel_planner/.env, nhờ đó thông tin đăng nhập của bạn vẫn được định cấu hình khi bạn cập nhật agent.py sau này.

🔍 Kiểm tra bài làm

Bạn sẽ thấy kết quả tương tự như sau:

Choose a model for the root agent:
1. gemini-3.5-flash
2. gemini-3.8-flash
3. Other models (fill later)
Choose model (1, 2, 3): 2
1. Google AI
2. Vertex AI
3. Login with Google
Choose a backend (1, 2, 3): 2

You need an existing Google Cloud account and project, check out this link for details:
https://google.github.io/adk-docs/get-started/quickstart/#gemini---google-cloud-vertex-ai

Enter Google Cloud project ID [google-cloud-workshop-4210]:
Enter Google Cloud region [us-central1]: global

Agent created in /home/your_username/adk-agents/travel_planner:
- .env
- .gitignore
- __init__.py
- agent.py

⚠️  WARNING: Secrets (like GOOGLE_API_KEY) are stored in .env.

Next steps:
- Chat with your agent in the terminal: adk run travel_planner
- Or in the browser: adk web .
- Have your coding agent evaluate and deploy it: uvx google-agents-cli setup
  (other install options: https://adk.dev/get-started/agents-cli/)

Mở thư mục hiện tại trong trình soạn thảo mã Cloud Shell để bạn có thể kiểm tra và chỉnh sửa các tệp song song với cửa sổ dòng lệnh:

which cloudshell >/dev/null 2>&1 && cloudshell workspace ~/adk-agents || true
cd ~/adk-agents
source .venv/bin/activate

Kiểm thử tác nhân đơn mặc định

Trước khi xây dựng quy trình làm việc nhiều tác nhân, hãy chạy Giao diện người dùng phát triển ADK để quan sát cách tác nhân đơn lẻ mặc định phản hồi một truy vấn lập kế hoạch du lịch chung:

cd ~/adk-agents
adk web --allow_origins "*"

Mở Giao diện người dùng phát triển trong trình duyệt bằng tính năng Xem trước trên web của Cloud Shell:

  1. Nhấp vào biểu tượng Web Preview (Bản xem trước trên web) trong thanh công cụ trên cùng bên phải của Cloud Shell.
  2. Chọn Thay đổi cổng, nhập 8000 rồi nhấp vào Thay đổi và xem trước.

Hộp thoại cấu hình cổng Xem trước trên web của Cloud Shell được đặt thành 8000

Sau khi giao diện người dùng web ADK tải xong, hãy gửi một lời chào như "hello, what can you do?" hoặc "Help me plan a trip to Japan":

Giao diện người dùng web phát triển ADK cho thấy một cuộc trò chuyện cơ bản với một tác nhân

Hãy lưu ý rằng root_agent duy nhất trả lời trực tiếp trong một lượt mà không cần trích xuất lựa chọn ưu tiên có cấu trúc, nghiên cứu web trực tiếp hoặc xác minh ngân sách.

Khi bạn kiểm thử xong, hãy nhấn tổ hợp phím Ctrl + C trong thiết bị đầu cuối Cloud Shell để dừng máy chủ adk web và quay lại dấu nhắc lệnh.

6. Xây dựng quy trình công việc SequentialAgent

Bây giờ, bạn sẽ xây dựng mẫu điều phối đầu tiên: một quy trình công việc tuyến tính dựa trên SequentialAgent. Trong quy trình tuần tự, các tác nhân phụ sẽ thực thi theo thứ tự nghiêm ngặt. Chuyên gia đầu tiên trích xuất các tham số có cấu trúc và lưu vào trạng thái phiên dùng chung bằng output_key="user_preferences", còn chuyên gia thứ hai đọc {user_preferences} từ trạng thái dùng chung để soạn thảo hành trình.

Sơ đồ cấu trúc cho thấy root_agent uỷ quyền cho master_travel_agent (SequentialAgent), chạy user_profiler_agent, sau đó là itinerary_synthesizer_agent thông qua trạng thái phiên dùng chung

Tạo chuyên gia ban đầu (specialists.py)

Mở một tệp mới có tên specialists.py bên trong travel_planner/:

cloudshell edit ~/adk-agents/travel_planner/specialists.py

Dán mã sau vào travel_planner/specialists.py để xác định user_profiler_agent và itinerary_synthesizer_agent (nhập trước ToolContext và google_search cho các bước tiếp theo):

from google.adk import Agent
from google.adk.tools import ToolContext, google_search

# --- Specialist 1: The User Profiler ---
user_profiler_agent = Agent(
    name="user_profiler_agent",
    description="Extracts travel preferences and constraints from user input.",
    instruction="""
        Extract destination, duration (default 1 day), budget, interests, and exclusions.
        Return a single JSON object with keys: "destination", "duration", "budget", "interests", "exclusions".
    """,
    output_key="user_preferences",  # Saves output to state['user_preferences']
)

# --- Specialist 2: The Synthesizer ---
itinerary_synthesizer_agent = Agent(
    name="itinerary_synthesizer_agent",
    description="Compiles preferences and research into a final Markdown itinerary.",
    instruction="""
        You are an elite Travel Concierge. Write a Markdown itinerary with an itemized USD and local currency cost breakdown using:
        - User Preferences: {user_preferences}
        - Activities (if available): {activity_recommendations?}
        - Restaurants (if available): {restaurant_recommendations?}
    """,
    output_key="final_itinerary",
)

Kết nối quy trình tuần tự (workflows.py)

Tạo một tệp mới có tên workflows.py bên trong travel_planner/ để điều phối các chuyên gia:

cloudshell edit ~/adk-agents/travel_planner/workflows.py

Thêm định nghĩa SequentialAgent sau vào travel_planner/workflows.py:

from google.adk.agents import SequentialAgent
from .specialists import (
    user_profiler_agent,
    itinerary_synthesizer_agent,
)

# 1. SEQUENTIAL PHASE: A linear two-step workflow
master_travel_agent = SequentialAgent(
    name="master_travel_agent",
    description="Orchestrates the end-to-end travel planning process for trip and itinerary requests.",
    sub_agents=[
        user_profiler_agent,         # Step 1: Extract constraints into user_preferences
        itinerary_synthesizer_agent,  # Step 2: Draft itinerary from user_preferences
    ],
)

Kết nối quy trình công việc với root_agent (agent.py)

Bây giờ, hãy đăng ký master_travel_agent làm đại lý phụ của root_agent. Mở travel_planner/agent.py:

cloudshell edit ~/adk-agents/travel_planner/agent.py

Thay thế nội dung của travel_planner/agent.py bằng mã sau:

from google.adk import Agent
from .workflows import master_travel_agent

MODEL = "gemini-3.8-flash"

root_agent = Agent(
    model=MODEL,
    name="root_agent",
    description="A helpful assistant for user questions.",
    instruction=(
        "Greet the user and delegate any travel or trip planning requests "
        "to master_travel_agent."
    ),
    sub_agents=[master_travel_agent],
)

🔍 Kiểm tra bài làm

Khởi động Giao diện người dùng web của ADK từ thiết bị đầu cuối:

cd ~/adk-agents
adk web --allow_origins "*"

Mở Bản xem trước trên web trên cổng 8000 rồi nhập câu lệnh:

Help me plan a trip to Kyoto

Bạn sẽ thấy kết quả tương tự như luồng thực thi sau đây trong chế độ xem Events (Sự kiện):

1. root_agent -> calls transfer_to_agent(agent_name="master_travel_agent")
2. user_profiler_agent -> outputs JSON {"destination": "Kyoto", "duration": "1 day", ...} to state['user_preferences']
3. itinerary_synthesizer_agent -> reads {user_preferences} and outputs the formatted Markdown itinerary

Giao diện người dùng web của ADK 2.14.0 cho thấy biểu đồ thực thi từ root_agent thông qua master_travel_agent đến user_profiler_agent và itinerary_synthesizer_agent cùng với hành trình đã tạo ở Kyoto

Nhấp vào huy hiệu sự kiện bất kỳ (hoặc khối State: final_itinerary) rồi chuyển sang thẻ State (Trạng thái) trong bảng điều khiển bên trái để xác nhận rằng cả user_preferences và final_itinerary đều được điền sẵn trong trạng thái phiên.

Khi bạn kiểm tra xong dấu vết, hãy nhấn Ctrl + C trong dòng lệnh để dừng adk web.

7. Tiến hành nghiên cứu bằng ParallelAgent

Mặc dù quy trình tuần tự tách biệt rõ ràng việc trích xuất lựa chọn ưu tiên khỏi việc soạn thảo hành trình, nhưng các đề xuất của quy trình này vẫn hoàn toàn dựa trên kiến thức huấn luyện tĩnh của mô hình. Bạn có thể dựa vào dữ liệu trực tiếp trên web để lên lịch trình bằng cách thêm hai nhà nghiên cứu chuyên trách được hỗ trợ bởi công cụ google_search tích hợp sẵn:

  • activity_finder_agent: Tìm 3 điểm tham quan cụ thể phù hợp với điểm đến và mối quan tâm của người dùng, cùng với giá vé ước tính.
  • restaurant_finder_agent: Tìm 3 nhà hàng địa phương được đánh giá cao và chi phí ước tính cho mỗi người.

Vì việc nghiên cứu các điểm tham quan và nghiên cứu nhà hàng không phụ thuộc vào nhau, nên việc chạy lần lượt các tác vụ này sẽ gây lãng phí thời gian. Thay vào đó, bạn sẽ gói cả hai nhà nghiên cứu vào một ParallelAgent (parallel_research_agent) để ADK thực thi đồng thời cả hai quy trình công việc của Google Tìm kiếm và điền sẵn {activity_recommendations?} và {restaurant_recommendations?} trước khi chuyển giao cho itinerary_synthesizer_agent.

Sơ đồ cấu trúc cho thấy master_travel_agent chạy user_profiler_agent ở Giai đoạn 1, parallel_research_agent (ParallelAgent với activity_finder_agent và restaurant_finder_agent) ở Giai đoạn 2 và itinerary_synthesizer_agent ở Giai đoạn 3

Thêm chuyên gia nghiên cứu song song vào specialists.py

Mở travel_planner/specialists.py:

cloudshell edit ~/adk-agents/travel_planner/specialists.py

Thêm hai chuyên gia Google Tìm kiếm sau đây vào cuối travel_planner/specialists.py (ngay bên dưới itinerary_synthesizer_agent):

# --- Specialist 3: The Activity Finder ---
activity_finder_agent = Agent(
    name="activity_finder_agent",
    description="Finds 3 attractions matching the user's destination and interests.",
    instruction="""
        Based on {user_preferences}, use google_search to find 3 specific attractions (including budget-friendly options).
        Return a JSON list with keys: "attraction_name", "estimated_cost_local", "estimated_cost_usd", "notes".
    """,
    tools=[google_search],
    output_key="activity_recommendations",
)

# --- Specialist 4: The Restaurant Finder ---
restaurant_finder_agent = Agent(
    name="restaurant_finder_agent",
    description="Finds 3 restaurants matching the destination and budget.",
    instruction="""
        Based on {user_preferences}, use google_search to find 3 highly-rated restaurants across price points.
        Return a JSON list with keys: "restaurant_name", "cuisine", "estimated_cost_local", "estimated_cost_usd".
    """,
    tools=[google_search],
    output_key="restaurant_recommendations",
)

Chèn ParallelAgent vào workflows.py

Mở travel_planner/workflows.py:

cloudshell edit ~/adk-agents/travel_planner/workflows.py

Cập nhật travel_planner/workflows.py để xác định parallel_research_agent bằng ParallelAgent và đặt giữa user_profiler_agent và itinerary_synthesizer_agent:

from google.adk.agents import ParallelAgent, SequentialAgent
from .specialists import (
    activity_finder_agent,
    itinerary_synthesizer_agent,
    restaurant_finder_agent,
    user_profiler_agent,
)

# Parallel branch: Run activity and restaurant research simultaneously
parallel_research_agent = ParallelAgent(
    name="parallel_research_agent",
    description="Runs activity and restaurant research concurrently.",
    sub_agents=[
        activity_finder_agent,
        restaurant_finder_agent,
    ],
)

# Master pipeline: Profile -> Parallel Research -> Synthesize
master_travel_agent = SequentialAgent(
    name="master_travel_agent",
    description="Orchestrates the end-to-end travel planning process for trip and itinerary requests.",
    sub_agents=[
        user_profiler_agent,          # Step 1: Extract constraints
        parallel_research_agent,      # Step 2: Research activities & restaurants in parallel
        itinerary_synthesizer_agent,  # Step 3: Synthesize into an itinerary
    ],
)

🔍 Kiểm tra bài làm

Chạy lại adk web để kiểm thử quy trình nghiên cứu song song:

cd ~/adk-agents
adk web --allow_origins "*"

Trong giao diện người dùng của Bản xem trước trên web, hãy gửi câu lệnh:

Help me plan a trip to Kyoto focused on historic temples and ramen

Bạn sẽ thấy kết quả tương tự như trình tự sau trong chế độ xem Events (Sự kiện):

1. user_profiler_agent -> writes state['user_preferences']
2. parallel_research_agent -> fans out concurrently:
   - activity_finder_agent invokes google_search -> writes state['activity_recommendations']
   - restaurant_finder_agent invokes google_search -> writes state['restaurant_recommendations']
3. itinerary_synthesizer_agent -> merges all three state keys into state['final_itinerary']
  1. Chế độ xem dấu vết: Nhấp vào Dấu vết ở đầu ngăn trò chuyện (bên cạnh Sự kiện) và kiểm tra lượt của bạn. Bạn sẽ thấy các khoảng thời gian trùng lặp cho activity_finder_agent và restaurant_finder_agent trong parallel_research_agent, giúp giảm gần một nửa tổng độ trễ của quá trình nghiên cứu trên web so với việc chạy tuần tự.
  2. Thẻ State (Trạng thái): Nhấp vào thẻ State (Trạng thái) trong bảng điều khiển trình kiểm tra bên trái để kiểm tra từ điển phiên hoạt động trực tiếp (user_preferences, activity_recommendations, restaurant_recommendations và final_itinerary).

Khi bạn kiểm thử xong, hãy nhấn Ctrl + C trong dòng lệnh để dừng adk web.

8. Tinh chỉnh bản nháp bằng LoopAgent

Ngay cả khi có kết quả tìm kiếm trực tiếp, bản nháp ban đầu do itinerary_synthesizer_agent tạo ra có thể vượt quá tổng ngân sách của người dùng hoặc vô tình bao gồm một danh mục bị loại trừ (chẳng hạn như phòng trưng bày nghệ thuật hiện đại khi người dùng yêu cầu không có).

Để đảm bảo tuân thủ quy tắc ràng buộc, bạn sẽ thêm một vòng lặp tinh chỉnh người tạo-người kiểm tra ở cuối quy trình bằng cách sử dụng LoopAgent:

  1. itinerary_critic_agent (Trình kiểm tra): Kiểm tra {final_itinerary} theo {user_preferences}. Công cụ này sẽ tính tổng chi phí ước tính, kiểm tra mọi quy tắc ràng buộc phủ định và viết hướng dẫn sửa đổi cụ thể cho critique_feedback hoặc phản hồi bằng cụm từ chính xác "APPROVED".
  2. itinerary_refiner_agent (Người tạo/Người thoát): Đọc {critique_feedback}. Nếu kết quả đánh giá bằng "APPROVED", thì mô hình sẽ gọi công cụ exit_loop (tool_context.actions.escalate = True) để thoát khỏi LoopAgent ngay lập tức. Nếu không, Gemini sẽ sửa đổi {final_itinerary} để khắc phục các vấn đề bị gắn cờ và ghi đè final_itinerary cho lần tiếp theo.

Sơ đồ cấu trúc cho thấy master_travel_agent với Stage 4 refinement_loop_agent (LoopAgent) lặp lại giữa itinerary_critic_agent và itinerary_refiner_agent cho đến khi exit_loop được gọi

Thêm exit_loop, Người phê bình và Người tinh chỉnh vào specialists.py

Mở travel_planner/specialists.py:

cloudshell edit ~/adk-agents/travel_planner/specialists.py

Thêm công cụ exit_loop (ToolContext), itinerary_critic_agent và itinerary_refiner_agent vào phần dưới cùng của travel_planner/specialists.py:

def exit_loop(tool_context: ToolContext) -> dict:
    """Call ONLY when the critique is APPROVED to exit the refinement loop."""
    print(f"[Tool Call] exit_loop triggered by {tool_context.agent_name}")
    tool_context.actions.escalate = True
    return {"status": "approved", "message": "Itinerary approved. Exiting refinement loop."}


# --- Specialist 5: The Budget & Constraint Critic (Inside LoopAgent) ---
itinerary_critic_agent = Agent(
    name="itinerary_critic_agent",
    include_contents="none",
    description="Audits the itinerary draft against budget and negative constraints.",
    instruction="""
        Audit Current Itinerary ({final_itinerary}) against User Preferences ({user_preferences}).
        Verify that the USD total stays within the user's budget and no excluded venue types appear.
        If all checks pass, respond EXACTLY with the single word "APPROVED".
        Otherwise, output 1-2 concise revision instructions explaining what to swap or adjust.
    """,
    output_key="critique_feedback",
)

# --- Specialist 6: The Itinerary Refiner / Exiter (Inside LoopAgent) ---
itinerary_refiner_agent = Agent(
    name="itinerary_refiner_agent",
    include_contents="none",
    description="Refines the itinerary from critique feedback, or calls exit_loop when APPROVED.",
    instruction="""
        Review Auditor Critique ({critique_feedback}) for Current Itinerary ({final_itinerary}).
        If the critique is EXACTLY "APPROVED", call `exit_loop` immediately and return the itinerary unchanged.
        Otherwise, revise the draft using {activity_recommendations} and {restaurant_recommendations}
        so all USD budget and exclusion rules pass, and output ONLY the updated Markdown itinerary.
    """,
    tools=[exit_loop],
    output_key="final_itinerary",
)

Thêm LoopAgent vào workflows.py

Mở travel_planner/workflows.py:

cloudshell edit ~/adk-agents/travel_planner/workflows.py

Cập nhật travel_planner/workflows.py để gói itinerary_critic_agent và itinerary_refiner_agent trong LoopAgent (max_iterations=3) rồi thêm vào làm giai đoạn thứ tư của master_travel_agent:

from google.adk.agents import LoopAgent, ParallelAgent, SequentialAgent
from .specialists import (
    activity_finder_agent,
    itinerary_critic_agent,
    itinerary_refiner_agent,
    itinerary_synthesizer_agent,
    restaurant_finder_agent,
    user_profiler_agent,
)

# Stage 2: Parallel research branch
parallel_research_agent = ParallelAgent(
    name="parallel_research_agent",
    description="Runs activity and restaurant research concurrently.",
    sub_agents=[
        activity_finder_agent,
        restaurant_finder_agent,
    ],
)

# Stage 4: Iterative Maker-Checker refinement loop
refinement_loop_agent = LoopAgent(
    name="refinement_loop_agent",
    description="Iteratively audits and refines the itinerary until constraints and budget are approved.",
    sub_agents=[
        itinerary_critic_agent,
        itinerary_refiner_agent,
    ],
    max_iterations=3,
)

# Master pipeline: Profile -> Parallel Research -> Synthesize -> Refinement Loop
master_travel_agent = SequentialAgent(
    name="master_travel_agent",
    description="Orchestrates the end-to-end travel planning process for trip and itinerary requests.",
    sub_agents=[
        user_profiler_agent,          # Stage 1: Extract constraints
        parallel_research_agent,      # Stage 2: Research activities & restaurants in parallel
        itinerary_synthesizer_agent,  # Stage 3: Draft initial itinerary
        refinement_loop_agent,        # Stage 4: Audit and refine until approved
    ],
)

🔍 Kiểm tra bài làm

Bắt đầu adk web để kiểm thử toàn bộ quy trình làm việc của nhiều tác nhân:

cd ~/adk-agents
adk web --allow_origins "*"

Mở giao diện người dùng Xem trước trên web trên cổng 8000, bắt đầu một Phiên mới và kiểm thử toàn bộ hệ thống bằng câu lệnh nhiều quy tắc ràng buộc này về Kyoto:

Design a full-day itinerary for Kyoto with a total budget of $100. My main interests are historical landmarks, temples, and authentic local cuisine. Please do not include any modern art museums or galleries.

Bạn sẽ thấy kết quả tương tự như trình tự thực thi sau đây trong chế độ xem Events (Sự kiện) và nhật ký thiết bị đầu cuối:

1. user_profiler_agent -> writes JSON with destination="Kyoto", budget="$100", exclusions=["modern art museums", "galleries"]
2. parallel_research_agent -> runs activity_finder_agent and restaurant_finder_agent in parallel
3. itinerary_synthesizer_agent -> produces initial draft in state['final_itinerary']
4. refinement_loop_agent:
   - itinerary_critic_agent -> audits USD budget and exclusions -> outputs "APPROVED" (or revision notes)
   - itinerary_refiner_agent -> triggers [Tool Call] exit_loop triggered by itinerary_refiner_agent and outputs the approved itinerary
  1. Chế độ xem sự kiện: Nhấp vào khối sự kiện bất kỳ trong itinerary_critic_agent hoặc itinerary_refiner_agent để kiểm tra tải trọng của sự kiện đó trong thẻ Thông tin ở bên trái. Khi itinerary_refiner_agent gọi exit_loop, hãy kiểm tra sự kiện để xem actions.escalate: true – tín hiệu cho LoopAgent biết cần dừng lặp lại trước khi đạt đến max_iterations=3.
  2. Thẻ State (Trạng thái): Nhấp vào thẻ State (Trạng thái) để xem state['critique_feedback'] và state['final_itinerary'] cập nhật trên các lượt truyền. Nếu bản nháp ban đầu vượt quá $100 USD, critique_feedback sẽ giữ lại hướng dẫn sửa đổi của người kiểm tra ở lượt 1 trước khi final_itinerary cập nhật các phương án thay thế có chi phí thấp hơn và critique_feedback thay đổi thành "APPROVED" ở lượt 2.

Khi bạn kiểm thử xong, hãy nhấn Ctrl + C trong dòng lệnh để dừng adk web.

9. Dọn dẹp

Xoá các tệp dự án cục bộ

Để xoá thư mục dự án adk-agents và môi trường ảo khỏi thư mục gốc của Cloud Shell, hãy chạy lệnh:

cd ~
rm -rf ~/adk-agents

Tắt Agent Platform API

Nếu không cần bật Agent Platform API trong dự án nữa, bạn có thể tắt API này bằng gcloud:

gcloud services disable aiplatform.googleapis.com --quiet

Xoá toàn bộ dự án trên đám mây của Google Cloud (Không bắt buộc)

PROJECT_ID=$(gcloud config get-value project)
gcloud projects delete "$PROJECT_ID" --quiet

🔍 Kiểm tra bài làm

Xác nhận rằng ~/adk-agents đã bị xoá:

test ! -d ~/adk-agents && echo "Workspace ~/adk-agents removed"

Bạn sẽ thấy kết quả tương tự như sau:

Workspace ~/adk-agents removed

10. Xin chúc mừng

Xin chúc mừng! Bạn đã xây dựng một hệ thống đa tác nhân phân cấp bằng Bộ công cụ phát triển tác nhân (ADK) của Google. Hệ thống này điều phối một nhóm gồm 6 tác nhân chuyên biệt trong các quy trình công việc tuần tự, song song và lặp lại.

Thành tích bạn đạt được

  • Giao tiếp có cấu trúc giữa các tác nhân thông qua trạng thái phiên dùng chung (chèn mẫu output_key và {state_variable})
  • Xây dựng quy trình từng bước tất định bằng SequentialAgent
  • Chạy đồng thời các tác nhân nghiên cứu độc lập trên Google Tìm kiếm bằng ParallelAgent
  • Triển khai vòng lặp xác minh tự động theo mô hình người tạo – người kiểm tra bằng LoopAgent và tool_context.actions.escalate = True

Các bước tiếp theo