Next '26 Developer Keynote: Building ADK Agents with Skills and Tools

1. Giới thiệu

Trong lớp học lập trình này, bạn sẽ xây dựng một Tác nhân lập kế hoạch chạy marathon phức tạp bằng Bộ công cụ phát triển tác nhân (ADK). Bạn sẽ dần dần xem xét các khả năng của tác nhân, từ lời nhắc hệ thống có cấu trúc rõ ràng đến việc tải kỹ năng động và ánh xạ các công cụ MCP. Cuối cùng, bạn sẽ kiểm thử tác nhân cục bộ và triển khai tác nhân đó vào Thời gian chạy tác nhân (Agent Engine).

Bạn sẽ thực hiện

  • Khởi động một dự án tác nhân ADK mới
  • Soạn một lệnh hệ thống mạnh mẽ bằng trình tạo có cấu trúc
  • Thêm các công cụ MCP của Google Maps để có ngữ cảnh vị trí thực tế
  • Tự động tải các kỹ năng vào bộ công cụ của tác nhân
  • Kiểm thử việc thực thi tác nhân cục bộ
  • Triển khai tác nhân vào Agent Engine (Cloud Run)

Bạn cần có

  • Một trình duyệt web như Chrome
  • Một dự án trên Google Cloud đã bật tính năng thanh toán
  • Hiểu biết cơ bản về Python

Lớp học lập trình này dành cho những nhà phát triển có trình độ trung cấp đang tìm cách xây dựng các tác nhân AI tạo sinh chuyên biệt.

Thời lượng ước tính: 45 phút

Các tài nguyên được tạo trong lớp học lập trình này sẽ có chi phí dưới 2 USD.

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

Tạo một dự án trên Google Cloud

  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.

Khởi động Cloud Shell

Cloud Shell là một môi trường dòng lệnh chạy trong Google Cloud và được tải sẵn các công cụ cần thiết.

  1. Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Cloud.
  2. Sau khi kết nối với Cloud Shell, hãy xác minh thông tin xác thực của bạn:
    gcloud auth list
    
  3. Xác nhận rằng dự án của bạn đã được định cấu hình:
    gcloud config get project
    
  4. Nếu dự án của bạn không được thiết lập như mong đợi, hãy thiết lập dự án:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    gcloud config set project $PROJECT_ID
    

Xác minh hoạt động xác thực:

gcloud auth list

Xác nhận dự án của bạn:

gcloud config get project

Đặt nếu cần:

export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

Bật API

Chạy lệnh này để bật tất cả các API bắt buộc:

gcloud services enable \
  aiplatform.googleapis.com \
  run.googleapis.com \
  secretmanager.googleapis.com \
  mapstools.googleapis.com \
  storage.googleapis.com \
  cloudresourcemanager.googleapis.com \
  serviceusage.googleapis.com

Tạo khoá API Google Maps

Để sử dụng các công cụ MCP của Google Maps, bạn cần tạo một khoá API Maps.

  1. Trong Bảng điều khiển Google Cloud, hãy dùng thanh tìm kiếm để chuyển đến Google Maps Platform > Thông tin xác thực.
  2. Nếu được nhắc, hãy xác nhận dự án trên đám mây của Google Cloud.
  3. Nhấp vào Tạo thông tin xác thực rồi chọn Khoá API.
  4. Sao chép khoá API đã tạo. Bạn sẽ cần mã này trong bước tiếp theo.

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

Đối với lớp học lập trình này, mã được lưu trữ trên GitHub. Bạn sẽ sao chép kho lưu trữ chứa cấu trúc thư mục và các thành phần phụ bắt buộc (chẳng hạn như thư mục skills/).

  1. Sao chép kho lưu trữ và chuyển đến thư mục dự án:
git clone https://github.com/GoogleCloudPlatform/next-26-keynotes
cd next-26-keynotes/devkey/demo-1
  1. Thiết lập môi trường ảo Python và cài đặt ADK:
uv venv
source .venv/bin/activate
uv sync
  1. Đặt khoá API Maps. Ứng dụng đọc thông tin này từ một biến môi trường:
