話(huà)到執(zhí)行:AI Agent 工程落地的關(guān)鍵設(shè)計(jì)與邊界控制)
最近在做一個(gè)自動(dòng)化文檔處理的內(nèi)部小項(xiàng)目發(fā)現(xiàn)一個(gè)很有意思的轉(zhuǎn)變。以前用大模型是“我問(wèn)一句它答一句”現(xiàn)在把模型接進(jìn)一個(gè)帶工具調(diào)用的循環(huán)里它開(kāi)始自己決定下一步調(diào)用哪個(gè)函數(shù)、拿到結(jié)果后再判斷下一步走哪條路。這種變化不是模型變聰明了那么簡(jiǎn)單而是整套使用方式從“伸手要答案”變成了“布置一個(gè)目標(biāo)”。所以當(dāng)“AI不再聽(tīng)命令了它開(kāi)始自己干活”這句話(huà)出現(xiàn)在眼前時(shí)我第一反應(yīng)是這說(shuō)的不是某個(gè)新工具而是 AI Agent 這個(gè)概念終于從演示走向了工程實(shí)踐。但真正落地時(shí)你會(huì)發(fā)現(xiàn)AI 自己干活并不是魔法而是一套需要目標(biāo)拆解、工具調(diào)用、狀態(tài)管理、失敗恢復(fù)、權(quán)限控制共同支撐的工程系統(tǒng)。這篇文章想聊的就是這件事。1. 先搞清楚“自己干活”到底指什么1.1 Chatbot 是在回答Agent 是在執(zhí)行很多人會(huì)把“能對(duì)話(huà)的 AI”和“會(huì)干活的 AI”搞混。你打開(kāi)一個(gè)聊天窗口讓它生成一段文案、寫(xiě)一段代碼、解釋一段報(bào)錯(cuò)它都能做到。但這是“回答”不是“干活”。干活意味著你給一個(gè)目標(biāo)它自己規(guī)劃路徑、調(diào)用外部工具、檢查中間結(jié)果、修正下一步動(dòng)作最后交付一個(gè)結(jié)果。比如“幫我把這個(gè) GitHub 倉(cāng)庫(kù)的最近 10 條 commit 整理成一份周報(bào)并按模塊分類(lèi)再生成一個(gè) Markdown 文件”Chatbot 只能給你一段建議或者一段示例文本剩下的復(fù)制粘貼、獲取數(shù)據(jù)、生成文件都要你自己做。而 Agent 會(huì)嘗試通過(guò)工具調(diào)用去拉取 commit 列表、調(diào)用模型總結(jié)、寫(xiě)文件最后給你輸出一個(gè)真實(shí)存在的文件。核心差異不在模型能力而在系統(tǒng)邊界。Chatbot 的邊界是“對(duì)話(huà)”Agent 的邊界是“任務(wù)”。這是“自己干活”的第一層含義。1.2 核心變化從“每一步都告訴它”到“我只給目標(biāo)”過(guò)去用自動(dòng)化腳本是人把每一步邏輯寫(xiě)死。比如用 Python 拉取數(shù)據(jù)、寫(xiě)文件流程是固定的。現(xiàn)在用 Agent人不需要把每一步都寫(xiě)死只需要描述目標(biāo)、提供工具清單讓模型自己決定調(diào)用順序。這聽(tīng)起來(lái)很像“把控制權(quán)交給 AI”但工程上更準(zhǔn)確的表述是把任務(wù)拆解從“寫(xiě)代碼時(shí)確定”變成了“運(yùn)行時(shí)動(dòng)態(tài)決定”。舉個(gè)例子同樣是生成周報(bào)傳統(tǒng)腳本先 git log再分詞再套模板每一步都是 if-else。Agent模型先判斷“哦我需要獲取 commit 列表”于是調(diào)用git_log工具拿到列表后又判斷“內(nèi)容太長(zhǎng)了我需要先過(guò)濾掉 merge commit”于是再調(diào)用git_parse最后判斷“生成 Markdown”然后調(diào)用write_file。這個(gè)流程不是預(yù)先寫(xiě)死的而是模型根據(jù)工具返回結(jié)果動(dòng)態(tài)生成的。這才叫“自己干活”。不過(guò)要注意這里的“自己”不是完全自主。Agent 的每一步行動(dòng)仍然受系統(tǒng)設(shè)計(jì)約束能調(diào)用哪些工具、最多走多少步、哪些操作需要人工確認(rèn)這些都是我們預(yù)先定義的。所以更準(zhǔn)確地說(shuō)它是在我們劃定的軌道里自主決策。2. 為什么是現(xiàn)在大模型和工程底座同時(shí)到位2.1 模型能力從“能對(duì)話(huà)”到“能遵循指令并調(diào)用工具”兩三年前想讓模型穩(wěn)定地給出一個(gè)“我要調(diào)用某個(gè)工具及參數(shù)”的 JSON都不是一件容易事。你構(gòu)想的 Agent 循環(huán)早就存在但模型經(jīng)常理解錯(cuò)工具參數(shù)、忘記上下文、在復(fù)雜任務(wù)里跑偏。現(xiàn)在的情況好了一些但也不是完全成熟。這里有兩個(gè)關(guān)鍵能力指令遵循能力模型能更準(zhǔn)確地按照系統(tǒng)提示輸出結(jié)構(gòu)化指令比如{tool: get_commits, params: {repo: foo}}。工具調(diào)用能力平臺(tái)層面把“模型決定調(diào)工具”和“執(zhí)行工具返回結(jié)果”做成了標(biāo)準(zhǔn)協(xié)議比如 Function Calling、Tool Use開(kāi)發(fā)者不用自己拼 prompt 解析文本模型直接返回結(jié)構(gòu)化調(diào)用請(qǐng)求。這兩個(gè)能力加在一起Agent 循環(huán)才變得可工程化。不是說(shuō)模型已經(jīng)完美而是“容錯(cuò)成本”降到了可以接受的范圍內(nèi)。2.2 工程底座任務(wù)編排、日志、消息隊(duì)列逐步補(bǔ)齊模型能力只是其中一半。另一個(gè)被很多人忽略的推動(dòng)力是工程基礎(chǔ)設(shè)施的成熟。一個(gè)真正“自己干活”的 Agent背后需要像任務(wù)調(diào)度系統(tǒng)一樣的循環(huán)控制什么時(shí)候調(diào)用大模型什么時(shí)候調(diào)工具工具超時(shí)怎么辦模型返回格式不對(duì)怎么辦任務(wù)失敗要不要重試每一步的狀態(tài)記錄在哪里如何讓用戶(hù)看到中間進(jìn)度任務(wù)中止邏輯是什么。這些不是模型解決的問(wèn)題而是工程問(wèn)題。以前這些都要從零搭很繁瑣。現(xiàn)在不少框架和平臺(tái)把循環(huán)控制、工具注冊(cè)、日志 trace、人工審核節(jié)點(diǎn)做成了現(xiàn)成模塊開(kāi)發(fā)者只需要聚焦業(yè)務(wù)本身。這也是為什么最近一年 AI Agent 開(kāi)發(fā)突然從“玩具”變成了“可落地項(xiàng)目”的原因之一。但我的經(jīng)驗(yàn)是不要因?yàn)榭蚣芏嗑图敝子谩O劝炎钚⊙h(huán)跑通再逐步替換組件遠(yuǎn)比一開(kāi)始引入一個(gè)復(fù)雜編排系統(tǒng)要穩(wěn)。3. 從零搭一個(gè)“自己干活”的 Agent最小可運(yùn)行示例3.1 場(chǎng)景定義自動(dòng)生成項(xiàng)目周報(bào)我們用最經(jīng)典的場(chǎng)景來(lái)拆解讓 Agent 自動(dòng)獲取倉(cāng)庫(kù) commit生成周報(bào)寫(xiě)入本地文件。這個(gè)場(chǎng)景足夠小但覆蓋了 Agent 的核心問(wèn)題感知外部數(shù)據(jù)、模型決策、調(diào)用工具、檢查結(jié)果、生成最終輸出。首先需要定義兩個(gè)工具get_commits(since_date, repo_path)拉取指定日期之后的提交列表。write_report(content, file_path)把內(nèi)容寫(xiě)入 Markdown 文件。Agent 要做的就是根據(jù)用戶(hù)目標(biāo)自己決定先調(diào)用哪個(gè)、怎么處理中間結(jié)果。從代碼結(jié)構(gòu)看核心是一個(gè)循環(huán)def agent_loop(user_goal, tools, max_steps10): messages [{role: user, content: user_goal}] for step in range(max_steps): response model_decision(messages, tools) # 情況一模型認(rèn)為任務(wù)已完成返回最終答案 if response.is_final_answer: return response.final_content # 情況二模型決定調(diào)用某個(gè)工具 tool_result execute_tool(response.tool_name, response.tool_arguments) messages.append({ role: tool, tool_call_id: response.tool_call_id, content: tool_result }) raise Exception(f超過(guò)最大步數(shù)任務(wù)未完成)這個(gè)循環(huán)并不復(fù)雜但它背后藏著幾個(gè)關(guān)鍵設(shè)計(jì)決策。3.2 工具注冊(cè)告訴模型“你能用什么”模型并不知道系統(tǒng)里有哪些函數(shù)你需要通過(guò)工具描述把能力暴露給它。比如[ { name: get_commits, description: 獲取指定 Git 倉(cāng)庫(kù)某日期之后的提交列表, parameters: { type: object, properties: { since_date: {type: string, description: 起始日期YYYY-MM-DD}, repo_path: {type: string, description: 本地倉(cāng)庫(kù)路徑} }, required: [since_date, repo_path] } }, { name: write_report, description: 把周報(bào)內(nèi)容寫(xiě)入 Markdown 文件, parameters: { type: object, properties: { content: {type: string, description: 完整 Markdown 內(nèi)容}, file_path: {type: string, description: 輸出文件路徑} }, required: [content, file_path] } } ]工具描述不要太含糊也不要太啰嗦。模型會(huì)根據(jù)這段描述判斷“我現(xiàn)在應(yīng)該調(diào)哪個(gè)工具、傳什么參數(shù)”。如果描述不清晰Agent 很容易在工具選擇上繞圈。3.3 關(guān)鍵參數(shù)最大步數(shù)、超時(shí)、輸出校驗(yàn)最小循環(huán)跑通容易但真正要穩(wěn)定運(yùn)行需要給 Agent 設(shè)邊界。最大步數(shù)防止模型在循環(huán)里空轉(zhuǎn)。通常是 5 到 15 步具體取決于任務(wù)復(fù)雜度。超過(guò)步數(shù)就終止并在日志里記錄。單次工具超時(shí)比如 git 命令可能因?yàn)閭}(cāng)庫(kù)過(guò)大卡住要給每個(gè)工具單獨(dú)設(shè)置超時(shí)。輸出校驗(yàn)?zāi)P头祷氐?JSON 不總是合法代碼里要做異常捕獲解析失敗時(shí)可以重試一次或者把錯(cuò)誤信息返回給模型讓它自行修正。注意不要一上來(lái)就把步數(shù)設(shè)到 50 或 100先設(shè) 10 步以?xún)?nèi)確保能穩(wěn)定完成后再逐步放寬。這個(gè)最小示例跑通以后才算真正理解了“AI 自己干活”的技術(shù)底層它是一個(gè)由模型決策驅(qū)動(dòng)的執(zhí)行循環(huán)而不是一個(gè)單純的對(duì)話(huà)服務(wù)。4. 別高興太早真正能穩(wěn)定跑起來(lái)的工程細(xì)節(jié)4.1 工具邊界Agent 能調(diào)什么不能調(diào)什么要寫(xiě)清楚這是我在實(shí)際項(xiàng)目里踩過(guò)的坑。如果工具列表里只有g(shù)et_commits和write_report那 Agent 最多也就是讀 Git 和寫(xiě)文件風(fēng)險(xiǎn)可控。但一旦加上“發(fā)送郵件”“執(zhí)行 shell 命令”“刪除文件”“推送遠(yuǎn)端倉(cāng)庫(kù)”這類(lèi)高風(fēng)險(xiǎn)工具就必須在系統(tǒng)層面對(duì) Agent 做權(quán)限收斂。具體做法是對(duì)工具做分級(jí)只讀工具默認(rèn)允許寫(xiě)操作需要確認(rèn)刪除/推送類(lèi)操作直接禁用或要求人工審批。在工具描述里明確約束比如“只有用戶(hù)明確要求時(shí)才能調(diào)用刪除功能”。在代碼層面強(qiáng)制校驗(yàn)工具參數(shù)不能完全依賴(lài)模型自律。Agent 以為自己很聰明但真正決定風(fēng)險(xiǎn)下限的是工具暴露面。工具給得越寬意外越多。4.2 失敗重試不是所有錯(cuò)誤都該重試很多 Agent 框架里都有自動(dòng)重試機(jī)制但錯(cuò)誤類(lèi)型不一樣對(duì)策也不一樣。常見(jiàn)的失敗分三類(lèi)臨時(shí)失敗網(wǎng)絡(luò)超時(shí)、API 限流、Git 倉(cāng)庫(kù)鎖占用等待幾秒后重試通常有效。輸入錯(cuò)誤模型傳錯(cuò)了參數(shù)比如日期格式不對(duì)、文件路徑不存在。此時(shí)盲目重試只會(huì)得到同樣的錯(cuò)誤應(yīng)該把報(bào)錯(cuò)信息返回給模型讓它自己修正。不可恢復(fù)錯(cuò)誤比如目標(biāo)倉(cāng)庫(kù)不存在、工具權(quán)限不足。這種情況應(yīng)該直接終止任務(wù)并告訴用戶(hù)原因。最簡(jiǎn)單的排查順序是先看環(huán)境再看輸入再看模型決策。如果模型連續(xù)三次選擇了同一個(gè)錯(cuò)誤工具大概率不是偶然而是工具描述有歧義。4.3 日志回放每一步的思考、調(diào)用、結(jié)果都要留痕“AI 自己干活”最怕什么不是它干不好而是你不知道它為什么干不好。所以 Agent 的日志要比普通腳本詳細(xì)得多。每一步至少記錄當(dāng)前是第幾步。模型本輪說(shuō)什么也可以記錄思考過(guò)程如果平臺(tái)支持。模型調(diào)用了哪個(gè)工具傳了什么參數(shù)。工具返回了什么內(nèi)容耗時(shí)多久。模型根據(jù)工具結(jié)果做了什么判斷。最終終止原因是什么。這套日志就是 Agent 的“黑匣子”。遇到問(wèn)題先回放不是靠猜。5. 什么場(chǎng)景適合讓 Agent“自己干活”什么場(chǎng)景最好別5.1 適合的場(chǎng)景流程固定但步驟多結(jié)果可驗(yàn)證從我的經(jīng)驗(yàn)看合適的 Agent 任務(wù)通常有三個(gè)特點(diǎn)有明確目標(biāo)比如“把 A 目錄下所有 PDF 轉(zhuǎn)成 Markdown”“從數(shù)據(jù)庫(kù)導(dǎo)出最近 30 天訂單并生成匯總表”。步驟雖然多但路徑相對(duì)清晰不需要太多天馬行空的創(chuàng)造更多是重復(fù)性操作。結(jié)果可驗(yàn)證生成的文件能不能打開(kāi)、數(shù)據(jù)有沒(méi)有缺失、格式對(duì)不對(duì)都可以用程序檢查。這類(lèi)任務(wù)交給 Agent 之后省下的不是思考時(shí)間而是“人來(lái)回切換系統(tǒng)”的成本。真正縮短的是流程鏈路不是模型輸出。5.2 不適合的場(chǎng)景不可逆、高風(fēng)險(xiǎn)、價(jià)值觀(guān)判斷凡是“錯(cuò)一次代價(jià)很高”的任務(wù)我都建議保守處理。舉幾個(gè)例子自動(dòng)刪除生產(chǎn)環(huán)境數(shù)據(jù)。自動(dòng)對(duì)外發(fā)送不可撤回的消息。自動(dòng)修改核心系統(tǒng)配置。自動(dòng)生成法律、醫(yī)療、金融領(lǐng)域的正式建議。這些場(chǎng)景不是模型能力不夠而是錯(cuò)誤容忍度太低。Agent 即使只錯(cuò)一次代價(jià)也可能非常大。安全起見(jiàn)可以讓 Agent 負(fù)責(zé)“準(zhǔn)備工作”和“草稿生成”最終決策和關(guān)鍵操作仍然由人完成。5.3 一個(gè)通用判斷清單可以拿下面這份清單快速判斷一個(gè)任務(wù)適不適合 Agent判斷維度適合不適合目標(biāo)是否明確是一條話(huà)能說(shuō)清楚模糊、需要反復(fù)澄清流程是否穩(wěn)定固定但有分支每次都不一樣完全無(wú)規(guī)律結(jié)果是否可驗(yàn)證可以用程序檢查只能靠人憑經(jīng)驗(yàn)判斷風(fēng)險(xiǎn)高低低錯(cuò)了改一下就行高錯(cuò)了代價(jià)大是否需要人類(lèi)價(jià)值觀(guān)基本不需要需要大量主觀(guān)判斷如果命中“不適合”列超過(guò)兩條建議不要上 Agent至少不要全自動(dòng)。6. 從我自己的經(jīng)驗(yàn)看先跑通、再優(yōu)化、最后才談自動(dòng)化6.1 階段一單任務(wù)跑通別先談復(fù)雜編排第一次做 Agent千萬(wàn)別直接設(shè)計(jì)一個(gè)多智能體協(xié)作系統(tǒng)。先把“一個(gè)模型 少量工具 一個(gè)循環(huán)”做到穩(wěn)定。比如上面那個(gè)周報(bào)生成示例先手動(dòng)跑 5 次確認(rèn)每次都能正確生成文件。這期間不用追求速度、不用追求復(fù)雜功能重點(diǎn)是把異常處理、日志、邊界參數(shù)打磨好。單次跑通只能說(shuō)明流程沒(méi)有斷。真正的問(wèn)題會(huì)在重復(fù)執(zhí)行和多場(chǎng)景覆蓋時(shí)浮出來(lái)。6.2 階段二加批量和并發(fā)觀(guān)察限流與資源占用單任務(wù)穩(wěn)定后下一個(gè)挑戰(zhàn)是批量和并發(fā)。假設(shè)你要同時(shí)為 10 個(gè)倉(cāng)庫(kù)生成周報(bào)就要考慮并發(fā)調(diào)用大模型 API 時(shí)是否觸發(fā)限流。本地命令執(zhí)行是否占用過(guò)多 CPU、內(nèi)存。輸出目錄是否沖突文件會(huì)不會(huì)被覆蓋。如果中途某幾個(gè)任務(wù)失敗是整體重跑還是只重跑失敗項(xiàng)。這時(shí)候再回頭看“AI 自己干活”你會(huì)發(fā)現(xiàn)干活的不只是 AI還有一堆工程細(xì)節(jié)。批處理和并發(fā)控制就是最常見(jiàn)的第一道坎。6.3 階段三加入監(jiān)控、權(quán)限、審核才能長(zhǎng)期用長(zhǎng)期可用的 Agent 系統(tǒng)和一次性腳本之間的區(qū)別在于可觀(guān)測(cè)、可干預(yù)、可審計(jì)。可觀(guān)測(cè)有指標(biāo)看板能看到 Agent 今天的成功率、平均步數(shù)、平均耗時(shí)。可干預(yù)任務(wù)執(zhí)行中支持人工暫停、修改參數(shù)、駁回某一步操作。可審計(jì)所有執(zhí)行記錄都能回溯出了問(wèn)題能定位到具體某一步。這三個(gè)能力不是一開(kāi)始就要做全但在 Agent 進(jìn)入真實(shí)業(yè)務(wù)之前至少要有一個(gè)能讓現(xiàn)場(chǎng)人員介入的“急停按鈕”。實(shí)際落地時(shí)建議每周復(fù)盤(pán)一次 Agent 日志從失敗樣本里反推工具描述是否需要優(yōu)化、步數(shù)上限是否合理、哪些工具權(quán)限太寬。這不是一次性的調(diào)參而是持續(xù)迭代。7. 最后AI 自己干活但先得知道哪條路不能省回到一開(kāi)始那個(gè)判斷AI 不再聽(tīng)命令了它開(kāi)始自己干活。這話(huà)沒(méi)錯(cuò)但“自己干活”不是模型單獨(dú)完成的而是模型、工具、工程邊界、日志審計(jì)共同完成的一件事。模型負(fù)責(zé)的是“決策”真正對(duì)結(jié)果負(fù)責(zé)的還是人。我們給 Agent 規(guī)劃目標(biāo)、劃定工具邊界、定義驗(yàn)證方式、設(shè)置失敗兜底它才能在一個(gè)可控范圍內(nèi)“自己干活”。所以如果你正準(zhǔn)備做一個(gè) Agent 項(xiàng)目我的建議是先從最小流程開(kāi)始不急著給工具開(kāi)權(quán)限不盲目追求多智能體、復(fù)雜規(guī)劃。把單任務(wù)跑通把日志埋好把失敗路徑想清楚再把任務(wù)范圍一點(diǎn)一點(diǎn)擴(kuò)大。這條路看著慢但到了生產(chǎn)環(huán)境會(huì)發(fā)現(xiàn)它其實(shí)是最快的路。