API 開發

多工具協作與內建工具:讓 Claude 一次用好幾把刀

處理多工具協作的關鍵是一個對話迴圈:反覆呼叫 Claude,只要回應的 stop_reason 是 tool_use,就執行所有請求的工具並把結果送回,直到它給出最終回答。加新工具只需四步:寫函式、定義 schema、加進 tools 清單、在路由加分支;Anthropic 另外內建 text editor 與 web search 兩個現成工具可直接取用。
多工具協作與內建工具:讓 Claude 一次用好幾把刀:文章重點卡

多工具協作與內建工具:讓 Claude 一次用好幾把刀

前幾篇的工具往返都是一問一答:Claude 要一次工具,你回一次結果。真實世界的問題沒這麼客氣,例如「距離今天 103 天後是哪一天」,Claude 得先查今天日期,再做日期加法,兩個工具接力才答得出來。

這一篇把對話迴圈做出來,讓 Claude 想用幾次工具就用幾次;接著看怎麼優雅地掛上更多工具,最後介紹 Anthropic 內建的兩個現成工具:text editorweb search

你將學到什麼

stop_reason 驅動迴圈

看一個欄位就知道 Claude 還想不想用工具。

工具路由與錯誤處理

多個 tool call 逐一執行,失敗也要好好回報。

加新工具的四步套路

函式、schema、tools 清單、路由分支,核心邏輯不用動。

兩個內建工具

text editor 給 schema 你寫實作,web search 全程代辦。

一個問題,好幾次工具接力

以「103 天後是哪一天」為例,幕後流程是這樣的:Claude 先回一個 tool use 區塊要求 get_current_datetime,你執行後回傳結果;它發現還不夠,再要求 add_duration_to_datetime;第二個結果回去之後,它才有材料給出最終答案。你的應用必須自動處理這種連環請求,不能每一步都人工接手。

呼叫 Claude帶著 tools 清單stop_reason是 tool_use 嗎?執行所有請求的工具結果以 user 訊息送回取得最終回答迴圈收工只要 Claude 還在開需求單,就一直繞這個圈
對話迴圈:stop_reason 是整個迴圈的開關

對話迴圈:stop_reason 是開關

怎麼知道 Claude 還想不想用工具?看回應訊息的 stop_reason 欄位:Claude 決定呼叫工具時,這個欄位會是 tool_use;不是的話,代表它已經準備好最終回答,迴圈就能收工。

def run_conversation(messages):
    while True:
        response = chat(messages, tools=[
            get_current_datetime_schema,
            add_duration_to_datetime_schema,
            set_reminder_schema
        ])
        add_assistant_message(messages, response)
        print(text_from_message(response))

        if response.stop_reason != "tool_use":
            break

        tool_results = run_tools(response)
        add_user_message(messages, tool_results)

    return messages

迴圈每一圈做四件事:呼叫 Claude、把回應完整塞回歷史、檢查是否還要工具、執行工具並把結果以 user 訊息送回。直到 Claude 不再開需求單為止。這裡的 text_from_message 是個小幫手:訊息現在是多區塊結構,它把其中所有 text 區塊撈出來串成一段,方便印給使用者看。

整份歷史則完整保留每一輪的工具往返,Claude 才能一路疊著先前的結果推進。

工具路由與錯誤處理

一則回應裡可能有多個 tool use 區塊。run_tools 先把它們全部濾出來,逐一執行,各自產生對應的 tool result 區塊,id 一一對上:

def run_tools(message):
    tool_requests = [
        block for block in message.content if block.type == "tool_use"
    ]
    tool_result_blocks = []

    for tool_request in tool_requests:
        try:
            tool_output = run_tool(tool_request.name, tool_request.input)
            block = {
                "type": "tool_result",
                "tool_use_id": tool_request.id,
                "content": json.dumps(tool_output),
                "is_error": False
            }
        except Exception as e:
            block = {
                "type": "tool_result",
                "tool_use_id": tool_request.id,
                "content": f"Error: {e}",
                "is_error": True
            }
        tool_result_blocks.append(block)

    return tool_result_blocks

def run_tool(tool_name, tool_input):
    if tool_name == "get_current_datetime":
        return get_current_datetime(**tool_input)
    elif tool_name == "add_duration_to_datetime":
        return add_duration_to_datetime(**tool_input)
    elif tool_name == "set_reminder":
        return set_reminder(**tool_input)

注意錯誤處理的姿勢:工具執行失敗時,不是讓程式炸掉,而是照樣回一個 tool result 區塊,把 is_error 設為 True、錯誤訊息放進 content。Claude 看得到錯誤內容,常常會修正參數重試。run_tool 則是一個簡單的路由:對名字、派工作,新工具加一個分支就好。