export GOOGLE_MAPS_API_KEY="<YOUR_MAPS_API_KEY>"

Định cấu hình các biến môi trường

Simulator Agent sử dụng tệp .env để định cấu hình. Sao chép tệp mẫu rồi cập nhật tệp đó bằng mã dự án của bạn.

  1. Sao chép tệp môi trường mẫu:
cp planner_agent/sample.env planner_agent/.env
  1. Mở planner_agent/.env và cập nhật trường GOOGLE_CLOUD_PROJECT bằng mã dự án thực tế của bạn trên Google Cloud, đồng thời cập nhật trường GOOGLE_MAPS_API_KEY bằng khoá API Google Maps mà bạn đã tạo.

Tệp này sẽ có dạng như sau:

GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=us-west1
GOOGLE_MAPS_API_KEY=<YOUR_MAPS_API_KEY>
GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY=true
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS=true

4. Tạo một tác nhân ADK mới

Khám phá tệp cốt lõi xác định tác nhân: planner_agent/agent.py.

Trong kho lưu trữ build-agents-with-skills, tác nhân được khởi tạo bằng lớp Agent của ADK. Nó chỉ định mô hình cơ bản, tên nhận dạng và kéo các hướng dẫn cũng như công cụ được xác định trong các mô-đun khác.

Mở planner_agent/agent.py để kiểm tra mã khởi chạy:

instruction="Answer user questions to the best of your knowledge"
description="A helpful assistant for user questions."
tools=[]

# ...

root_agent = Agent(
    model='gemini-3-flash-preview',
    name='planner_agent',
    description=description,
    instruction=instruction,
    tools=tools
)

Lớp Agent loại bỏ nhật ký tin nhắn, việc điều phối công cụ và hoạt động giao tiếp LLM, giúp bạn tập trung vào hành vi của tác nhân.

Hiện tại, tác nhân này rất chung chung. Bạn có thể tương tác với mô hình này như với bất kỳ LLM nào khác.

uv run adk run planner_agent

Lệnh này sẽ bắt đầu cuộc trò chuyện với nhân viên hỗ trợ. Công cụ này sử dụng gemini-3-flash-preview làm mô hình và có thể trả lời các câu hỏi cơ bản.

Running agent planner_agent, type exit to exit.
[user]: What is the length of a Marathon
[planner_agent]: The official length of a marathon is **26.2 miles**, which is
equivalent to **42.195 kilometers**.

Trợ lý ảo đã biết một số thông tin về các cuộc chạy marathon. Tuy nhiên, điều này là không đủ để lên kế hoạch cho một cuộc chạy marathon phù hợp với các quy tắc và kế hoạch về đường chạy.

5. Tạo câu lệnh hệ thống

Câu lệnh hệ thống (hướng dẫn) quy định hành vi của đặc vụ. Thay vì một chuỗi khổng lồ duy nhất, dự án này sử dụng PromptBuilder (planner_agent/utils.py) để tạo hướng dẫn một cách linh động.

Mở planner_agent/prompts.py để xem cách câu lệnh được cấu trúc thành các phần logic:

from collections import OrderedDict
from .utils import PromptBuilder

ROLE = """\
...
"""

RULES = """\
...
"""

WORKFLOW = """\
...
"""

###

# Planner instructions with no tools mentioned
PLANNER_INSTRUCTION_NO_TOOLS = PromptBuilder(
    OrderedDict(
        role=ROLE,
        rules=RULES,
        tools=TOOLS_PROMPT_ONLY,
        workflow=WORKFLOW_PROMPT_ONLY,
    )
).build()

# Planner instruction with skills and tools defined
PLANNER_INSTRUCTION = PromptBuilder(
    OrderedDict(
        role=ROLE,
        rules=RULES,
        skills=SKILLS,
        tools=TOOLS,
        workflow=WORKFLOW,
    )
).build()

Quay lại planner_agent/agent.py, mục tiêu này đã được nhập.

Tìm phần có TODO: Replace Instruction and Description và bỏ chú thích việc gán lại biến instructiondescription.

