1. Tổng quan
Các tác nhân AI đang ngày càng trở nên phổ biến, cách mạng hoá quy trình tự động hoá nhiệm vụ và ra quyết định nhờ khả năng hoạt động độc lập, học hỏi và tương tác với môi trường để đạt được mục tiêu.
Lớp học lập trình này sẽ giúp bạn bắt đầu bằng cách xây dựng một hệ thống đa tác nhân toàn diện. Bạn sẽ xây dựng một máy chủ MCP tiền tệ, xây dựng một tác nhân tiền tệ sử dụng máy chủ MCP và được hiển thị qua giao thức Agent2Agent (A2A), xây dựng một tác nhân du lịch có tác nhân phụ thời tiết trong quy trình sử dụng tác nhân tiền tệ qua A2A và cuối cùng là triển khai tất cả dịch vụ cho Cloud Run.

Công nghệ cốt lõi
Giao thức ngữ cảnh mô hình (MCP)
Giao thức ngữ cảnh mô hình (MCP) là một giao thức mở giúp chuẩn hoá cách các ứng dụng cung cấp ngữ cảnh và công cụ cho LLM. Hãy coi MCP như một cổng USB-C cho các ứng dụng AI: MCP cung cấp một cách thức chuẩn hoá để kết nối các mô hình AI với các nguồn dữ liệu, API và công cụ bên ngoài.
Trong lớp học lập trình này, currency_mcp_server sẽ hiển thị một công cụ get_exchange_rate qua HTTP có thể truyền trực tuyến (/mcp), được hỗ trợ bởi Frankfurter API công khai.
Bộ công cụ phát triển tác nhân (ADK)
Bộ công cụ phát triển tác nhân (ADK) là một khung điều phối linh hoạt để phát triển và triển khai các tác nhân AI. ADK không phụ thuộc vào mô hình, không phụ thuộc vào việc triển khai và được xây dựng để tương thích với các khung khác. ADK giúp việc phát triển tác nhân giống như kỹ thuật phần mềm tiêu chuẩn, giúp bạn dễ dàng tạo, kiểm thử và điều phối các quy trình làm việc phức tạp của tác nhân.
ADK xử lý các cuộc trò chuyện của người dùng, cung cấp giao diện người dùng web tương tác, kết nối với các công cụ MCP thông qua McpToolset và quản lý hoạt động giao tiếp A2A.
Giao thức Agent2Agent (A2A)
Giao thức Agent2Agent (A2A) là một tiêu chuẩn mở được thiết kế để hỗ trợ hoạt động giao tiếp và cộng tác giữa các tác nhân AI. Giống như cách MCP chuẩn hoá các kết nối giữa tác nhân và công cụ, A2A chuẩn hoá hoạt động cộng tác giữa các tác nhân! Trong một thế giới nơi các tác nhân được xây dựng trên nhiều khung, môi trường lưu trữ và tổ chức, A2A cung cấp một ngôn ngữ chung để khám phá và uỷ quyền nhiệm vụ.
ADK hiển thị currency_agent dưới dạng dịch vụ A2A (to_a2a) và cho phép travel_agent sử dụng dịch vụ này từ xa dưới dạng AgentTool (RemoteA2aAgent).
Tác nhân phụ cục bộ so với tác nhân A2A từ xa
Kiến trúc này làm nổi bật một mẫu quan trọng trong thiết kế đa tác nhân:
- Công cụ tác nhân cục bộ (
weather_agent): Chạy trong quy trình trong trình điều phối dưới dạngAgentTool, không có độ trễ mạng hoặc hao tổn tuần tự hoá giao thức. - Công cụ tác nhân từ xa (
currency_agent): Chạy dưới dạng một dịch vụ vi mô độc lập, được gọi trên mạng thông qua giao thức A2A.
Kiến thức bạn sẽ học được
- Cách tạo và kiểm thử máy chủ MCP cục bộ bằng FastMCP qua HTTP có thể truyền trực tuyến
- Cách xây dựng một Tác nhân bằng ADK sử dụng các công cụ MCP (
McpToolset) - Cách hiển thị tác nhân ADK dưới dạng máy chủ A2A (
to_a2a) - Cách kiểm thử máy chủ A2A bằng ứng dụng Python A2A (
a2a.client) - Cách xây dựng một tác nhân điều phối kết hợp các công cụ của tác nhân phụ cục bộ với các tác nhân A2A từ xa
- Cách chạy và kiểm thử toàn bộ hệ thống nhiều tác nhân trên máy bằng Giao diện người dùng web của ADK
- Cách đóng gói và triển khai cả ba thành phần lên Google Cloud Run
Bạn cần có
- Một trình duyệt, chẳng hạn như Chrome.
- Một dự án trên Google Cloud đã bật tính năng thanh toán.
2. Trước khi bắt đầu
Tạo dự án
Nếu bạn chưa có dự án trên Google Cloud, hãy tạo một dự án.
Trong Google Cloud Console, trên trang bộ chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud.
Ngoài ra, hãy đảm bảo rằng bạn đã bật tính năng thanh toán cho dự án trên đám mây của mình. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trong dự án hay không.
Kích hoạt Cloud Shell
Google Cloud Shell là một môi trường phát triển tương tác, dựa trên trình duyệt, được cung cấp ngay trong Google Cloud Console. Đây là cách dễ nhất để bắt đầu sử dụng Google Cloud mà không cần cài đặt công cụ trên máy.
Kích hoạt Cloud Shell bằng cách nhấp vào đường liên kết này. Bạn có thể chuyển đổi giữa Cloud Shell Terminal (để chạy các lệnh trên đám mây) và Editor (để xem tệp) bằng cách nhấp vào nút tương ứng trong Cloud Shell.
Sau khi kết nối với Cloud Shell, hãy xác minh rằng bạn đã được xác thực:
gcloud auth list
Xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project
Đặt mã dự án:
export PROJECT_ID=<YOUR_GOOGLE_CLOUD_PROJECT_ID>
gcloud config set project $PROJECT_ID
Bật Cloud API
Bật các API cần thiết cho Cloud Run, Cloud Build, Artifact Registry và Vertex AI:
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
aiplatform.googleapis.com
Lấy mã
Sao chép kho lưu trữ và chuyển đến thư mục python:
git clone https://github.com/meteatamel/getting-started-mcp-a2a-adk.git
cd getting-started-mcp-a2a-adk/python
Cài đặt các phần phụ thuộc bằng uv
uv là một trình quản lý dự án và gói Python nhanh. Công cụ này được cài đặt sẵn trong Cloud Shell. Nếu chạy cục bộ, bạn có thể cài đặt như sau:
# macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
# powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Thư mục Python được cấu trúc dưới dạng một uv hợp nhất
Workspace. Cài đặt tất cả phần phụ thuộc trên tất cả thành viên không gian làm việc (currency_mcp_server, currency_agent và travel_agent) vào một môi trường ảo bằng cách chạy:
uv sync
Định cấu hình biến môi trường
Định cấu hình các biến môi trường trong tệp .env trong thư mục python:
Lựa chọn A: Gemini Enterprise (Google Cloud / Cloud Shell)
echo "GOOGLE_GENAI_USE_ENTERPRISE=TRUE" >> .env \
&& echo "GOOGLE_CLOUD_PROJECT=$PROJECT_ID" >> .env \
&& echo "GOOGLE_CLOUD_LOCATION=global" >> .env
Lựa chọn B: Google AI Studio (khoá API cục bộ)
Nếu bạn muốn sử dụng khoá API của Google AI Studio:
echo "GOOGLE_API_KEY=<your_api_key_here>"<>>/span> .env \
&& echo "GOOGLE_GENAI_USE_ENTERPRISE=FALSE" >> .env
3. Tạo Máy chủ MCP tiền tệ
Trước khi tạo tác nhân, trước tiên, bạn sẽ khám phá máy chủ MCP hiển thị công cụ quy đổi tiền tệ.
Máy chủ MCP cho phép bạn viết các chương trình gọn nhẹ để hiển thị các chức năng dưới dạng công cụ. Sau đó, một tác nhân (hoặc nhiều tác nhân) có thể truy cập vào các công cụ này bằng Giao thức ngữ cảnh mô hình chuẩn hoá.
Bạn có thể tận dụng gói Python FastMCP để tạo một máy chủ MCP hiển thị một công cụ duy nhất có tên là get_exchange_rate. Công cụ get_exchange_rate gọi Frankfurter API để lấy tỷ giá hối đoái hiện tại giữa hai đơn vị tiền tệ.
Mã cho máy chủ MCP nằm trong currency_mcp_server/server.py:
import asyncio
import logging
import os
import httpx
from fastmcp import FastMCP
logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)
mcp = FastMCP("Currency MCP Server 💵")
@mcp.tool()
def get_exchange_rate(
currency_from: str = "USD",
currency_to: str = "EUR",
currency_date: str = "latest",
):
"""Use this to get current exchange rate.
Args:
currency_from: The currency to convert from (e.g., "USD").
currency_to: The currency to convert to (e.g., "EUR").
currency_date: The date for the exchange rate or "latest". Defaults to "latest".
Returns:
A dictionary containing the exchange rate data, or an error message if the request fails.
"""
logger.info(
f"--- 🛠️ Tool: get_exchange_rate called for converting {currency_from} to {currency_to} ---"
)
try:
response = httpx.get(
f"https://api.frankfurter.dev/v1/{currency_date}",
params={"from": currency_from, "to": currency_to},
)
response.raise_for_status()
data = response.json()
if "rates" not in data:
logger.error(f"❌ rates not found in response: {data}")
return {"error": "Invalid API response format."}
logger.info(f"✅ API response: {data}")
return data
except httpx.HTTPError as e:
logger.error(f"❌ API request failed: {e}")
return {"error": f"API request failed: {e}"}
except ValueError:
logger.error("❌ Invalid JSON response from API")
return {"error": "Invalid JSON response from API."}
if __name__ == "__main__":
port = int(os.getenv("PORT", 8080))
logger.info(f"🚀 MCP server started on port {port}")
# Could also use 'sse' transport, host="0.0.0.0" required for Cloud Run.
asyncio.run(
mcp.run_async(
transport="http",
host="0.0.0.0",
port=port,
)
)
Khởi động máy chủ MCP trên máy cục bộ
Khởi động máy chủ MCP trong dòng lệnh:
uv run python currency_mcp_server/server.py
Máy chủ khởi động trên cổng 8080 với điểm cuối HTTP có thể truyền trực tuyến tại /mcp (http://localhost:8080/mcp).
Kiểm thử máy chủ MCP
Mở cửa sổ dòng lệnh thứ hai (vẫn để máy chủ MCP chạy trong cửa sổ đầu tiên), chuyển đến thư mục python (cd getting-started-mcp-a2a-adk/python) rồi chạy tập lệnh kiểm thử:
uv run python currency_mcp_server/test_server.py
Tập lệnh kiểm thử kết nối với điểm cuối MCP bằng Client của FastMCP, liệt kê các công cụ và gọi get_exchange_rate:
Connecting to MCP server at: http://localhost:8080/mcp
--- 🛠️ Tool found: get_exchange_rate ---
--- 🪛 Calling get_exchange_rate tool for USD to EUR ---
--- ✅ Success: {"amount":1.0,"base":"USD","date":"2026-09-29","rates":{"EUR":0.84919}} ---
Tuyệt vời! Bạn có một máy chủ MCP đang hoạt động, cung cấp một công cụ chuyển đổi tiền tệ theo thời gian thực. Hãy mở cửa sổ dòng lệnh này để thực hiện các bước tiếp theo.
4. Tạo Tác nhân tiền tệ bằng ADK
Bây giờ, đã đến lúc tạo Tác nhân tiền tệ bằng Bộ công cụ phát triển tác nhân (ADK).
ADK cung cấp tính năng hỗ trợ tích hợp cho các công cụ MCP thông qua lớp McpToolset. Tác nhân tiền tệ kết nối với máy chủ MCP của chúng tôi bằng StreamableHTTPConnectionParams.
Hãy xem định nghĩa về tác nhân tiền tệ trong currency_agent/agent.py:
import logging
import os
from urllib.parse import urlparse
from dotenv import load_dotenv
from google.adk.agents import LlmAgent
from google.adk.a2a.utils.agent_to_a2a import to_a2a
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams
logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)
load_dotenv()
SYSTEM_INSTRUCTION = (
"You are a specialized assistant for currency conversions. "
"Your sole purpose is to use the 'get_exchange_rate' tool to answer questions about currency exchange rates. "
"If the user asks about anything other than currency conversion or exchange rates, "
"politely state that you cannot help with that topic and can only assist with currency-related queries. "
"Do not attempt to answer unrelated questions or use tools for other purposes."
)
mcp_server_url = os.getenv("MCP_SERVER_URL", "http://localhost:8080/mcp")
if not mcp_server_url.endswith("/mcp"):
mcp_server_url = f"{mcp_server_url.rstrip('/')}/mcp"
logger.info(f"--- 🔧 Loading MCP tools from MCP Server at {mcp_server_url}... ---")
logger.info("--- 🤖 Creating ADK Currency Agent... ---")
root_agent = LlmAgent(
model="gemini-3.8-flash",
name="currency_agent",
description="An agent that can help with currency conversions",
instruction=SYSTEM_INSTRUCTION,
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(
url=mcp_server_url
)
)
],
)
Hãy lưu ý cách McpToolset tự động khám phá và tải công cụ get_exchange_rate trực tiếp từ máy chủ MCP đang chạy qua HTTP.
Kiểm thử Tác nhân tiền tệ bằng Giao diện người dùng web của ADK
Bạn có thể kiểm thử riêng tác nhân bằng giao diện web phát triển của ADK. Trong cửa sổ dòng lệnh thứ hai, hãy chạy:
uv run adk web --allow_origins "*" currency_agent
Mở trình duyệt tại http://localhost:8000 (hoặc nhấp vào Web Preview (Xem trước trên web) trong Cloud Shell).

