EPISODE · Apr 23, 2026 · 4 MIN
@gregpr07:Agent harness 的苦澀教訓 不要封裝 LLM,也不要封裝它的工具。 你只需要一個 SKILL.md 和一些 Python 輔助函式。讓 …
from EasyVibeCoding Podcast · host Gregor Zunic
Agent harness 的苦澀教訓 不要封裝 LLM,也不要封裝它的工具。 你只需要一個 SKILL.md 和一些 Python 輔助函式。讓 LLM 擁有完全的自由,如果缺少什麼,就讓它自己寫出來。 學習心得 幾個月前,我們寫了《Agent 框架的苦澀教訓》(The Bitter Lesson of Agent Frameworks)。當時的論點是:不要用抽象層來封裝 LLM,應先給予最大的行動空間,再進行限制。 但當時我們仍在封裝它的工具。 每一個 click()、type()、scroll() 輔助函式,都是你自以為模型需要而強加的抽象層。每一個輔助函式,都是經過強化學習(RL)訓練的模型必須費力克服的限制。 為什麼選擇原生 CDP 當我們開發 Browser Use 的第一個版本時,我們發布了數千行的元素提取器、DOM 索引器以及點擊封裝器。 但 LLM 本身就懂 CDP(Chrome DevTools Protocol)。它們在訓練過程中已經讀過數百萬個 Page.navigate、DOM.querySelector 和 Runtime.evaluate 的 token。 CDP 是 Chrome 暴露出的最底層介面。直接把它交給模型: 跨來源 iframe:直接附加到目標,無需對抗任何框架抽象層。 Shadow DOM:像模型過去見過無數次那樣,直接遍歷 shadowRoot.querySelectorAll。 反機器人檢測:這本質上是 Chrome 在與自己對話。 我們錯在哪裡 幾個月前,我們在這個部落格寫了《更接近底層:從 Playwright 轉向 CDP》(Closer to the Metal: Leaving Playwright for CDP)。那篇文章的結論是:「我們的 Agent 不應該為了完成工作,而去了解 CDP Target 的細節。」 事實證明我們錯了。 那篇文章列出了 Chrome 分頁崩潰的十種方式。我們建立了監控服務來捕捉每一種情況——分頁崩潰、目標分離、渲染器記憶體溢出(OOM)、zygote 死亡、GPU 進程崩潰。每一個情況都有對應的處理程式,而每一個處理程式都必須與 Chrome 的內部機制保持同步。 只要給予 LLM 直接存取 CDP 的權限,並讓它有能力編輯自己的 harness,它就能自行處理這一切。分頁死掉、目標掛載錯誤、Chrome 卡住——Agent 會讀取錯誤訊息、重新掛載到新的目標、然後重試。它不需要監控服務,因為它已經讀過一萬篇關於 Chrome 崩潰的討論串,它早就知道該怎麼做。 我們試圖隱藏的那些「CDP 的複雜性」,根本不該被隱藏,而是應該讓模型直接看見。 四個檔案 這就是整個 harness 的全部內容: run.py (13 行) - 執行原生 Python 並預先載入輔助函式。 helpers.py (192 行) - 對 CDP 的輕量封裝,且 Agent 可以自行編輯它們。 daemon.py (220 行) - 保持 CDP websocket 連線存活。 SKILL.md - 告訴 Agent 如何使用上述內容。 總共約 600 行程式碼。 Agent 撰寫 Python 程式碼,Python 匯入這些輔助函式,輔助函式呼叫 CDP,Chrome 執行指令。Chrome 之上的所有東西都是可重寫的。 自我修復迴圈 當工具缺失時,會發生這種情況: 當缺少某個輔助函式時,Agent 會做任何 Claude Code 使用者都會做的事:搜尋 helpers.py,新增該函式,然後重新執行。 我們並沒有教它這麼做。我們只是給了它 Claude Code 標準的「讀取/編輯/寫入」能力加上 CDP 存取權。程式開發 Agent 本來就知道如何修復缺失的匯入(import)。 關鍵在於:Agent 並不是從零開始撰寫新程式碼,它只是編寫了缺失的那一個函式,就像它在任何程式庫中修復缺失的匯入一樣。 魔法時刻 檔案上傳:我們忘了加入 upload_file()。任務執行到一半,Agent 遇到一個檔案輸入框,它搜尋了 helpers.py,發現沒有這個功能,於是使用原生的 DOM.setFileInputFiles 寫出了這個函式並上傳了檔案。我們是在閱讀 git diff 時才發現的。 分塊上傳:在寫完 upload_file 後,Agent 嘗試上傳一個 12MB 的檔案。CDP websocket 的封包上限大約是 10MB。它觸發了限制、讀取了錯誤訊息,隨即切換到分塊上傳模式。 Gusto 到日曆:任務是將每位員工的生日放入我們的共享日曆中。這需要導覽 Gusto 的員工頁面、從 DOM 提取日期,然後建立 Google 日曆活動。 Azure 管理員角色:Azure 的管理入口網站是一堆嵌入在 iframe 中的面板。透過座標級別的 Input.dispatchMouseEvent,原生 CDP 可以直接在合成器(compositor)層級進行操作。 親自試試 為 Claude Code 或 Codex 設定 Prompt: `markdown Set up https://github.com/browser-use/browser-harness for me. ` 第一個找到它無法完成的任務(非驗證碼/雙重驗證)的人,可以獲得一台 Mac Mini。認真的。我已經試著搞垮它一週了,但完全做不到。 儲存庫:github.com/browser-use/browser-harness Agent harness 的苦澀教訓:你的輔助函式也是一種抽象層。刪掉它們,讓 Agent 自己寫出它需要的東西。 原文:https://easyvibecoding.app/curated/902
Embed this episode
Ready to play
@gregpr07:Agent harness 的苦澀教訓 不要封裝 LLM,也不要封裝它的工具。 你只需要一個 SKILL.md 和一些 Python 輔助函式。讓 …
No transcript for this episode yet
Similar Episodes
No similar episodes found.
Similar Podcasts
No similar podcasts found.