Phần mã đó sẽ có dạng như sau:

instruction=PLANNER_INSTRUCTION_NO_TOOLS
description="Expert GIS analyst for marathon route and event planning."

Bạn đang nhập một phiên bản câu lệnh cho tác nhân không tham chiếu đến bất kỳ công cụ nào. Bạn sẽ thêm các công cụ ở bước sau.

Bạn có thể kiểm thử phiên bản này của nhân viên hỗ trợ:

uv run adk run planner_agent

Trong cửa sổ trò chuyện, hãy gửi câu lệnh sau:

Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the
evening timeframe

Sau vài phút, bạn sẽ nhận được phản hồi tương tự như sau:

Running agent planner_agent, type exit to exit.
[user]: Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the evening timeframe
[planner_agent]: Here is the comprehensive marathon plan for Las Vegas.

As requested, I have designed this event for an evening start on April 24, 2027. Because certain parameters (theme and budget) were not specified, I have applied pragmatic defaults: this will be a "Neon Nights" scenic theme to capitalize on the evening Strip, operating on a moderate-to-high budget given the infrastructure needed to secure major Las Vegas corridors.

### 1. Intent Alignment
*   **City & Theme:** Las Vegas, Nevada. Theme: "Neon Nights" an evening race maximizing the visual impact of the illuminated city.
*   **Date & Time:** Saturday, April 24, 2027. Late April evenings in Las Vegas offer optimal running weather (temperatures dropping from ~70°F at sunset to ~60°F). Race start is 6:30 PM (sunset is approx. 7:20 PM).
...
...

Với một câu lệnh được xác định rõ ràng, kết quả đầu ra đã gần với kết quả dự kiến hơn nhiều. Trong bước tiếp theo, bạn sẽ thêm các công cụ để nâng cấp tác nhân.

6. Thêm kỹ năng và công cụ

Để bật các kỹ năng và công cụ trong planner_agent/agent.py, hãy tìm phần có TODO: Replaces Tools rồi bỏ chú thích hai dòng tiếp theo. Mã của bạn sẽ nhìn như sau:

instruction=PLANNER_INSTRUCTION
tools=get_tools()

Đó là thay đổi mã duy nhất cần thiết trong bước này. Phần còn lại của phần này giải thích các khái niệm đằng sau kỹ năng và công cụ.

Kỹ năng

Kỹ năng của tác nhân là một đơn vị chức năng độc lập mà tác nhân ADK có thể sử dụng để thực hiện một nhiệm vụ cụ thể. Agent Skill bao gồm các hướng dẫn, tài nguyên và công cụ cần thiết cho một tác vụ, dựa trên quy cách Agent Skill. Cấu trúc của một Kỹ năng cho phép tải tăng dần để giảm thiểu tác động đến cửa sổ ngữ cảnh hoạt động của tác nhân.

Đối với tác nhân lập kế hoạch chạy marathon, có 3 kỹ năng được xác định:

  1. gis-spatial-engineering – Chịu trách nhiệm xử lý dữ liệu GeoJSON để tạo tuyến đường chạy marathon.
  2. lập bản đồ – Sử dụng các công cụ của Google Maps để tìm kiếm địa điểm và thông tin thời tiết.
  3. race-director – Xác thực tuyến đường chạy marathon tuân thủ các nguyên tắc lập kế hoạch.

Các kỹ năng có thể có tập lệnh, tài sản và thông tin tham khảo bổ sung.

Ứng dụng tải tất cả các kỹ năng và cung cấp chúng dưới dạng công cụ trong planner_agent/tools.py. Lưu ý cách thực hiện việc này trong hàm get_tools():

def get_tools() -> list:
    """Build the planner's tool list with lazy-loaded skills."""
    from google.adk.code_executors.unsafe_local_code_executor import UnsafeLocalCodeExecutor

    skills_dir = pathlib.Path(__file__).parent / "skills"

    skills = []
    if skills_dir.exists():
        skills = [
            load_skill_from_dir(d)
            for d in sorted(skills_dir.iterdir())
            if d.is_dir() and not d.name.startswith("_") and (d / "SKILL.md").exists()
        ]

    additional_tools = _load_additional_tools(skills_dir)

    skill_toolset = SkillToolset(
        skills=skills,
        code_executor=UnsafeLocalCodeExecutor(),
        additional_tools=additional_tools,
    )

    tools = [
        skill_toolset,
        PreloadMemoryTool(),
    ]

    tools.extend(get_maps_tools())

    return tools

