跳至主要內容

    Agent 駕馭工程懶人包 (3)|工具回傳值怎麼寫給 Agent 看?5 種做法整理

    工具回傳值會影響 Agent 下一步做什麼。整理 SQLGlot、OpenAI Cookbook、Arize、Jason Liu 與 Amp oracle 的五種寫法,附回傳時機、內容與適用情況的對照表。

    sunny 桑尼· · 18 MIN READ · 92 次瀏覽

    Agent 駕馭工程懶人包 (3)|工具回傳值怎麼寫給 Agent 看?5 種做法整理
    本文目錄

    打開你的 Agent 紀錄,找一次工具呼叫,看最後那一欄的工具回傳值(tool result,工具執行後交回模型的內容):是一句 success: true,一長串原始錯誤堆疊,還是三千行檔案內容?這一欄提供的資訊,會影響模型下一步做什麼。在個人網站 jxnl.co 發表 RAG 與 context engineering 系列文章的 Jason Liu,2025 年 8 月 27 日把他的觀察寫成一句話:

    "The metadata became prompt engineering itself." (Jason Liu, Beyond Chunks: Why Context Engineering is the Future of RAG, jxnl.co, 2025-08-27)

    他的意思是,工具回傳的結構與附註,本身就在教 Agent 怎麼想。Arize 那篇 context 管理的整理站在另一邊:回傳值多附一段說明,就多佔一段 context window(模型一次能讀的內容上限),所以過大的結果要截斷。這篇把五個一手來源放在一起,看各自怎麼寫回傳值,又在哪裡互相拉扯。

    快速回答 工具回傳值可從五處改善:錯誤位置(SQLGlot)、評分未過的原因(OpenAI Cookbook)、過大結果的續讀提示(Arize 整理的四套 Agent 駕馭層,harness)、搜尋漏掉的類別統計(Jason Liu)、第二個模型的意見(Amp oracle)。這五個來源沒有提供做法之間的對照實驗,無法排名。能寫成規則的檢查先用程式,語意品質才交給模型;新增的內容也佔 context window,要能改變 Agent 的下一步才值得。

    圖 1 懶人包卡:五種寫法各一條結論。前四條為各方文件的做法摘要,最後一條的觸發條件是本站建議,細節見正文。

    圖 1 的五條結論各來自一個一手來源。下一節先把它們攤成一張表,再逐一看兩邊的說法在哪裡對不上。

    五種做法放在一起:什麼時候回、回什麼、給誰用?

    五種做法的差別在回傳的時機、內容與適用的工具類型,各自插在工具呼叫的不同位置。表 1 先給全貌,圖 2 標出每一種的位置。

    「回傳時機」指回傳值在工具呼叫的哪一刻產生:執行前攔下、結果回來時加工,或是另一條線上的回饋。「回傳內容」指最後落進模型視野的文字長什麼樣子。五個來源裡,SQLGlot 是函式庫,文件沒有談 agent;Arize 與 Jason Liu 寫的是設計觀察;OpenAI Cookbook 與 Amp 各是一套可以對照的實作。讀表時要留意,這五個來源的證據類型不同,彼此不能當作同一種對照實驗的五個組別。

    做法回傳時機回傳內容適用場景(本站歸納)

    SQLGlot 錯誤附位置
    回傳時機
    執行前,解析失敗時
    回傳內容
    錯誤描述、行、欄、前後文與反白片段
    適用場景(本站歸納)
    輸入有語法可驗證,例如 SQL
    OpenAI Cookbook 評分回饋
    回傳時機
    每輪產出之後,評分失敗時
    回傳內容
    程式評分器回預寫句;模型評審回評分理由
    適用場景(本站歸納)
    規格能寫成規則,或需語意判斷
    Arize 整理的截斷
    回傳時機
    結果超過上限時
    回傳內容
    預覽加續讀提示,或完整結果存磁碟
    適用場景(本站歸納)
    檔案讀取、grep 這類大輸出
    Jason Liu 的 facets
    回傳時機
    每次搜尋回傳時
    回傳內容
    結果加來源、分類統計(facets)與系統指示
    適用場景(本站歸納)
    檢索、搜尋類工具
    Amp oracle
    回傳時機
    Agent 主動呼叫時
    回傳內容
    唯讀子代理的分析(格式文件未寫明)
    適用場景(本站歸納)
    review、debug、規劃卡關時

    表 1 五種做法對照。「適用場景」一欄是本站歸納,五方各自沒有這樣分類。來源見各節與參考資料,查閱於 2026-10-23。

    圖 2 五種做法在一次工具呼叫前後的位置。Cookbook 的回饋送給改寫提示的代理,Amp oracle 由 Agent 主動呼叫,所以各自畫在另外兩條線上。

    圖 2 的線 A 是多數人想到的工具回傳值:模型發出呼叫,工具執行,結果回到模型。SQLGlot 的檢查插在執行之前,Arize 描述的截斷與 Jason Liu 的 facets 插在結果回來之後。線 B 與線 C 的回傳值不走這條路,後面兩節各用一段說明它們把文字送到誰手上。

    回饋文字該由程式寫,還是由模型寫?

    能寫成規則的檢查由程式回傳固定文字,寫不成規則的語意判斷才由模型生成理由;OpenAI Cookbook 的範例把兩種放在同一條流程裡。

    這份範例是〈Self-Evolving Agents: A Cookbook for Autonomous Agent Retraining〉,頁面署名 Calvin Maguranis 等五位貢獻者。第一版在 2025 年 11 月 7 日進入 cookbook 儲存庫(依 GitHub 提交紀錄),頁面沒有標發表日。任務是草擬藥品法規文件的摘要,系統裡有四個評分器(grader,判斷結果有沒有達標的角色):

    • 化學名稱:摘要有沒有保留原文的化學名稱,通過門檻 0.8。
    • 摘要長度:與預期 100 字的偏離程度,門檻 0.85。
    • 餘弦相似度:用分數衡量摘要與原文有多相近,分數越高越相近,門檻 0.85。
    • LLM 評審(用大型語言模型當評審):以 gpt-4.1 依評分標準打分,門檻 0.85。

    前三個是程式。它們失敗時,範例程式回傳事先寫好的句子,例如長度失敗就回:

    "The summary length deviates too much from the expected length." (OpenAI Cookbook, Self-Evolving Agents,collect_grader_feedback 函式)

    只有 LLM 評審的回饋是當次生成的:評審的推理文字原樣接進回饋。函式的說明寫著要把評分器的推理整理成「給 metaprompt agent 的可行動回饋」(原文:actionable feedback for the metaprompt agent)。收到回饋的是負責改寫提示的代理,它只在摘要沒通過寬鬆門檻時才執行,範例裡最多重試 3 次。頁面對 LLM 評審的定位是備援:

    "The LLM judge provides a holistic failsafe when edge cases slip past deterministic checks." (同上)

    SQLGlot 站在程式那一側。它是開源的 SQL 解析與轉譯函式庫,文件沒有談 agent;它的錯誤物件本來就帶了位置資訊。我在 2026 年 10 月 23 日用 30.24.0 版(PyPI 上 2026-10-20 發布的最新版)跑了一次:

    from sqlglot import parse_one
    from sqlglot.errors import ParseError
    try:
        parse_one("SELECT id FROM users WHERE")
    except ParseError as e:
        print(repr(str(e)))
        print(e.errors[0])
    

    第一行輸出是 "Required keyword: 'this' missing for <class 'sqlglot.expressions.query.Where'>. Line 1, Col: 26.\n SELECT id FROM users \x1b[4mWHERE\x1b[0m",第二行是同一個錯誤的欄位字典:description、line 為 1、col 為 26、start_context 為 SELECT id FROM users 、highlight 為 WHERE。

    兩件事要注意。字串版本裡的 \x1b[4m 是終端機的底線控制碼,直接丟給模型只會多出雜訊;欄位版本沒有這個問題。另外,SQLGlot 的 qualify 會依 schema(資料表與欄位的定義)檢查欄位是否存在。我給的 schema 是 users 表有 id、name、tenant_id 三欄,檢查 SELECT nme FROM users 時,錯誤是 Column 'nme' could not be resolved. Line: 1, Col: 10,只說哪個欄位找不到,沒有列出有哪些欄位可用。

    工程上的意思: 這個回傳值寫在工具外面那層包裝:先攔下 ParseError,只取 description、line、col、highlight 這幾個欄位組成回傳。要列出可用欄位,得由包裝層自己從 schema 查出來補上,這是本站的建議,SQLGlot 的文件沒有這樣做。

    兩邊的取捨在成本與穩定度。程式版本不需要再呼叫一次模型,同樣的輸入每次回同樣的句子,但 Cookbook 的固定句子不含實際數字,長度失敗時模型讀不到是偏長還是偏短(本站觀察,函式裡的三個字串確實沒有數值)。模型版本能說出具體哪裡不好,每次的措辭不同,也多一次呼叫。

    回傳值該多附一點,還是砍短一點?

    Jason Liu 主張在搜尋結果旁多附 facets 與指示,Arize 整理的四套 harness 則各自限制過大的輸出,例如 Pi 保留開頭並提示續讀,Claude Code 存磁碟、回傳預覽;兩邊的一手依據都成立,差別在回傳值要回答的問題。

    多附的一邊:Jason Liu。 他在那篇文章裡把搜尋工具的回傳分成四級,第四級加入 facets(對整批結果做的分類統計,例如各狀態各有幾筆)。他的示範是一個工單搜尋:回傳的 3 筆全是 Done,facets 卻顯示另有 5 筆 Open。回傳內容旁附了一段提示,建議再用 status="Open" 查一次。他的解釋是已解決的工單文件較完整,在相似度排序裡排得比較前面(這是他的說法,文中沒有量測)。第二級的範例則在結果後面加一段 <system-instruction>,告訴 Agent:同一份文件有多個片段時,改用 load_pages() 載入整頁。

    他自己也畫了界線:

    "Metadata that doesn't change agent behavior is just expensive noise." (同上)

    砍短的一邊:Arize。 Aparna Dhinakaran 在 Arize AI 的部落格(2026 年 4 月,文章先發表於 X)比較了 Pi、OpenClaw、Claude Code 與 Letta 四套 harness 的 context 管理。以下數字都是該文的描述,我沒有逐一對照原始碼:

    • Pi 的檔案讀取上限是 2,000 行或 50KB,先到先停,保留開頭、截掉後面,並在輸出尾端附上續讀提示:[Showing lines 1-2000 of 50000. Use offset=2001 to continue.]
    • OpenClaw 沿用 Pi 的讀取限制,另外給工具結果 16,000 字元或 context window 的 30%(取較小者)。結尾看起來重要時(錯誤、JSON 的結尾括號、摘要關鍵字)保留頭尾,否則只留開頭。
    • Claude Code 把過大的工具結果存到磁碟,換成 2KB 的預覽;單一工具上限 50,000 字元,單則訊息合計上限 200,000 字元。文中的例子是 60KB 的 grep 結果,在新 session 的第一輪就會被搬到磁碟。檔案超過 256KB 時,讀取會被拒絕,錯誤訊息指向 offset/limit 或 grep。

    這篇文章同時說明,Claude Code 的兩道讀取限制可由 Anthropic 遠端調整,所以上面的數字是 2026 年 4 月的快照。Arize 自己的產品 Alyx 也這樣做:工具結果上限 10,000 個 token,大型 JSON 拆成壓縮預覽加伺服器端完整副本,模型再用 jq(篩選 JSON 資料的工具)取出需要的部分。文章開頭描述好的系統怎麼做,其中一項是:

    "truncating content in a way that hints at what else can be accessed." (Aparna Dhinakaran, Context management in agent harnesses, arize.com, 2026-04)

    圖 3 Claude Code 對過大工具結果的處理(依 Arize 對其行為的描述):完整結果存磁碟,context 只留 2KB 預覽。依據:Arize,2026-04。

    工程上的意思: 上限與預覽要在工具包裝層設定。上限寫死在包裝層,模型就算沒要求,也不會一次收到五萬字元;續讀提示寫在回傳值裡,模型才知道下一步可以怎麼拿剩下的部分。

    兩邊的差別可以這樣歸納:Liu 的回傳值回答「還有什麼沒被看到」,Arize 描述的回傳值回答「剩下的怎麼拿」。一個加內容,一個減內容,共同點是都把下一步需要的線索留在回傳值裡。

    要不要把第二個模型包成工具?

    Amp 把第二個模型包成名為 oracle 的工具,回傳值是它的分析文字,並且刻意不在 system prompt 裡鼓勵主 Agent 常呼叫它。

    Amp 是一款 coding agent。官方 Chronicle 在 2025 年 7 月 4 日公告 oracle:背後是一個唯讀子代理,當時用 OpenAI 的 o3,主 Agent 是 Sonnet 4;公告說它比主 Agent 的模型慢一些、貴一些,但擅長 review、debug、分析與決定下一步。關於呼叫頻率,公告這樣寫:

    "We consciously haven't pushed the oracle too hard in the system prompt, to avoid unnecessarily increasing costs for you or slowing you down." (Amp, Oracle, ampcode.com, 2025-07-04)

    呼叫靠明講:公告列的範例提示包含請 oracle 檢查上一個 commit 的改動,以及遇到 bug 時要求 Amp 盡量多用 oracle(原文給的理由是它很聰明)。2025 年 10 月 1 日的公告說 GPT-5 取代 o3 成為 oracle 的模型,理由包含它不同的訓練來源,適合當 Sonnet 的搭檔。

    比這兩則公告更新的是 Amp 文件(我於 2026 年 10 月 23 日查閱):Task 子代理使用與主執行緒相同的模型與推理強度,在自己的 context window 裡工作;文件說要求「ask the oracle」或「use the librarian」時,系統派出的是負責 review 或調查的子代理。依這份文件,oracle 的請求會交給與主執行緒同模型的子代理,oracle 目前用哪個模型,我查閱的文件頁沒有寫。「第二個模型來自不同公司」這個前提,在 Amp 現況可能已經不成立。

    oracle 回傳的是另一個模型對 review、debug 或規劃的分析意見;Cookbook 的 LLM 評審則是檢查摘要,把評分理由交給改寫提示的代理。Amp 的公告沒有說明回傳的格式,也沒有說主 Agent 該如何處理與自己判斷衝突的意見。

    我的建議是:想試這一種,把呼叫條件寫成可檢查的規則,例如同一個測試連續失敗兩次就呼叫;Amp 的公告則是靠人在提示裡明講。這個規則版本我沒有實測,成立的前提是你的任務卡關時,額外一次呼叫的延遲與費用付得起。

    五種寫法看完,先改哪一欄?

    先看自己工具的回傳值屬於哪一格:只回 success: true 的,補上狀態;可能回很大輸出的,先加上限;能寫成規則的檢查,先用程式回傳。

    五種做法有一個共通處:每一種都在結果之外多放了一樣東西,位置、續讀提示、被漏掉的類別、失敗的理由、第二個意見。這是本站的歸納,五方各自沒有這樣講。

    我的做法會照成本由低到高加,因為前面幾步不用多呼叫模型。第一步,包裝層攔下錯誤,只回位置與原因。第二步,替輸出可能很大的工具設上限,並在回傳尾端寫明怎麼續讀。第三步,檢索類工具再考慮附 facets,附之前先問一句:這段 metadata 會讓 Agent 多做哪一個動作?答不出來就別附,這是用 Liu 自己的界線來檢查他的做法。LLM 評審與 oracle 放最後,兩者都多一次模型呼叫,語意判斷無法寫成規則時才值得。

    這個順序的前提是你的 Agent 已經會因為回傳值而走錯路。工具輸出一直很短、也沒有失敗紀錄的系統,不需要為了對齊這張表而改。

    回到開頭那一欄。Liu 說 metadata 成了 prompt engineering,Arize 的作者說截斷要留下線索,Cookbook 的固定句子與 Amp 的公告也都在做同一件事:把工具回傳值當成寫給模型的文字來設計。下次打開紀錄時,先看那一欄寫了什麼,再回頭調 system prompt。

    回傳值寫好之後,使用者在 Agent 執行到一半想插話,話要從哪個時機進去?下一篇接著談。

    常見問題

    工具失敗時,可以直接把原始錯誤堆疊丟給模型嗎?

    可以,但建議先整理。SQLGlot 是開源的 SQL 解析函式庫,它的 ParseError 同時有字串與欄位兩種形式,字串裡有終端機的底線控制碼,欄位則有 line、col 與 highlight。取欄位組成回傳,就能保留錯誤位置,並去掉終端機控制碼。

    回傳值太長要截斷時,該留開頭還是結尾?

    視輸出類型而定。依 Arize 2026 年 4 月的整理,Pi 的檔案讀取保留開頭並附續讀提示;OpenClaw 在結尾出現錯誤、JSON 結尾括號或摘要關鍵字等重要內容時,改留頭尾。這些是該文描述的處理方式。

    LLM 評審的回饋可以取代程式檢查嗎?

    OpenAI Cookbook 的〈Self-Evolving Agents〉範例沒有這樣做:四個評分器裡三個是程式,LLM 評審被描述為備援。程式檢查不必多呼叫一次模型,同樣輸入得到相同回饋;Cookbook 這份範例的固定回饋句沒有附實際數字。LLM 評審能說出具體問題,但每次措辭不同,也多一次模型呼叫。兩者的取捨取決於規格能不能寫成規則。

    Amp 的 oracle 一定要用另一家公司的模型嗎?

    從我讀到的文件無法確認有這項要求。Amp 2025 年的公告把不同訓練來源當成優點;2026 年 10 月 23 日查閱時,文件寫明 Task 子代理(接手子任務的代理)與主執行緒使用相同模型,但沒有說明 oracle 當時用哪個模型。

    延伸閱讀

    參考資料

    留言0

    登入後就能留言。

    登入