加新工具的固定套路

  1. 寫出工具函式本體。
  2. 為它定義 schema。
  3. 把 schema 加進 run_conversation 的 tools 清單。
  4. run_tool 路由裡加一個分支。

就這四步,核心對話邏輯完全不用動。拿提醒系統來驗收:「幫我設提醒,看醫生,時間是 2050 年 1 月 1 日之後 177 天」。Claude 會先用文字說明自己打算怎麼做,接著用日期加法工具算出目標日期是 2050 年 6 月 27 日,再呼叫 set_reminder 完成任務。

翻開對話歷史,你會看到 user 請求、夾著文字與 tool use 區塊的 assistant 訊息、tool result 訊息、後續 assistant 訊息,一層一層疊出完整的多工具協作。

內建工具一:text editor

除了自己造工具,Claude 也內建了一個 text editor 工具,能檢視檔案與目錄內容、看指定行數範圍、取代文字、建立新檔、在指定行插入文字、復原最近的編輯。等於一出廠就具備動手改檔案的介面,幾乎能直接扮演軟體工程師。

容易搞混的地方內建的是 schema,不是實作。Claude 知道怎麼「開口要求檔案操作」,但實際執行讀檔、改字、建檔的程式仍然要你自己寫。使用時依模型版本帶一個小小的 schema 存根,Claude 會自動展開成完整規格;各模型對應的版本字串,以官方文件為準。

你可能會問:編輯器都內建 AI 了,這工具幹嘛用?它的價值在於:當你要打造能自動改檔案的應用、在沒有完整編輯器的環境工作,或想把檔案編輯能力嵌進自己的 Claude 應用時,可以用它復刻出 AI 編輯器等級的功能,而且對檔案操作握有完全的控制權。

內建工具二:web search

web search 是另一種形態:連實作都不用寫,Claude 全程自己處理搜尋。你只要在 tools 裡放一個簡單的 schema,並注意組織要先在 Anthropic 主控台的設定裡啟用這個工具。

web_search_schema = {
    "type": "web_search_20250305",
    "name": "web_search",
    "max_uses": 5,
    "allowed_domains": ["nih.gov"]
}

max_uses 限制單次回答最多搜尋幾輪,因為 Claude 可能根據初步結果追加搜尋,這個上限能避免呼叫失控;allowed_domains 可以把搜尋範圍鎖在權威網域,例如查醫療議題時鎖定 nih.gov,拿到的就是實證來源而不是隨機部落格。

回應裡會帶上實際的搜尋查詢、逐筆結果與引用區塊,方便你在介面上把來源與引文攤開給使用者看,建立對答案的信任。

web search 最適合的場景:時事與最新發展、訓練資料裡沒有的專門資訊、需要查核事實或找權威來源的研究任務。只要把 schema 放進 tools 陣列,Claude 就會自己判斷什麼時候該搜尋。

到這裡,你手上已經有一套完整的工具架構:自訂工具補足 Claude 的短板,內建工具直接擴充它的手腳,對話迴圈把一切串起來。剩下的,就是依你的應用場景,決定要遞給它哪幾把刀。

參考出處本文取材自 Anthropic 官方 Claude Academy 免費課程「Building with the Claude API」,由酒Ann 消化後以自己的視角重新編寫。想看英文原版課程,可到 Claude Academy 修習。

延伸學習

把這篇文章分享給需要的人FacebookLINEThreadsX

常見問答

Claude 怎麼決定要連續呼叫幾次工具?
它每一輪都會評估手上的資訊夠不夠回答。不夠就再發工具請求,回應的 stop_reason 會是 tool_use;資訊足夠時它就給出最終回答,迴圈藉此收工,次數完全由任務需要決定。
工具執行失敗時該怎麼回報?
照樣回一個 tool result 區塊,把 is_error 設為 True、錯誤訊息放進 content,而不是讓程式炸掉。Claude 看得到錯誤內容,常常會修正參數重試。
text editor 工具是拿來就能用嗎?
一半一半。schema 內建在 Claude 裡,你只要帶一個小的 schema 存根;但檔案操作的實作要自己寫,Claude 只負責發出檢視、取代、建檔等請求,動手的是你的程式。
web search 和自己做搜尋工具差在哪?
web search 連實作都不用寫,Claude 全程自己處理搜尋並附上引用來源;你只要放一個 schema 並在組織設定裡啟用。自訂搜尋工具則什麼都自己來,換到的是完全的控制權。