這是使用 Next.js 15、CopilotKit 和 Google ADK 與 AG-UI 協定,實作客戶支援聊天機器人的完整範例。
# 1. 安裝相依套件
make setup
# 2. 設定 API 金鑰
cp agent/.env.example agent/.env
# 編輯 agent/.env 並加入您的 GOOGLE_API_KEY
# 3. 啟動後端和前端
make dev
# 4. 在瀏覽器中開啟 http://localhost:3000此實作展示了:
- ✅ Python ADK Agent:具備自訂工具
- ✅ FastAPI 後端:整合 AG-UI
- ✅ Next.js 15 前端:整合 CopilotKit
- ✅ 即時聊天介面:支援串流回應
- ✅ 工具增強回應:(知識庫、訂單查詢、建立工單)
- ✅ 完整的測試套件:(30+ 個測試)
- ✅ 可上線的架構
flowchart TD
%% ===============================
%% USER BROWSER
%% ===============================
subgraph USER["🖥️ 使用者瀏覽器"]
A1["Next.js 15 App<br>Port 3000<br>app/page.tsx<br>• Chat UI<br>• <CopilotKit> Provider<br>• <CopilotChat> Component"]
A2["@copilotkit/react-core<br>(TypeScript SDK)"]
end
USER -->|"AG-UI Protocol<br>(HTTP / SSE)"| BACKEND
%% ===============================
%% BACKEND SERVER
%% ===============================
subgraph BACKEND["🛠️ 後端伺服器 (Port 8000)"]
B1["FastAPI + ag_ui_adk"]
B2["/api/copilotkit Endpoint"]
B3["AG-UI Protocol Adapter"]
B4["Session Management"]
end
BACKEND -->|"Invoke Agent"| AGENT
%% ===============================
%% GOOGLE ADK AGENT
%% ===============================
subgraph AGENT["🤖 Google ADK Agent"]
C1["model:<br> gemini-2.0-flash-exp"]
C2["tools:<br>• search_knowledge_base<br>• lookup_order_status<br>• create_support_ticket"]
C3["instruction:<br>Customer Support Prompt"]
end
AGENT -->|"Gemini API"| GEMINI
%% ===============================
%% GEMINI MODEL
%% ===============================
subgraph GEMINI["✨ Gemini 2.0 Flash"]
D1["Text Generation"]
D2["Function Calling"]
D3["Streaming Responses"]
end
customer-support-agent/
├── agent/ # Python 後端
│ ├── __init__.py
│ ├── agent.py # ADK agent + FastAPI 應用程式
│ └── .env.example # 環境變數範本
├── nextjs_frontend/ # Next.js 前端
│ ├── app/
│ │ ├── layout.tsx # 根佈局
│ │ ├── page.tsx # 具備 CopilotKit 和進階功能的聊天頁面
│ │ ├── advanced/
│ │ │ └── page.tsx # 進階功能示範頁面
│ │ └── globals.css # Tailwind 樣式
│ ├── components/
│ │ ├── ThemeToggle.tsx # 深色/淺色模式切換
│ │ └── ProductCard.tsx # 生成式 UI 產品卡片
│ ├── package.json
│ ├── tsconfig.json
│ ├── next.config.js
│ └── tailwind.config.ts
├── tests/ # 測試套件
│ ├── test_agent.py # Agent 設定測試
│ ├── test_imports.py # 匯入驗證
│ ├── test_structure.py # 專案結構測試
│ └── test_tools.py # 工具函式測試 (包含進階功能)
├── Makefile # 建置指令
├── README.md # 本檔案
├── requirements.txt # Python 相依套件
└── pyproject.toml # Python 套件設定
此實作包含了教學 30 (customer-support-agent) 中的三個強大進階功能:
Agent 可以在聊天中直接渲染豐富的互動式 React 元件:
- 產品卡片:顯示產品圖片、價格、評分和庫存狀態
- 動態元件:Agent 決定何時使用視覺元件而非純文字
- 實作方式:
create_product_card()工具回傳結構化資料,由ProductCard元件進行渲染
試試看:"Show me product PROD-001" (顯示產品 PROD-001)
敏感操作需要明確的使用者批准:
- 退款批准:處理退款前須經使用者確認
- 確認對話框:批准前清楚顯示操作詳情
- 取消:使用者可以拒絕請求,Agent 會繼續提供替代方案
試試看:"I want a refund for order ORD-12345" (我想為訂單 ORD-12345 退款)
Agent 無需詢問即可即時存取使用者情境:
- 使用者資料:自動取得姓名、電子郵件、帳戶類型
- 訂單歷史:Agent 知道您的訂單 (ORD-12345, ORD-67890)
- 會員資訊:可存取加入日期和帳戶狀態
試試看:"What's my account status?" (我的帳戶狀態是什麼?)
了解更多:請造訪執行中應用程式的 /advanced 頁面以獲取詳細實作文件。
主頁面 (http://localhost:3000) 包含:
-
頁首區塊
- 客戶支援助理品牌標示
- 使用者帳戶顯示 (已登入為 John Doe)
- 進階功能導覽連結
- 深色/淺色模式切換
-
聊天介面 (固定高度:600px)
- 使用 CopilotKit 的即時 AI 聊天
- 初始訊息中的範例提示
- 串流回應
- 工具執行回饋
-
功能展示 (聊天視窗下方,可捲動)
- 分頁介面:在三個功能間切換
- 生成式 UI 分頁:即時 ProductCard 範例
- HITL 分頁:模擬退款批准對話框
- 共享狀態 分頁:使用者帳戶資訊顯示
- 直接顯示在首頁,方便立即探索
使用者流程:
- 進入頁面 → 看到帶有範例提示的聊天視窗
- 向下捲動 → 透過即時示範探索進階功能
- 點擊分頁 → 互動式體驗各項功能
- 造訪
/advanced→ 閱讀實作細節
make setup # 安裝所有相依套件 (後端 + 前端)
make setup-backend # 僅安裝後端相依套件
make setup-frontend # 僅安裝前端相依套件make dev # 啟動後端和前端
make dev-backend # 僅啟動後端 (埠號 8000)
make dev-frontend # 僅啟動前端 (埠號 3000)make test # 執行所有測試
make demo # 顯示示範提示make clean # 移除產生的檔案- "What is your refund policy?" (你的退款政策是什麼?)
- "How long does shipping take?" (運送需要多久?)
- "Tell me about your warranty" (告訴我關於保固的資訊)
- "How do I reset my password?" (我要如何重設密碼?)
- "Check order status for ORD-12345" (檢查訂單 ORD-12345 的狀態)
- "What's the status of order ORD-67890?" (訂單 ORD-67890 的狀態如何?)
- "Track my order ORD-11111" (追蹤我的訂單 ORD-11111)
- "My product stopped working after 2 months" (我的產品在 2 個月後停止運作)
- "I need help with a billing issue" (我需要協助解決帳單問題)
- "Create a ticket for account access problems" (為帳戶存取問題建立工單)
- "Show me product PROD-001" (顯示產品 PROD-001)
- "What products do you have available?" (你們有哪些產品?)
- "Tell me about the Widget Pro" (告訴我關於 Widget Pro 的資訊) (顯示產品卡片)
- "Display product PROD-002" (顯示產品 PROD-002) (顯示 Gadget Plus)
- "I want a refund for order ORD-12345" (我想為訂單 ORD-12345 退款)
- "Process a refund of $99.99 for my order" (為我的訂單處理 $99.99 的退款)
- "Can you refund my purchase?" (你能為我的購買退款嗎?) (需要批准對話框)
- "What's my account status?" (我的帳戶狀態是什麼?) (Agent 知道您的名字)
- "Show me my recent orders" (顯示我最近的訂單) (Agent 擁有訂單歷史)
- "When did I join?" (我什麼時候加入的?) (Agent 知道會員加入日期)
編輯 agent/.env:
# 必填
GOOGLE_API_KEY=your_api_key_here
# 選填
PORT=8000
HOST=0.0.0.0
ENVIRONMENT=development
LOG_LEVEL=INFO編輯 nextjs_frontend/.env:
NEXT_PUBLIC_AGENT_URL=http://localhost:8000本實作包含完整的測試:
# 執行所有測試
make test
# 執行特定測試檔案
pytest tests/test_agent.py -v
pytest tests/test_tools.py -v測試覆蓋範圍:
- ✅ Agent 設定驗證
- ✅ 工具函式行為
- ✅ 專案結構驗證
- ✅ 匯入驗證
- ✅ FastAPI 端點設定
- ✅ 錯誤處理
make dev
# 後端:http://localhost:8000
# 前端:http://localhost:3000後端 (Google Cloud Run):
cd agent
gcloud run deploy customer-support-agent \
--source . \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars="GOOGLE_API_KEY=your_key"前端 (Vercel):
cd nextjs_frontend
vercel
# 設定環境變數
vercel env add NEXT_PUBLIC_AGENT_URL production
# 輸入:https://customer-support-agent-xyz.run.app本實作支援兩種驗證方式:
export GOOGLE_API_KEY=your_api_key_here
# 在以下網址取得免費金鑰:https://aistudio.google.com/app/apikeyexport GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
export GOOGLE_CLOUD_PROJECT=your_project_id
# 在以下網址建立:https://console.cloud.google.com/iam-admin/serviceaccounts問題: ImportError: No module named 'ag_ui_adk'
# 解決方案:安裝相依套件
make setup-backend問題: Authentication failed (驗證失敗)
# 解決方案:檢查 API 金鑰
echo $GOOGLE_API_KEY # 應顯示您的金鑰
# 或設定它:
export GOOGLE_API_KEY=your_key問題: 前端無法連接到後端
# 解決方案:檢查後端是否正在執行
curl http://localhost:8000/health
# 應回傳:{"status": "healthy"}問題: 瀏覽器控制台出現 CORS 錯誤
# 解決方案:檢查 agent/agent.py 中的 CORS 設定
# 確保您的前端 URL 在 allow_origins 清單中問題: 聊天沒有回應
情境:瀏覽器控制台顯示:
Failed to load resource: the server responded with a status of 422 (Unprocessable Entity)
POST http://localhost:8000/api/copilotkit 422
這是預期且無害的!
CopilotKit 在頁面載入期間發送的初始握手請求與 AG-UI 協定架構不符。FastAPI 的驗證回傳 422,CopilotKit 會自動重試,當您發送第一條訊息時,連線將會成功建立。
行動:✅ 無需採取任何行動 - 這是設計使然
想了解完整解釋? 請參閱 TROUBLESHOOTING_422.md 以獲得完整的技術分析和驗證步驟。
情境:聊天介面底部出現紅色橫幅:
The requested agent was not found. Please set up at least one agent before proceeding.
已套用的修正:從 <CopilotKit> 元件移除了 agent="customer_support_agent" 屬性。AG-UI 協定會自動從後端發現 Agent。
如果您仍然看到此錯誤:
- 確保後端正在執行:
curl http://localhost:8000/health - 檢查瀏覽器控制台是否有連線錯誤
- 驗證
/api/copilotkit端點是否存在:curl http://localhost:8000/docs
情境:瀏覽器控制台出現錯誤:
Invalid adapter configuration: EmptyAdapter is only meant to be used with agent lock mode.
For non-agent components like useCopilotChatSuggestions, CopilotTextarea, or CopilotTask,
please use an LLM adapter instead.
根本原因:使用 ExperimentalEmptyAdapter (將所有 LLM 呼叫委派給您的 AG-UI Agent) 時,CopilotKit 要求啟用 "agent lock mode" (Agent 鎖定模式)。這確保所有請求都通過您的特定 Agent,而不是嘗試使用不存在的 LLM 轉接器。
已套用的修正:
- 前端 (
page.tsx):在 CopilotKit 元件加入agent屬性:
<CopilotKit runtimeUrl="/api/copilotkit" agent="customer_support_agent">
<ChatInterface />
</CopilotKit>- 後端路由 (
route.ts):確保 Agent 名稱相符:
const runtime = new CopilotRuntime({
agents: {
customer_support_agent: new HttpAgent({ url: `${backendUrl}/api/copilotkit` }),
},
});為什麼需要這樣做:
ExperimentalEmptyAdapter沒有 LLM - 它只代理給您的 Agent- CopilotKit 功能如
useCopilotChatSuggestions需要 LLM - Agent 鎖定模式告訴 CopilotKit:"所有事情都使用這個特定的 Agent"
- 如果沒有它,CopilotKit 嘗試使用 EmptyAdapter 不存在的 LLM → 錯誤
驗證:
- 檢查瀏覽器控制台 - 錯誤應已消失
page.tsx中的 Agent 名稱與route.ts中的 Agent 名稱相符route.ts中的 Agent 名稱與後端 Agent 名稱 (customer_support_agent) 相符
情境:聊天介面底部出現紅色橫幅:
[Network] Unknown error occurred
根本原因:CopilotKit 1.10.6+ 發送的訊息缺少 AG-UI 協定所需的 id 欄位。後端驗證拒絕這些訊息,導致無法建立連線。
為什麼會發生:
- AG-UI 協定要求 UserMessage 必須有:
{id, role, content} - CopilotKit 1.10.6 只發送:
{role, content} - FastAPI 驗證因缺少
id欄位回傳 422 - CopilotKit 顯示通用的 "Unknown error" 而非具體的驗證錯誤
驗證:
- 開啟瀏覽器開發者工具 (F12) → Console 分頁
- 尋找:
{"detail":[{"type":"missing","loc":["body","messages",0,"user","id"],"msg":"Field required"...}]} - 這確認了缺少
id欄位
解決方案選項:
- 嘗試發送訊息:有時在輸入並發送後錯誤會解決
- 等待 ag_ui_adk 更新:套件維護者已注意到此相容性問題
- 使用替代 UI 框架:教學 32 (Streamlit) 沒有此問題
- 檢查更新:執行
pip install --upgrade ag-ui-adk並重新啟動後端
狀態:🔴 CopilotKit 1.10.6 與 ag_ui_adk 0.1.0 之間的已知相容性問題
想了解完整解釋? 請參閱 TROUBLESHOOTING_422.md 以獲得完整的技術分析和驗證步驟。
情境:
Warning: Prop `className` did not match. Server: "..." Client: "..."
原因:瀏覽器擴充功能 (密碼管理器、Grammarly) 在 React 載入前修改了 HTML
解決方案:
- 忽略警告 (不影響功能)
- 在無痕模式下測試
- 暫時停用瀏覽器擴充功能
情境:Error: GOOGLE_API_KEY not configured
解決方案:
- 建立
agent/.env檔案:cp agent/.env.example agent/.env
- 加入您的 API 金鑰:
GOOGLE_API_KEY=your_key_here - 重新啟動後端:
make dev
情境:Cannot find module '@copilotkit/react-core'
解決方案:
- 安裝相依套件:
cd nextjs_frontend && npm install
- 或使用 Makefile:
make setup
情境:Error: Address already in use
解決方案:
- 停止現有程序:
# 尋找程序 lsof -i :8000 # 後端 lsof -i :3000 # 前端 # 終止程序 kill -9 <PID>
- 或在
.env檔案中使用不同埠號
-
檢查後端健康狀態:
curl http://localhost:8000/health
應回傳:
{"status": "healthy", ...} -
檢查 API 文件: 開啟 http://localhost:8000/docs
-
直接測試後端:
cd agent && python agent.py
查看啟動訊息和錯誤
-
檢查前端建置:
cd nextjs_frontend && npm run build
應完成且無錯誤
-
檢視網路請求:
- 開啟瀏覽器開發者工具 (F12)
- 前往 Network (網路) 分頁
- 發送聊天訊息
- 檢查請求/回應詳細資訊
- 檢查後端日誌中的錯誤
- 驗證 API 金鑰設定正確
- 確保所有相依套件已安裝
- 嘗試
make clean && make setup - 查看 implementation log 獲取詳細疑難排解資訊
-
知識庫搜尋 (
search_knowledge_base)- 搜尋常見問題和文件
- 回傳格式化的文章
- 優雅地處理未知查詢
-
訂單狀態查詢 (
lookup_order_status)- 檢索訂單詳情
- 顯示追蹤資訊
- 預估送達日期
-
建立支援工單 (
create_support_ticket)- 產生唯一的工單 ID
- 基於優先級的回應時間
- 詳細的問題追蹤
- 即時串流回應
- 美觀的 Tailwind CSS 樣式
- 響應式設計
- CopilotKit 預建聊天 UI
- 基於環境的設定
- 具備自動產生文件的 FastAPI
- AG-UI 協定整合
- 開發環境的 CORS 設定
- 健康檢查端點
- 結構化日誌
⚠️ 切勿將.env檔案提交到版本控制- ✅ 始終使用
.env.example作為範本 - ✅ 將 API 金鑰儲存在環境變數中
- ✅ 在正式環境使用服務帳戶
- ✅ 在正式環境啟用 HTTPS
- ✅ 為正式環境部署實作速率限制
- 核心概念:使用 Next.js 15、CopilotKit 和 Google ADK (AG-UI 協定) 構建完整的客戶支援聊天機器人。
- 關鍵技術:Google ADK, FastAPI, Next.js 15, CopilotKit, AG-UI Protocol, Gemini API。
- 重要結論:本專案展示了如何整合前後端技術,實現具備生成式 UI、人機協作 (HITL) 和共享狀態等進階功能的 AI 代理人。
- 行動項目:
- 依循快速入門步驟設定環境。
- 設定 API 金鑰。
- 執行
make dev啟動服務。 - 參考疑難排解章節解決常見問題。