上一篇我們第一次讓 LLM 呼叫 MCP Tool,不過當時的程式還有一個限制:一次只能處理一輪 Tool Call,像是昨天的程式碼如果輸入,幫我計算 10+20,然後把結果乘以 5
Gemini 第一次可能會先呼叫 Calculator 算出 30,拿到結果之後,它其實還可以繼續要求下一個 Tool Call,把 30 × 5 算出來,但之前的程式沒有辦法繼續處理第二次 Tool Call,所以最後就會出現問題,像下面這樣

所以今天要加入 Agent Loop,讓 Agent 不只是「呼叫一次 Tool 就結束」,而是可以根據前一次的結果,繼續決定下一步要做什麼。
簡單來說,就是讓 Agent 不斷重複這個過程:
詢問 LLM
↓
需要 Tool?
↓
是
↓
呼叫 MCP Tool
↓
把結果交回 LLM
↓
再判斷下一步
直到 LLM 判斷:
「這次不用再呼叫 Tool 了。」
這時才結束。
因此 Agent Loop 的核心其實就是:
while True:
讓 Agent 可以持續執行,而不是只處理一次。
這次不需要重新建立 MCP Server,直接修改上一篇的 agent.py 就可以,最大的差異有幾個。
上一篇只有執行一次:
response = client.models.generate_content(...)
現在改成:
while True:
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=contents,
config=types.GenerateContentConfig(
tools=[gemini_tool]
)
)
這樣 Gemini 如果又要求呼叫 Tool,就可以再次進入下一輪。
這次我們也加入:
contents = [
types.Content(
role="user",
parts=[
types.Part(
text=user_input
)
]
)
]
contents 可以理解成:
記錄這一次任務目前發生過什麼。
每次 Gemini 回應後,我們都把它加入:
contents.append(
response.candidates[0].content
)
Tool 執行完之後,也把結果加入:
contents.append(
types.Content(
role="user",
parts=[
types.Part(
function_response=types.FunctionResponse(
name=function_call.name,
response={
"result": str(
tool_result.content
)
}
)
)
]
)
)
因此下一輪 Gemini 就能看到前面的內容。
這裡要特別注意,這比較像是保存目前任務的 Context,而不是完整的 Agent Memory,今天是為了讓 Agent Loop 能夠繼續執行。
Tool 執行完之後,程式會再次回到 Gemini,如果 Gemini 還需要 Tool:
if response.function_calls:
就繼續執行。
如果 Gemini 已經可以直接回答:
if not response.function_calls:
print("\nGemini 最後回答:")
print(response.text)
break
就離開 while True。
所以整個流程就變成:
Gemini
↓
需要 Tool?
├─ 否 → 最後回答 → 結束
│
└─ 是
↓
MCP Tool
↓
Tool 結果
↓
回到 Gemini
↓
再判斷一次
打開終端機輸入python agent.py,接著打上問題,我的問題是幫我計算 10+20,然後把結果乘以 5

可以看到這次 Agent 就可以先取得 10+20 的結果,再根據這個結果繼續進行下一次 Tool Call 得出答案為150,之後我測試了連續三個運算,結果如下圖

可以看到還是有跑出正確的結果,代表這次的實作有成功
今天主要是在上一篇的基礎上,讓 Agent 開始具備「自己繼續做下一步」的能力,透過 while True,Agent 不再只能處理一次 Tool Call,而是可以根據 Tool 回傳的結果繼續詢問 LLM。
另外,我們也開始保存目前任務的 contents,讓每一輪都能知道前面發生過什麼,不過這裡的 Context 主要是為了支援這次任務的 Agent Loop,還不是完整的長期 Memory。後面如果要讓 Agent 記住不同對話或之前發生過的事情,還需要另外處理。