【A2A 系列 #4】動手做:用 Google ADK 打造你的第一個 A2A 多 Agent 協作 Demo
理論講完了,是時候動手。本文透過一個完整的開源專案 a2a-booklore,帶你用 Google ADK + A2A Protocol 實作一個三 Agent 協作系統,從 Agent Card 到 RemoteA2aAgent,從啟動到對話,完整走一遍。
本文為 A2A 系列第四篇。建議依序閱讀: → 【A2A 系列 #1】從對話到協作:為何 A2A 是 AI 演進的終局之戰? → 【A2A 系列 #2】深入剖析 A2A:如何讓 AI Agent 彼此溝通與分工? → 【A2A 系列 #3】Task 狀態機與安全架構:讓多 Agent 協作真正可信賴
前三篇我們把 A2A 協議從「為什麼需要」到「怎麼設計的」、從「Task 狀態機」到「四層安全架構」都走了一遍。理論上,你現在應該對 A2A 的全貌有了清晰的地圖。
這一篇,我們直接跳進程式碼。我用 Google ADK(Agent Development Kit) 搭配 A2A Protocol,打造了一個完整可運行的多 Agent 協作 Demo:a2a-booklore。三個 Agent、三個終端機、一段對話,你就能親眼看到 A2A 的 Agent Card 自動生成、跨服務任務委派、結果整合,前三篇文章講過的所有概念,全部在本機跑起來。
場景設計:技術書籍選書助手
Demo 的使用情境是一個「技術書籍選書助手」:使用者告訴系統自己想學什麼技術主題,系統會自動幫你找書、評書、給出閱讀建議。
這個場景雖然簡單,卻精準對應了多 Agent 協作的核心模式:一個 Orchestrator 協調多個專業 Worker,每個 Worker 只做一件事且做到極致。
架構總覽
flowchart TD
U([User Input])
U --> O
O["Orchestrator: booklore_planner\nport 8000 (adk web)"]
O -->|A2A Protocol| A
O -->|A2A Protocol| B
A["Worker A: book_search_agent\nport 8001"]
B["Worker B: book_review_agent\nport 8002"]
三個 Agent 各司其職:
| Agent | 角色 | 啟動方式 | Port |
|---|---|---|---|
booklore_planner | Orchestrator — 接收使用者需求,協調兩個 Worker | adk web | 8000 |
book_search_agent | Worker A — 根據技術主題搜尋並推薦 5 本最適合的書 | uvicorn + A2A | 8001 |
book_review_agent | Worker B — 對書單進行評分、摘要與適讀對象分析 | uvicorn + A2A | 8002 |
這裡有幾個值得注意的架構決策:
- Worker 透過 A2A 協議獨立部署,它們是獨立的 HTTP 服務,Orchestrator 透過網路呼叫
- Orchestrator 本身不暴露 A2A 端點,它是 ADK Web UI 的本地 Agent,直接面向使用者
- 三者可以跑在不同機器上,只要 Orchestrator 能透過 HTTP 存取 Worker 的 Agent Card
技術棧
- Google ADK — Agent Development Kit(Python),Google 官方的 Agent 開發框架
- A2A Protocol — Agent-to-Agent 通訊標準
- Gemini 2.5 Flash — 所有 Agent 使用的 LLM,實務上每個 Agent 可以掛載不同的 LLM
- uvicorn — 託管 Worker A2A 服務的 ASGI(Asynchronous Server Gateway Interface) Server
- uv — 新世代 Python 套件管理工具
核心程式碼解析
Worker 端:用 to_a2a() 一行暴露 A2A 服務
以 Book Search Agent 為例,核心程式碼極其精簡:
from google.adk.agents import Agent
from google.adk.a2a.utils.agent_to_a2a import to_a2a
root_agent = Agent(
model="gemini-2.5-flash",
name="book_search_agent",
description=(
"Technical book search expert. Given a technical topic provided by the user, "
"searches and returns the 5 most suitable recommended books."
),
instruction="""You are a professional technical book search agent.
## Your Task
When you receive a technical topic (e.g. "Kubernetes security", "Python machine learning"),
find the 5 books best suited for learning that topic.
## Output Format
Return the book list strictly in the following format, with no extra text:
BOOK_LIST_START
1. <Title> by <Author> (<Year>)
2. <Title> by <Author> (<Year>)
3. <Title> by <Author> (<Year>)
4. <Title> by <Author> (<Year>)
5. <Title> by <Author> (<Year>)
BOOK_LIST_END
...""",
)
# Wrap the ADK Agent as an A2A service (auto-generates Agent Card)
a2a_app = to_a2a(root_agent, port=8001)
to_a2a() 呼叫,做了三件事:
- 將 ADK Agent 包裝成 ASGI 應用程式
- 自動生成 Agent Card 並掛載到
/.well-known/agent-card.json - 暴露 A2A 協議所需的所有端點(Task 建立、狀態查詢等)
這就是我們在第二篇講的 A2A Exposing 模式的具體實現。你不需要手動撰寫 Agent Card JSON;ADK 從 Agent 的 name、description 等屬性自動推導生成。
Orchestrator 端:用 RemoteA2aAgent 連接遠端 Worker
Orchestrator 的程式碼展示了 A2A Consuming 模式:
from google.adk.agents import Agent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from google.adk.tools.agent_tool import AgentTool
# ── Worker A: Book Search Agent (connected via A2A, running at localhost:8001) ──
book_search_agent = RemoteA2aAgent(
name="book_search_agent",
description=(
"Technical book search agent. "
"Given a technical topic, returns a list of 5 recommended books."
),
agent_card="http://localhost:8001/.well-known/agent-card.json",
use_legacy=False,
)
# ── Worker B: Book Review Agent (connected via A2A, running at localhost:8002) ──
book_review_agent = RemoteA2aAgent(
name="book_review_agent",
description=(
"Technical book review analysis agent. "
"Given a book list, returns a rating (1-5 stars), summary, "
"and target audience for each book."
),
agent_card="http://localhost:8002/.well-known/agent-card.json",
use_legacy=False,
)
# ── Orchestrator: Book Planner (local Agent, coordinates both Workers) ──
root_agent = Agent(
model="gemini-2.5-flash",
name="booklore_planner",
description="Technical book selection assistant that helps users plan the best "
"reading list for their learning goals.",
instruction="""You are a professional technical book planner.
Your job is to coordinate two specialized worker agents to deliver a complete
book recommendation based on the user's learning needs.
## Workflow
**Step 1: Analyze the request**
Extract the core technical topic from the user's input.
**Step 2: Delegate book search (call book_search_agent)**
Send the extracted topic to book_search_agent to get a list of 5 recommended books.
**Step 3: Delegate review analysis (call book_review_agent)**
Send the full book list from Step 2 to book_review_agent to get ratings and summaries.
**Step 4: Consolidate and respond**
Merge results from both Workers into the following report format:
...""",
sub_agents=[],
tools=[AgentTool(agent=book_search_agent), AgentTool(agent=book_review_agent)],
)
核心概念:
RemoteA2aAgent是 ADK 提供的元件,負責讀取遠端 Agent Card、建立 A2A 連線agent_card參數直接指向 Worker 的.well-known/agent-card.json端點,即第二篇講的 Agent 自動發現機制AgentTool將遠端 Agent 包裝為 LLM 可呼叫的 Tool,Orchestrator 的 LLM 可以自行決定何時呼叫哪個 Worker
啟動流程:
前置準備
# Clone 專案
git clone https://github.com/charles-hsiao/a2a-booklore.git
cd a2a-booklore
# 安裝 dependencies(使用 uv)
uv sync
# 設定 API Key
cp .env.example .env
# 編輯 .env,填入 Google API Key
# 可從 https://aistudio.google.com/apikey 取得
Terminal 1:啟動 Worker A(Book Search Agent)
uv run uvicorn book_search_agent.agent:a2a_app --host localhost --port 8001
啟動後,可透過以下路徑驗證 Agent Card 是否正確生成:
http://localhost:8001/.well-known/agent-card.json
Terminal 2:啟動 Worker B(Book Review Agent)
uv run uvicorn book_review_agent.agent:a2a_app --host localhost --port 8002
同樣驗證 Agent Card:
http://localhost:8002/.well-known/agent-card.json
Terminal 3:啟動 Orchestrator(Book Planner)
uv run adk web .
開啟瀏覽器進入 http://localhost:8000,選擇 booklore_planner 即可開始對話。
Demo 實際對話流程
啟動完畢後,在 ADK Web UI 輸入:
I want to learn Kubernetes security
背後會發生以下事情:
User: I want to learn Kubernetes security
booklore_planner → [A2A] → book_search_agent (port 8001)
Request: "Kubernetes security"
Response: 5 本推薦書單
booklore_planner → [A2A] → book_review_agent (port 8002)
Request: [完整書單]
Response: 每本書的評分、摘要、適讀對象
booklore_planner → 整合報告 → User
最終使用者會收到一份結構化的書籍推薦報告,包含:
- 5 本推薦書籍清單
- 每本書的 1-5 星評分
- 內容摘要(2-3 句)
- 適讀對象(初學者 / 中階 / 進階)
- Planner 的個性化閱讀建議

