:先別急著啃框架,手寫(xiě)一次Demo再談)
1. 為什么說(shuō)“別一上來(lái)就啃框架”是入門(mén)的第一課這兩年 AI Agent 這個(gè)概念被炒得火熱打開(kāi)技術(shù)社區(qū)、招聘網(wǎng)站滿屏都是 Agent 應(yīng)用、Agent 開(kāi)發(fā)工程師的崗位。很多人一看這勢(shì)頭尤其是想轉(zhuǎn)行做 AI 的同學(xué)第一反應(yīng)就是沖去學(xué) LangChain、學(xué) LlamaIndex想趕緊把這些框架拿下來(lái)好像學(xué)會(huì)了就能做 Agent 了。但我見(jiàn)了太多這樣的例子下載了教程、跑通了 Demo、覺(jué)得自己會(huì)了結(jié)果讓他自己寫(xiě)一個(gè)能真正解決某個(gè)具體問(wèn)題的 Agent他愣是不知道從哪兒下手框架里的概念全認(rèn)識(shí)但串不起來(lái)。我自己也走過(guò)這條路。早幾年在做一個(gè)內(nèi)部知識(shí)庫(kù)問(wèn)答的智能化改造時(shí)我的第一想法也是先找一個(gè)成熟的 Agent 框架套上去省得從零搭建。結(jié)果折騰了小半個(gè)月工程上能跑可實(shí)際用起來(lái)效果非常差——召回的內(nèi)容不準(zhǔn)模型經(jīng)常答非所問(wèn)日志一堆報(bào)錯(cuò)根本不知道問(wèn)題出在哪層。后來(lái)我推倒重來(lái)把框架丟掉從最基礎(chǔ)的 Prompt、模型調(diào)用、工具封裝一步步做起反而兩個(gè)星期就把效果做到了可用。那次之后我就很確定一個(gè)道理Agent 的核心從來(lái)不是某個(gè)框架而是你對(duì)“模型怎么調(diào)、上下文怎么管、工具怎么接”這三件事的理解??蚣苤皇前涯阋呀?jīng)會(huì)的東西包裝得方便了一些而已。所以這篇內(nèi)容就是專門(mén)寫(xiě)給準(zhǔn)備入行或者正在考慮轉(zhuǎn)行的朋友的。我不會(huì)推薦你立刻去學(xué)某個(gè)框架也不會(huì)給你貼一堆讓人更焦慮的術(shù)語(yǔ)清單。我打算從零講清楚 AI Agent 到底是什么、做 Agent 真正需要掌握哪些底層能力、怎么不靠框架手搓一個(gè)跑得通的 Agent、以及什么時(shí)候你才真正需要框架。只要你跟著這篇的思路把基礎(chǔ)打扎實(shí)了以后再去看任何框架你的視角都會(huì)完全不一樣。2. 核心思路拆解Agent 的本質(zhì)與初學(xué)者最常見(jiàn)的“三大誤區(qū)”2.1 Agent 到底是什么先把概念還原成樸實(shí)的樣子很多新人被“Agent”這個(gè)詞嚇住了下意識(shí)把它想象成一個(gè)很玄的東西。拆穿了看Agent 不過(guò)是一個(gè)“能自己決定下一步做什么”的程序。舉個(gè)最樸素的例子你做菜的時(shí)候先看看冰箱里有什么材料決定做哪道菜然后開(kāi)始切菜、炒菜過(guò)程中發(fā)現(xiàn)鹽不夠了就臨時(shí)決定去樓下超市買(mǎi)一包。這個(gè)過(guò)程中你在不斷地觀察、決策、行動(dòng)、再觀察。Agent 干的事情本質(zhì)上也是這樣——它根據(jù)你給的目標(biāo)結(jié)合當(dāng)前掌握的信息選擇調(diào)用合適的工具執(zhí)行操作觀察結(jié)果再?zèng)Q定下一步怎么辦。直到目標(biāo)完成或者它認(rèn)為沒(méi)法繼續(xù)了才停下來(lái)??梢杂靡粋€(gè)更具體的場(chǎng)景來(lái)理解你做一個(gè)“周末出游規(guī)劃助手”。把它做成 Agent 之后用戶說(shuō)“幫我安排一個(gè)兩天一夜的周邊游”這個(gè) Agent 會(huì)先拆解任務(wù)——查天氣、找景點(diǎn)、查酒店、算路線、做預(yù)算然后它自己去調(diào)天氣查詢工具、地圖工具、訂房網(wǎng)站接口最后給你一個(gè)完整的行程單。傳統(tǒng)程序是你把所有邏輯都寫(xiě)在代碼里Agent 程序則是你只給它一個(gè)目標(biāo)和幾個(gè)工具剩下的路徑它自己摸索。能力更強(qiáng)的 Agent 甚至?xí)诎l(fā)現(xiàn)某條路走不通時(shí)主動(dòng)換一個(gè)搜索詞重新查。理解到這一層你就明白學(xué) Agent 不是在學(xué)某個(gè)神秘技術(shù)而是在學(xué)一套協(xié)調(diào)模型、數(shù)據(jù)、工具的方法。框架是什么框架是這套方法論里前人總結(jié)出來(lái)的標(biāo)準(zhǔn)件。你連標(biāo)準(zhǔn)零件長(zhǎng)什么樣、為什么要這么設(shè)計(jì)都還沒(méi)概念就先把整套流水線背下來(lái)了這不叫學(xué)會(huì)叫死記硬背稍微換個(gè)場(chǎng)景就失靈了。2.2 誤區(qū)一把“學(xué)會(huì)框架”誤當(dāng)成“學(xué)會(huì) Agent”我面試過(guò)不少簡(jiǎn)歷上寫(xiě)著“熟練使用 LangChain”的候選人結(jié)果我問(wèn)一個(gè)很基礎(chǔ)的問(wèn)題如果你要做一個(gè)“定時(shí)抓取競(jìng)品新聞并總結(jié)成周報(bào)”的小工具你覺(jué)得這個(gè)系統(tǒng)由哪幾個(gè)核心模塊組成很多人答不上來(lái)或者只會(huì)照著框架里的概念拼名詞什么 AgentExecutor、Chain、Tool但說(shuō)不清楚這些模塊各自是干什么的、數(shù)據(jù)怎么在這些模塊之間流轉(zhuǎn)。問(wèn)題就出在很多人是“先會(huì)了框架才來(lái)理解概念”。這個(gè)順序?qū)δ承┘夹g(shù)可能是可行的但對(duì) Agent 來(lái)說(shuō)是反的。Agent 的底層邏輯非常清晰大致就那么幾步接收任務(wù)、拆解任務(wù)、選擇工具、執(zhí)行工具、分析結(jié)果、更新計(jì)劃、直到收尾。框架做的只是把這幾步“模板化”了它在某些場(chǎng)景下幫你少寫(xiě)了代碼但絕不替你理解了你在做什么。所以我在帶新人時(shí)有一條鐵律至少先手寫(xiě)一個(gè)不依賴任何框架的 Agent Demo再去看框架。這個(gè)門(mén)檻不算高但只要你真寫(xiě)過(guò)了你對(duì) Agent 的掌控感會(huì)強(qiáng)非常多。2.3 誤區(qū)二以為做 Agent 就是寫(xiě)好 Prompt 然后調(diào) API這個(gè)誤區(qū)是另一個(gè)極端。有的人把 Agent 想得太難也有些人想得太簡(jiǎn)單。在他們的認(rèn)知里“AI 寫(xiě)代碼 發(fā)一段 Prompt 然后拿到返回結(jié)果”把 Agent 看成高級(jí)版的“問(wèn)答機(jī)器人”無(wú)非是多寫(xiě)幾條 Prompt 而已。但做 Agent 和做普通的問(wèn)答機(jī)器人有一個(gè)本質(zhì)區(qū)別Agent 的行為是“持續(xù)性的、多步驟的、需要外部反饋的”。你不能把完整答案一次性算出來(lái)你得一遍一遍地和模型交互每一次交互它只決定“下一步做什么”然后你幫它執(zhí)行這個(gè)動(dòng)作把結(jié)果返回給它看它再?zèng)Q定“然后呢”。所以除了 Prompt你還需要認(rèn)真設(shè)計(jì)整個(gè)循環(huán)控制邏輯什么時(shí)候該停止多次失敗之后怎么辦每一步的中間結(jié)果怎么存這些才是 Agent 開(kāi)發(fā)的真正難點(diǎn)而這些東西是單純“調(diào) API”學(xué)不到的。2.4 誤區(qū)三只關(guān)注代碼忽略數(shù)據(jù)準(zhǔn)備和上下文管理還有一個(gè)坑也是新手最快掉進(jìn)去的一上來(lái)就研究各種框架的功能編排完全忽略你的模型到底能吃哪些數(shù)據(jù)、能記住多少上下文、中間結(jié)果放哪兒。做過(guò)實(shí)際項(xiàng)目的人都有體會(huì)一個(gè) Agent 的效果好壞很多時(shí)候不取決于模型有多聰明而是取決于你有沒(méi)有把決策所需的關(guān)鍵信息在正確的時(shí)機(jī)喂到模型的窗口里。上下文一長(zhǎng)模型容易“迷失重點(diǎn)”上下文太短模型又缺乏足夠的背景給不出合理判斷。這種調(diào)配能力是你光看框架文檔永遠(yuǎn)學(xué)不到的。放下框架先把 Agent 的“骨架”摸熟把模型交互、上下文整理、工具調(diào)用這些地基打牢后面學(xué)框架真的很輕松。下面我挨個(gè)拆開(kāi)講。3. 核心基礎(chǔ)能力拆解你入門(mén)前真正要先掌握的幾件事3.1 提示詞工程Agent 的“底層操作系統(tǒng)”如果說(shuō)做 Agent 只需要認(rèn)真學(xué)一樣?xùn)|西我會(huì)毫不猶豫說(shuō)提示詞工程。不是那種寫(xiě)“請(qǐng)幫我...”的簡(jiǎn)單指令而是真正能設(shè)計(jì)出可靠、可控的提示詞結(jié)構(gòu)。為什么這件事這么關(guān)鍵因?yàn)槟P捅旧碛小安环€(wěn)定性”——同一個(gè)問(wèn)題你換一個(gè)問(wèn)法結(jié)果可能差別很大。而在 Agent 系統(tǒng)里模型要做的決策很多每一步都用 Prompt 控制。如果 Prompt 寫(xiě)得含糊模型就可能給出偏離預(yù)期的決定。比如你做的是一個(gè)客服 Agent用戶說(shuō)“我上周買(mǎi)的東西壞了”如果 Prompt 沒(méi)有明確說(shuō)明應(yīng)該“先查訂單再判斷是否在保修期”模型可能直接就道歉并承諾退款了這在真實(shí)業(yè)務(wù)里是不可接受的。新手學(xué)提示詞工程我建議從以下幾個(gè)點(diǎn)入手角色設(shè)定不用寫(xiě)得花哨核心是明確“你是誰(shuí)、你在什么場(chǎng)景下、受什么約束”。比如“你是一名智能客服只負(fù)責(zé)訂單問(wèn)題超出范圍請(qǐng)引導(dǎo)用戶找人工?!比蝿?wù)拆解式表達(dá)在 Prompt 里就把任務(wù)拆成有序步驟而不是含糊地說(shuō)“處理這個(gè)問(wèn)題”。你把步驟拆得越清楚模型越不容易跑偏。輸出格式鎖定用 JSON 或固定模板約束輸出結(jié)構(gòu)。Agent 里模型的每一步輸出都是一個(gè)輸入給后續(xù)邏輯看的“消息”格式亂了你后面代碼就難寫(xiě)。加例子給一個(gè)“什么是好回答”的例子比你說(shuō)一百句“要回答好”都管用。但例子也別太極端防止模型變得只會(huì)模仿而不懂變通。這里特別提醒一下。你寫(xiě)的每一個(gè) Prompt 都是 Agent 這條生產(chǎn)線上的一道工序?qū)?Prompt 不是發(fā)一條朋友圈而是有明確產(chǎn)出物、需要反復(fù)測(cè)試的工程文檔。我見(jiàn)過(guò)很多新人把 Prompt 寫(xiě)在 Jupyter Notebook 里隨手一跑效果時(shí)好時(shí)壞也不深究原因。做 Agent 如果這樣后面線上跑起來(lái)你能被各種不確定性問(wèn)題活活累死。3.2 上下文的管理你要面對(duì)的核心矛盾模型不是無(wú)限的。不管用什么型號(hào)它的上下文窗口總有一個(gè)上限。而 Agent 在處理真實(shí)任務(wù)時(shí)你不可能把所有信息一股腦全塞給模型——成本高不說(shuō)模型還會(huì)因?yàn)樾畔⑦^(guò)載反而表現(xiàn)變差。所以你必須掌握“什么信息該保留、什么信息可以壓縮、什么信息可以丟棄”的判斷能力。初學(xué)者最容易犯的錯(cuò)是“把每輪對(duì)話歷史都原樣拼進(jìn)下一次請(qǐng)求”。一開(kāi)始還行到第十輪以后你發(fā)現(xiàn) Prompt 變得巨大一方面響應(yīng)慢另一方面模型已經(jīng)完全不記得最初的目標(biāo)是什么了。更麻煩的是有些信息是中間過(guò)程的臨時(shí)狀態(tài)模型根本不需要知道但你全塞給它它的注意力被分散最后的決策自然就差。我做 Agent 時(shí)有一個(gè)習(xí)慣定義一套清晰的上下文更新規(guī)則。哪些信息是任務(wù)相關(guān)的核心信息必須全程保留哪些信息只需要摘要一下把完整細(xì)節(jié)存到外部存儲(chǔ)里哪些信息是一次性的用完就丟。這套規(guī)則聽(tīng)起來(lái)不復(fù)雜但能不能落地直接區(qū)分你有沒(méi)有真正理解 Agent。3.3 工具調(diào)用的心智模型Agent 的“手和腳”工具調(diào)用是實(shí)現(xiàn) Agent 價(jià)值的核心通道。一個(gè)“只會(huì)說(shuō)不會(huì)做”的 Agent 是聊勝于無(wú)的你要給它配上“手和腳”——也就是它能調(diào)用的工具。這里的工具可以是一個(gè)天氣查詢 API、一個(gè)數(shù)據(jù)庫(kù)查詢函數(shù)、一個(gè)計(jì)算器、一個(gè)爬蟲(chóng)腳本甚至一個(gè)發(fā)給某個(gè)同事的審批通知。做 Agent 的你在“工具調(diào)用”這件事上需要想明白三件事工具定義的清晰度。模型不是人它無(wú)法“看一眼就明白”你的工具是干什么的。你必須用自然語(yǔ)言加上明確的輸入輸出參數(shù)描述把工具的用途寫(xiě)得足夠清楚。工具名別取得模棱兩可參數(shù)說(shuō)明要寫(xiě)到具體類(lèi)型和單位。同一個(gè)功能你叫它“search”還是“search_news_by_keyword”看起來(lái)差別不大但模型決策時(shí)的準(zhǔn)確率可能差很多。錯(cuò)誤處理與重試機(jī)制。真實(shí)世界里沒(méi)有不出錯(cuò)的工具。網(wǎng)絡(luò)超時(shí)、接口返回異常、參數(shù)格式不對(duì)全是常態(tài)。Agent 工具能不能“繞過(guò)去”是項(xiàng)目落地成敗的關(guān)鍵。比如你的 Agent 調(diào)一個(gè)天氣接口失敗了你是直接報(bào)錯(cuò)結(jié)束還是讓它換個(gè)搜索方式再試一次這些兜底邏輯需要你設(shè)計(jì)好而不是指望模型自己會(huì)“靈機(jī)一動(dòng)”。工具權(quán)限邊界。給 Agent 的工具能力越強(qiáng)它“闖禍”的能力也越強(qiáng)。比如你給它一個(gè)“執(zhí)行任意代碼”的工具它可能真的會(huì)在某些情況下做出你不想看到的操作。所以我建議給工具設(shè)計(jì)清晰的權(quán)限級(jí)別能只讀就別給寫(xiě)入能返回少量數(shù)據(jù)就別把整個(gè)庫(kù)導(dǎo)出來(lái)給它。安全底線問(wèn)題在 Agent 上要格外留心。這一塊是新手容易淺嘗輒止的地方。不少人認(rèn)為“工具調(diào)用有啥好學(xué)的無(wú)非就是寫(xiě)一個(gè)函數(shù)然后聲明一下”。真到了實(shí)際項(xiàng)目中你會(huì)知道工具注冊(cè)、參數(shù)校驗(yàn)、超時(shí)管理、日志追蹤、權(quán)限控制每一環(huán)都有講究。3.4 循環(huán)機(jī)制Agent 的“大腦皮層”Agent 的智能來(lái)自“循環(huán)”。人的思考過(guò)程不是一次性的而是反復(fù)進(jìn)行的。模型的單次輸出也類(lèi)似Agent 的循環(huán)機(jī)制就是把它的一次次預(yù)測(cè)、執(zhí)行、觀察串成一個(gè)持續(xù)逼近目標(biāo)的過(guò)程。循環(huán)機(jī)制聽(tīng)起來(lái)高大上核心就三件事條件判斷什么時(shí)候該繼續(xù)什么時(shí)候該結(jié)束比如設(shè)定最大循環(huán)輪次防止死循環(huán)或者當(dāng)模型輸出“任務(wù)完成”標(biāo)記時(shí)就退出。中間狀態(tài)保存執(zhí)行了兩三步之后的中間結(jié)果放哪兒怎么傳給下一步?jīng)Q策這是 Agent 能“記住自己做到哪兒了”的關(guān)鍵。錯(cuò)誤恢復(fù)某一步執(zhí)行失敗是跳過(guò)、重試還是直接認(rèn)輸在新手項(xiàng)目里這一步只要寫(xiě)好了效果會(huì)有質(zhì)的提升??蚣芾镞@些東西已經(jīng)有現(xiàn)成的封裝但如果你自己不親自寫(xiě)一遍出了 bug 你連在哪一層出的都定位不了。我見(jiàn)過(guò)太多開(kāi)發(fā)者在框架里調(diào) Agent日志里翻半天結(jié)果發(fā)現(xiàn)是底層循環(huán)邏輯和工具返回值格式之間出了問(wèn)題但因?yàn)橹虚g被框架黑盒包住了排查起來(lái)非常痛苦。3.5 模型選型的務(wù)實(shí)建議別盲目追求“最強(qiáng)”最后說(shuō)一個(gè)很多人忽略的點(diǎn)模型選型。新手總覺(jué)得效果不好就該換更大的模型但現(xiàn)實(shí)是不同任務(wù)的難度差距很大在 Agent 的每個(gè)環(huán)節(jié)里你用的模型可以不一樣。復(fù)雜的決策步驟可以用高能力的模型來(lái)保證準(zhǔn)確率一些簡(jiǎn)單的信息抽取、格式整理之類(lèi)的機(jī)械活用便宜的小模型就足夠了省下來(lái)的成本非??捎^。我在做一個(gè)輕量級(jí) Agent 時(shí)做過(guò)一個(gè)對(duì)比測(cè)試同一個(gè)任務(wù)全部步驟用大模型單次總成本大概幾毛錢(qián)而把其中整理類(lèi)、抽取類(lèi)的步驟換到小模型效果沒(méi)明顯下降單次總成本卻降到了幾分錢(qián)。這種優(yōu)化意識(shí)建議盡早培養(yǎng)它對(duì)工程化思維非常有益。4. 手把手搭建你的第一個(gè) Agent不依賴框架的實(shí)戰(zhàn)過(guò)程這一章我們來(lái)點(diǎn)實(shí)在的。我會(huì)帶你從一個(gè)最簡(jiǎn)單的“個(gè)人助理型 Agent”開(kāi)始一步步不走框架只用基礎(chǔ)代碼把整個(gè) Agent 的運(yùn)作機(jī)制跑通。主角是一個(gè)文本分析小工具你可以把它理解成“幫我查資料并做總結(jié)”的極簡(jiǎn)版。只要你把這個(gè) Demo 完整寫(xiě)一遍你對(duì) Agent 內(nèi)功的理解會(huì)上一個(gè)臺(tái)階。4.2 明確需求與準(zhǔn)備基礎(chǔ)環(huán)境先定一個(gè)目標(biāo)做一個(gè)“問(wèn)答型 Agent”。用戶問(wèn)它一個(gè)技術(shù)或常識(shí)類(lèi)問(wèn)題它能自己判斷是否需要調(diào)用工具需要的話調(diào)用工具比如搜索引擎 API 或一個(gè)內(nèi)置的簡(jiǎn)單百科查詢接口然后把最終結(jié)果整理成一段有條理的回答。開(kāi)始前需要準(zhǔn)備Python 3.10 或更高版本一個(gè)可用的模型 API 接口哪家都行這里用通用的 OpenAI 風(fēng)格調(diào)用方式舉例一個(gè)簡(jiǎn)單的外部工具我建議就先寫(xiě)一個(gè)本地函數(shù)查某個(gè)城市當(dāng)前的天氣因?yàn)閿?shù)據(jù)好偽造方便調(diào)試。核心代碼結(jié)構(gòu)不復(fù)雜重在理清四件事模型接口的封裝、工具的定義與注冊(cè)、模型返回結(jié)果的解析、循環(huán)控制邏輯。4.3 Handcraft 一個(gè)“會(huì)調(diào)用工具”的最小 Agent下面我用一個(gè)精簡(jiǎn)到極致的示例把“模型決策—工具執(zhí)行—再?zèng)Q策”的循環(huán)完整呈現(xiàn)一遍。你先看全貌我再逐段解釋。import json from openai import OpenAI client OpenAI( api_key你的API_KEY, base_url你的API_BASE_URL ) # 1. 定義一個(gè)模擬的“查天氣”工具 def get_weather(city: str) - str: # 真實(shí)場(chǎng)景中這里會(huì)去請(qǐng)求外部API這里先返回固定數(shù)據(jù) weather_map { 北京: 晴26度微風(fēng), 上海: 小雨22度東南風(fēng)3級(jí), 廣州: 雷陣雨30度南風(fēng)2級(jí), } return weather_map.get(city, 暫無(wú)該城市天氣數(shù)據(jù)) # 2. 工具注冊(cè)表給模型看的“工具說(shuō)明” TOOLS [ { type: function, function: { name: get_weather, description: 查詢指定城市的實(shí)時(shí)天氣情況。, parameters: { type: object, properties: { city: { type: string, description: 城市名稱如北京 } }, required: [city] } } } ] # 3. 工具分發(fā)器把模型想調(diào)用的函數(shù)名映射到真實(shí)函數(shù) def call_tool(name: str, arguments: dict) - str: if name get_weather: return json.dumps({result: get_weather(arguments[city])}, ensure_asciiFalse) return json.dumps({error: f未找到工具: {name}}, ensure_asciiFalse) # 4. 主循環(huán)Agent 的核心邏輯 def run_agent(user_query: str, max_steps: int 5): messages [{role: user, content: user_query}] step 0 while step max_steps: # 4.1 把當(dāng)前消息與工具定義發(fā)給模型 response client.chat.completions.create( modelgpt-4o-mini, # 換成你實(shí)際能用的模型 messagesmessages, toolsTOOLS, tool_choiceauto ) msg response.choices[0].message # 4.2 模型沒(méi)有要求調(diào)用工具說(shuō)明它認(rèn)為可以直接回答了 if not msg.tool_calls: print(最終回答:, msg.content) break # 4.3 模型要求調(diào)用工具把工具調(diào)用加入消息列表 messages.append(msg) for tool_call in msg.tool_calls: tool_name tool_call.function.name tool_args json.loads(tool_call.function.arguments) tool_result call_tool(tool_name, tool_args) messages.append({ role: tool, tool_call_id: tool_call.id, content: tool_result }) print(fStep {step 1}: 調(diào)用 {tool_name}({tool_args}) - {tool_result}) step 1 if step max_steps: print(達(dá)到最大循環(huán)輪次強(qiáng)制停止) if __name__ __main__: run_agent(北京今天天氣怎么樣適合穿短袖嗎)這個(gè) Demo 的代碼量不大但麻雀雖小五臟俱全。把它的執(zhí)行流程走一遍你就會(huì)發(fā)現(xiàn) Agent 的運(yùn)行邏輯其實(shí)非常直白模型收到問(wèn)題后不是先憋一個(gè)答案而是“判斷自己是否需要工具”。如果它調(diào)用了get_weather我們的代碼就把工具返回值作為一條roletool的消息追加到對(duì)話歷史里再帶著新增信息去問(wèn)模型“現(xiàn)在信息夠了嗎”。直到模型覺(jué)得沒(méi)必要再調(diào)用工具直接輸出最終回答循環(huán)結(jié)束。你可以分別拿“北京今天天氣怎么樣”和“幫我講個(gè)笑話”這兩個(gè)問(wèn)題試試看。第二個(gè)問(wèn)題模型大概率不會(huì)調(diào)用任何工具直接輸出回答。這個(gè)對(duì)比能讓你直觀感受到Agent 與普通問(wèn)答的區(qū)別不在于每次都必須調(diào)用工具而在于“有需要時(shí)它有路徑可以拿到外部信息”。4.4 核心代碼設(shè)計(jì)的幾個(gè)關(guān)鍵注意點(diǎn)第一個(gè)關(guān)鍵細(xì)節(jié)tools 參數(shù)的結(jié)構(gòu)。這里的字段名稱和層級(jí)都不是隨便寫(xiě)的模型接口要求的 schema 風(fēng)格決定了它怎么解析你的工具。name要給得簡(jiǎn)短但有區(qū)分度description是模型判斷“該不該用這個(gè)工具”的最重要依據(jù)寧可多寫(xiě)幾句背景也不要只寫(xiě)一個(gè)詞。parameters里則是把每個(gè)參數(shù)的類(lèi)型、含義、約束寫(xiě)清楚凡是能想到的邊界條件都加上說(shuō)明。第二個(gè)關(guān)鍵細(xì)節(jié)tool_call_id必須原樣回傳。模型發(fā)出的每個(gè)工具調(diào)用都帶有唯一 ID你執(zhí)行完工具后要拿到結(jié)果并以tool角色 對(duì)應(yīng)tool_call_id返回模型才能把結(jié)果和它的調(diào)用對(duì)上號(hào)。新手經(jīng)常在這掉鏈子忘了傳 ID或者把 ID 寫(xiě)錯(cuò)了結(jié)果模型一臉茫然死循環(huán)就出現(xiàn)了。第三個(gè)關(guān)鍵細(xì)節(jié)最大循環(huán)輪次的設(shè)定。模型不是每次都能理智地判斷“夠了”。有時(shí)候它會(huì)因?yàn)楣ぞ叻祷氐慕Y(jié)果不夠符合預(yù)期反復(fù)調(diào)用同一個(gè)工具。如果你不做最大輪次限制它不僅會(huì)一直燒你的 token還可能跑出一些意想不到的行為。我這里設(shè)了 5 步相當(dāng)于一個(gè)安全保險(xiǎn)。第四個(gè)關(guān)鍵細(xì)節(jié)工具結(jié)果一定要序列化成字符串再返回。模型接口接收的content是字符串你不能直接把 Python 字典塞進(jìn)去。所以call_tool里用json.dumps轉(zhuǎn)了一下保證了結(jié)構(gòu)可以完整傳遞。你要是隨意用str()轉(zhuǎn)換中文會(huì)變成\uXXXX的轉(zhuǎn)義形式模型看起來(lái)就費(fèi)勁回答質(zhì)量會(huì)下降。4.5 從這個(gè) Demo 中你能提煉出的通用經(jīng)驗(yàn)寫(xiě)完了這個(gè) Demo我希望你不僅把它跑通更要能回答出這幾個(gè)問(wèn)題回答得出來(lái)恭喜你Agent 的地基你就打得很牢了如果模型連續(xù)調(diào)用工具三次之后還沒(méi)有輸出最終答案你該怎么辦工具返回的結(jié)果本身就是一個(gè)很長(zhǎng)的 JSON但你想讓模型只關(guān)注其中幾個(gè)字段你在代碼里怎么處理是直接全量塞給模型還是先篩選一遍如果你有兩個(gè)工具一個(gè)查天氣、一個(gè)查新聞模型在回答“北京今天適合穿什么樣式的衣服”時(shí)會(huì)不會(huì)先查完天氣又查新聞你怎么避免這種多余調(diào)用這些問(wèn)題都沒(méi)有標(biāo)準(zhǔn)答案但它們才是真正能在實(shí)際項(xiàng)目里幫你省時(shí)間的能力??蚣苷f(shuō)白了就是幫你把這些問(wèn)題的若干種常見(jiàn)解答方案打包好了而已?;A(chǔ)設(shè)施你已經(jīng)會(huì)自己搭了框架對(duì)你來(lái)說(shuō)就只是“省事”而不是“救命”。5. 技術(shù)棧之外轉(zhuǎn)行者最容易忽視的“軟技能”與工程習(xí)慣5.1 把需求拆成“模型能理解、代碼能執(zhí)行”的能力轉(zhuǎn)行或者剛?cè)腴T(mén)的人還有一個(gè)很大的困擾“我好像能讀懂技術(shù)文檔但拿到一個(gè)業(yè)務(wù)需求時(shí)仍然不知道從何下手?!边@個(gè)問(wèn)題的本質(zhì)是缺少“需求拆解”的訓(xùn)練。比如產(chǎn)品經(jīng)理說(shuō)“我想做一個(gè)能自動(dòng)回郵件的小助手”你腦子里應(yīng)該立刻冒出這些問(wèn)題郵件從哪來(lái)是用戶轉(zhuǎn)發(fā)、收件箱抓取還是手動(dòng)粘貼回復(fù)的標(biāo)準(zhǔn)是什么要不要帶上客戶的歷史溝通信息語(yǔ)氣風(fēng)格有沒(méi)有要求是否需要人在發(fā)送前確認(rèn)把這些細(xì)節(jié)問(wèn)清楚之后這個(gè)“小助手”才能真正變成一個(gè)可以開(kāi)發(fā)的項(xiàng)目。Agent 開(kāi)發(fā)中這種拆解能力尤其重要因?yàn)槟P捅旧聿簧瞄L(zhǎng)“自己把所有未知細(xì)節(jié)都問(wèn)清楚”它只會(huì)你喂什么它處理什么。你如果連目標(biāo)的邊界條件都沒(méi)定義好那 Agent 就只能靠猜測(cè)工作效果自然不穩(wěn)定。我建議初學(xué)者每次拿到需求先強(qiáng)制自己寫(xiě)一份“輸入是什么、輸出是什么、可用資源是什么、限制條件是什么、例外情況怎么處理”的五段式說(shuō)明寫(xiě)清楚了你再動(dòng)代碼。5.2 日志、追蹤與可觀測(cè)性面向復(fù)雜系統(tǒng)的必備習(xí)慣手寫(xiě) Demo 時(shí)你可能覺(jué)得日志就是print。等到 Agent 真正在生成環(huán)境里跑起來(lái)你面對(duì)的是多步、多工具調(diào)用、偶爾失敗重試的復(fù)雜流程。如果每一步中間結(jié)果、每一次工具調(diào)用、每一個(gè)模型輸出都沒(méi)有留下痕跡排查問(wèn)題就像在黑箱子里摸東西完全靠猜。所以從一開(kāi)始就養(yǎng)成給 Agent 加日志的習(xí)慣模型的每次思考輸出、工具調(diào)用入?yún)⒑统鰠?、以及本輪命中哪個(gè)分支都要記錄下來(lái)。這樣當(dāng)最終結(jié)果與預(yù)期不符時(shí)你是可以按步驟回溯的而不是拿到一句錯(cuò)誤的最終回答就開(kāi)始瞎試。我見(jiàn)過(guò)很多線上事故最后排查下來(lái)都是中間某一步的工具返回了臟數(shù)據(jù)但因?yàn)闆](méi)有日志花了很長(zhǎng)時(shí)間才定位到這一層。5.3 成本意識(shí)知道你的 Agent 每跑一次要花多少錢(qián)這是一個(gè)很現(xiàn)實(shí)的問(wèn)題。模型是按 token 計(jì)費(fèi)的Agent 是多輪對(duì)話、多工具反饋重試的系統(tǒng)它的 token 消耗遠(yuǎn)高于一個(gè)簡(jiǎn)單的問(wèn)答。如果你不做任何優(yōu)化一次完整任務(wù)的成本可能是你想像的幾倍。我在實(shí)際項(xiàng)目里常用的三個(gè)降本招數(shù)分享給各位精簡(jiǎn)上下文每一輪都篩選最有價(jià)值的信息避免把大量中間過(guò)程塞進(jìn)請(qǐng)求小模型前置分類(lèi)先用一個(gè)小模型判斷問(wèn)題類(lèi)型再?zèng)Q定是否調(diào)用大模型做深度處理設(shè)置預(yù)算上限在循環(huán)機(jī)制里統(tǒng)計(jì) token 消耗超過(guò)一定閾值強(qiáng)制切換低成本模型或終止任務(wù)。這些能力看起來(lái)不“性感”但對(duì)實(shí)際項(xiàng)目落地影響很大。初學(xué)者在滿足“能跑”之后一定要盡早補(bǔ)上成本意識(shí)這一課。6. 什么時(shí)候才需要引入框架如何選型與避坑6.1 判斷標(biāo)準(zhǔn)你的項(xiàng)目復(fù)雜度到了哪一級(jí)看到這里你應(yīng)該能理解我并不是反對(duì)框架框架本質(zhì)上是對(duì)“手搓積木”的沉淀它提高了大量重復(fù)工作的效率。但問(wèn)題是什么階段引入框架最合適、選型時(shí)最該關(guān)注什么很多新手完全沒(méi)有概念。我給你一個(gè)很干的判斷方式你的 Agent 如果只需要調(diào)用一到三個(gè)工具、邏輯散落在幾個(gè)簡(jiǎn)單函數(shù)里、調(diào)用流程不超過(guò)五步那完全不需要框架手寫(xiě)就夠了。這個(gè)階段引入框架反而會(huì)平白增加你的學(xué)習(xí)成本和抽象復(fù)雜度。但如果你開(kāi)始面對(duì)這些場(chǎng)景需要管理多個(gè) Agent 協(xié)作、工具數(shù)量超過(guò)十個(gè)、上下文和歷史操作需要共享、需要可視化的操作追蹤面板、或者你的 Agent 需要接入復(fù)雜的記憶系統(tǒng)那就確實(shí)需要考慮用框架了。6.2 選型時(shí)我一般看四個(gè)維度第一是社區(qū)活躍度與文檔質(zhì)量??蚣苌鷳B(tài)是否活躍、遇到新問(wèn)題能不能搜到思路、文檔里的例子是否貼合真實(shí)場(chǎng)景這些比某個(gè)炫酷特性重要得多。第二是抽象層是否足夠薄。有些框架把一切都封裝成“漂亮”的高級(jí) API看起來(lái)方便但你很難定位問(wèn)題我建議選那些核心概念貼近底層邏輯、你也容易打開(kāi)的框架。第三是獨(dú)立于框架的模型與工具接入自由度??蚣茉介_(kāi)放你才越不會(huì)后期被限制住手腳。第四是團(tuán)隊(duì)里其他人的熟悉程度。如果只有你一個(gè)人會(huì)用它再優(yōu)秀也不能給團(tuán)隊(duì)帶來(lái)持續(xù)價(jià)值。6.3 一個(gè)常見(jiàn)架構(gòu)落地案例從手寫(xiě)過(guò)渡到框架為了讓你更直觀理解什么時(shí)候要升級(jí)我舉個(gè)例子。某個(gè)人在做一個(gè)“內(nèi)容安全審核 Agent”初期就是手寫(xiě)的流程模型先用一個(gè)小模型判斷內(nèi)容是否疑似違規(guī)疑似的話再調(diào)用后端敏感詞過(guò)濾工具和人工復(fù)審隊(duì)列接口。手寫(xiě)代碼跑得挺順暢因?yàn)檫壿嫼?jiǎn)單就兩個(gè)分支迭代快。后來(lái)需求變了要求 Agent 能對(duì)不同平臺(tái)的不同規(guī)則做分別處理還要能根據(jù)審核記錄的反饋持續(xù)自我優(yōu)化規(guī)則。工具數(shù)量從三個(gè)漲到了十幾個(gè)工作流也從單線變成了可以分叉合并的拓?fù)浣Y(jié)構(gòu)。這個(gè)時(shí)候再手寫(xiě) while 循環(huán)就去很痛苦了。于是他遷移到框架用現(xiàn)成的狀態(tài)機(jī)、記憶抽象和管理界面把更多時(shí)間花在業(yè)務(wù)規(guī)則的精細(xì)化上而非自己維護(hù)一套工作流引擎。這個(gè)例子說(shuō)明手寫(xiě)和框架不是對(duì)立的而是兩個(gè)不同階段的合適工具。你的目標(biāo)應(yīng)該是能隨時(shí)在這兩者之間來(lái)回切換而不是把某一個(gè)的使用當(dāng)成信仰。6.4 新手選框架時(shí)最該避開(kāi)的坑選框架有兩個(gè)常見(jiàn)的坑。一個(gè)是“看名氣”誰(shuí)火就選誰(shuí)也不管項(xiàng)目實(shí)際是什么狀態(tài)。很多框架停留在原型階段API 說(shuō)變就變你今天照著文檔寫(xiě)的代碼下個(gè)月就全廢了。另一個(gè)是“貪多”上來(lái)就想用一個(gè)框架解決所有問(wèn)題。結(jié)果把編排、記憶、工具庫(kù)、界面全綁死在一個(gè)生態(tài)里后期想換其中一個(gè)組件時(shí)發(fā)現(xiàn)牽一發(fā)而動(dòng)全身。我自己的經(jīng)驗(yàn)是先把手寫(xiě)好的代碼和框架的核心抽象對(duì)齊一下判斷框架對(duì)每個(gè)組件的封裝是否符合我當(dāng)前的使用方式。如果符合就引進(jìn)來(lái)把重復(fù)的部分替換掉如果不符合那就手寫(xiě)這一部分框架不強(qiáng)求。這個(gè)做法能讓你的項(xiàng)目長(zhǎng)期保持在“可控”的狀態(tài)。7. 新手實(shí)戰(zhàn)中常踩的坑與快速排查手冊(cè)7.1 模型就是不調(diào)用工具怎么辦這個(gè)現(xiàn)象新手很容易遇到。你明明把工具定義傳過(guò)去了模型卻像完全看不見(jiàn)工具一樣每次都直接給你最終回答。這個(gè)時(shí)候建議你先做一次“極小化排查”把模型叫出來(lái)故意問(wèn)一個(gè)只有用工具才能回答的問(wèn)題比如“幫我查一下上?,F(xiàn)在的天氣”確認(rèn)工具描述是否足夠明確然后嘗試在系統(tǒng)提示詞里加一句“如果需要實(shí)時(shí)數(shù)據(jù)請(qǐng)務(wù)必調(diào)用工具獲取后再回答”。有時(shí)候模型不調(diào)工具真的是因?yàn)樗X(jué)得“自己知道答案”這和工具定義沒(méi)太大關(guān)系。提示詞引導(dǎo)一下就好。7.2 工具被反復(fù)調(diào)用進(jìn)入了“死循環(huán)”這個(gè)問(wèn)題在高復(fù)雜度任務(wù)里尤其常見(jiàn)。模型可能因?yàn)榈谝淮握{(diào)用工具的結(jié)果不符合預(yù)期就一直重復(fù)調(diào)用同一個(gè)工具白白消耗資源。處理思路從上到下依次是設(shè)定最大循環(huán)次數(shù)這是底線每一次工具調(diào)用的結(jié)果都要作為新的上下文內(nèi)容返回讓模型看到“這次已經(jīng)查過(guò)了結(jié)果是什么”有助于它停止重復(fù)還可以在 Prompt 里要求模型“如果上次工具結(jié)果已經(jīng)足夠回答請(qǐng)直接做出回答”。7.3 模型對(duì)工具參數(shù)的理解出現(xiàn)偏差比如你的工具需要傳入“城市中文名”模型卻喜歡傳拼音縮寫(xiě)或者你的工具需要“日期”模型卻給你傳“今天”。這類(lèi)問(wèn)題的核心是參數(shù)描述和格式示例做得不夠。在description和properties里把“支持的值類(lèi)型”和“典型寫(xiě)法”寫(xiě)清楚相當(dāng)有效。還有一個(gè)辦法就是把工具函數(shù)內(nèi)部做成容錯(cuò)型比如做一個(gè)拼音到中文的映射表把常見(jiàn)的別名都?xì)w攏一下。人有模糊表達(dá)的自由代碼就得學(xué)會(huì)做兜底。7.4 返回結(jié)果格式不穩(wěn)定代碼解析頻繁報(bào)錯(cuò)不按照你設(shè)定的 schema 輸出是常見(jiàn)的煩惱。無(wú)論你 Prompt 寫(xiě)多少遍“必須輸出 JSON”模型還是偶爾給你加幾句解釋文字。這時(shí)候不能只靠“寫(xiě)完 Prompt 祈禱它守規(guī)矩”最穩(wěn)妥的做法是在代碼里做一層魯棒解析。先提取其中的 JSON 片段再加以解析失敗時(shí)用正則兜底。同時(shí)設(shè)計(jì)“解析失敗重試”邏輯讓模型重新輸出一遍。對(duì)于重要字段解析失敗時(shí)寧可拋出中斷也不要讓臟數(shù)據(jù)繼續(xù)流轉(zhuǎn)下去。7.5 排查工具速查表為了讓你少走彎路我把常見(jiàn)問(wèn)題分類(lèi)整理了一下后續(xù)調(diào)試時(shí)直接對(duì)照著檢查就好。現(xiàn)象最可能的原因優(yōu)先排查方向模型從不調(diào)用工具提示詞未明確要求或工具描述太弱檢查系統(tǒng)提示詞明確“必須調(diào)工具以獲取實(shí)時(shí)數(shù)據(jù)”工具調(diào)用后模型仍答非所問(wèn)工具結(jié)果未正確追加到消息歷史檢查roletool的消息是否拼接正確工具參數(shù)數(shù)值錯(cuò)誤參數(shù)描述不完善缺少格式示例補(bǔ)充參數(shù)類(lèi)型及枚舉示例循環(huán)無(wú)法終止缺少最大輪次或未標(biāo)記“完成”信號(hào)引入max_steps和顯式的任務(wù)完成標(biāo)記輸出格式不穩(wěn)定提示詞約束不夠或模型版本太弱用少量示例固定結(jié)構(gòu)代碼里加魯棒解析單次任務(wù)成本過(guò)高上下文越長(zhǎng)越大沒(méi)有壓縮與篩選做上下文清理小模型前置處理報(bào)錯(cuò)信息指向不明缺少中間過(guò)程日志給每一步加結(jié)構(gòu)化日志記錄入?yún)⒑统鰠?. 寫(xiě)在最后的幾點(diǎn)個(gè)人建議看到這里你應(yīng)該已經(jīng)意識(shí)到了AI Agent 的學(xué)習(xí)路徑不是從“認(rèn)識(shí)框架”開(kāi)始的而是從“理解 Agent 的底層邏輯”開(kāi)始的。打好基礎(chǔ)之后看框架就像看一份別人幫你整理好的筆記很多概念早就在你的腦子里了。所以如果你正打算入行或者轉(zhuǎn)行我先建議你花一周時(shí)間把文中那個(gè)最小 Demo 自己敲一遍、調(diào)試一遍、改出點(diǎn)自己的花樣來(lái)再?zèng)Q定要不要碰框架這個(gè)順序會(huì)讓你的學(xué)習(xí)效率高非常多。你可能會(huì)問(wèn)“我已經(jīng)開(kāi)始啃框架了現(xiàn)在再看這篇還來(lái)得及嗎”任何時(shí)候都來(lái)得及你缺的不是進(jìn)度而是對(duì)底層邏輯的掌控感。就算看完了框架再回頭補(bǔ)手寫(xiě)基礎(chǔ)也不丟人反而會(huì)讓你把框架用得更好。我也見(jiàn)過(guò)不少?gòu)奈疫@里手寫(xiě) Demo 之后的人回去再翻 LangChain 文檔一眼就能看出哪個(gè)抽象是省事的糖哪個(gè)抽象是保命的必需品。最后再分享一個(gè)小技巧。入門(mén)階段不要太糾結(jié)于“選擇哪個(gè)模型”“用哪個(gè)框架”而是把時(shí)間花在“把一個(gè)小 Agent 從‘偶爾能用’調(diào)到‘穩(wěn)定可用’”這個(gè)過(guò)程中。這個(gè)過(guò)程里遇到的所有問(wèn)題都是你進(jìn)步最快的教材。保持記錄這些問(wèn)題的好習(xí)慣把每一次排查過(guò)程寫(xiě)成你的個(gè)人知識(shí)庫(kù)你會(huì)比那些只刷教程的人成長(zhǎng)快得多。加油動(dòng)手寫(xiě)起來(lái)吧。