Hỏi tác nhân:
"250 USD bằng bao nhiêu EUR?"
Bạn sẽ thấy tác nhân gọi công cụ MCP get_exchange_rate và trả về số tiền đã chuyển đổi. Dừng quy trình adk web bằng Ctrl+C trước khi tiếp tục.
5. Giao thức Agent2Agent (A2A)
Giao thức Agent2Agent (A2A) là một tiêu chuẩn mở được thiết kế để hỗ trợ hoạt động giao tiếp và cộng tác giữa các tác nhân AI.
Trong các hệ thống đa tác nhân hiện đại, các tác nhân thường được xây dựng bằng nhiều khung (ADK, LangChain, CrewAI, AutoGen) và được triển khai trên nhiều cơ sở hạ tầng. A2A phá vỡ các rào cản này bằng cách xác định một hợp đồng giao tiếp được chuẩn hoá.

Các khái niệm chính về A2A
- Khám phá tác nhân (Thẻ tác nhân): Mọi tác nhân tuân thủ A2A đều quảng cáo các chức năng, chế độ I/O được hỗ trợ, yêu cầu xác thực và kỹ năng của mình thông qua một tệp JSON chuẩn được lưu trữ tại
/.well-known/agent-card.json. - Kỹ năng của tác nhân (
AgentSkill): Các chức năng hoặc công cụ cụ thể mà tác nhân có thể thực thi. Các tác nhân khác đọc những kỹ năng này để quyết định thời điểm uỷ quyền nhiệm vụ. - Giao tiếp JSON-RPC: Các tác nhân trao đổi thông báo, nhiệm vụ và cấu phần phần mềm có cấu trúc qua các phương thức truyền tải tiêu chuẩn như HTTP JSON-RPC 2.0.