ADK Web UI 也內建了完整的 Trace 檢視功能,可以逐步展開每個 Agent 的呼叫過程,包含 Orchestrator 的推理步驟、發出的 A2A 請求、各 Worker LLM 的輸入輸出,對於理解多 Agent 協作的實際執行路徑非常有幫助。

A2A 協議在 Demo 中的具體體現
這個 Demo 雖然程式碼量不大,卻完整展示了 A2A 協議的四個核心概念:
| 概念 | 說明 | 程式碼對應 |
|---|---|---|
| Exposing | Worker 用 to_a2a() 將 ADK Agent 包裝為 HTTP A2A 服務 | book_search_agent/agent.py |
| Agent Card | 自動生成的 JSON 描述檔,告知其他 Agent 如何呼叫此服務 | /.well-known/agent-card.json |
| RemoteA2aAgent | Orchestrator 用來連接遠端 Worker 的元件 | booklore_planner/agent.py |
| Consuming | Orchestrator 將 Worker 作為 Tool 使用,ADK 處理所有網路通訊 | tools=[AgentTool(...)] |
對照前三篇的理論:
- Agent Card → 第二篇的「Agent 的履歷」
- Task 生命週期 → 第三篇的 FSM 狀態機(
submitted→working→completed) - 跨服務呼叫 → 第一篇講的「專業分工 + 標準化溝通介面」
設計決策與思考
為什麼選擇 Google ADK?
截至 2026 年 5 月,ADK 是目前對 A2A Protocol 支援最完整的 Agent 框架之一。它的 to_a2a() 和 RemoteA2aAgent 讓你用最少的程式碼,就能完成 A2A 服務的 Expose 與 Consume。不需要手寫 Agent Card、不需要自己處理 HTTP 路由、不需要手動管理 Task 狀態機,框架幫你搞定了這些基礎設施層的事情。
為什麼 Orchestrator 用 tools 而不是 sub_agents?
你可能注意到 root_agent 的 sub_agents=[] 是空的,Worker 是透過 AgentTool 掛載到 tools 清單上。這是 ADK 處理 A2A 遠端 Agent 的慣用模式:將遠端 Agent 視為 LLM 可呼叫的 Tool,讓模型自行判斷何時、以什麼順序呼叫它們。
這個設計有一個深層意涵:Agent 的執行順序不是硬編碼的,而是由 LLM 的推理能力動態決定。 Orchestrator 的 instruction 定義了建議的工作流程(先搜書、再評書),但如果未來業務邏輯改變,你只需要調整 prompt,不用改程式碼結構。
為什麼三個 Agent 各自獨立部署?
這不是為了增加複雜度,而是為了展示 A2A 的核心價值:Worker 可以是任何人、任何團隊、任何語言寫的服務。 在真實場景中,Book Search Agent 可能由資料團隊維護、跑在 AWS Lambda 上;Book Review Agent 可能由內容團隊提供、部署在 GCP Cloud Run 上,只要遵循 A2A 協議,Orchestrator 就能無縫整合。
你可以嘗試的延伸情境
啟動 Demo 後,除了 Kubernetes security,你也可以試試:
Recommend some books on Python machine learning
I'm a senior engineer looking to go deep on distributed systems design
觀察 Orchestrator 如何根據不同的技術主題,調整它與 Worker 之間的互動方式。
小結:從理論到可運行的程式碼
四篇文章走下來,我們從 A2A 的動機、核心元件、狀態機、安全架構,一路走到了可以在本機跑起來的完整 Demo。
回顧這個旅程:
- 第一篇:為什麼多 Agent 協作是 AI 的終局方向
- 第二篇:A2A 的五個核心元件(Agent Card、Task、Message、Part、Artifact)
- 第三篇:Task 狀態機、安全架構、A2A 與 MCP 的關係
- 本篇:用 Google ADK 實作一個完整的三 Agent A2A Demo
如果你想更深入理解 A2A 在雲原生環境中的落地,也可以看看 kagent 這個已經支援 A2A Protocol 的 CNCF Sandbox 專案。
延伸閱讀:【AIOps】Kubernetes 原生的 AI Agent 框架:kagent 完整解析
A2A 協議還在快速演進中。規格會更新、API 會改動、其他框架也會陸續出現,但這些都不是等待的理由,恰恰相反,這是現在入場的最佳時機。
每一個你今天踩到的坑、每一個讓你困惑的設計決策,都是這個生態系統還需要工程師參與塑造的訊號。HTTP 在 1991 年只有三個 Method,但那些在協議還粗糙的年代就動手寫 Web 應用的人,後來成了定義這個時代的工程師。
多 Agent 協作的基礎設施正在被建造。俗話說:「坐而言不如起而行」,程式碼在這裡,去跑跑看吧:github.com/charles-hsiao/a2a-booklore
延伸閱讀
A2A 系列完整回顧:
- 【A2A 系列 #1】從對話到協作:為何 A2A 是 AI 演進的終局之戰?
- 【A2A 系列 #2】深入剖析 A2A:如何讓 AI Agent 彼此溝通與分工?
- 【A2A 系列 #3】Task 狀態機與安全架構:讓多 Agent 協作真正可信賴
相關文章:
- 【AIOps】Kubernetes 原生的 AI Agent 框架:kagent 完整解析 — 已支援 A2A Protocol 的 CNCF Sandbox 專案
- 【Agentic Web】IsItAgentReady — 你的網站準備好被 AI Agent 存取了嗎?