化實(shí)戰(zhàn):讓大模型看見屏幕并操控電腦)
如果你問(wèn)一個(gè)經(jīng)常用AI的人AI到底能替自己干哪些活得到的答案大概率是寫文案、改代碼、查資料、做翻譯。這些事有一個(gè)共同點(diǎn)——都發(fā)生在對(duì)話框里AI負(fù)責(zé)“說(shuō)”你負(fù)責(zé)“做”。但現(xiàn)實(shí)中的工作絕大多數(shù)不在對(duì)話框里整理下載目錄、批量重命名文件、把表格里的數(shù)據(jù)錄進(jìn)網(wǎng)頁(yè)、每天定時(shí)備份文件夾……這些重復(fù)、瑣碎、規(guī)則明確的事恰恰最適合交給自動(dòng)化系統(tǒng)卻恰恰是傳統(tǒng)AI最“夠不著”的地方。這篇文章是我自己動(dòng)手實(shí)踐“AI Agent賦能桌面自動(dòng)化”的一份真實(shí)記錄核心目標(biāo)很簡(jiǎn)單讓AI從“只會(huì)回答”變成“能夠操作”——它要能看見屏幕、移動(dòng)鼠標(biāo)、敲擊鍵盤、規(guī)劃步驟最終替我把一件完整的事情做完。如果你也想讓AI助手不再只是個(gè)“聊天框”希望這篇實(shí)戰(zhàn)演練能給你一條能直接落地的路徑。1. 對(duì)話框里的AI和桌面自動(dòng)化的差距到底差在哪1.1 AI能答但不能做我在剛開始做這個(gè)項(xiàng)目的時(shí)候最先意識(shí)到的問(wèn)題是大語(yǔ)言模型天然是“文本進(jìn)、文本出”的閉環(huán)。你讓它“幫我寫一份周報(bào)”它能給出結(jié)構(gòu)完整的模板你讓它“把下載文件夾整理一下”它大概率只能告訴你“建議按文件類型創(chuàng)建子文件夾然后將對(duì)應(yīng)文件移動(dòng)進(jìn)去”——然后就沒(méi)有然后了。這不是模型笨而是交互模態(tài)決定的。對(duì)話框里不存在“操作”的對(duì)象模型既看不到你的屏幕也沒(méi)有手去點(diǎn)鼠標(biāo)。它能做的只是基于語(yǔ)言常識(shí)給出建議??涩F(xiàn)實(shí)任務(wù)是靠“動(dòng)作”完成的打開窗口、選中文件、右鍵、移動(dòng)、確認(rèn)彈窗。這些動(dòng)作鏈一旦中斷整件事就做不成。所以我一直覺(jué)得真正讓AI產(chǎn)生生產(chǎn)力躍遷的不是它說(shuō)話更聰明而是它能不能把話轉(zhuǎn)化成實(shí)際操作。這一步跨出去就相當(dāng)于給AI裝上了手和眼睛。1.2 桌面自動(dòng)化Agent需要補(bǔ)上的三塊拼圖一個(gè)能操作桌面的Agent至少要同時(shí)具備三塊能力缺一塊都跑不起來(lái)感知能看到屏幕上的窗口、圖標(biāo)、按鈕、文字。沒(méi)有感知一切動(dòng)作都是盲猜。決策把“整理下載文件夾”這樣的高層目標(biāo)拆解成一個(gè)個(gè)原子操作并決定操作順序。執(zhí)行把決策落實(shí)到鼠標(biāo)點(diǎn)擊、鍵盤輸入、窗口切換等真實(shí)動(dòng)作上。這三塊拼圖正好對(duì)應(yīng)人的三種器官眼睛、大腦、手。傳統(tǒng)自動(dòng)化比如按鍵腳本只解決了“手”的問(wèn)題用固定坐標(biāo)和固定流程跑一旦界面變了就崩。而AI Agent真正有價(jià)值的地方是讓“大腦”參與進(jìn)來(lái)根據(jù)實(shí)時(shí)看到的屏幕內(nèi)容做動(dòng)態(tài)決策。它不是背流程而是看一步走一步。1.3 什么樣的任務(wù)才值得交給它不是所有任務(wù)都適合桌面Agent。我在實(shí)踐后總結(jié)了一個(gè)判斷標(biāo)準(zhǔn)用一張表就能說(shuō)清適合交給Agent的任務(wù)特征不適合交給Agent的任務(wù)特征重復(fù)執(zhí)行、步驟固定、操作對(duì)象明確需要強(qiáng)專業(yè)判斷如醫(yī)療診斷、法務(wù)審核操作過(guò)程中有清晰的視覺(jué)反饋純后臺(tái)計(jì)算無(wú)界面可觀察需要跨多個(gè)軟件協(xié)同涉及敏感數(shù)據(jù)且需要嚴(yán)格審計(jì)的流程規(guī)則會(huì)偶爾變化純腳本難以維護(hù)毫秒級(jí)實(shí)時(shí)響應(yīng)如交易下單人可以遠(yuǎn)程看著它操作后果不可逆如刪除生產(chǎn)數(shù)據(jù)庫(kù)簡(jiǎn)單說(shuō)凡是“你盯著屏幕能做、但不想親自做”的活都是Agent的候選任務(wù)。理解了這個(gè)邊界后面選技術(shù)方案才不會(huì)跑偏。2. 技術(shù)底座怎么選視覺(jué)方案對(duì)比傳統(tǒng)UI自動(dòng)化2.1 傳統(tǒng)UI自動(dòng)化的三條死胡同做桌面自動(dòng)化的技術(shù)方案不止一種我早期都試過(guò)最后才定下視覺(jué)方案。先說(shuō)為什么老路子走不通。第一類是坐標(biāo)腳本。用錄制工具記下鼠標(biāo)點(diǎn)擊的像素坐標(biāo)回放時(shí)按固定坐標(biāo)執(zhí)行。優(yōu)點(diǎn)是簡(jiǎn)單缺點(diǎn)是脆弱窗口稍微挪一下、分辨率改一下、任務(wù)欄多一個(gè)圖標(biāo)坐標(biāo)就全廢了。維護(hù)成本比寫腳本本身還高。第二類是UI控件樹方案。通過(guò)系統(tǒng)輔助功能接口讀取界面上的控件層級(jí)定位按鈕、輸入框后再操作。這個(gè)方案比坐標(biāo)穩(wěn)定但嚴(yán)重依賴軟件本身是否暴露控件信息很多第三方工具、老軟件、自繪界面根本讀不到任何控件等于瞎了。第三類是OCR加固定模板。截屏后用OCR識(shí)別文字位置再按預(yù)設(shè)模板點(diǎn)擊。這個(gè)方案對(duì)“文字按鈕”有效但界面布局一變模板就要重做本質(zhì)上還是在寫死規(guī)則只是把坐標(biāo)換成了文字位置。這三條死胡同的共同問(wèn)題它們都是“人先預(yù)判所有可能性再寫死應(yīng)對(duì)邏輯”。但真實(shí)桌面狀態(tài)千變?nèi)f化窮舉是窮舉不完的。2.2 視覺(jué)方案的本質(zhì)變化讓Agent擁有“眼睛”視覺(jué)方案的思路完全不同。它不關(guān)心底層控件接口不依賴固定模板只做一件事像人一樣看屏幕。把當(dāng)前屏幕截下來(lái)交給有視覺(jué)理解能力的大模型讓模型直接根據(jù)圖像內(nèi)容判斷“這是什么窗口、哪里有按鈕、下一步該點(diǎn)什么”。這個(gè)思路的本質(zhì)變化是從“窮舉狀態(tài)”變成“實(shí)時(shí)感知狀態(tài)”。Agent不再需要預(yù)先知道界面的每一種長(zhǎng)相它只需要每走一步就重新看一眼然后基于當(dāng)前畫面決策。這就解決了傳統(tǒng)方案最大的痛點(diǎn)界面變了怎么辦——界面變了我重看一眼就行。我實(shí)測(cè)下來(lái)視覺(jué)方案對(duì)“屏幕上有清晰文字和按鈕”的操作場(chǎng)景識(shí)別得非常準(zhǔn)。它最擅長(zhǎng)的是那些人類一眼就能看明白的界面比如文件管理器、設(shè)置頁(yè)、表單頁(yè)最怕的是圖形密集、無(wú)文字提示的純視覺(jué)界面。所以在設(shè)計(jì)任務(wù)時(shí)我會(huì)盡量把操作對(duì)象放在有文字標(biāo)識(shí)的界面里這是提高成功率的重要竅門。2.3 動(dòng)作執(zhí)行層為什么用模擬鍵鼠而不是系統(tǒng)原生接口看清楚了屏幕接下來(lái)要?jiǎng)邮?。?zhí)行層我選了最“笨”也最通用的方案模擬鼠標(biāo)鍵盤輸入也就是在系統(tǒng)層面注入點(diǎn)擊、移動(dòng)、鍵入事件。有人可能會(huì)問(wèn)為什么不直接調(diào)用系統(tǒng)自動(dòng)化接口原因是接口這條路只對(duì)支持輔助功能的軟件有效覆蓋面太窄。而模擬鍵鼠是操作系統(tǒng)提供的通用能力任何軟件都能接收輸入和真人操作完全一致。缺點(diǎn)是速度沒(méi)有原生接口快精確度也依賴坐標(biāo)計(jì)算但對(duì)于“幫人省去重復(fù)勞動(dòng)”這個(gè)目標(biāo)完全夠用。這個(gè)選擇就像請(qǐng)人代駕你不是讓代駕去拆車的控制系統(tǒng)而是讓他像你一樣握方向盤、踩油門。雖然笨但任何車都能開。3. 從零搭建一個(gè)能“看見并操作”桌面的Agent3.1 環(huán)境準(zhǔn)備依賴越少越好這個(gè)項(xiàng)目我全程用的是 Python 3.11加幾個(gè)輕量庫(kù)不到一百行核心代碼就能把主體邏輯跑通。依賴列表極簡(jiǎn)組件用途截圖庫(kù)抓取屏幕畫面?zhèn)鹘o視覺(jué)模型鍵鼠模擬庫(kù)移動(dòng)鼠標(biāo)、點(diǎn)擊、輸入文字、滾動(dòng)視覺(jué)理解模型根據(jù)截圖內(nèi)容輸出下一步動(dòng)作圖像比較工具動(dòng)作前后截圖差異分析用于驗(yàn)證執(zhí)行是否生效我不建議上來(lái)就套重型Agent框架??蚣芊庋b程度高出了問(wèn)題你很難判斷是模型的問(wèn)題還是框架調(diào)度的問(wèn)題。自己寫一個(gè)二十行的循環(huán)反而能把每一步都看得明明白白等跑通了再考慮要不要引入框架。3.2 把鼠標(biāo)鍵盤封裝成Agent的工具箱Agent不能直接調(diào)用操作系統(tǒng)它只能通過(guò)我們暴露給它的“工具”來(lái)操作。這一步非常關(guān)鍵工具設(shè)計(jì)的好壞直接決定Agent能不能穩(wěn)定執(zhí)行。我先寫了一批最底層的工具函數(shù)每個(gè)函數(shù)只做一件事參數(shù)明確返回值可讀# tools.py —— 把桌面操作封裝成 Agent 可用的工具 import time import pyautogui from PIL import Image def screen_shot(): 截取當(dāng)前屏幕返回圖像對(duì)象 img pyautogui.screenshot() return img def click(x: int, y: int): 移動(dòng)到指定坐標(biāo)并單擊 pyautogui.moveTo(x, y, duration0.2) pyautogui.click(x, y) time.sleep(0.5) return {result: clicked, position: (x, y)} def type_text(text: str): 逐字輸入文字 pyautogui.typewrite(text, interval0.05) return {result: typed, length: len(text)} def press_key(key: str): 按下按鍵如 enter、ctrlc pyautogui.press(key) return {result: pressed, key: key} def scroll(amount: int): 滾動(dòng)鼠標(biāo)滾輪正數(shù)向上負(fù)數(shù)向下 pyautogui.scroll(amount) return {result: scrolled, amount: amount}每個(gè)工具函數(shù)就是Agent的一只手。函數(shù)越原子越好不要寫一個(gè)“整理文件”這種大而全的工具否則Agent的決策能力就浪費(fèi)了。讓它自己用click、type_text、press_key去組合出“整理文件”的完整動(dòng)作鏈這才是Agent應(yīng)該干的事。3.3 Agent主循環(huán)觀察、思考、行動(dòng)工具準(zhǔn)備好之后核心邏輯就是一個(gè)循環(huán)截圖傳給模型模型返回一個(gè)動(dòng)作執(zhí)行動(dòng)作記錄結(jié)果再截圖驗(yàn)證直到模型判定任務(wù)完成。# agent_loop.py —— 最小實(shí)現(xiàn)觀察-思考-行動(dòng) from tools import screen_shot, click, type_text MAX_STEPS 20 history [] task 把下載文件夾里的文件按類型整理到對(duì)應(yīng)子文件夾 for step in range(MAX_STEPS): screenshot screen_shot() action ask_model(screenshot, history, task) # 調(diào)用視覺(jué)模型 result execute_action(action) history.append({step: step, action: action, result: result}) if action[tool] finish: break這里的靈魂在ask_model這個(gè)函數(shù)的輸入設(shè)計(jì)上。模型不是一個(gè)自由聊天的角色它是一個(gè)“只會(huì)調(diào)用工具的操作員”。我在系統(tǒng)提示詞里嚴(yán)格規(guī)定了它的輸出格式和規(guī)則這是整個(gè)系統(tǒng)穩(wěn)定性的基石你是運(yùn)行在用戶電腦上的桌面自動(dòng)化助手。 你的唯一溝通方式是通過(guò)工具調(diào)用輸出 JSON禁止輸出解釋性文字。 可用工具 - screen_shot: 截取當(dāng)前屏幕 - click(x, y): 點(diǎn)擊屏幕坐標(biāo) - type_text(text): 輸入文字 - press_key(key): 按下按鍵如 enter, ctrlc - scroll(amount): 滾動(dòng)鼠標(biāo)滾輪 - finish(summary): 任務(wù)結(jié)束 每輪只能輸出一個(gè)工具調(diào)用動(dòng)作完成后觀察新截圖再繼續(xù)。 如果某個(gè)動(dòng)作重復(fù)3次仍沒(méi)有效果換一種方式嘗試。 執(zhí)行之前先確認(rèn)目標(biāo)元素在截圖中的位置不確定時(shí)先放大截圖再?zèng)Q定。 注意不要假設(shè)上一步已經(jīng)成功必須從最新截圖中獲取信息??吹揭?guī)則里的“禁止輸出解釋性文字”了嗎這個(gè)設(shè)計(jì)很關(guān)鍵。如果允許模型先用文字解釋再輸出動(dòng)作它在解釋過(guò)程中很容易“跑題”而且解析輸出也會(huì)變得復(fù)雜。強(qiáng)制JSON輸出讓Agent保持“動(dòng)作密集”狀態(tài)每輪都必須往前走一步。3.4 坐標(biāo)系換算截圖像素和屏幕像素的鴻溝第一版代碼跑起來(lái)之后我遇到一個(gè)很基礎(chǔ)的坑模型在截圖上看到了一個(gè)按鈕給出的坐標(biāo)是(650, 420)但實(shí)際點(diǎn)擊卻偏了位置明顯不對(duì)。問(wèn)題出在截圖尺寸和屏幕邏輯尺寸不一致。很多桌面系統(tǒng)默認(rèn)開啟了縮放顯示比如150%縮放截圖返回的是物理像素而鼠標(biāo)API接收的是邏輯像素兩者存在固定比例差。解決方式是在截完圖后做一次坐標(biāo)換算# 假設(shè)截圖尺寸為 image_w x image_h屏幕邏輯尺寸為 screen_w x screen_h scale_x screen_w / image_w scale_y screen_h / image_h def to_screen_pos(img_x, img_y): return int(img_x * scale_x), int(img_y * scale_y)如果你用的是常見截圖方式建議先打印一下截圖尺寸和屏幕邏輯尺寸到底一不一致不一致就按比例算不要直接拿截圖坐標(biāo)去點(diǎn)擊。這個(gè)坑不解決后面所有動(dòng)作都是歪的。4. 實(shí)戰(zhàn)演示讓Agent替我把下載文件夾里的散亂文件歸好類4.1 給Agent的第一個(gè)真實(shí)任務(wù)理論講完直接上實(shí)戰(zhàn)。我給Agent分配的任務(wù)是把下載文件夾里的文件按類型整理到對(duì)應(yīng)子文件夾。當(dāng)時(shí)那個(gè)文件夾里大概有60多個(gè)文件混合著PDF、圖片、壓縮包、安裝程序、Word文檔亂成一團(tuán)。第一步是讓Agent打開文件管理器并定位到目標(biāo)文件夾。我給它提供的不是一個(gè)“自動(dòng)定位文件夾”的高層工具而是最底層的操作能力。Agent的做法是先打開文件管理器然后一路點(diǎn)擊左側(cè)的目錄樹最后在搜索框里輸入文件夾路徑回車截屏查看結(jié)果。整個(gè)過(guò)程大約用了10步每一步它都會(huì)停下來(lái)看一看確認(rèn)沒(méi)有點(diǎn)錯(cuò)再繼續(xù)。這個(gè)環(huán)節(jié)的亮點(diǎn)不在于快而在于“錯(cuò)了會(huì)糾正”。我回放日志時(shí)發(fā)現(xiàn)Agent第一次點(diǎn)擊目錄樹時(shí)點(diǎn)偏了落到了相鄰的文件夾上但它截圖后立即發(fā)現(xiàn)當(dāng)前界面不對(duì)于是右鍵返回上一級(jí)重新定位。這在傳統(tǒng)坐標(biāo)腳本里是不可想象的——腳本只會(huì)按預(yù)定坐標(biāo)走點(diǎn)錯(cuò)了也不會(huì)知道。4.2 Agent是怎么一步一步規(guī)劃和執(zhí)行的進(jìn)入目標(biāo)目錄后Agent的規(guī)劃是這樣的我直接從運(yùn)行日志里摘的截屏觀察當(dāng)前文件列表中都有什么類型的文件決定按擴(kuò)展名分組因?yàn)檫@是最清晰、最不容易產(chǎn)生歧義的分類維度依次創(chuàng)建PDF、圖片、壓縮包、安裝程序、文檔這幾個(gè)子文件夾從列表第一個(gè)文件開始逐個(gè)選中并移動(dòng)到對(duì)應(yīng)子文件夾全部處理完截屏確認(rèn)每個(gè)子文件夾里文件數(shù)量與預(yù)期一致。這里有一個(gè)細(xì)節(jié)值得說(shuō)創(chuàng)建文件夾時(shí)Agent選擇了右鍵菜單里的“新建文件夾”而沒(méi)有用鍵盤快捷鍵。表面上看這是個(gè)笨辦法但它的理由很實(shí)際——右鍵菜單在當(dāng)前界面一定可見快捷鍵可能因窗口焦點(diǎn)不同而失效。視覺(jué)Agent不是追求最優(yōu)路徑而是優(yōu)先選擇“確定性最高”的路徑。對(duì)自動(dòng)化系統(tǒng)來(lái)說(shuō)這恰恰是非??少F的品質(zhì)。4.3 執(zhí)行中的兩個(gè)小技巧第一次跑通之后我又連續(xù)跑了三輪在迭代中總結(jié)出兩個(gè)對(duì)識(shí)別率影響極大的技巧。技巧一先切換到列表視圖再開始操作。文件管理器默認(rèn)可能是圖標(biāo)視圖圖標(biāo)大、文字小模型識(shí)別文件名時(shí)容易把相鄰的圖標(biāo)文字?jǐn)囋谝黄稹G械皆敿?xì)信息列表視圖之后每個(gè)文件獨(dú)占一行文件名從行首開始識(shí)別錯(cuò)誤率明顯下降點(diǎn)擊坐標(biāo)也更好對(duì)齊。技巧二不要逐個(gè)文件拖拽而是多選同類文件后統(tǒng)一操作。逐個(gè)拖拽對(duì)Agent來(lái)說(shuō)有兩個(gè)難點(diǎn)一是拖拽終點(diǎn)坐標(biāo)要求極高二是拖出去的過(guò)程中容易誤觸發(fā)其他窗口。我的做法是讓Agent按住Ctrl逐個(gè)點(diǎn)選同一類型的文件然后右鍵選擇“移動(dòng)到”在彈出的對(duì)話框里選擇目標(biāo)文件夾。每一步都有清晰的視覺(jué)反饋穩(wěn)定性比拖拽高一個(gè)量級(jí)。4.4 結(jié)果與代價(jià)最終這輪任務(wù)跑了大約11分鐘一共執(zhí)行了34步動(dòng)作中途出現(xiàn)過(guò)一次小失誤一個(gè)名字叫“報(bào)告_v2.pdf”的文件因?yàn)槲募飵А皏2”被Agent誤判成了版本管理類放進(jìn)了“文檔”文件夾而不是“PDF”文件夾。我后來(lái)讓Agent自己復(fù)查一遍它通過(guò)對(duì)比“文件大小、擴(kuò)展名、目標(biāo)文件夾命名”三者的關(guān)系很快發(fā)現(xiàn)了這個(gè)錯(cuò)誤并自動(dòng)移正了。說(shuō)實(shí)話這個(gè)速度比人手動(dòng)操作慢得多手動(dòng)整理最多2分鐘。但它解決的問(wèn)題不是“快”而是“你不用坐在電腦前”。你只要把任務(wù)下發(fā)給它它就能在你離開電腦的這段時(shí)間把活干完。對(duì)真正有“大量重復(fù)性整理需求”的人來(lái)說(shuō)這個(gè)時(shí)間換得值。5. 實(shí)測(cè)翻車記錄Agent自動(dòng)化中那些高頻坑任何Agent系統(tǒng)第一版都不可能穩(wěn)定我不止一次看著它在我面前表演“花式跑偏”。這章把實(shí)戰(zhàn)中踩得最深的幾個(gè)坑和排查思路完整寫出來(lái)希望你遇到時(shí)不用再?gòu)牧闩挪椤?.1 坐標(biāo)漂移分辨率縮放和一屏多窗惹的禍現(xiàn)象是Agent在截圖里看到的按鈕坐標(biāo)是(650, 420)但點(diǎn)擊實(shí)際落到了(975, 630)附近完全不在按鈕上。我一開始以為是模型識(shí)別錯(cuò)了后來(lái)排查半天才發(fā)現(xiàn)是DPI縮放導(dǎo)致截圖分辨率與鼠標(biāo)邏輯坐標(biāo)不一致。排查思路建議按順序走先對(duì)比截圖尺寸和系統(tǒng)邏輯分辨率再確認(rèn)有沒(méi)有多顯示器且縮放比例不同最后檢查Agent的窗口是否和鼠標(biāo)所在的顯示器一致。這四步能過(guò)濾掉90%的坐標(biāo)偏斜問(wèn)題。解決方案就是前面寫的to_screen_pos換算函數(shù)統(tǒng)一坐標(biāo)系后再下發(fā)動(dòng)作。5.2 幻覺(jué)動(dòng)作模型說(shuō)“已點(diǎn)擊”實(shí)際沒(méi)點(diǎn)這個(gè)坑非常隱蔽。有一次Agent輸出“click(500, 320)已點(diǎn)擊保存按鈕”但我在日志里對(duì)比前后兩張截圖發(fā)現(xiàn)畫面幾乎沒(méi)有任何變化。原因是語(yǔ)言模型在訓(xùn)練數(shù)據(jù)里見過(guò)大量“點(diǎn)擊保存后窗口關(guān)閉”的常識(shí)于是它憑常識(shí)生成了“應(yīng)該已經(jīng)關(guān)閉”的預(yù)測(cè)性文本跳過(guò)了真實(shí)的觀察環(huán)節(jié)。排查這件事不能只靠截圖“肉眼看差異”我把動(dòng)作前后的截圖做了一次像素級(jí)比較。如果兩張圖幾乎一模一樣就認(rèn)為動(dòng)作沒(méi)有產(chǎn)生可觀察變化系統(tǒng)會(huì)強(qiáng)制把“狀態(tài)未變化”這個(gè)信息塞回模型輸入要求它重新觀察并糾正。這個(gè)機(jī)制上線后幻覺(jué)動(dòng)作大幅減少。5.3 死循環(huán)反復(fù)執(zhí)行同一個(gè)失敗動(dòng)作不退出有這么一次Agent需要確認(rèn)某個(gè)文件是否已經(jīng)移動(dòng)到位但它反復(fù)打開同一個(gè)文件夾、反復(fù)“查看”行動(dòng)就是沒(méi)有進(jìn)展?;胤湃罩緯r(shí)我才發(fā)現(xiàn)目標(biāo)文件夾在視圖下方的滾動(dòng)區(qū)之外Agent的截圖里根本看不到它但模型沒(méi)有意識(shí)到需要滾動(dòng)一直在原地打轉(zhuǎn)。排查后發(fā)現(xiàn)模型的重試策略太死板失敗后它傾向于用完全相同的動(dòng)作再試一次而不是切換策略。我加了三條規(guī)則第一全局步數(shù)上限超過(guò)20步自動(dòng)停止第二同一工具連續(xù)失敗3次必須換工具第三連續(xù)兩次動(dòng)作結(jié)果相同且任務(wù)未推進(jìn)時(shí)強(qiáng)制調(diào)用滾動(dòng)或搜索來(lái)打破僵局。這三條組合拳之后我基本沒(méi)再見過(guò)無(wú)限循環(huán)。5.4 彈窗搶焦點(diǎn)一切計(jì)劃被一個(gè)彈窗打亂這是一個(gè)典型的“非目標(biāo)狀態(tài)干擾”。Agent正按部就班點(diǎn)擊表單時(shí)右下角突然彈出一個(gè)系統(tǒng)通知或某個(gè)軟件升級(jí)彈窗跳到了前臺(tái)。Agent的下一步點(diǎn)擊按原坐標(biāo)執(zhí)行結(jié)果全點(diǎn)到了彈窗上后續(xù)流程直接崩掉。排查思路是不要讓Agent對(duì)“彈窗出現(xiàn)”毫無(wú)感知。我設(shè)計(jì)了一個(gè)輕量機(jī)制每輪截圖后先用文本識(shí)別掃一遍全屏文字如果發(fā)現(xiàn)“是否”“允許”“確定”“取消”這類彈窗特征詞先把彈窗處理掉再繼續(xù)主任務(wù)。另外在任務(wù)啟動(dòng)前我會(huì)手動(dòng)把通知開到免打擾模式從源頭減少?gòu)棿俺霈F(xiàn)的概率。5.5 窗口重復(fù)打開Agent不知道自己已經(jīng)打開了窗口這個(gè)問(wèn)題的本質(zhì)是Agent沒(méi)有“狀態(tài)記憶”。它下達(dá)第一個(gè)“打開文件管理器”的動(dòng)作后如果不觀察任務(wù)欄就不知道自己已經(jīng)打開了窗口下一步它可能又去菜單里找“文件管理器”嘩啦啦開了七八個(gè)窗口。桌面一亂后續(xù)識(shí)別率直線下降。我想了兩個(gè)辦法組合解決一是在系統(tǒng)提示詞里強(qiáng)調(diào)“每次打開應(yīng)用前先截圖查看桌面和任務(wù)欄確認(rèn)是否已存在該窗口”二是在上下文里維護(hù)一個(gè)簡(jiǎn)單的“已打開窗口清單”每執(zhí)行一步就更新一次讓模型隨時(shí)知道當(dāng)前的窗口狀態(tài)。這兩個(gè)小改動(dòng)讓整個(gè)系統(tǒng)看起來(lái)“冷靜”很多。6. 從能跑到好用工作流設(shè)計(jì)經(jīng)驗(yàn)與后續(xù)擴(kuò)展6.1 邊界劃分確定性腳本和LLM決策各干各的跑通基礎(chǔ)版本后我最大的體會(huì)是不要什么事都讓模型干。模型擅長(zhǎng)的是“看情況判斷”不擅長(zhǎng)“反復(fù)執(zhí)行機(jī)械動(dòng)作”。比如移動(dòng)文件這個(gè)操作如果讓模型一步一步地點(diǎn)擊每一個(gè)文件、再點(diǎn)擊目標(biāo)文件夾不但慢而且容易出錯(cuò)。正確做法是把機(jī)械步驟封裝成確定性函數(shù)。我后來(lái)加了一個(gè)move_files(file_list, target_dir)工具模型只需要判斷“哪些文件屬于哪一類”然后調(diào)用一次工具就完成了批量移動(dòng)。這就像項(xiàng)目經(jīng)理和員工的分工經(jīng)理負(fù)責(zé)拍板員工負(fù)責(zé)執(zhí)行。模型的決策能力是稀缺資源動(dòng)作執(zhí)行這種沒(méi)有智力的體力活應(yīng)該交給確定性代碼。6.2 回放日志沒(méi)有日志排查只能靠猜有一次任務(wù)跑到第41步失敗光看最終截圖根本判斷不出問(wèn)題出在哪兒。從那以后我養(yǎng)成了一個(gè)習(xí)慣把每一步的截圖、模型原始輸出、工具返回結(jié)果、動(dòng)作耗時(shí)全部寫進(jìn)結(jié)構(gòu)化日志。字段示例用途step13定位到具體步驟actionclick(500, 320)看模型決策是否合理resultclicked看動(dòng)作是否執(zhí)行成功screenshot附件還原現(xiàn)場(chǎng)elapsed2.3s排查超時(shí)問(wèn)題有了這份日志排查效率是幾何級(jí)提升。任務(wù)失敗時(shí)我從最后一步往前翻一眼就能看出是哪一步開始偏離預(yù)期。建議所有做Agent的朋友日志系統(tǒng)一定要從第一天就開始建不要等翻車了再補(bǔ)。6.3 護(hù)欄與急停Agent必須能被隨時(shí)叫停一個(gè)能控制鼠標(biāo)鍵盤的Agent本質(zhì)上已經(jīng)擁有了操作電腦的完整權(quán)限。權(quán)限越大越需要護(hù)欄。我設(shè)置了三層防護(hù)第一層是全局急??旖萱I我設(shè)定連續(xù)按5次F9終止當(dāng)前任務(wù)不管模型卡在哪都強(qiáng)制退出第二層是目錄白名單Agent只能讀寫我指定的一個(gè)工作目錄絕不觸碰其他位置第三層是操作確認(rèn)對(duì)于刪除、覆蓋這類不可逆動(dòng)作必須先停下讓用戶確認(rèn)。這些護(hù)欄不是說(shuō)Agent會(huì)“惡意操作”而是模型天然存在隨機(jī)性可能某個(gè)錯(cuò)誤判斷就會(huì)導(dǎo)致不可逆后果。你永遠(yuǎn)不會(huì)希望看到一個(gè)自動(dòng)化程序在錯(cuò)誤的目錄里執(zhí)行了刪除操作?;ㄒ恍r(shí)搭建護(hù)欄能避免一萬(wàn)小時(shí)的后悔。6.4 后續(xù)還能怎么玩定時(shí)觸發(fā)、多Agent、經(jīng)驗(yàn)沉淀基礎(chǔ)跑通之后擴(kuò)展方向其實(shí)很豐富。我目前已經(jīng)把這套東西接入了定時(shí)觸發(fā)每天下班后自動(dòng)歸檔當(dāng)天產(chǎn)生的下載文件跑了一周穩(wěn)定率在九成以上。剩下的一成失敗基本都來(lái)自“桌面環(huán)境被我沒(méi)關(guān)的窗口干擾”這類人為因素而不是Agent本身的問(wèn)題。多Agent協(xié)同是另一個(gè)有意思的方向一個(gè)Agent專門負(fù)責(zé)監(jiān)控屏幕任務(wù)欄另一個(gè)負(fù)責(zé)執(zhí)行主任務(wù)第三個(gè)在出錯(cuò)時(shí)負(fù)責(zé)恢復(fù)現(xiàn)場(chǎng)。相當(dāng)于從“單打獨(dú)斗”升級(jí)成“團(tuán)隊(duì)協(xié)作”。還有一種方向是經(jīng)驗(yàn)沉淀把每次成功執(zhí)行的動(dòng)作軌跡保存成模板下次遇到相似任務(wù)直接從模板起步省去模型重新規(guī)劃的時(shí)間。這條路我還在試目前看下來(lái)潛力很大。我個(gè)人的體會(huì)是做這類桌面自動(dòng)化Agent真正的門檻不在模型而在于工程細(xì)節(jié)——坐標(biāo)換算了沒(méi)有、動(dòng)作執(zhí)行后驗(yàn)證了沒(méi)有、失敗后有沒(méi)有止損機(jī)制、每一步有沒(méi)有日志。這些聽起來(lái)很瑣碎的環(huán)節(jié)恰恰決定了Agent從“能跑”到“能信”的距離。如果你也想動(dòng)手試我的建議是先選一個(gè)特別小的場(chǎng)景比如“把下載目錄里的圖片移到圖片文件夾”完整跑通一條路徑再逐步加復(fù)雜功能。