Phần thú vị nhất là phương thức load_skill_from_dir trong ADK. Có một cách khác để tạo kỹ năng trong ADK, đó là nội tuyến. Mặc dù không được dùng trong lớp học lập trình này, nhưng nó sẽ có dạng như sau:

from google.adk.skills import models

greeting_skill = models.Skill(
    frontmatter=models.Frontmatter(
        name="greeting-skill",
        description=(
            "A friendly greeting skill that can say hello to a specific person."
        ),
    ),
    instructions=(
        "Step 1: Read the 'references/hello_world.txt' file to understand how"
        " to greet the user. Step 2: Return a greeting based on the reference."
    ),
    resources=models.Resources(
        references={
            "hello_world.txt": "Hello! So glad to have you here!",
            "example.md": "This is an example reference.",
        },
    ),
)

Thêm công cụ lập bản đồ

Công cụ lập kế hoạch chạy marathon cần có bối cảnh không gian để tạo tuyến đường. Bạn cung cấp thông tin này bằng cách tích hợp máy chủ MCP (Giao thức ngữ cảnh mô hình) của Google Maps.

Trong planner_agent/tools.py, hãy lưu ý cách máy chủ MCP được đăng ký bằng công cụ ApiRegistry:

from google.adk.integrations.api_registry import ApiRegistry

class MapsApiRegistry(ApiRegistry):
    """ApiRegistry subclass that strips ADC headers to force API key auth."""

    def get_toolset(self, *args, **kwargs):  # noqa: ANN002, ANN003
        toolset = super().get_toolset(*args, **kwargs)
        conn = getattr(toolset, "_connection_params", None)
        headers = getattr(conn, "headers", None) if conn else None
        if headers:
            headers.pop("Authorization", None)  # type: ignore[union-attr]
            headers.pop("x-goog-user-project", None)  # type: ignore[union-attr]
        return toolset

def get_maps_tools() -> list:
    """Return Maps MCP toolset if configured."""
    project_id = os.getenv("GOOGLE_CLOUD_PROJECT", "").strip()
    maps_key = _resolve_maps_key()

    if not project_id or not maps_key:
        return []

    # Map the MCP server location on Google Cloud
    mcp_server_name = f"projects/{project_id}/locations/global/mcpServers/google-mapstools.googleapis.com-mcp"
    
    # Initialize the custom API registry that supports header injection
    api_registry = MapsApiRegistry(
        api_registry_project_id=project_id,
        header_provider=header_provider,
    )
    return [api_registry.get_toolset(mcp_server_name=mcp_server_name)]

Bằng cách thêm bộ công cụ MCP, tác nhân sẽ tự động có khả năng truy vấn Google Maps để biết thông tin chi tiết về tuyến đường, độ cao và vị trí!

7. Chạy tác nhân cục bộ

Giờ đây, khi tác nhân, câu lệnh và công cụ đã được kết nối với nhau, hãy chạy tác nhân cục bộ. Lần này, bạn sẽ sử dụng adk web để có thể xem các sự kiện Tải kỹ năng và Gọi công cụ.

uv run adk web

Bạn sẽ thấy nội dung tương tự

INFO:     Started server process [99665]
INFO:     Waiting for application startup.

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://127.0.0.1:8000.                         |
+-----------------------------------------------------------------------------+

INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
  1. Mở trình duyệt rồi truy cập vào URL xuất hiện trong cửa sổ dòng lệnh (thường là http://localhost:8000).
  2. Trong trình đơn thả xuống ở trên cùng bên trái, hãy chọn biểu tượng planner_agent.
  3. Trong cửa sổ trò chuyện, hãy gửi câu lệnh sau:
Plan a marathon for 10000 participants in Las Vegas on April 24, 2027 in the
evening timeframe

Bạn sẽ thấy các kỹ năng đang được tải và các công cụ đang được gọi. Sau vài giây, tác nhân sẽ tạo một kế hoạch chạy marathon.

Giao diện người dùng của bạn sẽ có dạng như sau:

Giao diện người dùng web ADK

8. Triển khai tác nhân

Sau khi hài lòng với hiệu suất của tác nhân ở cấp độ cục bộ, bạn có thể triển khai tác nhân đó cho Agent Engine. Nền tảng này sẽ lưu trữ tác nhân trên Cloud Run một cách an toàn.

Để triển khai tác nhân, hãy dùng lệnh triển khai ADK CLI:

uv run adk deploy agent_engine \
  --env_file planner_agent/.env \
  planner_agent

Khi quá trình triển khai kết thúc, CLI sẽ xuất ra một điểm cuối được lưu trữ an toàn cho tác nhân của bạn. Giờ đây, bạn có thể tích hợp điểm cuối này vào các ứng dụng giao diện người dùng, chatbot hoặc các hệ thống phụ trợ khác. Bạn cũng có thể sử dụng Agent Runtime Playground để thử nghiệm tác nhân.

Kết quả sẽ có dạng như sau:

Files and dependencies resolved
Deploying to agent engine...
✅ Created agent engine: projects/<PROJECT_ID>/locations/us-west1/reasoningEngines/<AGENT_ID>

Bạn có thể sử dụng tập lệnh Python được cung cấp để giao tiếp với tác nhân.

  1. Sao chép tệp môi trường mẫu:
cp sample.env .env
  1. Mở .env rồi cập nhật trường GOOGLE_CLOUD_PROJECT bằng mã dự án thực tế của bạn trên Google Cloud.

Tệp sẽ có dạng như sau:

GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT_ID>
GOOGLE_CLOUD_LOCATION=us-west1
  1. Bạn có thể liệt kê các tác nhân trong dự án của mình.
python main.py list

Bạn sẽ thấy nội dung tương tự

Listing deployed agents...

ID: <AGENT_ID> | Display Name: planner_agent

Sau khi triển khai Mã nhận dạng tác nhân, bạn có thể gửi một câu lệnh:

export AGENT_ID=<AGENT_ID>
python main.py prompt --agent-id ${AGENT_ID} --message "Plan a marathon for
10000 participants in Las Vegas on April 24, 2027 in the evening timeframe"

Bạn sẽ nhận được kết quả có dạng như sau:

Streaming response from agent <AGENT_ID>:

{'model_version': 'gemini-3-flash-preview', 'content': {'parts': [{'text': 'Here is a comprehensive
...
...
...

9. Dọn dẹp

Để tránh các khoản phí phát sinh cho tài khoản Google Cloud của bạn, hãy xoá các tài nguyên đã tạo trong lớp học lập trình này.

Xoá dịch vụ Cloud Run do hoạt động triển khai tạo:

python main.py delete --agent-id ${AGENT_ID}

Nếu bạn lưu trữ khoá API Maps trong Secret Manager, hãy xoá khoá bí mật đó:

gcloud secrets delete maps-api-key --project=$PROJECT_ID

Nếu đã tạo một dự án trên đám mây mới cho lớp học lập trình này, bạn có thể xoá toàn bộ dự án để xoá tất cả tài nguyên và API được liên kết với dự án đó:

gcloud projects delete $PROJECT_ID

10. Xin chúc mừng

Xin chúc mừng! Bạn đã xây dựng một Tác nhân lập kế hoạch chạy marathon phức tạp bằng ADK.

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

  • Khởi chạy một dự án Bộ công cụ phát triển tác nhân (ADK)
  • Sử dụng PromptBuilder cho câu lệnh hệ thống theo mô-đun
  • Tích hợp các chức năng lập bản đồ bằng công cụ MCP và ApiRegistry
  • Tải các kỹ năng có điều kiện bằng cách sử dụng SkillToolset
  • Kiểm thử cục bộ và triển khai cho Agent Engine

Tài liệu tham khảo