這篇是 FDE 面試系列第二篇。
RAG 是知識,Agent 是行動。
FDE 的工作常常是兩者都要。
為什麼 Agent 幾乎必考
JD 裡通常明寫:
- LangGraph
- CrewAI
- ADK(Google Agent Development Kit)
- ReAct
- Hierarchical Delegation
- MCP(Model Context Protocol)
這些詞出現在 JD 不是意外。FDE 的日常工作就是幫客戶設計和部署這些東西。
什麼是 Agent
用一句話說:
Agent = LLM + Tools + Loop
LLM 負責決策,Tools 負責執行,Loop 讓它可以反覆思考直到完成任務。
最經典的 Loop 模式叫 ReAct:
Thought: 我需要查一下這個客戶的訂單狀態
Action: call_tool("get_order", customer_id="C123")
Observation: 訂單 #456 目前在「出貨中」狀態
Thought: 我知道答案了,可以回覆用戶
Action: respond("您的訂單 #456 目前正在出貨,預計明天到達")
Reason(思考)→ Act(行動)→ Observe(觀察)→ 再思考,這就是 ReAct。
系統設計考題:AI Customer Support Agent
這是面試最常出現的設計題。
面試官可能問:
「設計一個 AI 客服系統,能夠查訂單、回答 FAQ、轉接人工。」
第一步:畫架構圖
用戶
↓
API Gateway(身份驗證、Rate Limiting)
↓
Orchestrator Agent(主控)
↓ ↓ ↓
Tool Router
├── CRM Tool(查訂單、客戶資料)
├── Knowledge Base Tool(RAG,查 FAQ / 政策文件)
├── Escalation Tool(轉接人工)
└── Ticketing Tool(建立工單)
↓
LLM(Claude / Gemini)
↓
Response
第二步:定義每個元件的職責
Orchestrator(主控 Agent)
- 接收用戶輸入
- 決定呼叫哪個 Tool
- 整合 Tool 結果,生成最終回應
Tool Router
- 根據意圖路由到對應 Tool
- 管理 Tool 的輸入 / 輸出格式
Knowledge Base Tool(這是 RAG)
- 查內部文件:退款政策、產品說明、FAQ
- 回傳相關段落
CRM Tool
- 查訂單狀態、交易記錄
- 需要安全控管,不能讓 AI 隨意修改資料
第三步:用 LangGraph 實作
LangGraph 的核心概念是狀態圖:Agent 在不同節點之間流動,每個節點處理一件事。
1from typing import TypedDict, Annotated
2import operator
3from langgraph.graph import StateGraph, END
4
5class SupportState(TypedDict):
6 user_message: str
7 intent: str # 訂單查詢 / FAQ / 轉接
8 tool_results: Annotated[list, operator.add]
9 final_response: str
10 escalate: bool
11
12def classify_intent(state: SupportState) -> SupportState:
13 """判斷用戶意圖"""
14 # 呼叫 LLM 分類
15 intent = llm_classify(state["user_message"])
16 return {"intent": intent}
17
18def query_crm(state: SupportState) -> SupportState:
19 """查 CRM 訂單資料"""
20 order_info = crm_tool.get_order(state["user_message"])
21 return {"tool_results": [order_info]}
22
23def query_knowledge_base(state: SupportState) -> SupportState:
24 """查知識庫(RAG)"""
25 relevant_docs = rag_tool.search(state["user_message"])
26 return {"tool_results": [relevant_docs]}
27
28def generate_response(state: SupportState) -> SupportState:
29 """根據 Tool 結果生成回應"""
30 context = "\n".join(state["tool_results"])
31 response = llm_generate(context, state["user_message"])
32 return {"final_response": response}
33
34def route_by_intent(state: SupportState) -> str:
35 """根據意圖決定下一個節點"""
36 intent = state["intent"]
37 if intent == "order_inquiry":
38 return "query_crm"
39 elif intent == "general_faq":
40 return "query_knowledge_base"
41 elif intent == "escalate":
42 return "escalate"
43 return "generate_response"
44
45# 建立狀態圖
46workflow = StateGraph(SupportState)
47workflow.add_node("classify_intent", classify_intent)
48workflow.add_node("query_crm", query_crm)
49workflow.add_node("query_knowledge_base", query_knowledge_base)
50workflow.add_node("generate_response", generate_response)
51
52workflow.set_entry_point("classify_intent")
53workflow.add_conditional_edges("classify_intent", route_by_intent)
54workflow.add_edge("query_crm", "generate_response")
55workflow.add_edge("query_knowledge_base", "generate_response")
56workflow.add_edge("generate_response", END)
57
58app = workflow.compile()
面試必考:什麼時候要用 Multi-Agent
這是我最愛問的判斷題。
很多人的答案是「當任務複雜的時候」。這個答案不夠好。
正確的判斷邏輯
單一 Agent 就夠了,當:
- 任務流程是線性的
- 工具少(5 個以內)
- 任務可以在一個 context window 裡完成
需要 Multi-Agent,當:
- 任務需要並行執行(不同 Agent 同時工作)
- 任務需要專業分工(不同角色做不同的事)
- 任務太長,單一 context window 裝不下
- 需要相互檢查(一個 Agent 驗證另一個 Agent 的輸出)
典型 Multi-Agent 架構
Planner(規劃師)
↓ 分配任務
├── Researcher(研究員)—— 搜集資料
├── Analyst(分析師)—— 分析數據
└── Writer(撰寫者)—— 生成報告
↓
Reviewer(審核者)—— 檢查輸出品質
↓
最終輸出
用 CrewAI 實作:
1from crewai import Agent, Task, Crew
2
3researcher = Agent(
4 role="研究員",
5 goal="蒐集關於{topic}的最新市場資料",
6 backstory="你是一位專業的市場研究員,擅長快速找到可靠的資訊來源",
7 tools=[search_tool, scraper_tool]
8)
9
10analyst = Agent(
11 role="數據分析師",
12 goal="分析研究員提供的資料,找出關鍵趨勢",
13 backstory="你是一位資深的數據分析師,善於從大量資料中提取洞察",
14 tools=[calculator_tool, chart_tool]
15)
16
17writer = Agent(
18 role="報告撰寫者",
19 goal="根據分析結果撰寫清晰易懂的執行摘要",
20 backstory="你是一位商業寫作專家,能把複雜資訊轉化為清楚的報告"
21)
22
23research_task = Task(
24 description="搜集 {topic} 的市場現況、競爭者分析",
25 agent=researcher,
26 expected_output="包含來源連結的市場研究報告"
27)
28
29analysis_task = Task(
30 description="分析研究員的報告,找出 3 個關鍵洞察",
31 agent=analyst,
32 expected_output="3 個數據支撐的市場洞察",
33 context=[research_task] # 依賴 research_task 的輸出
34)
35
36crew = Crew(
37 agents=[researcher, analyst, writer],
38 tasks=[research_task, analysis_task, write_task]
39)
面試必考:Agent Loop 如何避免失控
這是面試官想知道你有沒有工程常識的題目。
設計 Agent 最大的風險之一:無限循環。
Agent 決策錯誤 → 再嘗試 → 還是錯 → 繼續嘗試 → 無限循環 → 費用爆炸。
四道防線
① Max Iterations(迭代上限)
1MAX_ITERATIONS = 10
2
3iteration = 0
4while not task_complete:
5 if iteration >= MAX_ITERATIONS:
6 return "任務超過最大迭代次數,請人工處理"
7
8 result = agent.step()
9 iteration += 1
② Timeout(時間上限)
1import asyncio
2
3async def run_agent_with_timeout(agent, task, timeout_seconds=60):
4 try:
5 result = await asyncio.wait_for(
6 agent.run(task),
7 timeout=timeout_seconds
8 )
9 return result
10 except asyncio.TimeoutError:
11 agent.stop()
12 return "任務超時,已強制停止"
③ Cost Budget(費用預算)
1class BudgetedAgent:
2 def __init__(self, max_cost_usd: float = 1.0):
3 self.max_cost = max_cost_usd
4 self.current_cost = 0.0
5
6 def call_llm(self, prompt: str) -> str:
7 estimated_cost = estimate_cost(prompt)
8
9 if self.current_cost + estimated_cost > self.max_cost:
10 raise BudgetExceededError(
11 f"預算已達上限 ${self.max_cost},已使用 ${self.current_cost:.4f}"
12 )
13
14 response = llm.invoke(prompt)
15 self.current_cost += actual_cost(response)
16 return response
④ Human Approval(人工確認)
高風險操作不讓 Agent 自己決定:
1HIGH_RISK_ACTIONS = [
2 "delete_customer_data",
3 "process_refund",
4 "send_mass_email",
5 "modify_pricing"
6]
7
8def execute_action(action_name: str, params: dict) -> str:
9 if action_name in HIGH_RISK_ACTIONS:
10 # 暫停,等待人工確認
11 approval = request_human_approval(
12 action=action_name,
13 params=params,
14 timeout=300 # 5 分鐘內沒確認就取消
15 )
16 if not approval.approved:
17 return f"操作 {action_name} 已取消"
18
19 return execute(action_name, params)
MCP:Model Context Protocol
這是 Google / Anthropic 都在推的標準協議。
簡單說:定義 AI 如何和外部工具溝通的規範。
就像 HTTP 讓瀏覽器和伺服器能溝通,MCP 讓 Agent 和工具能用標準方式溝通。
Agent
↓ MCP 請求(標準格式)
MCP Server(你的 CRM / 資料庫 / API)
↓ MCP 回應(標準格式)
Agent
好處:工具只要實作 MCP Server,任何支援 MCP 的 Agent 框架都能用。
1# MCP Server 範例(簡化)
2from mcp.server import MCPServer
3
4server = MCPServer(name="crm-service")
5
6@server.tool("get_customer_order")
7async def get_customer_order(customer_id: str) -> dict:
8 """查詢客戶訂單狀態"""
9 order = await crm_db.fetch_order(customer_id)
10 return {
11 "order_id": order.id,
12 "status": order.status,
13 "estimated_delivery": order.eta
14 }
15
16@server.tool("create_support_ticket")
17async def create_support_ticket(
18 customer_id: str,
19 issue_description: str,
20 priority: str = "normal"
21) -> dict:
22 """建立客服工單"""
23 ticket = await ticketing_system.create(
24 customer_id=customer_id,
25 description=issue_description,
26 priority=priority
27 )
28 return {"ticket_id": ticket.id, "status": "created"}
Google ADK 簡介
如果面試的是 Google 客戶相關的 FDE 職位,ADK(Agent Development Kit)可能被問到。
核心概念:
1from google.adk.agents import Agent
2from google.adk.tools import google_search, code_execution
3
4root_agent = Agent(
5 name="enterprise_assistant",
6 model="gemini-2.0-flash",
7 instruction="""
8 你是一位企業 AI 助理。
9 你可以搜尋資訊、執行程式碼分析數據。
10 回答時請保持專業,並引用資料來源。
11 """,
12 tools=[google_search, code_execution]
13)
14
15# ADK 內建的 Agent Loop
16response = root_agent.run("分析上個季度的銷售數據趨勢")
ADK 和 LangGraph 的定位不同:
- LangGraph:給你完整控制,你自己定義每個節點和邊
- ADK:更高層的抽象,Gemini 原生支援,適合快速原型
面試答題框架
系統設計題的回答結構:
1. 釐清需求(2 分鐘)
- 用戶是誰?
- 最關鍵的幾個功能?
- 有什麼特殊限制?(latency / cost / compliance)
2. 畫高層架構(5 分鐘)
- 畫出主要元件
- 說明每個元件的職責
3. 深入細節(10 分鐘)
- 選一兩個最關鍵的部分深入
- 說明 trade-off
4. 說明失敗模式(3 分鐘)
- 這個設計最容易在哪裡出問題?
- 怎麼偵測?怎麼恢復?
小結
Agent 系統設計考的不是你記了多少框架的 API,而是:
- 你知道什麼時候該用 Single Agent,什麼時候要 Multi-Agent
- 你清楚 Agent 的失控風險,而且有對策
- 你能在白板上畫出一個可以實際落地的架構
下一篇:傳統 ML / AI 基礎知識 — FDE 面試中哪些經典 ML 知識還是必須知道的。