Trong bước tiếp theo, bạn sẽ hiển thị ADK Currency Agent dưới dạng máy chủ A2A để các tác nhân khác có thể khám phá và uỷ quyền các nhiệm vụ chuyển đổi tiền tệ cho tác nhân này!
6. Hiển thị Tác nhân tiền tệ dưới dạng Máy chủ A2A
ADK giúp bạn dễ dàng biến mọi LlmAgent thành một máy chủ tương thích với A2A bằng hàm hiệu dụng to_a2a().
Xem phần dưới cùng của currency_agent/agent.py:
# Make the agent A2A-compatible
PORT = int(os.getenv("PORT", 8081))
AGENT_URL = os.getenv("AGENT_URL")
if AGENT_URL:
parsed = urlparse(AGENT_URL)
protocol = parsed.scheme or "https"
host = parsed.hostname
port = parsed.port or 443
else:
protocol = "http"
host = "localhost"
port = PORT
a2a_app = to_a2a(root_agent, host=host, port=port, protocol=protocol)
if __name__ == "__main__":
import uvicorn
logger.info(f"🚀 Starting currency_agent on port {PORT}")
uvicorn.run(a2a_app, host="0.0.0.0", port=PORT)
Trình trợ giúp to_a2a() tự động:
- Kiểm tra các công cụ và hướng dẫn của
LlmAgent. - Tạo một A2A
AgentCardmô tả các kỹ năng của ứng dụng (ví dụ:currency_agent-get_exchange_rate). - Gói tác nhân trong một ứng dụng FastAPI (
a2a_app) hỗ trợ các điểm cuối JSON-RPC. - Tự động định cấu hình
urlđược quảng cáo trong Thẻ tác nhân dựa trênAGENT_URL(hoặc máy chủ cục bộ).
Khởi động máy chủ A2A của Tác nhân tiền tệ
Trong thiết bị đầu cuối thứ hai, hãy khởi động tác nhân tiền tệ:
uv run python currency_agent/agent.py
Máy chủ khởi động trên cổng 8081:
[INFO]: --- 🔧 Loading MCP tools from MCP Server at http://localhost:8080/mcp... ---
[INFO]: --- 🤖 Creating ADK Currency Agent... ---
[INFO]: 🚀 Starting currency_agent on port 8081
INFO: Started server process
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8081 (Press CTRL+C to quit)
Kiểm tra Thẻ tác nhân
Trong trình duyệt, hãy truy cập vào điểm cuối Thẻ tác nhân: http://localhost:8081/.well-known/agent-card.json
Bạn sẽ thấy siêu dữ liệu JSON được tạo tự động:
{
"name": "currency_agent",
"description": "An agent that can help with currency conversions",
"supportedInterfaces": [
{
"url": "http://localhost:8081",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
}
],
"version": "0.0.1",
"capabilities": {
"streaming": true
},
"defaultInputModes": [
"text/plain"
],
"defaultOutputModes": [
"text/plain"
],
"skills": [
{
"id": "currency_agent",
"name": "model",
"description": "An agent that can help with currency conversions",
"tags": [
"llm"
]
},
{
"id": "currency_agent-get_exchange_rate",
"name": "get_exchange_rate",
"description": "Use this to get current exchange rate.",
"tags": [
"llm",
"tools"
]
}
]
}
Thử nghiệm với ứng dụng A2A
Mở cửa sổ dòng lệnh thứ ba, chuyển đến thư mục python (cd getting-started-mcp-a2a-adk/python) rồi kiểm thử điểm cuối A2A bằng tập lệnh ứng dụng kiểm thử A2A chuyên dụng:
uv run python currency_agent/test_a2aclient.py
Ứng dụng phân giải thẻ tác nhân bằng A2ACardResolver và gửi thông báo JSON-RPC:
🔄 Fetching the agent card at http://localhost:8081
✅ Successfully fetched the agent card
====================================================
AgentCard
====================================================
Name : currency_agent
Description : An agent that can help with currency conversions
Interfaces : [0] http://localhost:8081 (JSONRPC 1.0)
Skills : currency_agent, currency_agent-get_exchange_rate
====================================================
🔄 Initializing a non-streaming client
Sending request: "how much is 100 USD in GBP?"
Response:
100 USD is currently equal to approximately 73.37 GBP...
Currency Agent hiện đang hoạt động như một máy chủ A2A có đầy đủ chức năng!
7. Xây dựng công ty du lịch
Bây giờ, bạn sẽ xây dựng Đại lý du lịch điều phối. Tác nhân này minh hoạ cách một tác nhân ADK có thể dễ dàng kết hợp hai mô hình công cụ khác nhau:
- Công cụ tác nhân cục bộ (
weather_agent): Một tác nhân phụ ADK trong quy trình chạy trong cùng một thời gian chạy Python, tránh mọi độ trễ mạng hoặc chuyển đổi tuần tự. - Công cụ tác nhân từ xa (
currency_agent): Một tác nhân bên ngoài được kết nối qua mạng thông qua giao thức A2A bằngRemoteA2aAgent.
+-----------------------------+
| travel_agent |
| (Orchestrator with Web UI) |
+--------------+--------------+
|
+---------------------+---------------------+
| (In-process call) | (A2A Network Hop)
v v
+-------------------------+ +-------------------------+
| weather_agent | | currency_agent |
| (Local AgentTool) | | (Remote A2A Agent) |
| Calls wttr.in API | | Calls Currency MCP Svc |
+-------------------------+ +-------------------------+
1. Tác nhân phụ về thời tiết địa phương
Hãy xem travel_agent/subagents/weather_agent.py:
import logging
import httpx
from google.adk.agents import LlmAgent
logger = logging.getLogger(__name__)
SYSTEM_INSTRUCTION = (
"You are a specialized assistant for providing weather forecasts and conditions for travel destinations. "
"Your sole purpose is to use the 'get_weather' tool to fetch weather information. "
"Provide clear, concise summaries of current weather conditions, temperatures, and forecasts to help travelers pack and plan."
)
def get_weather(location: str = "London") -> dict:
"""Gets the current weather and forecast for a given location or city."""
logger.info(f"--- 🌤️ Tool: get_weather called for {location} ---")
try:
response = httpx.get(
f"https://wttr.in/{location}?format=j1",
headers={"User-Agent": "curl/7.68.0"},
timeout=8.0,
)
response.raise_for_status()
data = response.json()
current = data["current_condition"][0]
return {
"location": location,
"condition": current.get("weatherDesc", [{}])[0].get("value", "Unknown"),
"temperature_celsius": f"{current.get('temp_C', 'N/A')}°C",
"temperature_fahrenheit": f"{current.get('temp_F', 'N/A')}°F",
"humidity": f"{current.get('humidity', 'N/A')}%",
"wind_speed_kmph": f"{current.get('windspeedKmph', 'N/A')} km/h",
}
except Exception as e:
logger.warning(f"⚠️ Weather lookup failed: {e}. Returning simulated estimate.")
return {
"location": location,
"condition": "Partly Cloudy",
"temperature_celsius": "20°C",
"temperature_fahrenheit": "68°F",
"humidity": "55%",
"wind_speed_kmph": "10 km/h",
"note": f"Live data unavailable ({e}); showing estimated conditions.",
}
weather_agent = LlmAgent(
model="gemini-3.8-flash",
name="weather_agent",
description="A local specialist agent that provides current weather reports and forecasts for travel destinations.",
instruction=SYSTEM_INSTRUCTION,
tools=[get_weather],
)
Tác nhân thời tiết là một LlmAgent có công cụ hàm giúp tìm nạp thông tin thời tiết theo thời gian thực từ wttr.in bằng một phương án dự phòng linh hoạt.
2. Hệ thống điều phối công ty du lịch
Bây giờ, hãy xem travel_agent/agent.py:
import logging
import os
from dotenv import load_dotenv
from google.adk.agents import LlmAgent
from google.adk.tools.agent_tool import AgentTool
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent, AGENT_CARD_WELL_KNOWN_PATH
try:
from travel_agent.subagents.weather_agent import weather_agent
except ImportError:
from subagents.weather_agent import weather_agent
logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)
load_dotenv()
SYSTEM_INSTRUCTION = (
"You are a helpful travel assistant. You help users plan trips, recommend places, "
"and answer travel-related questions.\n\n"
"- Whenever a user asks about currency exchange rates or money conversions, "
"delegate the request to the 'currency_agent' tool.\n"
"- Whenever a user asks about the weather, climate, or forecasts for a destination, "
"delegate the request to the 'weather_agent' tool."
)
CURRENCY_AGENT_URL = os.getenv("CURRENCY_AGENT_URL", "http://localhost:8081").rstrip("/")
logger.info(
"--- 🔗 Connecting to Remote A2A Currency Agent at %s... ---",
CURRENCY_AGENT_URL,
)
currency_remote_agent = RemoteA2aAgent(
name="currency_agent",
agent_card=f"{CURRENCY_AGENT_URL}{AGENT_CARD_WELL_KNOWN_PATH}",
description="An agent that can help with currency conversions and exchange rates.",
)
logger.info("--- 🤖 Creating ADK Travel Agent... ---")
root_agent = LlmAgent(
model="gemini-3.8-flash",
name="travel_agent",
description="A travel assistant that can help plan trips, check weather forecasts via the local weather agent, and convert currencies via the remote currency agent.",
instruction=SYSTEM_INSTRUCTION,
tools=[
AgentTool(agent=currency_remote_agent),
AgentTool(agent=weather_agent),
],
)
if __name__ == "__main__":
import uvicorn
from google.adk.cli.fast_api import get_fast_api_app
PORT = int(os.getenv("PORT", 8082))
logger.info(f"🚀 Starting travel_agent Web UI on port {PORT}")
app = get_fast_api_app(web=True, allow_origins=["*"], agents_dir=os.path.dirname(__file__) or ".")
uvicorn.run(app, host="0.0.0.0", port=PORT)
Điểm nổi bật chính:
RemoteA2aAgenttìm nạp thẻ của Đại lý tiền tệ từhttp://localhost:8081/.well-known/agent-card.json.- Cả
currency_remote_agentvàweather_agentđều được gói bằngAgentToolcủa ADK. - Khi chạy
travel_agent/agent.py, Giao diện người dùng web của ADK sẽ trực tiếp khởi động trên cổng8082bằngget_fast_api_app(web=True).
8. Chạy và kiểm thử Hệ thống nhiều tác nhân trên máy cục bộ
Giờ đây, bạn đã có cả ba thành phần! Hãy chạy và kiểm thử toàn bộ hệ thống trên máy.
Chạy cả ba dịch vụ
Đảm bảo các dịch vụ đang chạy trên 3 cửa sổ dòng lệnh riêng biệt (từ thư mục getting-started-mcp-a2a-adk/python) theo thứ tự sau:
Terminal 1 (Máy chủ MCP về tiền tệ):
uv run python currency_mcp_server/server.py
(Chạy trên cổng 8080)
Terminal 2 (Tác nhân A2A hiện tại):
uv run python currency_agent/agent.py
(Chạy trên cổng 8081)
Terminal 3 (Công ty du lịch có giao diện người dùng web):
uv run python travel_agent/agent.py
(Chạy trên cổng 8082)
Kiểm thử thông qua giao diện người dùng web của ADK
Mở trình duyệt tại http://localhost:8082 (hoặc sử dụng Web Preview (Xem trước trên web) trên cổng 8082 trong Cloud Shell).
Đặt cho Tác nhân du lịch một câu hỏi phức tạp cần cả hai công cụ:
"Tôi đang lên kế hoạch cho một chuyến đi đến London. Thời tiết như thế nào và 200 EUR bằng bao nhiêu GBP?"
Xem quy trình thực thi:
- Công ty du lịch nhận được yêu cầu trong giao diện người dùng web.
- Nó uỷ quyền câu hỏi về thời tiết trong quá trình cho
weather_agentcục bộ, lấy điều kiện hiện tại từwttr.in. - Tác nhân này uỷ quyền quy đổi tiền tệ qua giao thức A2A cho
currency_agenttrên cổng 8081. currency_agentgọicurrency_mcp_servertrên cổng 8080 thông qua MCP để tìm nạp tỷ giá hối đoái.- Tất cả kết quả đều được tổng hợp và trả về cho bạn trong một câu trả lời thống nhất và hữu ích!

Kiểm thử qua dòng lệnh
Bạn cũng có thể kiểm thử truy vấn ngay từ CLI mà không cần mở trình duyệt:
uv run adk run travel_agent "What is the weather in London and how much is 100 USD in EUR?"
Giờ đây, mọi thứ đều hoạt động liền mạch trên máy cục bộ của bạn, hãy triển khai toàn bộ hệ thống cho Google Cloud Run!
9. Triển khai hệ thống đa tác nhân lên Cloud Run
Mỗi thành phần đều có Dockerfile riêng và pyproject.toml độc lập để có thể được xây dựng và triển khai độc lập cho Cloud Run.
Khi sử dụng gcloud, bạn sẽ triển khai từng dịch vụ và tự động kết nối các URL của chúng với nhau.
Đặt các biến môi trường
Đặt mã dự án trên đám mây và vùng mục tiêu:
export PROJECT_ID=<YOUR_GOOGLE_CLOUD_PROJECT_ID>
export REGION=us-central1
Bước 1: Triển khai máy chủ MCP về tiền tệ
Triển khai máy chủ MCP trực tiếp từ nguồn:
# 1. Deploy MCP server
gcloud run deploy currency-mcp-server \
--source currency_mcp_server \
--region $REGION \
--allow-unauthenticated
# 2. Capture the deployed MCP server URL
MCP_SERVER_URL=$(gcloud run services describe currency-mcp-server --region $REGION --format='value(status.url)')/mcp
echo "MCP Server URL: $MCP_SERVER_URL"
Bước 2: Triển khai Currency Agent
Vì URL công khai của currency-agent được chỉ định trong lần triển khai đầu tiên, nên trước tiên, hãy triển khai dịch vụ, thu thập URL của dịch vụ và cập nhật biến môi trường AGENT_URL để Thẻ tác nhân A2A của dịch vụ quảng cáo địa chỉ HTTPS công khai chính xác:
# 1. Deploy Currency Agent connected to the deployed MCP Server
gcloud run deploy currency-agent \
--source currency_agent \
--region $REGION \
--allow-unauthenticated \
--update-env-vars MCP_SERVER_URL="$MCP_SERVER_URL",GOOGLE_GENAI_USE_ENTERPRISE="true",GOOGLE_CLOUD_PROJECT="$PROJECT_ID",GOOGLE_CLOUD_LOCATION="global"
# 2. Capture its assigned Cloud Run URL
CURRENCY_AGENT_URL=$(gcloud run services describe currency-agent --region $REGION --format='value(status.url)')
echo "Currency Agent URL: $CURRENCY_AGENT_URL"
# 3. Update AGENT_URL so the agent advertises its public HTTPS endpoint in its Agent Card
gcloud run services update currency-agent \
--region $REGION \
--update-env-vars AGENT_URL="$CURRENCY_AGENT_URL"
Bước 3: Triển khai Travel Agent
Bây giờ, hãy triển khai Travel Agent, định cấu hình bằng CURRENCY_AGENT_URL:
# 1. Deploy Travel Agent (with ADK Web UI) connected to Currency Agent
gcloud run deploy travel-agent \
--source travel_agent \
--region $REGION \
--allow-unauthenticated \
--update-env-vars CURRENCY_AGENT_URL="$CURRENCY_AGENT_URL",GOOGLE_GENAI_USE_ENTERPRISE="true",GOOGLE_CLOUD_PROJECT="$PROJECT_ID",GOOGLE_CLOUD_LOCATION="global"
# 2. Capture its assigned Cloud Run URL
TRAVEL_AGENT_URL=$(gcloud run services describe travel-agent --region $REGION --format='value(status.url)')
echo "Travel Agent URL: $TRAVEL_AGENT_URL"
10. Kiểm thử hệ thống đa tác nhân trong Cloud Run
Sau khi triển khai cả ba dịch vụ vi mô, hãy xác minh từng lớp trong Cloud Run.
1. Kiểm thử máy chủ MCP từ xa
Kiểm thử máy chủ MCP Cloud Run đã triển khai từ dòng lệnh:
MCP_SERVER_URL="$MCP_SERVER_URL" uv run python currency_mcp_server/test_server.py
Bạn sẽ thấy công cụ này được liệt kê và gọi thành công trên Cloud Run.
2. Thử nghiệm Tác nhân tiền tệ qua A2A
Kiểm thử Tác nhân tiền tệ đã triển khai bằng ứng dụng kiểm thử A2A:
AGENT_URL="$CURRENCY_AGENT_URL" uv run python currency_agent/test_a2aclient.py
Ứng dụng sẽ tìm nạp Thẻ nhân viên hỗ trợ từ xa từ Cloud Run và trao đổi thông báo qua HTTPS JSON-RPC.
3. Kiểm thử giao diện người dùng web của công ty du lịch trong Cloud Run
Mở $TRAVEL_AGENT_URL trong trình duyệt!
Giao diện người dùng web ADK hoàn chỉnh được phân phát trực tiếp từ Cloud Run. Thử hỏi:
"Tôi đang lên kế hoạch cho một chuyến đi đến Tokyo. Thời tiết thế nào và 500 USD bằng bao nhiêu JPY?"
[Browser]
│
▼ (HTTPS)
[Cloud Run: travel-agent]
├──> Local in-process tool: weather_agent (wttr.in)
└──> A2A JSON-RPC (HTTPS)
│
▼
[Cloud Run: currency-agent]
└──> MCP Streamable HTTP (HTTPS)
│
▼
[Cloud Run: currency-mcp-server] (Frankfurter API)
Cả ba dịch vụ đều mở rộng quy mô một cách độc lập trên cơ sở hạ tầng không máy chủ, giao tiếp liền mạch thông qua các giao thức mở!
11. Chúc mừng và dọn dẹp
Thành tích bạn đã đạt được
Xin chúc mừng! Bạn đã xây dựng và triển khai một hệ thống nhiều tác nhân cấp sản xuất:
- Giao thức ngữ cảnh mô hình (MCP): Tạo một máy chủ FastMCP cung cấp các công cụ API trực tiếp qua HTTP có thể truyền trực tuyến.
- Bộ công cụ phát triển tác nhân (ADK): Tạo các tác nhân mô-đun bằng
LlmAgent, kết nối các công cụ MCP vớiMcpToolsetvà lưu trữ Giao diện người dùng web ADK. - Giao thức Agent2Agent (A2A): Hiển thị một tác nhân dưới dạng dịch vụ A2A (
to_a2a), xuất bản Thẻ tác nhân (agent-card.json) và sử dụng các tác nhân từ xa bằngRemoteA2aAgent. - Kiến trúc đa tác nhân: Kết hợp các tác nhân phụ cục bộ trong quy trình (
weather_agent) với các tác nhân từ xa phân tán (currency_agent). - Triển khai không máy chủ trên Cloud Run: Đóng gói và triển khai cả ba dịch vụ bằng cấu hình tự động.
Để xem mã đầy đủ (bao gồm cả cách triển khai Python và Java) và các bản cập nhật trong tương lai, hãy truy cập vào kho lưu trữ getting-started-mcp-a2a-adk.
Dọn dẹp
Để tránh bị tính phí vào tài khoản Google Cloud cho các dịch vụ Cloud Run được tạo trong lớp học lập trình này, hãy làm như sau:
Xoá các dịch vụ Cloud Run đã triển khai:
gcloud run services delete currency-mcp-server --region $REGION --quiet
gcloud run services delete currency-agent --region $REGION --quiet
gcloud run services delete travel-agent --region $REGION --quiet
Ngoài ra, nếu đã tạo một dự án riêng cho lớp học lập trình này, bạn có thể tắt toàn bộ dự án:
gcloud projects delete $PROJECT_ID